Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
* Added unit testing in `tests/` directory
* Added zig build option
* `extras/menu.h` - New widget added for adding a vertical scrolling menu
* `extras/border.h` - New widget added for drawing borders around a given
vector of strings
* `screen.h` - Added hashing for `Pos` object to use as a key in
`std::unordered_map` and other hashed objects
* `text.h` - Add `raw_str` function to strip a string of any added ansi escape
codes
* Added new examples:
* `examples/vertical_menu.cpp` for trialing menu.h
* `examples/game.cpp` porting a simple "collect the coin" game to Rawterm

* `examples/borders.cpp` for a simple display of how to use border.h

### v4.0.6
* `extras/pane.h` - Added handling for blacklisting Regions from the cursor
Expand Down
6 changes: 4 additions & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
include_directories(${PROJECT_SOURCE_DIR}/rawterm)

add_executable(border borders.cpp)
add_executable(cells cells.cpp)
add_executable(colors colors.cpp)
add_executable(cursor_position cursor_position.cpp)
add_executable(game game.cpp)
add_executable(hello_world hello_world.cpp)
add_executable(keys keys.cpp)
add_executable(raw_escapes raw_escapes.cpp)
add_executable(red_blue_panes red_blue_panes.cpp)
add_executable(vertical_menu vertical_menu.cpp)
add_executable(game game.cpp)

target_link_libraries(border PUBLIC rawterm)
target_link_libraries(cells PUBLIC rawterm)
target_link_libraries(colors PUBLIC rawterm)
target_link_libraries(cursor_position PUBLIC rawterm)
target_link_libraries(game PUBLIC rawterm)
target_link_libraries(hello_world PUBLIC rawterm)
target_link_libraries(keys PUBLIC rawterm)
target_link_libraries(raw_escapes PUBLIC rawterm)
target_link_libraries(red_blue_panes PUBLIC rawterm)
target_link_libraries(vertical_menu PUBLIC rawterm)
target_link_libraries(game PUBLIC rawterm)
33 changes: 33 additions & 0 deletions examples/borders.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <rawterm/color.h>
#include <rawterm/core.h>
#include <rawterm/cursor.h>
#include <rawterm/extras/border.h>
#include <rawterm/screen.h>

#include <string>
#include <vector>

int main() {
rawterm::enable_raw_mode();
rawterm::enter_alt_screen();
rawterm::enable_signals();

rawterm::Cursor::cursor_hide();
rawterm::Cursor cur;
cur.reset();

std::vector<std::string> text = {"Hello world", "foo", "bar", "some text again and again"};
rawterm::Region region = rawterm::Region(rawterm::Pos(3, 3), rawterm::Pos(10, 25));
auto border = rawterm::Border(region).set_padding(1).set_title("Hello world");
border.draw(cur, &text);

rawterm::Region region2 = rawterm::Region(rawterm::Pos(13, 3), rawterm::Pos(20, 40));

auto color = rawterm::Color(109, 192, 35);
auto border2 = rawterm::Border(region2, '#').set_title("This is my title").set_color(color);
border2.draw(cur, &text);

std::ignore = rawterm::wait_for_input();
rawterm::Cursor::cursor_show();
return 0;
}
1 change: 0 additions & 1 deletion examples/keys.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <rawterm/color.h>
#include <rawterm/core.h>
#include <rawterm/extras/extras.h>
// #include <sys/types.h>

#include <cctype>
#include <iostream>
Expand Down
41 changes: 41 additions & 0 deletions rawterm/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
BasedOnStyle: Chromium
AlignAfterOpenBracket: AlwaysBreak
AllowShortIfStatementsOnASingleLine: WithoutElse
ColumnLimit: '100'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
Cpp11BracedListStyle: 'true'
IncludeBlocks: Regroup
IncludeCategories:
# Standard library headers (e.g., <vector>, <iostream>)
- Regex: '<(algorithm|array|cassert|cctype|cerrno|cfloat|chrono|cmath|complex|condition_variable|csetjmp|csignal|cstdarg|cstddef|cstdint|cstdio|cstdlib|cstring|ctime|cwchar|cwctype|deque|exception|fstream|functional|initializer_list|iomanip|ios|iosfwd|iostream|istream|iterator|limits|list|locale|map|memory|mutex|new|numeric|ostream|queue|random|regex|scoped_allocator|set|sstream|stack|stdexcept|string|strstream|system_error|thread|tuple|type_traits|typeindex|typeinfo|unordered_map|unordered_set|utility|valarray|vector|[c]*[a-z_]+)>'
Priority: 1
SortPriority: 1
CaseSensitive: false

