Skip to content
Merged

E key #179

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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ moves back that amount of space
* Added `;f` command to find a given string further on in the buffer
* Iris now handles horizontal scrolling when a line is longer than the screen
* Allow for specifying file to save to from command bar
* `e` key now moves cursor to end of the current word

* Resolved issue with iris crashing after opening an existing file with 0 bytes
* Resolved issue where filename isn't centered in the status bar
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ perform the following actions (alphabetically ordered):
| <kbd>b</kbd> | Move cursor back one word |
| <kbd>dl</kbd> | Delete the current line |
| <kbd>dw</kbd> | Delete the current word |
| <kbd>f</kbd> | Find next entered char ahead in file |
| <kbd>e</kbd> | Find next entered char ahead in file |
| <kbd>f</kbd> | Move cursor to end of current word |
| <kbd>F</kbd> | Find next entered char back in file |
| <kbd>g</kbd> | Go to top of file |
| <kbd>G</kbd> | Go to bottom of file |
Expand Down
2 changes: 1 addition & 1 deletion milestones.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,5 @@
* [x] `w` (delete word)
* [x] `J`
* [x] `K`
* [ ] `e`
* [x] `e`
* [ ] `>` / `<` (indentation)
16 changes: 16 additions & 0 deletions src/action.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum class ActionType {
DelCurrentLine,
DelCurrentWord,
EndOfLine,
JumpEndOfWord,
JumpNextPara,
JumpPrevPara,
JumpNextWord,
Expand Down Expand Up @@ -170,6 +171,21 @@ template <typename T, typename U>
v->cursor_end_of_line();
} break;

case ActionType::JumpEndOfWord: {
auto logger = spdlog::get("basic_logger");
if (logger != nullptr) {
logger->info("Action called: JumpEndOfWord");
}

std::optional<int> count = v->get_active_model()->end_of_word_pos();
if (count.has_value()) {
for (int i = 0; i < count.value(); i++) {
v->cursor_right();
}
}

} break;

case ActionType::JumpNextPara: {
auto logger = spdlog::get("basic_logger");
if (logger != nullptr) {
Expand Down
4 changes: 4 additions & 0 deletions src/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ void Controller::start_action_engine() {
continue;
}

// Go to end of current word
} else if (k.value() == rawterm::Key('e')) {
parse_action<void, None>(&view, Action<void> {ActionType::JumpEndOfWord});

// find forward
} else if (k.value() == rawterm::Key('f')) {
auto k2 = rawterm::wait_for_input();
Expand Down
30 changes: 29 additions & 1 deletion src/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void Model::insert(const char c) {
return (idx < static_cast<int>(buf.size()) && idx >= 0);
}

// Word (noun) - a sequence of characters that match regex A-Za-z
// Word (noun) - a sequence of characters that match regex A-Za-z0-9
[[nodiscard]] std::optional<int> Model::next_word_pos() {
if (current_char == buf.at(current_line).size() - 1) {
return {};
Expand Down Expand Up @@ -216,6 +216,34 @@ void Model::insert(const char c) {
return distance;
}

[[nodiscard]] std::optional<int> Model::end_of_word_pos() {
if (current_char == buf.at(current_line).size() - 1) {
return {};
} else if (buf.at(current_line).empty()) {
return {};
}

uint incrementer = 0;
std::string_view line_frag =
std::string_view(buf.at(current_line)).substr(current_char, buf.at(current_line).size());

// If the _next_ char is a space, we want to go past that
if (line_frag.at(1) == ' ') {
incrementer += 2;
};

// go to end of current "word"
while (is_letter(line_frag.at(incrementer))) {
incrementer++;

if (incrementer == line_frag.size() - 1) {
return incrementer;
}
}

return --incrementer;
}

void Model::replace_char(const char c) {
if (buf.at(current_line).empty()) {
buf.at(current_line).push_back(c);
Expand Down
1 change: 1 addition & 0 deletions src/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct Model {
[[nodiscard]] std::optional<int> prev_word_pos();
[[nodiscard]] std::optional<unsigned int> next_para_pos();
[[nodiscard]] std::optional<unsigned int> prev_para_pos();
[[nodiscard]] std::optional<int> end_of_word_pos();
void replace_char(const char);
void toggle_case();
[[nodiscard]] std::optional<rawterm::Pos> find_next(const char);
Expand Down
10 changes: 6 additions & 4 deletions src/text_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ void rtrim(std::string& str) {
return result;
}

// TODO: Investigate if symbols should count here
[[nodiscard]] bool is_letter(const char& c) {
std::array<char, 52> alphabet = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
std::array<char, 62> alphabet = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

return std::find(alphabet.begin(), alphabet.end(), c) != alphabet.end();
}
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/normal_mode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,14 @@ def test_dw_key(r: TmuxRunner):
r.type_str("dw") # delete word

assert "Lorem ipsum" not in r.lines()[0]


@setup("tests/fixture/test_file_1.txt")
def test_e_key(r: TmuxRunner):
assert r.statusbar_parts()[-1] == "1:1"

r.press("e")
assert r.statusbar_parts()[-1] == "1:4"

r.press("e")
assert r.statusbar_parts()[-1] == "1:7"
35 changes: 35 additions & 0 deletions tests/model_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,41 @@ TEST_CASE("prev_para_pos", "[model]") {
REQUIRE(opt.value() == 2);
}

TEST_CASE("end_of_word_pos", "[model]") {
auto m = Model({"line one", "", "line five"}, "");

m.current_char = 7;
REQUIRE(m.end_of_word_pos() == std::nullopt);

m.current_char = 0;
m.current_line = 1;
REQUIRE(m.end_of_word_pos() == std::nullopt);

m.current_line = 0;
REQUIRE(m.end_of_word_pos().has_value());
REQUIRE(m.end_of_word_pos().value() == 3);

m.current_char = 3;
REQUIRE(m.end_of_word_pos().has_value());
REQUIRE(m.end_of_word_pos().value() == 4);
}

TEST_CASE("replace_char", "[model]") {
auto m = Model({"line one", "", "line five"}, "");

m.current_line = 1;
m.replace_char('c');
REQUIRE(m.buf.at(1).size() == 1);
REQUIRE(m.buf.at(1) == "c");

m.current_line = 2;
m.current_char = 4;
m.replace_char('_');
REQUIRE(m.buf.at(2).size() == 9);
REQUIRE(m.buf.at(2).at(4) == '_');
REQUIRE(m.buf.at(2) == "line_five");
}

TEST_CASE("toggle_case", "[model]") {
auto m = Model({"line one", "line two", "line three", "", "line four", "line five"}, "");

Expand Down
Loading