Use a sorted array for keymap rather than an unordered map

with ~100 entry, a binary search finds in < 7 step, unordered map
is overkill.
This commit is contained in:
Maxime Coste 2015-03-08 11:40:50 +00:00
parent 3ece7bcf75
commit 0bbaef6e48
4 changed files with 141 additions and 134 deletions

View File

@ -127,13 +127,15 @@ public:
{ {
if (m_hooks_disabled) if (m_hooks_disabled)
do_restore_hooks = true; do_restore_hooks = true;
auto it = keymap.find(key); auto it = std::lower_bound(keymap.begin(), keymap.end(), key,
if (it != keymap.end()) [](const NormalCmdDesc& lhs, const Key& rhs)
{ return lhs.key < rhs; });
if (it != keymap.end() and it->key == key)
{ {
if (context().options()["autoinfo"].get<int>() >= 2 and context().has_ui()) if (context().options()["autoinfo"].get<int>() >= 2 and context().has_ui())
context().ui().info_show(key_to_str(key), it->second.docstring, CharCoord{}, context().ui().info_show(key_to_str(key), it->docstring, CharCoord{},
get_face("Information"), InfoStyle::Prompt); get_face("Information"), InfoStyle::Prompt);
it->second.func(context(), m_params); it->func(context(), m_params);
} }
m_params = { 0, '"' }; m_params = { 0, '"' };
} }

View File

