From 27e6fba2efac53caeb3c8ad52ed1a3aa56fbad09 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 8 Sep 2012 01:10:29 -0400 Subject: [PATCH] add forward/backword WORD motion --- README.rst | 2 ++ termite.cc | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/README.rst b/README.rst index 2bc3201..ef768d5 100644 --- a/README.rst +++ b/README.rst @@ -41,6 +41,8 @@ COMMAND MODE +------------------------+-----------------------------------------------------------+ | ``w``/``b`` | forward/backward word | +------------------------+-----------------------------------------------------------+ +| ``W``/``B`` | forward/backward WORD (non-whitespace) | ++------------------------+-----------------------------------------------------------+ | ``$`` | end-of-line | +------------------------+-----------------------------------------------------------+ | ``^`` | beginning-of-line | diff --git a/termite.cc b/termite.cc index 3120f94..ddc2ac8 100644 --- a/termite.cc +++ b/termite.cc @@ -237,6 +237,44 @@ static void move_backward_word(VteTerminal *vte, select_info *select) { g_free(content); } +static void move_backward_blank_word(VteTerminal *vte, select_info *select) { + long cursor_col, cursor_row; + vte_terminal_get_cursor_position(vte, &cursor_col, &cursor_row); + + char *content = vte_terminal_get_text_range(vte, cursor_row, 0, + cursor_row, cursor_col, + NULL, NULL, NULL); + + if (!content) { + return; + } + + glong length; + gunichar *codepoints = g_utf8_to_ucs4(content, -1, NULL, &length, NULL); + + if (!codepoints) { + return; + } + + bool in_word = false; + + for (gunichar *c = codepoints + length - 2; c > codepoints; c--) { + if (g_unichar_isspace(*(c - 1))) { + if (in_word) { + break; + } + } else { + in_word = true; + } + cursor_col--; + } + vte_terminal_set_cursor_position(vte, cursor_col, cursor_row); + update_selection(vte, select); + + g_free(codepoints); + g_free(content); +} + static void move_forward_word(VteTerminal *vte, select_info *select) { long cursor_col, cursor_row; vte_terminal_get_cursor_position(vte, &cursor_col, &cursor_row); @@ -276,6 +314,45 @@ static void move_forward_word(VteTerminal *vte, select_info *select) { g_free(content); } +static void move_forward_blank_word(VteTerminal *vte, select_info *select) { + long cursor_col, cursor_row; + vte_terminal_get_cursor_position(vte, &cursor_col, &cursor_row); + + const long end_col = vte_terminal_get_column_count(vte) - 1; + + char *content = vte_terminal_get_text_range(vte, cursor_row, cursor_col, + cursor_row, end_col, + NULL, NULL, NULL); + + if (!content) { + return; + } + + gunichar *codepoints = g_utf8_to_ucs4(content, -1, NULL, NULL, NULL); + + if (!codepoints) { + return; + } + + bool end_of_word = false; + + for (gunichar *c = codepoints; *c != 0; c++) { + if (!g_unichar_isspace(*c)) { + if (end_of_word) { + break; + } + } else { + end_of_word = true; + } + cursor_col++; + } + vte_terminal_set_cursor_position(vte, cursor_col, cursor_row); + update_selection(vte, select); + + g_free(codepoints); + g_free(content); +} + static void set_cursor_column(VteTerminal *vte, const select_info *select, long column) { long cursor_row; vte_terminal_get_cursor_position(vte, nullptr, &cursor_row); @@ -319,9 +396,15 @@ gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, keybind_info *info) case GDK_KEY_b: move_backward_word(vte, &info->select); break; + case GDK_KEY_B: + move_backward_blank_word(vte, &info->select); + break; case GDK_KEY_w: move_forward_word(vte, &info->select); break; + case GDK_KEY_W: + move_forward_blank_word(vte, &info->select); + break; case GDK_KEY_asciicircum: set_cursor_column(vte, &info->select, 0); break;