From 4a9be7bf1125acf3aee4c2dc2dfdb59e85fa71f1 Mon Sep 17 00:00:00 2001 From: Julian Aron Prenner Date: Wed, 22 Jan 2014 10:00:44 +0100 Subject: [PATCH] Experimental support for f,F,t,T vi commands. Input functions can now have arguments --- input.cpp | 65 +++++++++++++++++++++-- input.h | 9 +++- reader.cpp | 34 ++++++++++++ share/functions/fish_vi_key_bindings.fish | 5 ++ 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/input.cpp b/input.cpp index ab5d438d5..576d7d560 100644 --- a/input.cpp +++ b/input.cpp @@ -61,6 +61,8 @@ #include #define DEFAULT_TERM L"ansi" +#define MAX_INPUT_FUNCTION_ARGS 20 + /** Struct representing a keybinding. Returned by input_get_mappings. */ @@ -137,7 +139,9 @@ static const wchar_t * const name_arr[] = L"accept-autosuggestion", L"begin-selection", L"end-selection", - L"kill-selection" + L"kill-selection", + L"forward-jump", + L"backward-jump" } ; @@ -230,7 +234,9 @@ static const wchar_t code_arr[] = R_ACCEPT_AUTOSUGGESTION, R_BEGIN_SELECTION, R_END_SELECTION, - R_KILL_SELECTION + R_KILL_SELECTION, + R_FORWARD_JUMP, + R_BACKWARD_JUMP } ; @@ -259,6 +265,9 @@ static bool is_init = false; */ static void input_terminfo_init(); +wchar_t input_function_args[MAX_INPUT_FUNCTION_ARGS]; +int input_function_args_index = 0; + /** Return the current bind mode */ @@ -283,6 +292,30 @@ bool input_set_bind_mode(const wchar_t *bm) return true; } + +/** + Returns the arity of a given input function +*/ +int input_function_arity(int function) +{ + switch(function) + { + case R_FORWARD_JUMP: + case R_BACKWARD_JUMP: + return 1; + default: + return 0; + } +} + +/** + Returns the nth argument for a given input function +*/ +wchar_t input_function_get_arg(int index) +{ + return input_function_args[index]; +} + /** Returns the function description for the given function code. */ @@ -454,13 +487,40 @@ void input_destroy() } } +void input_function_push_arg(wchar_t arg) +{ + input_function_args[input_function_args_index++] = arg; +} +wchar_t input_function_pop_arg() +{ + return input_function_args[--input_function_args_index]; +} + +void input_function_push_args(int code) +{ + int arity = input_function_arity(code); + for(int i = 0; i < arity; i++) + { + input_function_push_arg(input_common_readch(0)); + } +} /** Perform the action of the specified binding */ static void input_mapping_execute(const input_mapping_t &m) { + for(int i = m.commands.size() - 1; i >= 0; i--) + { + wcstring command = m.commands.at(i); + wchar_t code = input_function_get_code(command); + if (code != (wchar_t)-1) + { + input_function_push_args(code); + } + } + for(int i = m.commands.size() - 1; i >= 0; i--) { wcstring command = m.commands.at(i); @@ -581,7 +641,6 @@ static void input_mapping_execute_matching_or_generic() } } - wint_t input_readch() { CHECK_BLOCK(R_NULL); diff --git a/input.h b/input.h index d74122128..a8e2dffb7 100644 --- a/input.h +++ b/input.h @@ -64,12 +64,14 @@ enum R_ACCEPT_AUTOSUGGESTION, R_BEGIN_SELECTION, R_END_SELECTION, - R_KILL_SELECTION + R_KILL_SELECTION, + R_FORWARD_JUMP, + R_BACKWARD_JUMP } ; #define R_MIN R_NULL -#define R_MAX R_KILL_SELECTION +#define R_MAX R_BACKWARD_JUMP /** Initialize the terminal by calling setupterm, and set up arrays @@ -145,6 +147,9 @@ const wchar_t *input_get_bind_mode(); */ bool input_set_bind_mode(const wchar_t *bind_mode); + +wchar_t input_function_pop_arg(); + /** Return the sequence for the terminfo variable of the specified name. diff --git a/reader.cpp b/reader.cpp index a5cb411da..1e629af17 100644 --- a/reader.cpp +++ b/reader.cpp @@ -3861,6 +3861,40 @@ const wchar_t *reader_readline(void) break; } + case R_FORWARD_JUMP: + { + wchar_t target = input_function_pop_arg(); + size_t len = data->command_length(); + + for(int i = data->buff_pos + 1; i < len; i++) + { + if(buff[i] == target) + { + update_buff_pos(i); + break; + } + } + reader_repaint(); + break; + } + + case R_BACKWARD_JUMP: + { + wchar_t target = input_function_pop_arg(); + size_t len = data->command_length(); + + for(int i = data->buff_pos - 1; i >= 0; i--) + { + if(buff[i] == target) + { + update_buff_pos(i); + break; + } + } + reader_repaint(); + break; + } + /* Other, if a normal character, we add it to the command */ default: { diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index 8dc40da51..122d1fb79 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -129,6 +129,11 @@ function fish_vi_key_bindings -d "vi-like key bindings for fish" bind ygE backward-kill-word yank bind ygE backward-kill-word yank + bind f forward-jump + bind F backward-jump + bind t forward-jump backward-char + bind T backward-jump forward-char + # in emacs yank means paste bind p yank bind P backward-char yank