diff --git a/src/input_handler.cc b/src/input_handler.cc index 4f921a8a..b25e4174 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -258,21 +258,19 @@ public: context().client().info_hide(); do_restore_hooks = true; - auto it = std::lower_bound(keymap.begin(), keymap.end(), key, - [](const NormalCmdDesc& lhs, const Key& rhs) - { return lhs.key < rhs; }); + auto it = keymap.find(key); if (it != keymap.end() and it->key == key) { auto autoinfo = context().options()["autoinfo"].get(); if (autoinfo & AutoInfo::Normal and context().has_client()) - context().client().info_show(key_to_str(key), it->docstring.str(), + context().client().info_show(key_to_str(key), it->value.docstring.str(), {}, InfoStyle::Prompt); // reset m_params now to be reentrant NormalParams params = m_params; m_params = { 0, 0 }; - it->func(context(), params); + it->value.func(context(), params); } } diff --git a/src/main.cc b/src/main.cc index 19eb351f..347428f1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -805,10 +805,6 @@ int main(int argc, char* argv[]) }; try { - std::sort(keymap.begin(), keymap.end(), - [](const NormalCmdDesc& lhs, const NormalCmdDesc& rhs) - { return lhs.key < rhs.key; }); - ParametersParser parser(params, param_desc); const bool list_sessions = (bool)parser.get_switch("l"); diff --git a/src/normal.cc b/src/normal.cc index 119b91d1..aa7ec225 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1779,190 +1779,187 @@ void force_redraw(Context& context, NormalParams) } } -static NormalCmdDesc cmds[] = -{ - { 'h', "move left", move }, - { 'j', "move down", move }, - { 'k', "move up", move }, - { 'l', "move right", move }, +const HashMap keymap{ + { {'h'}, {"move left", move} }, + { {'j'}, {"move down", move} }, + { {'k'}, {"move up", move} }, + { {'l'}, {"move right", move} }, - { 'H', "extend left", move }, - { 'J', "extend down", move }, - { 'K', "extend up", move }, - { 'L', "extend right", move }, + { {'H'}, {"extend left", move} }, + { {'J'}, {"extend down", move} }, + { {'K'}, {"extend up", move} }, + { {'L'}, {"extend right", move} }, - { 't', "select to next character", select_to_next_char }, - { 'f', "select to next character included", select_to_next_char }, - { 'T', "extend to next character", select_to_next_char }, - { 'F', "extend to next character included", select_to_next_char }, - { alt('t'), "select to previous character", select_to_next_char }, - { alt('f'), "select to previous character included", select_to_next_char }, - { alt('T'), "extend to previous character", select_to_next_char }, - { alt('F'), "extend to previous character included", select_to_next_char }, + { {'t'}, {"select to next character", select_to_next_char} }, + { {'f'}, {"select to next character included", select_to_next_char} }, + { {'T'}, {"extend to next character", select_to_next_char} }, + { {'F'}, {"extend to next character included", select_to_next_char} }, + { {alt('t')}, {"select to previous character", select_to_next_char} }, + { {alt('f')}, {"select to previous character included", select_to_next_char} }, + { {alt('T')}, {"extend to previous character", select_to_next_char} }, + { {alt('F')}, {"extend to previous character included", select_to_next_char} }, - { 'd', "erase selected text", erase_selections }, - { 'c', "change selected text", change }, - { 'i', "insert before selected text", enter_insert_mode }, - { 'I', "insert at line begin", enter_insert_mode }, - { 'a', "insert after selected text", enter_insert_mode }, - { 'A', "insert at line end", enter_insert_mode }, - { 'o', "insert on new line below", enter_insert_mode }, - { 'O', "insert on new line above", enter_insert_mode }, - { 'r', "replace with character", replace_with_char }, + { {'d'}, {"erase selected text", erase_selections} }, + { {'c'}, {"change selected text", change} }, + { {'i'}, {"insert before selected text", enter_insert_mode} }, + { {'I'}, {"insert at line begin", enter_insert_mode} }, + { {'a'}, {"insert after selected text", enter_insert_mode} }, + { {'A'}, {"insert at line end", enter_insert_mode} }, + { {'o'}, {"insert on new line below", enter_insert_mode} }, + { {'O'}, {"insert on new line above", enter_insert_mode} }, + { {'r'}, {"replace with character", replace_with_char} }, - { 'g', "go to location", goto_commands }, - { 'G', "extend to location", goto_commands }, + { {'g'}, {"go to location", goto_commands} }, + { {'G'}, {"extend to location", goto_commands} }, - { 'v', "move view", view_commands }, - { 'V', "move view (locked)", view_commands }, + { {'v'}, {"move view", view_commands} }, + { {'V'}, {"move view (locked)", view_commands} }, - { 'y', "yank selected text", yank }, - { 'p', "paste after selected text", repeated> }, - { 'P', "paste before selected text", repeated> }, - { alt('p'), "paste every yanked selection after selected text", paste_all }, - { alt('P'), "paste every yanked selection before selected text", paste_all }, - { 'R', "replace selected text with yanked text", paste }, - { alt('R'), "replace selected text with yanked text", paste_all }, + { {'y'}, {"yank selected text", yank} }, + { {'p'}, {"paste after selected text", repeated>} }, + { {'P'}, {"paste before selected text", repeated>} }, + { {alt('p')}, {"paste every yanked selection after selected text", paste_all} }, + { {alt('P')}, {"paste every yanked selection before selected text", paste_all} }, + { {'R'}, {"replace selected text with yanked text", paste} }, + { {alt('R')}, {"replace selected text with yanked text", paste_all} }, - { 's', "select regex matches in selected text", select_regex }, - { 'S', "split selected text on regex matches", split_regex }, - { alt('s'), "split selected text on line ends", split_lines }, + { {'s'}, {"select regex matches in selected text", select_regex} }, + { {'S'}, {"split selected text on regex matches", split_regex} }, + { {alt('s')}, {"split selected text on line ends", split_lines} }, - { '.', "repeat last insert command", repeat_last_insert }, - { alt('.'), "repeat last object select/character find", repeat_last_select }, + { {'.'}, {"repeat last insert command", repeat_last_insert} }, + { {alt('.')}, {"repeat last object select/character find", repeat_last_select} }, - { '%', "select whole buffer", select_whole_buffer }, + { {'%'}, {"select whole buffer", select_whole_buffer} }, - { ':', "enter command prompt", command }, - { '|', "pipe each selection through filter and replace with output", pipe }, - { alt('|'), "pipe each selection through command and ignore output", pipe }, - { '!', "insert command output", insert_output }, - { alt('!'), "append command output", insert_output }, + { {':'}, {"enter command prompt", command} }, + { {'|'}, {"pipe each selection through filter and replace with output", pipe} }, + { {alt('|')}, {"pipe each selection through command and ignore output", pipe} }, + { {'!'}, {"insert command output", insert_output} }, + { {alt('!')}, {"append command output", insert_output} }, - { ' ', "remove all selection except main", keep_selection }, - { alt(' '), "remove main selection", remove_selection }, - { ';', "reduce selections to their cursor", clear_selections }, - { alt(';'), "swap selections cursor and anchor", flip_selections }, - { alt(':'), "ensure selection cursor is after anchor", ensure_forward }, - { alt('m'), "merge consecutive selections", merge_consecutive }, + { {' '}, {"remove all selection except main", keep_selection} }, + { {alt(' ')}, {"remove main selection", remove_selection} }, + { {';'}, {"reduce selections to their cursor", clear_selections} }, + { {alt(';')}, {"swap selections cursor and anchor", flip_selections} }, + { {alt(':')}, {"ensure selection cursor is after anchor", ensure_forward} }, + { {alt('m')}, {"merge consecutive selections", merge_consecutive} }, - { 'w', "select to next word start", repeated<&select>> }, - { 'e', "select to next word end", repeated>> }, - { 'b', "select to previous word start", repeated>> }, - { 'W', "extend to next word start", repeated>> }, - { 'E', "extend to next word end", repeated>> }, - { 'B', "extend to previous word start", repeated>> }, + { {'w'}, {"select to next word start", repeated<&select>>} }, + { {'e'}, {"select to next word end", repeated>>} }, + { {'b'}, {"select to previous word start", repeated>>} }, + { {'W'}, {"extend to next word start", repeated>>} }, + { {'E'}, {"extend to next word end", repeated>>} }, + { {'B'}, {"extend to previous word start", repeated>>} }, - { alt('w'), "select to next WORD start", repeated>> }, - { alt('e'), "select to next WORD end", repeated>> }, - { alt('b'), "select to previous WORD start", repeated>> }, - { alt('W'), "extend to next WORD start", repeated>> }, - { alt('E'), "extend to next WORD end", repeated>> }, - { alt('B'), "extend to previous WORD start", repeated>> }, + { {alt('w')}, {"select to next WORD start", repeated>>} }, + { {alt('e')}, {"select to next WORD end", repeated>>} }, + { {alt('b')}, {"select to previous WORD start", repeated>>} }, + { {alt('W')}, {"extend to next WORD start", repeated>>} }, + { {alt('E')}, {"extend to next WORD end", repeated>>} }, + { {alt('B')}, {"extend to previous WORD start", repeated>>} }, - { alt('l'), "select to line end", repeated>> }, - { Key::End, "select to line end", repeated>> }, - { alt('L'), "extend to line end", repeated>> }, - { alt('h'), "select to line begin", repeated>> }, - { Key::Home, "select to line begin", repeated>> }, - { alt('H'), "extend to line begin", repeated>> }, + { {alt('l')}, {"select to line end", repeated>>} }, + { {Key::End}, {"select to line end", repeated>>} }, + { {alt('L')}, {"extend to line end", repeated>>} }, + { {alt('h')}, {"select to line begin", repeated>>} }, + { {Key::Home}, {"select to line begin", repeated>>} }, + { {alt('H')}, {"extend to line begin", repeated>>} }, - { 'x', "select line", repeated> }, - { 'X', "extend line", repeated> }, - { alt('x'), "extend selections to whole lines", select }, - { alt('X'), "crop selections to whole lines", select }, + { {'x'}, {"select line", repeated>} }, + { {'X'}, {"extend line", repeated>} }, + { {alt('x')}, {"extend selections to whole lines", select} }, + { {alt('X')}, {"crop selections to whole lines", select} }, - { 'm', "select to matching character", select }, - { 'M', "extend to matching character", select }, + { {'m'}, {"select to matching character", select} }, + { {'M'}, {"extend to matching character", select} }, - { '/', "select next given regex match", search }, - { '?', "extend with next given regex match", search }, - { alt('/'), "select previous given regex match", search }, - { alt('?'), "extend with previous given regex match", search }, - { 'n', "select next current search pattern match", search_next }, - { 'N', "extend with next current search pattern match", search_next }, - { alt('n'), "select previous current search pattern match", search_next }, - { alt('N'), "extend with previous current search pattern match", search_next }, - { '*', "set search pattern to main selection content", use_selection_as_search_pattern }, - { alt('*'), "set search pattern to main selection content, do not detect words", use_selection_as_search_pattern }, + { {'/'}, {"select next given regex match", search} }, + { {'?'}, {"extend with next given regex match", search} }, + { {alt('/')}, {"select previous given regex match", search} }, + { {alt('?')}, {"extend with previous given regex match", search} }, + { {'n'}, {"select next current search pattern match", search_next} }, + { {'N'}, {"extend with next current search pattern match", search_next} }, + { {alt('n')}, {"select previous current search pattern match", search_next} }, + { {alt('N')}, {"extend with previous current search pattern match", search_next} }, + { {'*'}, {"set search pattern to main selection content", use_selection_as_search_pattern} }, + { {alt('*')}, {"set search pattern to main selection content, do not detect words", use_selection_as_search_pattern} }, - { 'u', "undo", undo }, - { 'U', "redo", redo }, - { alt('u'), "move backward in history", move_in_history }, - { alt('U'), "move forward in history", move_in_history }, + { {'u'}, {"undo", undo} }, + { {'U'}, {"redo", redo} }, + { {alt('u')}, {"move backward in history", move_in_history} }, + { {alt('U')}, {"move forward in history", move_in_history} }, - { alt('i'), "select inner object", select_object }, - { alt('a'), "select whole object", select_object }, - { '[', "select to object start", select_object }, - { ']', "select to object end", select_object }, - { '{', "extend to object start", select_object }, - { '}', "extend to object end", select_object }, - { alt('['), "select to inner object start", select_object }, - { alt(']'), "select to inner object end", select_object }, - { alt('{'), "extend to inner object start", select_object }, - { alt('}'), "extend to inner object end", select_object }, + { {alt('i')}, {"select inner object", select_object} }, + { {alt('a')}, {"select whole object", select_object} }, + { {'['}, {"select to object start", select_object} }, + { {']'}, {"select to object end", select_object} }, + { {'{'}, {"extend to object start", select_object} }, + { {'}'}, {"extend to object end", select_object} }, + { {alt('[')}, {"select to inner object start", select_object} }, + { {alt(']')}, {"select to inner object end", select_object} }, + { {alt('{')}, {"extend to inner object start", select_object} }, + { {alt('}')}, {"extend to inner object end", select_object} }, - { alt('j'), "join lines", join_lines }, - { alt('J'), "join lines and select spaces", join_lines_select_spaces }, + { {alt('j')}, {"join lines", join_lines} }, + { {alt('J')}, {"join lines and select spaces", join_lines_select_spaces} }, - { alt('k'), "keep selections matching given regex", keep }, - { alt('K'), "keep selections not matching given regex", keep }, - { '$', "pipe each selection through shell command and keep the ones whose command succeed", keep_pipe }, + { {alt('k')}, {"keep selections matching given regex", keep} }, + { {alt('K')}, {"keep selections not matching given regex", keep} }, + { {'$'}, {"pipe each selection through shell command and keep the ones whose command succeed", keep_pipe} }, - { '<', "deindent", deindent }, - { '>', "indent", indent }, - { alt('>'), "indent, including empty lines", indent }, - { alt('<'), "deindent, not including incomplete indent", deindent }, + { {'<'}, {"deindent", deindent} }, + { {'>'}, {"indent", indent} }, + { {alt('>')}, {"indent, including empty lines", indent} }, + { {alt('<')}, {"deindent, not including incomplete indent", deindent} }, - { /*ctrl('i')*/Key::Tab, "jump forward in jump list",jump }, // until we can distinguish tab a ctrl('i') - { ctrl('o'), "jump backward in jump list", jump }, - { ctrl('s'), "push current selections in jump list", push_selections }, + { {/*ctrl('i')*/Key::Tab}, {"jump forward in jump list",jump} }, // until we can distinguish tab a ctrl('i') + { {ctrl('o')}, {"jump backward in jump list", jump} }, + { {ctrl('s')}, {"push current selections in jump list", push_selections} }, - { '\'', "rotate main selection", rotate_selections }, - { alt('\''), "rotate main selection", rotate_selections }, - { alt('"'), "rotate selections content", rotate_selections_content }, + { {'\''}, {"rotate main selection", rotate_selections} }, + { {alt('\'')}, {"rotate main selection", rotate_selections} }, + { {alt('"')}, {"rotate selections content", rotate_selections_content} }, - { 'q', "replay recorded macro", replay_macro }, - { 'Q', "start or end macro recording", start_or_end_macro_recording }, + { {'q'}, {"replay recorded macro", replay_macro} }, + { {'Q'}, {"start or end macro recording", start_or_end_macro_recording} }, - { Key::Escape, "end macro recording", end_macro_recording }, + { {Key::Escape}, {"end macro recording", end_macro_recording} }, - { '`', "convert to lower case in selections", for_each_codepoint }, - { '~', "convert to upper case in selections", for_each_codepoint }, - { alt('`'), "swap case in selections", for_each_codepoint }, + { {'`'}, {"convert to lower case in selections", for_each_codepoint} }, + { {'~'}, {"convert to upper case in selections", for_each_codepoint} }, + { {alt('`')}, { "swap case in selections", for_each_codepoint} }, - { '&', "align selection cursors", align }, - { alt('&'), "copy indentation", copy_indent }, + { {'&'}, {"align selection cursors", align} }, + { {alt('&')}, {"copy indentation", copy_indent} }, - { '@', "convert tabs to spaces in selections", tabs_to_spaces }, - { alt('@'), "convert spaces to tabs in selections", spaces_to_tabs }, + { {'@'}, {"convert tabs to spaces in selections", tabs_to_spaces} }, + { {alt('@')}, {"convert spaces to tabs in selections", spaces_to_tabs} }, - { 'C', "copy selection on next lines", copy_selections_on_next_lines }, - { alt('C'), "copy selection on previous lines", copy_selections_on_next_lines }, + { {'C'}, {"copy selection on next lines", copy_selections_on_next_lines} }, + { {alt('C')}, {"copy selection on previous lines", copy_selections_on_next_lines} }, - { ',', "user mappings", exec_user_mappings }, + { {','}, {"user mappings", exec_user_mappings} }, - { Key::Left, "move left", move }, - { Key::Down, "move down", move }, - { Key::Up, "move up", move }, - { Key::Right, "move right", move }, + { {Key::Left}, { "move left", move} }, + { {Key::Down}, { "move down", move} }, + { {Key::Up}, { "move up", move} }, + { {Key::Right}, {"move right", move} }, - { ctrl('b'), "scroll one page up", scroll }, - { ctrl('f'), "scroll one page down", scroll }, - { ctrl('u'), "scroll half a page up", scroll }, - { ctrl('d'), "scroll half a page down", scroll }, + { {ctrl('b')}, {"scroll one page up", scroll} }, + { {ctrl('f')}, {"scroll one page down", scroll} }, + { {ctrl('u')}, {"scroll half a page up", scroll} }, + { {ctrl('d')}, {"scroll half a page down", scroll} }, - { Key::PageUp, "scroll one page up", scroll }, - { Key::PageDown, "scroll one page down", scroll }, + { {Key::PageUp}, { "scroll one page up", scroll} }, + { {Key::PageDown}, {"scroll one page down", scroll} }, - { 'z', "restore selections from register", restore_selections }, - { alt('z'), "append selections from register", restore_selections }, - { 'Z', "save selections to register", save_selections }, - { alt('Z'), "append selections to register", save_selections }, + { {'z'}, {"restore selections from register", restore_selections} }, + { {alt('z')}, {"append selections from register", restore_selections} }, + { {'Z'}, {"save selections to register", save_selections} }, + { {alt('Z')}, {"append selections to register", save_selections} }, - { ctrl('l'), "force redraw", force_redraw }, + { {ctrl('l')}, {"force redraw", force_redraw} }, }; -KeyMap keymap = cmds; - } diff --git a/src/normal.hh b/src/normal.hh index 96cf1457..bb2d3ecc 100644 --- a/src/normal.hh +++ b/src/normal.hh @@ -1,7 +1,7 @@ #ifndef normal_hh_INCLUDED #define normal_hh_INCLUDED -#include "array_view.hh" +#include "hash_map.hh" #include "keys.hh" #include "string.hh" @@ -16,15 +16,13 @@ struct NormalParams char reg; }; -struct NormalCmdDesc +struct NormalCmd { - Key key; StringView docstring; void (*func)(Context& context, NormalParams params); }; -using KeyMap = const ArrayView; -extern KeyMap keymap; +extern const HashMap keymap; }