diff --git a/.gitignore b/.gitignore index aa093f5..5fdc79d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/ .cache zig-out/ .zig-cache +iris.log diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1df52a9..3c5a552 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ --- repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-case-conflict - id: check-merge-conflict @@ -9,7 +9,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.7 + rev: v21.1.1 hooks: - id: clang-format types_or: [c++, c, cuda] diff --git a/CHANGELOG.md b/CHANGELOG.md index 84e1c29..2a20162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ -### v4.0.8 +### main/HEAD * Add new Cursor::move overload to accept two integers +* Handle bug in border rendering crashing with no lines of text ### v4.0.7 * Added unit testing in `tests/` directory diff --git a/examples/borders.cpp b/examples/borders.cpp index 523ea47..d91b8a5 100644 --- a/examples/borders.cpp +++ b/examples/borders.cpp @@ -16,13 +16,14 @@ int main() { rawterm::Cursor cur; cur.reset(); - std::vector text = {"Hello world", "foo", "bar", "some text again and again"}; + std::vector text = {}; 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)); + text = {"Hello world", "foo", "bar", "some text again and again"}; 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); diff --git a/examples/red_blue_panes.cpp b/examples/red_blue_panes.cpp index a0df5e9..5126b16 100644 --- a/examples/red_blue_panes.cpp +++ b/examples/red_blue_panes.cpp @@ -89,9 +89,10 @@ int main() { } auto pane_mgr = rawterm::PaneManager(rawterm::get_term_size()); - pane_mgr.set_content(std::vector( - lryics_2.begin(), - lryics_2.begin() + std::min(term_size.vertical, static_cast(lryics_2.size())))); + pane_mgr.set_content( + std::vector( + lryics_2.begin(), + lryics_2.begin() + std::min(term_size.vertical, static_cast(lryics_2.size())))); pane_mgr.set_pane_background(rawterm::Colors::aqua); diff --git a/rawterm/extras/border.h b/rawterm/extras/border.h index 53bfde5..cb3d343 100644 --- a/rawterm/extras/border.h +++ b/rawterm/extras/border.h @@ -66,12 +66,14 @@ namespace rawterm { [[nodiscard]] std::vector render(const std::vector* text) const { auto trunc_title = truncated_title(); std::vector render = {""}; - std::size_t longest_txt = - std::max_element( - text->begin(), text->end(), - [](const std::string& a, const std::string& b) { return a.size() < b.size(); }) - ->size() + - std::size_t(border_padding); + std::size_t longest_txt = text->empty() + ? 0 + : std::max_element( + text->begin(), text->end(), + [](const std::string& a, const std::string& b) { + return a.size() < b.size(); + })->size() + + std::size_t(border_padding); if (longest_txt > size.width()) { longest_txt = size.width() - 2; @@ -92,30 +94,32 @@ namespace rawterm { } // 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; + if (!text->empty()) { + 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() > static_cast(longest_txt)) { + drawable_text = line.substr(0, static_cast(longest_txt)); + } + const std::size_t line_buffer = + size.width() - drawable_text.size() - border_padding - 2; + 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); } - - std::string drawable_text = line; - if (line.size() > static_cast(longest_txt)) { - drawable_text = line.substr(0, static_cast(longest_txt)); - } - const std::size_t line_buffer = - size.width() - drawable_text.size() - border_padding - 2; - 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 diff --git a/tests/border_test.cpp b/tests/border_test.cpp index 7755e87..acaa82b 100644 --- a/tests/border_test.cpp +++ b/tests/border_test.cpp @@ -42,6 +42,13 @@ boost::ut::suite<"Border"> border_suite = [] { expect(rendered.at(1).size() == 14); }; + "render without passed text"_test = [&b] { + std::vector expected = {"┌────────┐", "└────────┘"}; + std::vector given = {}; + auto rendered = b.render(&given); + expect(rendered == expected); + }; + "Set title"_test = [&b, &b2] { b.set_title("Super long title please"); expect(b.border_title == "Super long title please"); diff --git a/tests/include/ut.hpp b/tests/include/ut.hpp index f392b72..a3ae81e 100644 --- a/tests/include/ut.hpp +++ b/tests/include/ut.hpp @@ -2118,8 +2118,9 @@ namespace boost::inline ext::ut::inline v2_1_1 { if (filter_(level_, path_)) { if (not level_++) { - reporter_.on(events::test_begin { - .type = test.type, .name = test.name, .location = test.location}); + reporter_.on( + events::test_begin { + .type = test.type, .name = test.name, .location = test.location}); } else { reporter_.on(events::test_run {.type = test.type, .name = test.name}); } @@ -2146,13 +2147,14 @@ namespace boost::inline ext::ut::inline v2_1_1 { } #endif - if (not--level_) { + if (not --level_) { reporter_.on(events::test_end {.type = test.type, .name = test.name}); } else { // N.B. prev. only root-level tests were signalled on // finish if constexpr (requires { - reporter_.on(events::test_finish { - .type = test.type, .name = test.name}); + reporter_.on( + events::test_finish { + .type = test.type, .name = test.name}); }) { reporter_.on(events::test_finish {.type = test.type, .name = test.name}); } @@ -2172,14 +2174,16 @@ namespace boost::inline ext::ut::inline v2_1_1 { } if (static_cast(assertion.expr)) { - reporter_.on(events::assertion_pass { - .expr = assertion.expr, .location = assertion.location}); + reporter_.on( + events::assertion_pass { + .expr = assertion.expr, .location = assertion.location}); return true; } ++fails_; - reporter_.on(events::assertion_fail { - .expr = assertion.expr, .location = assertion.location}); + reporter_.on( + events::assertion_fail { + .expr = assertion.expr, .location = assertion.location}); return false; }