@ -528,6 +528,10 @@ int main(int argc, char* argv[])
}; };
try try
{ {
std::sort(keymap.begin(), keymap.end(),
[](const NormalCmdDesc& lhs, const NormalCmdDesc& rhs)
{ return lhs.key < rhs.key; });
ParametersParser parser(params, param_desc); ParametersParser parser(params, param_desc);
if (parser.has_option("p")) if (parser.has_option("p"))

View File

@ -1350,169 +1350,169 @@ void move(Context& context, NormalParams params)
selections.sort_and_merge_overlapping(); selections.sort_and_merge_overlapping();
} }
const KeyMap keymap = KeyMap keymap =
{ {
{ 'h', { "move left", move<CharCount, Backward> } }, { 'h', "move left", move<CharCount, Backward> },
{ 'j', { "move down", move<LineCount, Forward> } }, { 'j', "move down", move<LineCount, Forward> },
{ 'k', { "move up", move<LineCount, Backward> } }, { 'k', "move up", move<LineCount, Backward> },
{ 'l', { "move right", move<CharCount, Forward> } }, { 'l', "move right", move<CharCount, Forward> },
{ 'H', { "extend left", move<CharCount, Backward, SelectMode::Extend> } }, { 'H', "extend left", move<CharCount, Backward, SelectMode::Extend> },
{ 'J', { "extend down", move<LineCount, Forward, SelectMode::Extend> } }, { 'J', "extend down", move<LineCount, Forward, SelectMode::Extend> },
{ 'K', { "extend up", move<LineCount, Backward, SelectMode::Extend> } }, { 'K', "extend up", move<LineCount, Backward, SelectMode::Extend> },
{ 'L', { "extend right", move<CharCount, Forward, SelectMode::Extend> } }, { 'L', "extend right", move<CharCount, Forward, SelectMode::Extend> },
{ 't', { "select to next character", select_to_next_char<SelectFlags::None> } }, { 't', "select to next character", select_to_next_char<SelectFlags::None> },
{ 'f', { "select to next character included", select_to_next_char<SelectFlags::Inclusive> } }, { 'f', "select to next character included", select_to_next_char<SelectFlags::Inclusive> },
{ 'T', { "extend to next character", select_to_next_char<SelectFlags::Extend> } }, { 'T', "extend to next character", select_to_next_char<SelectFlags::Extend> },
{ 'F', { "extend to next character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Extend> } }, { 'F', "extend to next character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Extend> },
{ alt('t'), { "select to previous character", select_to_next_char<SelectFlags::Reverse> } }, { alt('t'), "select to previous character", select_to_next_char<SelectFlags::Reverse> },
{ alt('f'), { "select to previous character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Reverse> } }, { alt('f'), "select to previous character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Reverse> },
{ alt('T'), { "extend to previous character", select_to_next_char<SelectFlags::Extend | SelectFlags::Reverse> } }, { alt('T'), "extend to previous character", select_to_next_char<SelectFlags::Extend | SelectFlags::Reverse> },
{ alt('F'), { "extend to previous character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Extend | SelectFlags::Reverse> } }, { alt('F'), "extend to previous character included", select_to_next_char<SelectFlags::Inclusive | SelectFlags::Extend | SelectFlags::Reverse> },
{ 'd', { "erase selected text", erase_selections } }, { 'd', "erase selected text", erase_selections },
{ 'c', { "change selected text", change } }, { 'c', "change selected text", change },
{ 'i', { "insert before selected text", enter_insert_mode<InsertMode::Insert> } }, { 'i', "insert before selected text", enter_insert_mode<InsertMode::Insert> },
{ 'I', { "insert at line begin", enter_insert_mode<InsertMode::InsertAtLineBegin> } }, { 'I', "insert at line begin", enter_insert_mode<InsertMode::InsertAtLineBegin> },
{ 'a', { "insert after selected text", enter_insert_mode<InsertMode::Append> } }, { 'a', "insert after selected text", enter_insert_mode<InsertMode::Append> },
{ 'A', { "insert at line end", enter_insert_mode<InsertMode::AppendAtLineEnd> } }, { 'A', "insert at line end", enter_insert_mode<InsertMode::AppendAtLineEnd> },
{ 'o', { "insert on new line below", enter_insert_mode<InsertMode::OpenLineBelow> } }, { 'o', "insert on new line below", enter_insert_mode<InsertMode::OpenLineBelow> },
{ 'O', { "insert on new line above", enter_insert_mode<InsertMode::OpenLineAbove> } }, { 'O', "insert on new line above", enter_insert_mode<InsertMode::OpenLineAbove> },
{ 'r', { "replace with character", replace_with_char } }, { 'r', "replace with character", replace_with_char },
{ 'g', { "go to location", goto_commands<SelectMode::Replace> } }, { 'g', "go to location", goto_commands<SelectMode::Replace> },
{ 'G', { "extend to location", goto_commands<SelectMode::Extend> } }, { 'G', "extend to location", goto_commands<SelectMode::Extend> },
{ 'v', { "move view", view_commands } }, { 'v', "move view", view_commands },
{ 'y', { "yank selected text", yank } }, { 'y', "yank selected text", yank },
{ 'p', { "paste after selected text", repeated<paste<InsertMode::Append>> } }, { 'p', "paste after selected text", repeated<paste<InsertMode::Append>> },
{ 'P', { "paste before selected text", repeated<paste<InsertMode::Insert>> } }, { 'P', "paste before selected text", repeated<paste<InsertMode::Insert>> },
{ alt('p'), { "paste every yanked selection after selected text", paste_all<InsertMode::Append> } }, { alt('p'), "paste every yanked selection after selected text", paste_all<InsertMode::Append> },
{ alt('P'), { "paste every yanked selection before selected text", paste_all<InsertMode::Insert> } }, { alt('P'), "paste every yanked selection before selected text", paste_all<InsertMode::Insert> },
{ 'R', { "replace selected text with yanked text", paste<InsertMode::Replace> } }, { 'R', "replace selected text with yanked text", paste<InsertMode::Replace> },
{ 's', { "select regex matches in selected text", select_regex } }, { 's', "select regex matches in selected text", select_regex },
{ 'S', { "split selected text on regex matches", split_regex } }, { 'S', "split selected text on regex matches", split_regex },
{ alt('s'), { "split selected text on line ends", split_lines } }, { alt('s'), "split selected text on line ends", split_lines },
{ '.', { "repeat last insert command", repeat_last_insert } }, { '.', "repeat last insert command", repeat_last_insert },
{ '%', { "select whole buffer", [](Context& context, NormalParams) { select_buffer(context.selections()); } } }, { '%', "select whole buffer", [](Context& context, NormalParams) { select_buffer(context.selections()); } },
{ ':', { "enter command prompt", command } }, { ':', "enter command prompt", command },
{ '|', { "pipe each selection through filter and replace with output", pipe<true> } }, { '|', "pipe each selection through filter and replace with output", pipe<true> },
{ alt('|'), { "pipe each selection through command and ignore output", pipe<false> } }, { alt('|'), "pipe each selection through command and ignore output", pipe<false> },
{ '!', { "insert command output", insert_output<InsertMode::Insert> } }, { '!', "insert command output", insert_output<InsertMode::Insert> },
{ alt('!'), { "append command output", insert_output<InsertMode::Append> } }, { alt('!'), "append command output", insert_output<InsertMode::Append> },
{ ' ', { "remove all selection except main", [](Context& context, NormalParams p) { keep_selection(context.selections(), p.count ? p.count-1 : context.selections().main_index()); } } }, { ' ', "remove all selection except main", [](Context& context, NormalParams p) { keep_selection(context.selections(), p.count ? p.count-1 : context.selections().main_index()); } },
{ alt(' '), { "remove main selection", [](Context& context, NormalParams p) { remove_selection(context.selections(), p.count ? p.count-1 : context.selections().main_index()); } } }, { alt(' '), "remove main selection", [](Context& context, NormalParams p) { remove_selection(context.selections(), p.count ? p.count-1 : context.selections().main_index()); } },
{ ';', { "reduce selections to their cursor", [](Context& context, NormalParams) { clear_selections(context.selections()); } } }, { ';', "reduce selections to their cursor", [](Context& context, NormalParams) { clear_selections(context.selections()); } },
{ alt(';'), { "swap selections cursor and anchor", [](Context& context, NormalParams) { flip_selections(context.selections()); } } }, { alt(';'), "swap selections cursor and anchor", [](Context& context, NormalParams) { flip_selections(context.selections()); } },
{ 'w', { "select to next word start", repeated<&select<SelectMode::Replace, select_to_next_word<Word>>> } }, { 'w', "select to next word start", repeated<&select<SelectMode::Replace, select_to_next_word<Word>>> },
{ 'e', { "select to next word end", repeated<select<SelectMode::Replace, select_to_next_word_end<Word>>> } }, { 'e', "select to next word end", repeated<select<SelectMode::Replace, select_to_next_word_end<Word>>> },
{ 'b', { "select to prevous word start", repeated<select<SelectMode::Replace, select_to_previous_word<Word>>> } }, { 'b', "select to prevous word start", repeated<select<SelectMode::Replace, select_to_previous_word<Word>>> },
{ 'W', { "extend to next word start", repeated<select<SelectMode::Extend, select_to_next_word<Word>>> } }, { 'W', "extend to next word start", repeated<select<SelectMode::Extend, select_to_next_word<Word>>> },
{ 'E', { "extend to next word end", repeated<select<SelectMode::Extend, select_to_next_word_end<Word>>> } }, { 'E', "extend to next word end", repeated<select<SelectMode::Extend, select_to_next_word_end<Word>>> },
{ 'B', { "extend to prevous word start", repeated<select<SelectMode::Extend, select_to_previous_word<Word>>> } }, { 'B', "extend to prevous word start", repeated<select<SelectMode::Extend, select_to_previous_word<Word>>> },
{ alt('w'), { "select to next WORD start", repeated<select<SelectMode::Replace, select_to_next_word<WORD>>> } }, { alt('w'), "select to next WORD start", repeated<select<SelectMode::Replace, select_to_next_word<WORD>>> },
{ alt('e'), { "select to next WORD end", repeated<select<SelectMode::Replace, select_to_next_word_end<WORD>>> } }, { alt('e'), "select to next WORD end", repeated<select<SelectMode::Replace, select_to_next_word_end<WORD>>> },
{ alt('b'), { "select to prevous WORD start", repeated<select<SelectMode::Replace, select_to_previous_word<WORD>>> } }, { alt('b'), "select to prevous WORD start", repeated<select<SelectMode::Replace, select_to_previous_word<WORD>>> },
{ alt('W'), { "extend to next WORD start", repeated<select<SelectMode::Extend, select_to_next_word<WORD>>> } }, { alt('W'), "extend to next WORD start", repeated<select<SelectMode::Extend, select_to_next_word<WORD>>> },
{ alt('E'), { "extend to next WORD end", repeated<select<SelectMode::Extend, select_to_next_word_end<WORD>>> } }, { alt('E'), "extend to next WORD end", repeated<select<SelectMode::Extend, select_to_next_word_end<WORD>>> },
{ alt('B'), { "extend to prevous WORD start", repeated<select<SelectMode::Extend, select_to_previous_word<WORD>>> } }, { alt('B'), "extend to prevous WORD start", repeated<select<SelectMode::Extend, select_to_previous_word<WORD>>> },
{ alt('l'), { "select to line end", repeated<select<SelectMode::Replace, select_to_eol>> } }, { alt('l'), "select to line end", repeated<select<SelectMode::Replace, select_to_eol>> },
{ alt('L'), { "extend to line end", repeated<select<SelectMode::Extend, select_to_eol>> } }, { alt('L'), "extend to line end", repeated<select<SelectMode::Extend, select_to_eol>> },
{ alt('h'), { "select to line begin", repeated<select<SelectMode::Replace, select_to_eol_reverse>> } }, { alt('h'), "select to line begin", repeated<select<SelectMode::Replace, select_to_eol_reverse>> },
{ alt('H'), { "extend to line begin", repeated<select<SelectMode::Extend, select_to_eol_reverse>> } }, { alt('H'), "extend to line begin", repeated<select<SelectMode::Extend, select_to_eol_reverse>> },
{ 'x', { "select line", repeated<select<SelectMode::Replace, select_line>> } }, { 'x', "select line", repeated<select<SelectMode::Replace, select_line>> },
{ 'X', { "extend line", repeated<select<SelectMode::Extend, select_line>> } }, { 'X', "extend line", repeated<select<SelectMode::Extend, select_line>> },
{ alt('x'), { "extend selections to whole lines", select<SelectMode::Replace, select_lines> } }, { alt('x'), "extend selections to whole lines", select<SelectMode::Replace, select_lines> },
{ alt('X'), { "crop selections to whole lines", select<SelectMode::Replace, trim_partial_lines> } }, { alt('X'), "crop selections to whole lines", select<SelectMode::Replace, trim_partial_lines> },
{ 'm', { "select to matching character", select<SelectMode::Replace, select_matching> } }, { 'm', "select to matching character", select<SelectMode::Replace, select_matching> },
{ 'M', { "extend to matching character", select<SelectMode::Extend, select_matching> } }, { 'M', "extend to matching character", select<SelectMode::Extend, select_matching> },
{ '/', { "select next given regex match", search<SelectMode::Replace, Forward> } }, { '/', "select next given regex match", search<SelectMode::Replace, Forward> },
{ '?', { "extend with next given regex match", search<SelectMode::Extend, Forward> } }, { '?', "extend with next given regex match", search<SelectMode::Extend, Forward> },
{ alt('/'), { "select previous given regex match", search<SelectMode::Replace, Backward> } }, { alt('/'), "select previous given regex match", search<SelectMode::Replace, Backward> },
{ alt('?'), { "extend with previous given regex match", search<SelectMode::Extend, Backward> } }, { alt('?'), "extend with previous given regex match", search<SelectMode::Extend, Backward> },
{ 'n', { "select next current search pattern match", search_next<SelectMode::Replace, Forward> } }, { 'n', "select next current search pattern match", search_next<SelectMode::Replace, Forward> },
{ 'N', { "extend with next current search pattern match", search_next<SelectMode::Append, Forward> } }, { 'N', "extend with next current search pattern match", search_next<SelectMode::Append, Forward> },
{ alt('n'), { "select previous current search pattern match", search_next<SelectMode::Replace, Backward> } }, { alt('n'), "select previous current search pattern match", search_next<SelectMode::Replace, Backward> },
{ alt('N'), { "extend with previous current search pattern match", search_next<SelectMode::Append, Backward> } }, { alt('N'), "extend with previous current search pattern match", search_next<SelectMode::Append, Backward> },
{ '*', { "set search pattern to main selection content", use_selection_as_search_pattern<true> } }, { '*', "set search pattern to main selection content", use_selection_as_search_pattern<true> },
{ alt('*'), { "set search pattern to main selection content, do not detect words", use_selection_as_search_pattern<false> } }, { alt('*'), "set search pattern to main selection content, do not detect words", use_selection_as_search_pattern<false> },
{ 'u', { "undo", undo } }, { 'u', "undo", undo },
{ 'U', { "redo", redo } }, { 'U', "redo", redo },
{ alt('i'), { "select inner object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd | ObjectFlags::Inner> } }, { alt('i'), "select inner object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd | ObjectFlags::Inner> },
{ alt('a'), { "select whole object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd> } }, { alt('a'), "select whole object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd> },
{ '[', { "select to object start", select_object<ObjectFlags::ToBegin> } }, { '[', "select to object start", select_object<ObjectFlags::ToBegin> },
{ ']', { "select to object end", select_object<ObjectFlags::ToEnd> } }, { ']', "select to object end", select_object<ObjectFlags::ToEnd> },
{ '{', { "extend to object start", select_object<ObjectFlags::ToBegin, SelectMode::Extend> } }, { '{', "extend to object start", select_object<ObjectFlags::ToBegin, SelectMode::Extend> },
{ '}', { "extend to object end", select_object<ObjectFlags::ToEnd, SelectMode::Extend> } }, { '}', "extend to object end", select_object<ObjectFlags::ToEnd, SelectMode::Extend> },
{ alt('['), { "select to inner object start", select_object<ObjectFlags::ToBegin | ObjectFlags::Inner> } }, { alt('['), "select to inner object start", select_object<ObjectFlags::ToBegin | ObjectFlags::Inner> },
{ alt(']'), { "select to inner object end", select_object<ObjectFlags::ToEnd | ObjectFlags::Inner> } }, { alt(']'), "select to inner object end", select_object<ObjectFlags::ToEnd | ObjectFlags::Inner> },
{ alt('{'), { "extend to inner object start", select_object<ObjectFlags::ToBegin | ObjectFlags::Inner, SelectMode::Extend> } }, { alt('{'), "extend to inner object start", select_object<ObjectFlags::ToBegin | ObjectFlags::Inner, SelectMode::Extend> },
{ alt('}'), { "extend to inner object end", select_object<ObjectFlags::ToEnd | ObjectFlags::Inner, SelectMode::Extend> } }, { alt('}'), "extend to inner object end", select_object<ObjectFlags::ToEnd | ObjectFlags::Inner, SelectMode::Extend> },
{ alt('j'), { "join lines", join_lines } }, { alt('j'), "join lines", join_lines },
{ alt('J'), { "join lines and select spaces", join_lines_select_spaces } }, { alt('J'), "join lines and select spaces", join_lines_select_spaces },
{ alt('k'), { "keep selections matching given regex", keep<true> } }, { alt('k'), "keep selections matching given regex", keep<true> },
{ alt('K'), { "keep selections not matching given regex", keep<false> } }, { alt('K'), "keep selections not matching given regex", keep<false> },
{ '$', { "pipe each selection through shell command and keep the ones whose command succeed", keep_pipe } }, { '$', "pipe each selection through shell command and keep the ones whose command succeed", keep_pipe },
{ '<', { "deindent", deindent<true> } }, { '<', "deindent", deindent<true> },
{ '>', { "indent", indent<false> } }, { '>', "indent", indent<false> },
{ alt('>'), { "indent, including empty lines", indent<true> } }, { alt('>'), "indent, including empty lines", indent<true> },
{ alt('<'), { "deindent, not including incomplete indent", deindent<false> } }, { alt('<'), "deindent, not including incomplete indent", deindent<false> },
{ ctrl('i'), { "jump forward in jump list",jump<Forward> } }, { ctrl('i'), "jump forward in jump list",jump<Forward> },
{ ctrl('o'), { "jump backward in jump list", jump<Backward> } }, { ctrl('o'), "jump backward in jump list", jump<Backward> },
{ ctrl('s'), { "push current selections in jump list", save_selections } }, { ctrl('s'), "push current selections in jump list", save_selections },
{ alt('r'), { "rotate main selection", rotate_selections } }, { alt('r'), "rotate main selection", rotate_selections },
{ alt('R'), { "rotate selections content", rotate_selections_content } }, { alt('R'), "rotate selections content", rotate_selections_content },
{ 'q', { "replay recorded macro", replay_macro } }, { 'q', "replay recorded macro", replay_macro },
{ 'Q', { "start or end macro recording", start_or_end_macro_recording } }, { '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_char<to_lower> } }, { '`', "convert to lower case in selections", for_each_char<to_lower> },
{ '~', { "convert to upper case in selections", for_each_char<to_upper> } }, { '~', "convert to upper case in selections", for_each_char<to_upper> },
{ alt('`'), { "swap case in selections", for_each_char<swap_case> } }, { alt('`'), "swap case in selections", for_each_char<swap_case> },
{ '&', { "align selection cursors", align } }, { '&', "align selection cursors", align },
{ alt('&'), { "copy indentation", copy_indent } }, { alt('&'), "copy indentation", copy_indent },
{ '@', { "convert tabs to spaces in selections", tabs_to_spaces } }, { '@', "convert tabs to spaces in selections", tabs_to_spaces },
{ alt('@'), { "convert spaces to tabs in selections", spaces_to_tabs } }, { alt('@'), "convert spaces to tabs in selections", spaces_to_tabs },
{ 'C', { "copy selection on next lines", copy_selections_on_next_lines<Forward> } }, { 'C', "copy selection on next lines", copy_selections_on_next_lines<Forward> },
{ alt('C'), { "copy selection on previous lines", copy_selections_on_next_lines<Backward> } }, { alt('C'), "copy selection on previous lines", copy_selections_on_next_lines<Backward> },
{ ',', { "user mappings", exec_user_mappings } }, { ',', "user mappings", exec_user_mappings },
{ Key::Left, { "move left", move<CharCount, Backward> } }, { Key::Left, "move left", move<CharCount, Backward> },
{ Key::Down, { "move down", move<LineCount, Forward> } }, { Key::Down, "move down", move<LineCount, Forward> },
{ Key::Up, { "move up", move<LineCount, Backward> } }, { Key::Up, "move up", move<LineCount, Backward> },
{ Key::Right, { "move right", move<CharCount, Forward> } }, { Key::Right, "move right", move<CharCount, Forward> },
{ ctrl('b'), { "scroll one page up", scroll<Key::PageUp> } }, { ctrl('b'), "scroll one page up", scroll<Key::PageUp> },
{ ctrl('f'), { "scroll one page down", scroll<Key::PageDown> } }, { ctrl('f'), "scroll one page down", scroll<Key::PageDown> },
{ Key::PageUp, { "scroll one page up", scroll<Key::PageUp> } }, { Key::PageUp, "scroll one page up", scroll<Key::PageUp> },
{ Key::PageDown, { "scroll one page down", scroll<Key::PageDown> } }, { Key::PageDown, "scroll one page down", scroll<Key::PageDown> },
}; };
} }

View File

@ -18,12 +18,13 @@ struct NormalParams
struct NormalCmdDesc struct NormalCmdDesc
{ {
Key key;
StringView docstring; StringView docstring;
void (*func)(Context& context, NormalParams params); void (*func)(Context& context, NormalParams params);
}; };
using KeyMap = UnorderedMap<Key, NormalCmdDesc>; using KeyMap = Vector<NormalCmdDesc>;
extern const KeyMap keymap; extern KeyMap keymap;
} }