diff options
author | Julian Aron Prenner <julian@linux4you.it> | 2014-01-01 00:11:32 +0100 |
---|---|---|
committer | Julian Aron Prenner <julian@linux4you.it> | 2014-01-01 00:11:32 +0100 |
commit | dc90cd6bc4fdbb7b2b0a893cf40256f50b11c012 (patch) | |
tree | 9a4047997d691cfae6a32f458361782041e38614 /input.cpp | |
parent | f408bc4808c592afce93e877e587c8c98a590dd9 (diff) |
Better input handling; add support multiple binding commands
Diffstat (limited to 'input.cpp')
-rw-r--r-- | input.cpp | 225 |
1 files changed, 109 insertions, 116 deletions
@@ -64,16 +64,17 @@ /** Struct representing a keybinding. Returned by input_get_mappings. */ + struct input_mapping_t { wcstring seq; /**< Character sequence which generates this event */ - wcstring command; /**< command that should be evaluated by this mapping */ + std::vector<wcstring> commands; /**< commands that should be evaluated by this mapping */ wcstring mode; /**< mode in which this command should be evaluated */ wcstring new_mode; /** new mode that should be switched to after command evaluation */ - input_mapping_t(const wcstring &s, const wcstring &c, + input_mapping_t(const wcstring &s, const std::vector<wcstring> &c, const wcstring &m = DEFAULT_BIND_MODE, - const wcstring &nm = DEFAULT_BIND_MODE) : seq(s), command(c), mode(m), new_mode(nm) {} + const wcstring &nm = DEFAULT_BIND_MODE) : seq(s), commands(c), mode(m), new_mode(nm) {} }; /** @@ -285,27 +286,35 @@ bool input_set_bind_mode(const wchar_t *bm) Returns the function description for the given function code. */ -void input_mapping_add(const wchar_t *sequence, const wchar_t *command, +void input_mapping_add(const wchar_t *sequence, const wchar_t **commands, size_t commands_len, const wchar_t *mode, const wchar_t *new_mode) { CHECK(sequence,); - CHECK(command,); + CHECK(commands,); CHECK(mode,); CHECK(new_mode,); // debug( 0, L"Add mapping from %ls to %ls in mode %ls", escape(sequence, 1), escape(command, 1 ), mode); + std::vector<wcstring> commands_vector(commands, commands + commands_len); + for (size_t i=0; i<mapping_list.size(); i++) { input_mapping_t &m = mapping_list.at(i); if (m.seq == sequence && m.mode == mode) { - m.command = command; + m.commands = commands_vector; m.new_mode = new_mode; return; } } - mapping_list.push_back(input_mapping_t(sequence, command, mode, new_mode)); + mapping_list.push_back(input_mapping_t(sequence, commands_vector, mode, new_mode)); +} + +void input_mapping_add(const wchar_t *sequence, const wchar_t *command, + const wchar_t *mode, const wchar_t *new_mode) +{ + input_mapping_add(sequence, &command, 1, mode, new_mode); } /** @@ -444,55 +453,37 @@ void input_destroy() } } + + /** Perform the action of the specified binding */ -static wint_t input_exec_binding(const input_mapping_t &m, const wcstring &seq) +static void input_mapping_execute(const input_mapping_t &m) { - wchar_t code = input_function_get_code(m.command); - if (code != (wchar_t)-1) + for(int i = m.commands.size() - 1; i >= 0; i--) { - switch (code) - { - - case R_SELF_INSERT: - { - return seq[0]; - } - - default: - { - return code; - } - + wcstring command = m.commands.at(i); + wchar_t code = input_function_get_code(command); + if (code != (wchar_t)-1) + { + input_unreadch(code); + } + else + { + /* + This key sequence is bound to a command, which + is sent to the parser for evaluation. + */ + int last_status = proc_get_last_status(); + parser_t::principal_parser().eval(command.c_str(), io_chain_t(), TOP); + + proc_set_last_status(last_status); + + input_unreadch(R_NULL); } } - else - { - /* - This key sequence is bound to a command, which - is sent to the parser for evaluation. - */ - int last_status = proc_get_last_status(); - - parser_t::principal_parser().eval(m.command.c_str(), io_chain_t(), TOP); - - proc_set_last_status(last_status); - - /* - We still need to return something to the caller, R_NULL - tells the reader that no key press needs to be handled, - and no repaint is needed. - - Bindings that produce output should emit a R_REPAINT - function by calling 'commandline -f repaint' to tell - fish that a repaint is in order. - */ - - return R_NULL; - - } + input_set_bind_mode(m.new_mode.c_str()); } @@ -500,22 +491,12 @@ static wint_t input_exec_binding(const input_mapping_t &m, const wcstring &seq) /** Try reading the specified function mapping */ -static wint_t input_try_mapping(const input_mapping_t &m) +static bool input_mapping_is_match(const input_mapping_t &m) { - wint_t c=0; + wint_t c = 0; int j; - /* - Check if the actual function code of this mapping is on the stack - */ - c = input_common_readch(0); - if (c == input_function_get_code(m.command)) - { - return input_exec_binding(m, m.seq); - } - input_unreadch(c); - - //debug(0, L"trying mapping %ls (%ls)\n", escape(m.seq.c_str(), 1), m.command.c_str()); + //debug(0, L"trying mapping %ls\n", escape(m.seq.c_str(), 1)); const wchar_t *str = m.seq.c_str(); for (j=0; str[j] != L'\0'; j++) { @@ -532,7 +513,7 @@ static wint_t input_try_mapping(const input_mapping_t &m) { //debug(0, L"matched mapping %ls (%ls)\n", escape(m.seq.c_str(), 1), m.command.c_str()); /* We matched the entire sequence */ - return input_exec_binding(m, m.seq); + return true; } else { @@ -547,7 +528,7 @@ static wint_t input_try_mapping(const input_mapping_t &m) } } - return 0; + return false; } @@ -556,6 +537,48 @@ void input_unreadch(wint_t ch) input_common_unreadch(ch); } +static void input_mapping_execute_matching_or_generic() +{ + const input_mapping_t *generic = NULL; + + for (int i = 0; i < mapping_list.size(); i++) + { + const input_mapping_t &m = mapping_list.at(i); + + //debug(0, L"trying mapping (%ls,%ls,%ls)\n", escape(m.seq.c_str(), 1), + // m.mode.c_str(), m.new_mode.c_str()); + + if(wcscmp(m.mode.c_str(), input_get_bind_mode())) + { + //debug(0, L"skipping mapping because mode %ls != %ls\n", m.mode.c_str(), input_get_bind_mode()); + continue; + } + + if (m.seq.length() == 0) + { + generic = &m; + } + else if(input_mapping_is_match(m)) + { + input_mapping_execute(m); + return; + } + } + + if (generic) + { + input_mapping_execute(*generic); + } + else + { + //debug(0, L"no generic found, ignoring..."); + wchar_t c = input_common_readch(0); + if (c == R_EOF) + input_common_unreadch(c); + } +} + + wint_t input_readch() { size_t i; @@ -573,61 +596,30 @@ wint_t input_readch() while (1) { - const input_mapping_t *generic = 0; - for (i=0; i<mapping_list.size(); i++) - { - const input_mapping_t &m = mapping_list.at(i); - - //debug(0, L"trying mapping (%ls,%ls,%ls,%ls)\n", escape(m.seq.c_str(), 1), - // m.command.c_str(), m.mode.c_str(), m.new_mode.c_str()); - - if(wcscmp(m.mode.c_str(), input_get_bind_mode())) - { - //debug(0, L"skipping mapping because mode %ls != %ls\n", m.mode.c_str(), input_get_bind_mode()); - continue; - } - - wint_t res = input_try_mapping(m); - if (res) - { - input_set_bind_mode(m.new_mode.c_str()); - return res; - } - - if (m.seq.length() == 0) - { - generic = &m; - } - - } - - /* - No matching exact mapping, try to find generic mapping. - */ + wchar_t c = input_common_readch(0); - if (generic) + if (c >= R_MIN && c <= R_MAX) { - wchar_t arr[2]= - { - 0, - 0 - } - ; - arr[0] = input_common_readch(0); - - return input_exec_binding(*generic, arr); + switch (c) + { + case R_EOF: /* If it's closed, then just return */ + { + return WEOF; + } + case R_SELF_INSERT: + { + return input_common_readch(0); + } + default: + { + return c; + } + } } - - /* - No action to take on specified character, ignore it - and move to next one. - */ - wchar_t c = input_common_readch(0); - - /* If it's closed, then just return */ - if (c == R_EOF) + else { - return WEOF; + input_unreadch(c); + input_mapping_execute_matching_or_generic(); } } } @@ -669,7 +661,7 @@ bool input_mapping_erase(const wchar_t *sequence, const wchar_t *mode) return result; } -bool input_mapping_get(const wcstring &sequence, wcstring &cmd, wcstring &mode) +bool input_mapping_get(const wcstring &sequence, std::vector<wcstring> &cmds, wcstring &mode, wcstring &new_mode) { size_t i, sz = mapping_list.size(); @@ -678,8 +670,9 @@ bool input_mapping_get(const wcstring &sequence, wcstring &cmd, wcstring &mode) const input_mapping_t &m = mapping_list.at(i); if (sequence == m.seq) { - cmd = m.command; + cmds = m.commands; mode = m.mode; + new_mode = m.new_mode; return true; } } |