diff --git a/CHANGELOG.md b/CHANGELOG.md index 857a30b..cdc2846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### main / head +* `>` now intends the current line. * Implement `;!` to execute a shell command from the command bar * Disabled continuous deployment in GHA. See `.github/workflows/build_artifact.yml` for details diff --git a/README.md b/README.md index f6527c3..a5102c8 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ perform the following actions (alphabetically ordered): | ] | Go to end of paragraph (next empty line) | | _ | Go to beginning of line | | $ | Go to end of line | +| > | Indent current line | ### Command mode Likewise, you can switch to `command` mode with the semicolon `;` key. The diff --git a/src/action.h b/src/action.h index 2bed2d2..019848b 100644 --- a/src/action.h +++ b/src/action.h @@ -19,6 +19,7 @@ enum class ActionType { DelCurrentLine, DelCurrentWord, EndOfLine, + IndentLine, JumpEndOfWord, JumpNextPara, JumpPrevPara, @@ -161,6 +162,12 @@ template v->cursor_end_of_line(); } break; + case ActionType::IndentLine: { + auto logger = spdlog::get("basic_logger"); + if (logger != nullptr) { logger->info("Action called: IndentLine"); } + v->get_active_model()->indent_curr_line(); + } break; + case ActionType::JumpEndOfWord: { auto logger = spdlog::get("basic_logger"); if (logger != nullptr) { logger->info("Action called: JumpEndOfWord"); } diff --git a/src/controller.cpp b/src/controller.cpp index fbd49da..a89daae 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -399,6 +399,12 @@ void Controller::start_action_engine() { parse_action(&view, Action {ActionType::ToggleCase}); view.draw_line(Draw_Line_dir::None); + + // Increment line + } else if (k.value() == rawterm::Key('>')) { + if (is_readonly_model()) { continue; } + parse_action(&view, Action {ActionType::IndentLine}); + view.draw_line(Draw_Line_dir::None); } } diff --git a/src/model.cpp b/src/model.cpp index c526d7a..9a15b78 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -529,3 +529,7 @@ std::optional Model::find_next_str(std::string_view sv) { return std::nullopt; } + +void Model::indent_curr_line() { + if (buf.at(current_line).size()) { buf.at(current_line).insert(0, TAB_SIZE, ' '); } +} diff --git a/src/model.h b/src/model.h index d07f2f8..58a48c7 100644 --- a/src/model.h +++ b/src/model.h @@ -71,6 +71,7 @@ struct Model { [[nodiscard]] std::vector search_text(const std::string&) const; void search_and_replace(const std::string&); std::optional find_next_str(std::string_view); + void indent_curr_line(); }; #endif // MODEL_H diff --git a/tests/integration/normal_mode_test.py b/tests/integration/normal_mode_test.py index 4001ad9..f6fb536 100644 --- a/tests/integration/normal_mode_test.py +++ b/tests/integration/normal_mode_test.py @@ -532,3 +532,9 @@ def test_e_key(r: TmuxRunner): r.press("e") assert r.statusbar_parts()[-1] == "1:7" + + +@setup("tests/fixture/test_file_1.txt") +def test_right_chevron_key(r: TmuxRunner): + r.press('>') + assert " This" in r.lines()[0] diff --git a/tests/model_test.cpp b/tests/model_test.cpp index 3cbc379..7d36c38 100644 --- a/tests/model_test.cpp +++ b/tests/model_test.cpp @@ -702,3 +702,14 @@ TEST_CASE("find_next_str", "[model]") { REQUIRE(m.search_str == "line"); } } + +TEST_CASE("indent_curr_line", "[model]") { + auto m = Model({"foo", "bar"}, ""); + m.indent_curr_line(); + + REQUIRE(m.buf.at(0).size() == 7); + REQUIRE(m.buf.at(1).size() == 3); + + REQUIRE(m.buf.at(0).at(0) == ' '); + REQUIRE(m.buf.at(0).at(4) == 'f'); +}