# Third-party headers (enclosed in <>, but not standard library)
- Regex: '<.+[/0-9a-z_]*\.h[p]?[p]?>'
Priority: 2
SortPriority: 2
CaseSensitive: false

# Project headers (enclosed in "", without paths)
- Regex: '".*\.h[p]?[p]?"'
Priority: 3
SortPriority: 3
CaseSensitive: false

# Project headers (enclosed in "", with paths)
- Regex: '".+[/0-9a-z_]*\.h[p]?[p]?"'
Priority: 4
SortPriority: 4
CaseSensitive: false
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: 'true'
SpaceBeforeCpp11BracedList: 'true'
SpacesInContainerLiterals: 'true'
Standard: Cpp11
TabWidth: '4'
6 changes: 5 additions & 1 deletion rawterm/color.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef RAWTERM_COLOR_H
#define RAWTERM_COLOR_H

#include <cstdint>
#include <string>

namespace rawterm {
Expand All @@ -20,6 +19,10 @@ namespace rawterm {
return os << std::to_string(c.red) + ";" + std::to_string(c.green) + ";" +
std::to_string(c.blue) + "m";
}

[[nodiscard]] bool operator==(const Color& other) const {
return this->red == other.red && this->blue == other.blue && this->green == other.green;
}
};

// Color presets
Expand All @@ -41,6 +44,7 @@ namespace rawterm {
inline const Color purple {128, 0, 128};
inline const Color fuchsia {255, 0, 255};
inline const Color orange {255, 127, 0};
inline const std::string reset = "\x1b[0m";
} // namespace Colors

[[nodiscard]] std::string set_foreground(const std::string&, const Color&);
Expand Down
6 changes: 3 additions & 3 deletions rawterm/core.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#ifndef RAWTERM_CORE_H
#define RAWTERM_CORE_H

#include <poll.h>
#include <unistd.h>

#include <array>
#include <cctype>
#include <cmath>
Expand All @@ -21,6 +18,9 @@
#include <utility>
#include <vector>

#include <poll.h>
#include <unistd.h>

#if __linux__
#include <sys/ioctl.h>
#include <termios.h>
Expand Down
163 changes: 163 additions & 0 deletions rawterm/extras/border.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#ifndef RAWTERM_BORDER_H
#define RAWTERM_BORDER_H

#include <algorithm>
#include <optional>
#include <string>
#include <vector>

#include <rawterm/color.h>
#include <rawterm/core.h>
#include <rawterm/cursor.h>
#include <rawterm/screen.h>

