From cb984cf761debdc858db48065b2c1d94b31de49e Mon Sep 17 00:00:00 2001 From: Michael Steed Date: Sat, 30 May 2015 16:44:25 -0600 Subject: [PATCH] Add 'bigword' vi key bindings - Add four new functions: forward-bigword, backward-bigword, kill-bigword, backward-kill-bigword - Add new enum move_word_style_whitespace and related state machine method - Change vi key bindings to operate on bigwords: B, gE, W, E, dW, diW, daW, dE, dB, dgE, cW, ciW, caW, cE, cB, cgE, yW, yiW, yaW, yE, yB, ygE --- input.cpp | 8 +++ input.h | 4 ++ reader.cpp | 40 ++++++++++++++- share/functions/fish_vi_key_bindings.fish | 62 +++++++++++------------ tokenizer.cpp | 55 ++++++++++++++++++++ tokenizer.h | 4 +- 6 files changed, 139 insertions(+), 34 deletions(-) diff --git a/input.cpp b/input.cpp index 02b526889..15cb7b4ea 100644 --- a/input.cpp +++ b/input.cpp @@ -112,6 +112,8 @@ static const wchar_t * const name_arr[] = L"backward-char", L"forward-word", L"backward-word", + L"forward-bigword", + L"backward-bigword", L"history-search-backward", L"history-search-forward", L"delete-char", @@ -126,8 +128,10 @@ static const wchar_t * const name_arr[] = L"backward-kill-line", L"kill-whole-line", L"kill-word", + L"kill-bigword", L"backward-kill-word", L"backward-kill-path-component", + L"backward-kill-bigword", L"history-token-search-backward", L"history-token-search-forward", L"self-insert", @@ -218,6 +222,8 @@ static const wchar_t code_arr[] = R_BACKWARD_CHAR, R_FORWARD_WORD, R_BACKWARD_WORD, + R_FORWARD_BIGWORD, + R_BACKWARD_BIGWORD, R_HISTORY_SEARCH_BACKWARD, R_HISTORY_SEARCH_FORWARD, R_DELETE_CHAR, @@ -232,8 +238,10 @@ static const wchar_t code_arr[] = R_BACKWARD_KILL_LINE, R_KILL_WHOLE_LINE, R_KILL_WORD, + R_KILL_BIGWORD, R_BACKWARD_KILL_WORD, R_BACKWARD_KILL_PATH_COMPONENT, + R_BACKWARD_KILL_BIGWORD, R_HISTORY_TOKEN_SEARCH_BACKWARD, R_HISTORY_TOKEN_SEARCH_FORWARD, R_SELF_INSERT, diff --git a/input.h b/input.h index a3a3a076c..323eb26d4 100644 --- a/input.h +++ b/input.h @@ -30,6 +30,8 @@ enum R_BACKWARD_CHAR, R_FORWARD_WORD, R_BACKWARD_WORD, + R_FORWARD_BIGWORD, + R_BACKWARD_BIGWORD, R_HISTORY_SEARCH_BACKWARD, R_HISTORY_SEARCH_FORWARD, R_DELETE_CHAR, @@ -44,8 +46,10 @@ enum R_BACKWARD_KILL_LINE, R_KILL_WHOLE_LINE, R_KILL_WORD, + R_KILL_BIGWORD, R_BACKWARD_KILL_WORD, R_BACKWARD_KILL_PATH_COMPONENT, + R_BACKWARD_KILL_BIGWORD, R_HISTORY_TOKEN_SEARCH_BACKWARD, R_HISTORY_TOKEN_SEARCH_FORWARD, R_SELF_INSERT, diff --git a/reader.cpp b/reader.cpp index 4fdd6cebd..086a2a5f9 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1172,6 +1172,8 @@ static bool command_ends_paging(wchar_t c, bool focused_on_search_field) case R_END_OF_LINE: case R_FORWARD_WORD: case R_BACKWARD_WORD: + case R_FORWARD_BIGWORD: + case R_BACKWARD_BIGWORD: case R_DELETE_CHAR: case R_BACKWARD_DELETE_CHAR: case R_KILL_LINE: @@ -1180,8 +1182,10 @@ static bool command_ends_paging(wchar_t c, bool focused_on_search_field) case R_BACKWARD_KILL_LINE: case R_KILL_WHOLE_LINE: case R_KILL_WORD: + case R_KILL_BIGWORD: case R_BACKWARD_KILL_WORD: case R_BACKWARD_KILL_PATH_COMPONENT: + case R_BACKWARD_KILL_BIGWORD: case R_SELF_INSERT: case R_TRANSPOSE_CHARS: case R_TRANSPOSE_WORDS: @@ -3775,9 +3779,12 @@ const wchar_t *reader_readline(int nchars) /* kill one word left */ case R_BACKWARD_KILL_WORD: case R_BACKWARD_KILL_PATH_COMPONENT: + case R_BACKWARD_KILL_BIGWORD: { - move_word_style_t style = (c == R_BACKWARD_KILL_PATH_COMPONENT ? move_word_style_path_components : move_word_style_punctuation); - bool newv = (last_char != R_BACKWARD_KILL_WORD && last_char != R_BACKWARD_KILL_PATH_COMPONENT); + move_word_style_t style = + (c == R_BACKWARD_KILL_BIGWORD ? move_word_style_whitespace : + c == R_BACKWARD_KILL_PATH_COMPONENT ? move_word_style_path_components : move_word_style_punctuation); + bool newv = (last_char != R_BACKWARD_KILL_WORD && last_char != R_BACKWARD_KILL_PATH_COMPONENT && last_char != R_BACKWARD_KILL_BIGWORD); move_word(data->active_edit_line(), MOVE_DIR_LEFT, true /* erase */, style, newv); break; } @@ -3789,6 +3796,13 @@ const wchar_t *reader_readline(int nchars) break; } + /* kill one bigword right */ + case R_KILL_BIGWORD: + { + move_word(data->active_edit_line(), MOVE_DIR_RIGHT, true /* erase */, move_word_style_whitespace, last_char!=R_KILL_BIGWORD); + break; + } + /* move one word left*/ case R_BACKWARD_WORD: { @@ -3796,6 +3810,13 @@ const wchar_t *reader_readline(int nchars) break; } + /* move one bigword left */ + case R_BACKWARD_BIGWORD: + { + move_word(data->active_edit_line(), MOVE_DIR_LEFT, false /* do not erase */, move_word_style_whitespace, false); + break; + } + /* move one word right*/ case R_FORWARD_WORD: { @@ -3811,6 +3832,21 @@ const wchar_t *reader_readline(int nchars) break; } + /* move one bigword right */ + case R_FORWARD_BIGWORD: + { + editable_line_t *el = data->active_edit_line(); + if (el->position < el->size()) + { + move_word(el, MOVE_DIR_RIGHT, false /* do not erase */, move_word_style_whitespace, false); + } + else + { + accept_autosuggestion(false /* accept only one word */); + } + break; + } + case R_BEGINNING_OF_HISTORY: { if (data->is_navigating_pager_contents()) diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index 2140cf687..69049e70f 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -59,13 +59,13 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind -k up up-or-search bind b backward-word - bind B backward-word - bind gE backward-word - bind gE backward-word + bind B backward-bigword + bind ge backward-word + bind gE backward-bigword bind w forward-word - bind W forward-word + bind W forward-bigword bind e forward-word - bind E forward-word + bind E forward-bigword bind x delete-char bind X backward-delete-char @@ -81,17 +81,17 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind d\x24 kill-line bind d\x5e backward-kill-line bind dw kill-word - bind dW kill-word + bind dW kill-bigword bind diw forward-char forward-char backward-word kill-word - bind diW forward-char forward-char backward-word kill-word + bind diW forward-char forward-char backward-bigword kill-bigword bind daw forward-char forward-char backward-word kill-word - bind daW forward-char forward-char backward-word kill-word + bind daW forward-char forward-char backward-bigword kill-bigword bind de kill-word - bind dE kill-word + bind dE kill-bigword bind db backward-kill-word - bind dB backward-kill-word - bind dgE backward-kill-word - bind dgE backward-kill-word + bind dB backward-kill-bigword + bind dge backward-kill-word + bind dgE backward-kill-bigword bind -m insert s delete-char force-repaint bind -m insert S kill-whole-line force-repaint @@ -100,17 +100,17 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind -m insert c\x24 kill-line force-repaint bind -m insert c\x5e backward-kill-line force-repaint bind -m insert cw kill-word force-repaint - bind -m insert cW kill-word force-repaint + bind -m insert cW kill-bigword force-repaint bind -m insert ciw forward-char forward-char backward-word kill-word force-repaint - bind -m insert ciW forward-char forward-char backward-word kill-word force-repaint + bind -m insert ciW forward-char forward-char backward-bigword kill-bigword force-repaint bind -m insert caw forward-char forward-char backward-word kill-word force-repaint - bind -m insert caW forward-char forward-char backward-word kill-word force-repaint + bind -m insert caW forward-char forward-char backward-bigword kill-bigword force-repaint bind -m insert ce kill-word force-repaint - bind -m insert cE kill-word force-repaint + bind -m insert cE kill-bigword force-repaint bind -m insert cb backward-kill-word force-repaint - bind -m insert cB backward-kill-word force-repaint - bind -m insert cgE backward-kill-word force-repaint - bind -m insert cgE backward-kill-word force-repaint + bind -m insert cB backward-kill-bigword force-repaint + bind -m insert cge backward-kill-word force-repaint + bind -m insert cgE backward-kill-bigword force-repaint bind '~' capitalize-word bind gu downcase-word @@ -124,17 +124,17 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind y\x24 kill-line yank bind y\x5e backward-kill-line yank bind yw kill-word yank - bind yW kill-word yank + bind yW kill-bigword yank bind yiw forward-char forward-char backward-word kill-word yank - bind yiW forward-char forward-char backward-word kill-word yank + bind yiW forward-char forward-char backward-bigword kill-bigword yank bind yaw forward-char forward-char backward-word kill-word yank - bind yaW forward-char forward-char backward-word kill-word yank + bind yaW forward-char forward-char backward-bigword kill-bigword yank bind ye kill-word yank - bind yE kill-word yank + bind yE kill-bigword yank bind yb backward-kill-word yank - bind yB backward-kill-word yank - bind ygE backward-kill-word yank - bind ygE backward-kill-word yank + bind yB backward-kill-bigword yank + bind yge backward-kill-word yank + bind ygE backward-kill-bigword yank bind f forward-jump bind F backward-jump @@ -212,13 +212,13 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind -M visual l forward-char bind -M visual b backward-word - bind -M visual B backward-word - bind -M visual gE backward-word - bind -M visual gE backward-word + bind -M visual B backward-bigword + bind -M visual ge backward-word + bind -M visual gE backward-bigword bind -M visual w forward-word - bind -M visual W forward-word + bind -M visual W forward-bigword bind -M visual e forward-word - bind -M visual E forward-word + bind -M visual E forward-bigword bind -M visual -m default d kill-selection end-selection force-repaint bind -M visual -m default x kill-selection end-selection force-repaint diff --git a/tokenizer.cpp b/tokenizer.cpp index 07253328e..659084669 100644 --- a/tokenizer.cpp +++ b/tokenizer.cpp @@ -913,6 +913,59 @@ bool move_word_state_machine_t::consume_char_path_components(wchar_t c) return consumed; } +bool move_word_state_machine_t::consume_char_whitespace(wchar_t c) +{ + enum + { + s_always_one = 0, + s_blank, + s_graph, + s_end + }; + + bool consumed = false; + while (state != s_end && ! consumed) + { + switch (state) + { + case s_always_one: + /* Always consume the first character */ + consumed = true; + state = s_blank; + break; + + case s_blank: + if (iswblank(c)) + { + /* Consumed whitespace */ + consumed = true; + } + else + { + state = s_graph; + } + break; + + case s_graph: + if (iswgraph(c)) + { + /* Consumed printable non-space */ + consumed = true; + } + else + { + state = s_end; + } + break; + + case s_end: + default: + break; + } + } + return consumed; +} + bool move_word_state_machine_t::consume_char(wchar_t c) { switch (style) @@ -921,6 +974,8 @@ bool move_word_state_machine_t::consume_char(wchar_t c) return consume_char_punctuation(c); case move_word_style_path_components: return consume_char_path_components(c); + case move_word_style_whitespace: + return consume_char_whitespace(c); default: return false; } diff --git a/tokenizer.h b/tokenizer.h index d7e202ba5..954957cc4 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -192,7 +192,8 @@ int oflags_for_redirection_type(enum token_type type); enum move_word_style_t { move_word_style_punctuation, //stop at punctuation - move_word_style_path_components //stops at path components + move_word_style_path_components, //stops at path components + move_word_style_whitespace // stops at whitespace }; /* Our state machine that implements "one word" movement or erasure. */ @@ -203,6 +204,7 @@ private: bool consume_char_punctuation(wchar_t c); bool consume_char_path_components(wchar_t c); bool is_path_component_character(wchar_t c); + bool consume_char_whitespace(wchar_t c); int state; move_word_style_t style;