diff options
author | Nico Weber <thakis@chromium.org> | 2020-08-06 16:52:35 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-07 09:04:28 +0200 |
commit | 530fb7eb820f80016b9220cb7f3e4241715cc9dd (patch) | |
tree | 28738c2404a06acf66baf0be6f9b6d528af720c5 | |
parent | c1fb5263a5d749cc60e557d7ee73bdc01da9ccbc (diff) | |
download | serenity-530fb7eb820f80016b9220cb7f3e4241715cc9dd.zip |
LibLine: Add Alt-t shortcut for transposing words
-rw-r--r-- | Libraries/LibLine/Editor.cpp | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/Libraries/LibLine/Editor.cpp b/Libraries/LibLine/Editor.cpp index 49f79be942..9aa24f80c1 100644 --- a/Libraries/LibLine/Editor.cpp +++ b/Libraries/LibLine/Editor.cpp @@ -591,7 +591,7 @@ void Editor::handle_read_event() do_cursor_right(Word); m_state = InputState::Free; continue; - case ctrl('H'): // ^[^H: alt-backspace: backward delete word + case '\b': // ^[^H: alt-backspace: backward delete word { // A word here is contiguous alnums. `foo=bar baz` is three words. bool has_seen_alnum = false; @@ -644,6 +644,57 @@ void Editor::handle_read_event() m_state = InputState::Free; continue; } + case 't': // ^[t: alt-t: transpose words + { + // A word here is contiguous alnums. `foo=bar baz` is three words. + + // 'abcd,.:efg...' should become 'efg...,.:abcd' if caret is after + // 'efg...'. If it's in 'efg', it should become 'efg,.:abcd...' + // with the caret after it, which then becomes 'abcd...,.:efg' + // when alt-t is pressed a second time. + + // Move to end of word under (or after) caret. + size_t cursor = m_cursor; + while (cursor < m_buffer.size() && !isalnum(m_buffer[cursor])) + ++cursor; + while (cursor < m_buffer.size() && isalnum(m_buffer[cursor])) + ++cursor; + + // Move left over second word and the space to its right. + size_t end = cursor; + size_t start = cursor; + while (start > 0 && !isalnum(m_buffer[start - 1])) + --start; + while (start > 0 && isalnum(m_buffer[start - 1])) + --start; + size_t start_second_word = start; + + // Move left over space between the two words. + while (start > 0 && !isalnum(m_buffer[start - 1])) + --start; + size_t start_gap = start; + + // Move left over first word. + while (start > 0 && isalnum(m_buffer[start - 1])) + --start; + + if (start != start_gap) { + // To swap the two words, swap each word (and the gap) individually, and then swap the whole range. + auto swap_range = [this](auto from, auto to) { + for (size_t i = 0; i < (to - from) / 2; ++i) + swap(m_buffer[from + i], m_buffer[to - 1 - i]); + }; + swap_range(start, start_gap); + swap_range(start_gap, start_second_word); + swap_range(start_second_word, end); + swap_range(start, end); + m_cursor = cursor; + // FIXME: Update anchored styles too. + m_refresh_needed = true; + } + m_state = InputState::Free; + continue; + } default: m_state = InputState::Free; continue; |