namespace rawterm {
struct Border {
Region size;
int border_padding = 0;

std::optional<char> border_char;
std::optional<std::string> border_title;
std::optional<Color> border_color;

static constexpr std::string CORNER_TL = "\u250C";
static constexpr std::string CORNER_TR = "\u2510";
static constexpr std::string CORNER_BL = "\u2514";
static constexpr std::string CORNER_BR = "\u2518";
static constexpr std::string VERTICAL_BAR = "\u2502";
static constexpr std::string HORIZONTAL_BAR = "\u2500";

Border(Region size) : size(size), border_char(std::nullopt) {}
Border(Region size, char border_char) : size(size), border_char(border_char) {}

Border& set_padding(int padding) {
border_padding = padding;
return *this;
}

Border& set_title(const std::string& title) {
border_title = title;
return *this;
}

Border& set_color(const Color& color) {
border_color = color;
return *this;
}

[[nodiscard]] const std::string truncated_title() const {
if (!(border_title.has_value())) {
return "";
}

const int truncated_length = size.width() - 2;
if (truncated_length < 4) {
return "...";
}
if (truncated_length >= border_title.value().size()) {
return border_title.value();
}
return border_title.value().substr(0, size.width() - 4) + "...";
}

[[nodiscard]] std::vector<std::string> render(const std::vector<std::string>* text) const {
auto trunc_title = truncated_title();
std::vector<std::string> render = {""};
int longest_txt =
std::max_element(
text->begin(), text->end(),
[](const std::string& a, const std::string& b) { return a.size() < b.size(); })
->size() +
border_padding;
if (longest_txt > size.width()) {
longest_txt = size.width() - 2;
}

// Top line
const int post_title_len = (longest_txt + border_padding + 2) - trunc_title.size() - 1;
if (border_char.has_value()) {
render.at(0) = border_char.value() + trunc_title;
render.at(0) += std::string(post_title_len, border_char.value());
} else {
render.at(0) = CORNER_TL + trunc_title;
for (int i = 0; i < post_title_len; i++) {
render.at(0) += HORIZONTAL_BAR;
}
render.at(0) += CORNER_TR;
}

// Drawing text
for (const auto& line : *text) {
std::string rendered_line = "";
if (border_char.has_value()) {
rendered_line.push_back(border_char.value());
} else {
rendered_line += VERTICAL_BAR;
}

std::string drawable_text = line;
if (line.size() > longest_txt) {
drawable_text = line.substr(0, longest_txt);
}
const int line_buffer = longest_txt - drawable_text.size();
rendered_line += std::string(border_padding, ' ') + drawable_text +
std::string(border_padding + line_buffer, ' ');

if (border_char.has_value()) {
rendered_line.push_back(border_char.value());
} else {
rendered_line += VERTICAL_BAR;
}

render.push_back(rendered_line);
}

// Bottom line
std::string btm = "";
if (border_char.has_value()) {
btm = std::string(render.at(0).size(), border_char.value());
} else {
btm = CORNER_BL;
for (int i = 0; i <= longest_txt + border_padding; i++) {
btm += HORIZONTAL_BAR;
}
btm += CORNER_BR;
}

render.push_back(btm);

return render;
};

void draw(Cursor& cur, const std::vector<std::string>* text) const {
// Disable if rawterm_debug
if (detail::is_debug()) {
return;
}

// Check if terminal size is reasonable and early return if not
const Pos current_term_size = get_term_size();
if (current_term_size.vertical < size.height()) {
return;
} else if (current_term_size.horizontal < size.width()) {
return;
}

const std::vector<std::string> render_lines = render(text);
for (int i = 0; i < render_lines.size(); i++) {
cur.move({size.top_left.vertical + i, size.top_left.horizontal});

if (border_color.has_value()) {
std::cout << "\x1b[" << border_color.value();
}
std::cout << render_lines.at(i) << std::flush;
if (border_color.has_value()) {
std::cout << Colors::reset;
}
}
}
};

} // namespace rawterm

#endif // RAWTERM_BORDER_H
12 changes: 6 additions & 6 deletions rawterm/extras/pane.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
#include <rawterm/color.h>
#include <rawterm/core.h>
#include <rawterm/cursor.h>
#include <rawterm/screen.h>
#include <rawterm/text.h>

#include <algorithm>
#include <array>
#include <functional>
Expand All @@ -15,6 +9,12 @@
#include <type_traits>
#include <vector>

#include <rawterm/color.h>
#include <rawterm/core.h>
#include <rawterm/cursor.h>
#include <rawterm/screen.h>
#include <rawterm/text.h>

namespace rawterm {
template <typename T = std::vector<std::string>>
class PaneManager {
Expand Down
9 changes: 9 additions & 0 deletions rawterm/screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,13 @@ namespace rawterm {
// Return the intersection region
return {intersection_top_left, intersection_bottom_right};
}

[[nodiscard]] const int Region::width() const {
return bottom_right.horizontal - top_left.horizontal;
}

[[nodiscard]] const int Region::height() const {
return bottom_right.vertical - top_left.vertical;
}

} // namespace rawterm
2 changes: 2 additions & 0 deletions rawterm/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace rawterm {
Region(const Pos& tl, const Pos& br) : top_left(tl), bottom_right(br) {}
[[nodiscard]] bool contains(const Pos& cmp) const;
[[nodiscard]] Region intersect(const Region& other);
[[nodiscard]] const int width() const;
[[nodiscard]] const int height() const;
};
} // namespace rawterm

Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_compile_options(-g)
add_executable(test_exe
main.cpp # DO not modify

border_test.cpp
color_test.cpp
core_test.cpp
cursor_test.cpp
Expand Down
Loading
Loading