aboutsummaryrefslogtreecommitdiffhomepage
path: root/input.cpp
diff options
context:
space:
mode:
authorGravatar Julian Aron Prenner <julian@linux4you.it>2014-01-01 00:11:32 +0100
committerGravatar Julian Aron Prenner <julian@linux4you.it>2014-01-01 00:11:32 +0100
commitdc90cd6bc4fdbb7b2b0a893cf40256f50b11c012 (patch)
tree9a4047997d691cfae6a32f458361782041e38614 /input.cpp
parentf408bc4808c592afce93e877e587c8c98a590dd9 (diff)
Better input handling; add support multiple binding commands
Diffstat (limited to 'input.cpp')
-rw-r--r--input.cpp225
1 files changed, 109 insertions, 116 deletions
diff --git a/input.cpp b/input.cpp
index 035188e3..1c32260c 100644
--- a/input.cpp
+++ b/input.cpp
@@ -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;
}
}