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');
+}