From a1881512f3050e8d6719a28b55846c1f4c93acab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Fri, 13 May 2016 23:13:52 +0200 Subject: vis: clean up key mapping implementation --- main.c | 2 +- vis-cmds.c | 25 ++++--------------------- vis-lua.c | 16 +--------------- vis-modes.c | 54 ++++++++++++++++++++++++++++++++++-------------------- vis-prompt.c | 12 ++++++------ vis.h | 9 +++++---- 6 files changed, 51 insertions(+), 67 deletions(-) diff --git a/main.c b/main.c index 3a7f831..d0c0c73 100644 --- a/main.c +++ b/main.c @@ -2125,7 +2125,7 @@ int main(int argc, char *argv[]) { for (int i = 0; i < LENGTH(default_bindings); i++) { for (const KeyBinding **binding = default_bindings[i]; binding && *binding; binding++) { for (const KeyBinding *kb = *binding; kb->key; kb++) { - vis_mode_map(vis, i, kb->key, kb); + vis_mode_map(vis, i, false, kb->key, kb); } } } diff --git a/vis-cmds.c b/vis-cmds.c index e52072d..92ba417 100644 --- a/vis-cmds.c +++ b/vis-cmds.c @@ -755,36 +755,19 @@ static bool cmd_map(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor return false; } - char *lhs = strdup(argv[2]); + const char *lhs = argv[2]; char *rhs = strdup(argv[3]); - if (!lhs || !rhs || !(binding = calloc(1, sizeof *binding))) + if (!rhs || !(binding = calloc(1, sizeof *binding))) goto err; - char *next = lhs; - while (cmd->flags == '!' && next) { - char tmp; - next = (char*)vis_keys_next(vis, next); - if (next) { - tmp = *next; - *next = '\0'; - } - if (local) - vis_window_mode_unmap(win, mode, lhs); - else - vis_mode_unmap(vis, mode, lhs); - if (next) - *next = tmp; - } - binding->alias = rhs; if (local) - mapped = vis_window_mode_map(win, mode, lhs, binding); + mapped = vis_window_mode_map(win, mode, cmd->flags == '!', lhs, binding); else - mapped = vis_mode_map(vis, mode, lhs, binding); + mapped = vis_mode_map(vis, mode, cmd->flags == '!', lhs, binding); err: - free(lhs); if (!mapped) { free(rhs); free(binding); diff --git a/vis-lua.c b/vis-lua.c index a5a28d8..18259ef 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -410,21 +410,7 @@ static int map(lua_State *L) { binding->action = action; - char *lhs = strdup(key), *next = lhs; - while (next) { - char tmp; - next = (char*)vis_keys_next(vis, next); - if (next) { - tmp = *next; - *next = '\0'; - } - vis_mode_unmap(vis, mode, lhs); - if (next) - *next = tmp; - } - free(lhs); - - if (!vis_mode_map(vis, mode, key, binding)) + if (!vis_mode_map(vis, mode, true, key, binding)) goto err; lua_pushboolean(L, true); diff --git a/vis-modes.c b/vis-modes.c index 62a9541..ad866f7 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -25,37 +25,51 @@ void vis_mode_switch(Vis *vis, enum VisMode mode) { mode_set(vis, &vis_modes[mode]); } -static bool mode_map(Mode *mode, const char *key, const KeyBinding *binding) { +static bool mode_unmap(Mode *mode, const char *key) { + return mode && mode->bindings && map_delete(mode->bindings, key); +} + +bool vis_mode_unmap(Vis *vis, enum VisMode id, const char *key) { + return id < LENGTH(vis_modes) && mode_unmap(&vis_modes[id], key); +} + +bool vis_window_mode_unmap(Win *win, enum VisMode id, const char *key) { + return id < LENGTH(win->modes) && mode_unmap(&win->modes[id], key); +} + +static bool mode_map(Vis *vis, Mode *mode, bool force, const char *key, const KeyBinding *binding) { if (!mode) return false; if (binding->alias && key[0] != '<' && strncmp(key, binding->alias, strlen(key)) == 0) return false; - if (!mode->bindings) { - mode->bindings = map_new(); - if (!mode->bindings) + if (!mode->bindings && !(mode->bindings = map_new())) + return false; + if (force) { + char *lhs = strdup(key), *next = lhs; + if (!lhs) return false; + while (next) { + char tmp; + next = (char*)vis_keys_next(vis, next); + if (next) { + tmp = *next; + *next = '\0'; + } + mode_unmap(mode, lhs); + if (next) + *next = tmp; + } + free(lhs); } return (strcmp(key, "<") == 0 || !map_contains(mode->bindings, key)) && map_put(mode->bindings, key, binding); } -bool vis_mode_map(Vis *vis, enum VisMode id, const char *key, const KeyBinding *binding) { - return id < LENGTH(vis_modes) && mode_map(&vis_modes[id], key, binding); +bool vis_mode_map(Vis *vis, enum VisMode id, bool force, const char *key, const KeyBinding *binding) { + return id < LENGTH(vis_modes) && mode_map(vis, &vis_modes[id], force, key, binding); } -bool vis_window_mode_map(Win *win, enum VisMode id, const char *key, const KeyBinding *binding) { - return id < LENGTH(win->modes) && mode_map(&win->modes[id], key, binding); -} - -static bool mode_unmap(Mode *mode, const char *key) { - return mode && mode->bindings && map_delete(mode->bindings, key); -} - -bool vis_mode_unmap(Vis *vis, enum VisMode id, const char *key) { - return id < LENGTH(vis_modes) && mode_unmap(&vis_modes[id], key); -} - -bool vis_window_mode_unmap(Win *win, enum VisMode id, const char *key) { - return id < LENGTH(win->modes) && mode_unmap(&win->modes[id], key); +bool vis_window_mode_map(Win *win, enum VisMode id, bool force, const char *key, const KeyBinding *binding) { + return id < LENGTH(win->modes) && mode_map(win->vis, &win->modes[id], force, key, binding); } /** mode switching event handlers */ diff --git a/vis-prompt.c b/vis-prompt.c index 01dc916..8f7e1a9 100644 --- a/vis-prompt.c +++ b/vis-prompt.c @@ -165,12 +165,12 @@ void vis_prompt_show(Vis *vis, const char *title) { view_draw(prompt->view); prompt->parent = active; prompt->parent_mode = vis->mode; - vis_window_mode_map(prompt, VIS_MODE_NORMAL, "", &prompt_enter_binding); - vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_enter_binding); - vis_window_mode_map(prompt, VIS_MODE_VISUAL, "", &prompt_enter_binding); - vis_window_mode_map(prompt, VIS_MODE_NORMAL, "", &prompt_esc_binding); - vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_up_binding); - vis_window_mode_map(prompt, VIS_MODE_INSERT, "", &prompt_backspace_binding); + vis_window_mode_map(prompt, VIS_MODE_NORMAL, true, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_VISUAL, true, "", &prompt_enter_binding); + vis_window_mode_map(prompt, VIS_MODE_NORMAL, true, "", &prompt_esc_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "", &prompt_up_binding); + vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "", &prompt_backspace_binding); vis_mode_switch(vis, VIS_MODE_INSERT); vis_draw(vis); } diff --git a/vis.h b/vis.h index b751063..ab7eade 100644 --- a/vis.h +++ b/vis.h @@ -132,10 +132,11 @@ enum VisMode { }; void vis_mode_switch(Vis*, enum VisMode); -/* in the specified mode: map a given key to a binding (binding->key is ignored), - * fails if key is already mapped */ -bool vis_mode_map(Vis*, enum VisMode, const char *key, const KeyBinding*); -bool vis_window_mode_map(Win*, enum VisMode, const char *key, const KeyBinding*); +/* In the specified mode: map a given key to a binding (binding->key is ignored). + * Fails if a prefix of `key' is already mapped and `force' is false. Otherwise + * all such prefixes are unmapped. */ +bool vis_mode_map(Vis*, enum VisMode, bool force, const char *key, const KeyBinding*); +bool vis_window_mode_map(Win*, enum VisMode, bool force, const char *key, const KeyBinding*); /* in the specified mode: unmap a given key, fails if the key is not currently mapped */ bool vis_mode_unmap(Vis*, enum VisMode, const char *key); bool vis_window_mode_unmap(Win*, enum VisMode, const char *key); -- cgit v1.2.3