diff --git a/src/core/BufferView.cc b/src/core/BufferView.cc index 2c2f950..f461301 100644 --- a/src/core/BufferView.cc +++ b/src/core/BufferView.cc @@ -131,6 +131,7 @@ bool BufferView::cursor_move(CursorMovement which, uint32_t c, bool allow_eol) m_target_screen_column = INT_MAX; m_target_virtual_column = INT_MAX; break; + case CursorMovement::START_OF_FILE: case CursorMovement::FIRST_LINE: { auto it = m_buffer->begin(); @@ -143,6 +144,21 @@ bool BufferView::cursor_move(CursorMovement which, uint32_t c, bool allow_eol) m_target_screen_column = 0; m_target_virtual_column = 0; break; + case CursorMovement::END_OF_FILE: + { + auto it = m_buffer->end(); + it.go_back(); + /* TODO: optimize this */ + it.go_start_of_line(); + it.go_end_of_line(allow_eol); + if (it != *m_iterator) + { + *m_iterator = it; + moved = true; + } + } + m_update_target_column = true; + break; case CursorMovement::LAST_LINE: { auto it = m_buffer->end(); @@ -199,9 +215,11 @@ bool BufferView::cursor_move(CursorMovement which, uint32_t c, bool allow_eol) case CursorMovement::BACK_ON_TO_CHAR: determine_new_cursor_screen_row(); break; + case CursorMovement::START_OF_FILE: case CursorMovement::FIRST_LINE: m_cursor_screen_row = 0; break; + case CursorMovement::END_OF_FILE: case CursorMovement::LAST_LINE: m_cursor_screen_row = m_height - 1; break; diff --git a/src/core/BufferView.h b/src/core/BufferView.h index c19f3e7..e9b09c1 100644 --- a/src/core/BufferView.h +++ b/src/core/BufferView.h @@ -22,6 +22,8 @@ public: DOWN, SOL, EOL, + START_OF_FILE, + END_OF_FILE, FIRST_LINE, LAST_LINE, SCREEN_ROW_UP, diff --git a/src/core/Command.h b/src/core/Command.h index dce4880..71907c6 100644 --- a/src/core/Command.h +++ b/src/core/Command.h @@ -32,6 +32,8 @@ public: PUT, PUT_BEFORE, CHANGE_CHAR, + GO_START_OF_FILE, + GO_END_OF_FILE, GO_TO_LINE, GO_TO_LAST_LINE, GO_LEFT, diff --git a/src/core/DefaultCommandMap.cc b/src/core/DefaultCommandMap.cc index 98c388f..bbd7759 100644 --- a/src/core/DefaultCommandMap.cc +++ b/src/core/DefaultCommandMap.cc @@ -60,7 +60,9 @@ void DefaultCommandMap::build() dcm->add("N", Command::PREV, nullptr, false); dcm->add({JES_KEY_HOME}, Command::GO_START_OF_LINE, nullptr, false); + dcm->add({JES_KEY_MODS_CTRL + JES_KEY_HOME}, Command::GO_START_OF_FILE, nullptr, false); dcm->add({JES_KEY_END}, Command::GO_END_OF_LINE, nullptr, false); + dcm->add({JES_KEY_MODS_CTRL + JES_KEY_END}, Command::GO_END_OF_FILE, nullptr, false); dcm->add({JES_KEY_PAGE_UP}, Command::SCROLL_WINDOW_UP_WHOLE_SCREEN, nullptr, false); dcm->add({JES_KEY_PAGE_DOWN}, Command::SCROLL_WINDOW_DOWN_WHOLE_SCREEN, nullptr, false); diff --git a/src/gui/Window.cc b/src/gui/Window.cc index 548124d..2cfca3e 100644 --- a/src/gui/Window.cc +++ b/src/gui/Window.cc @@ -390,6 +390,12 @@ void Window::execute_command(const Command & command) break; case Command::CHANGE_CHAR: break; + case Command::GO_START_OF_FILE: + m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::START_OF_FILE, 0u); + break; + case Command::GO_END_OF_FILE: + m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::END_OF_FILE, 0u); + break; case Command::GO_TO_LINE: m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::FIRST_LINE, 0u); break; diff --git a/test/src/test_BufferView.cc b/test/src/test_BufferView.cc index c527b27..3e9d14a 100644 --- a/test/src/test_BufferView.cc +++ b/test/src/test_BufferView.cc @@ -410,7 +410,7 @@ TEST(BufferViewTest, moves_view_up_while_jumping_to_start_of_a_wrapped_line) EXPECT_EQ(C('2'), **iterator); } -TEST(BufferViewTest, warps_view_when_jumping_to_beginning_and_end_of_buffer) +TEST(BufferViewTest, warps_view_when_jumping_to_first_and_last_line_of_buffer) { auto b = buffer1(); auto iterator = b->add_iterator(); @@ -432,6 +432,29 @@ TEST(BufferViewTest, warps_view_when_jumping_to_beginning_and_end_of_buffer) EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::FIRST_LINE, 0u, false)); } +TEST(BufferViewTest, warps_view_when_jumping_to_beginning_and_end_of_file) +{ + auto b = buffer1(); + auto iterator = b->add_iterator(); + BufferView bv(b, iterator, Cwd); + bv.resize(4, 4); + EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::END_OF_FILE, 0u, false)); + bv.update(); + EXPECT_EQ(C('2'), **iterator); + EXPECT_EQ(12, LineNumber(iterator)); + EXPECT_EQ(3, bv.cursor_screen_row()); + EXPECT_EQ(1, bv.cursor_screen_column()); + EXPECT_EQ(1, bv.cursor_virtual_column()); + EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::END_OF_FILE, 0u, false)); + EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::START_OF_FILE, 0u, false)); + bv.update(); + EXPECT_EQ(0, LineNumber(iterator)); + EXPECT_EQ(0, bv.cursor_screen_row()); + EXPECT_EQ(0, bv.cursor_screen_column()); + EXPECT_EQ(0, bv.cursor_virtual_column()); + EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::START_OF_FILE, 0u, false)); +} + TEST(BufferViewTest, sets_target_column_to_eol_when_jumping_to_SOL_and_EOL) { auto b = buffer1();