From 722fedc8fd590cb436109a553fb68f02790117f3 Mon Sep 17 00:00:00 2001 From: Sanne Wouda Date: Fri, 17 Apr 2015 15:49:52 +0200 Subject: [PATCH] rewrite input_mapping_execute for clarity For the case ``` bind \et "commandline -i 1" "commandline -i 2" ``` the order of execution of the commands is now in-order. Note that functions codes are prepended to the queue in reverse order, so they will be executed in-order. This should allow all bindings of the form ``` bind \et beginning-of-line force-repaint ``` to remain unchanged. --- input.cpp | 85 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/input.cpp b/input.cpp index 4ddf35691..02b526889 100644 --- a/input.cpp +++ b/input.cpp @@ -562,52 +562,67 @@ void input_function_push_args(int code) */ static void input_mapping_execute(const input_mapping_t &m, bool allow_commands) { - /* By default input functions always succeed */ - input_function_status = true; + /* has_functions: there are functions that need to be put on the input + queue + has_commands: there are shell commands that need to be evaluated */ + bool has_commands = false, has_functions = false; - size_t idx = m.commands.size(); - while (idx--) + for (wcstring_list_t::const_iterator it = m.commands.begin(), end = m.commands.end(); it != end; it++) { - wcstring command = m.commands.at(idx); - wchar_t code = input_function_get_code(command); - if (code != (wchar_t)-1) - { - input_function_push_args(code); - } + if (input_function_get_code(*it) != -1) + has_functions = true; + else + has_commands = true; } - idx = m.commands.size(); - while (idx--) + /* !has_functions && !has_commands: only set bind mode */ + if (!has_commands && !has_functions) { - wcstring command = m.commands.at(idx); - wchar_t code = input_function_get_code(command); - if (code != (wchar_t)-1) + input_set_bind_mode(m.sets_mode); + return; + } + + if (!allow_commands) + { + /* We don't want to run commands yet. Put the characters back and return + R_NULL */ + for (wcstring::const_reverse_iterator it = m.seq.rbegin(), end = m.seq.rend(); it != end; ++it) { + input_common_next_ch(*it); + } + input_common_next_ch(R_NULL); + return; /* skip the input_set_bind_mode */ + } + else if (has_functions && !has_commands) + { + /* functions are added at the head of the input queue */ + for (wcstring_list_t::const_reverse_iterator it = m.commands.rbegin(), end = m.commands.rend (); it != end; it++) + { + wchar_t code = input_function_get_code(*it); + input_function_push_args(code); input_common_next_ch(code); } - else if (allow_commands) - { - /* - 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); + } + else if (has_commands && !has_functions) + { + /* Execute all commands. - proc_set_last_status(last_status); - - input_common_next_ch(R_NULL); - } - else + FIXME(snnw): if commands add stuff to input queue (e.g. commandline + -f execute), we won't see that until all other commands have also + been run. */ + int last_status = proc_get_last_status(); + for (wcstring_list_t::const_iterator it = m.commands.begin(), end = m.commands.end(); it != end; it++) { - /* We don't want to run commands yet. Put the characters back and return R_NULL */ - for (wcstring::const_reverse_iterator it = m.seq.rbegin(), end = m.seq.rend(); it != end; ++it) - { - input_common_next_ch(*it); - } - input_common_next_ch(R_NULL); - return; /* skip the input_set_bind_mode */ + parser_t::principal_parser().eval(it->c_str(), io_chain_t(), TOP); } + proc_set_last_status(last_status); + input_common_next_ch(R_NULL); + } + else + { + /* invalid binding, mixed commands and functions. We would need to + execute these one by one. */ + input_common_next_ch(R_NULL); } input_set_bind_mode(m.sets_mode);