From 9d3604215dd4bb1a69f2f2be67786de921b607de Mon Sep 17 00:00:00 2001 From: ronak69 Date: Wed, 3 Jan 2024 13:14:34 +0000 Subject: [PATCH] LibLine: Implement basic cut-and-paste functionality Every cut operation (erase last word backward/forward, erase line till start/end) stores the erased characters in `m_last_erased` u32 vector. The last erased characters will get inserted into the buffer when `Ctrl+Y` (`insert_last_erased()` internal function) is pressed. --- Userland/Libraries/LibLine/Editor.cpp | 1 + Userland/Libraries/LibLine/Editor.h | 2 + .../Libraries/LibLine/InternalFunctions.cpp | 48 ++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibLine/Editor.cpp b/Userland/Libraries/LibLine/Editor.cpp index de70ef91c2..89944e0293 100644 --- a/Userland/Libraries/LibLine/Editor.cpp +++ b/Userland/Libraries/LibLine/Editor.cpp @@ -164,6 +164,7 @@ void Editor::set_default_keybinds() // ^[.: alt-.: insert last arg of previous command (similar to `!$`) register_key_input_callback(Key { '.', Key::Alt }, EDITOR_INTERNAL_FUNCTION(insert_last_words)); + register_key_input_callback(ctrl('Y'), EDITOR_INTERNAL_FUNCTION(insert_last_erased)); register_key_input_callback(Key { 'b', Key::Alt }, EDITOR_INTERNAL_FUNCTION(cursor_left_word)); register_key_input_callback(Key { 'f', Key::Alt }, EDITOR_INTERNAL_FUNCTION(cursor_right_word)); register_key_input_callback(Key { ctrl('B'), Key::Alt }, EDITOR_INTERNAL_FUNCTION(cursor_left_nonspace_word)); diff --git a/Userland/Libraries/LibLine/Editor.h b/Userland/Libraries/LibLine/Editor.h index e5fad28e3e..a32c32f470 100644 --- a/Userland/Libraries/LibLine/Editor.h +++ b/Userland/Libraries/LibLine/Editor.h @@ -124,6 +124,7 @@ struct Configuration { M(transpose_characters) \ M(transpose_words) \ M(insert_last_words) \ + M(insert_last_erased) \ M(erase_alnum_word_backwards) \ M(erase_alnum_word_forwards) \ M(capitalize_word) \ @@ -505,6 +506,7 @@ private: RefPtr m_notifier; Vector m_paste_buffer; + Vector m_last_erased; bool m_initialized { false }; bool m_refresh_needed { false }; diff --git a/Userland/Libraries/LibLine/InternalFunctions.cpp b/Userland/Libraries/LibLine/InternalFunctions.cpp index e53699d0e3..bada78017b 100644 --- a/Userland/Libraries/LibLine/InternalFunctions.cpp +++ b/Userland/Libraries/LibLine/InternalFunctions.cpp @@ -221,8 +221,15 @@ void Editor::finish_edit() void Editor::kill_line() { - for (size_t i = 0; i < m_cursor; ++i) + if (m_cursor == 0) + return; + + m_last_erased.clear_with_capacity(); + + for (size_t i = 0; i < m_cursor; ++i) { + m_last_erased.append(m_buffer[0]); remove_at_index(0); + } m_cursor = 0; m_inline_search_cursor = m_cursor; m_refresh_needed = true; @@ -230,6 +237,11 @@ void Editor::kill_line() void Editor::erase_word_backwards() { + if (m_cursor == 0) + return; + + m_last_erased.clear_with_capacity(); + // A word here is space-separated. `foo=bar baz` is two words. bool has_seen_nonspace = false; while (m_cursor > 0) { @@ -239,20 +251,36 @@ void Editor::erase_word_backwards() } else { has_seen_nonspace = true; } + + m_last_erased.append(m_buffer[m_cursor - 1]); erase_character_backwards(); } + + m_last_erased.reverse(); } void Editor::erase_to_end() { - while (m_cursor < m_buffer.size()) + if (m_cursor == m_buffer.size()) + return; + + m_last_erased.clear_with_capacity(); + + while (m_cursor < m_buffer.size()) { + m_last_erased.append(m_buffer[m_cursor]); erase_character_forwards(); + } } void Editor::erase_to_beginning() { } +void Editor::insert_last_erased() +{ + insert(Utf32View { m_last_erased.data(), m_last_erased.size() }); +} + void Editor::transpose_characters() { if (m_cursor > 0 && m_buffer.size() >= 2) { @@ -507,6 +535,11 @@ void Editor::insert_last_words() void Editor::erase_alnum_word_backwards() { + if (m_cursor == 0) + return; + + m_last_erased.clear_with_capacity(); + // A word here is contiguous alnums. `foo=bar baz` is three words. bool has_seen_alnum = false; while (m_cursor > 0) { @@ -516,12 +549,21 @@ void Editor::erase_alnum_word_backwards() } else { has_seen_alnum = true; } + + m_last_erased.append(m_buffer[m_cursor - 1]); erase_character_backwards(); } + + m_last_erased.reverse(); } void Editor::erase_alnum_word_forwards() { + if (m_cursor == m_buffer.size()) + return; + + m_last_erased.clear_with_capacity(); + // A word here is contiguous alnums. `foo=bar baz` is three words. bool has_seen_alnum = false; while (m_cursor < m_buffer.size()) { @@ -531,6 +573,8 @@ void Editor::erase_alnum_word_forwards() } else { has_seen_alnum = true; } + + m_last_erased.append(m_buffer[m_cursor]); erase_character_forwards(); } }