diff --git a/CHANGELOG.md b/CHANGELOG.md index 0681f21..1febdef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Disabled continuous deployment in GHA. See `.github/workflows/build_artifact.yml` for details * `M` now marks the current row to the given letter on the keyboard +* `;lm` now lists all marks in the current file in an overlay * Resolve crash when user tries to switch top or bottom line outside of scope * Resolved crash when the user tries to `delete word` past the end of a line diff --git a/README.md b/README.md index 98ff937..4dc09bd 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ following commands in alphabetical order are available: | `;f ` | Find the next occurence of the given string in the buffer | | `;f` | Find the next occurence of the previously entered string | | `;lb` | List all open buffers | +| `;lm` | List marks on the current file | | `;ping` | `pong` (for testing purposes) | | `;e` | Open a new buffer - specify a filename to open an existing file | | `;q` | Quit | diff --git a/src/controller.cpp b/src/controller.cpp index 30cf085..1794f68 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -109,6 +109,11 @@ void Controller::start_action_engine() { if (!(k.has_value())) { continue; } + if (view.overlay_open) { + view.overlay_open = false; + view.draw_screen(); + } + if (mode == Mode::Write) { if (k.value() == rawterm::Key(' ', rawterm::Mod::Escape)) { parse_action(&view, Action {ActionType::ChangeMode, Mode::Read}); @@ -608,6 +613,26 @@ bool Controller::parse_command() { return false; + // list marks + } else if (cmd.substr(0, 3) == ";lm") { + std::vector body = {}; + const Model* const active_model = view.get_active_model(); + + for (const auto& m : active_model->marks) { + body.push_back( + std::format("{} | {}:{}", m.first, m.second.line_pos, m.second.char_pos)); + + if (body.size() == 7) { break; } + } + + while (body.size() < 7) { + body.push_back(""); + } + + const std::string title = "Marks (" + active_model->filename + ")"; + + view.draw_overlay(body, title); + // find/replace (sed) } else if (cmd.substr(0, 2) == ";s" && cmd.size() > 2) { view.get_active_model()->search_and_replace(cmd.substr(3, cmd.size())); diff --git a/src/view.cpp b/src/view.cpp index 644a0e1..d8fc16c 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -573,13 +573,17 @@ bool View::set_buffer(const std::size_t bufnr, const std::size_t model_len) { // TODO: Make this more generic for overlays in other locations void View::draw_overlay(std::span contents, std::string_view title) { - // rawterm::Pos top_left = {view_size.vertical - 7 - 3, line_number_offset + 2}; rawterm::Pos top_left = {view_size.vertical - 7 - 3, 0}; rawterm::Pos bottom_right = {view_size.vertical - 1, view_size.horizontal - 1}; auto region = rawterm::Region(top_left, bottom_right); auto border = rawterm::Border(region).set_padding(1).set_title(std::format(" {} ", title)); + const rawterm::Cursor cur_pos = cur; + border.draw(cur, contents); + + cur = cur_pos; + overlay_open = true; } [[nodiscard]] std::string View::render_cursor_coords() const { diff --git a/src/view.h b/src/view.h index 83da062..bdebe18 100644 --- a/src/view.h +++ b/src/view.h @@ -33,6 +33,7 @@ struct View { std::string command_text = ";"; std::string git_branch = ""; std::string prev_tab_bar = ""; // For ensuring we only redraw when we need to + bool overlay_open = false; View(Controller*, const rawterm::Pos); void add_model(Model*); diff --git a/tests/integration/command_mode_test.py b/tests/integration/command_mode_test.py index be841ca..2b8c354 100644 --- a/tests/integration/command_mode_test.py +++ b/tests/integration/command_mode_test.py @@ -1,5 +1,6 @@ import os import time +from typing import Final from setup import setup from setup import TmuxRunner @@ -415,3 +416,14 @@ def test_run_shell_cmd_stderr(r: TmuxRunner): msg: str = r.color_screenshot()[-1] assert "hello" in msg assert "255;0;0" in msg # red text + + +@setup("tests/fixture/lorem_ipsum.txt") +def test_list_marks(r: TmuxRunner): + r.type_str("ma") + r.iris_cmd("lm") + + title_line: Final[str] = r.lines()[-11] + assert "Marks" in title_line + assert "lorem_ipsum.txt" in title_line + assert "a | 0:0 " in r.lines()[-10]