aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c2
-rw-r--r--vis-cmds.c25
-rw-r--r--vis-lua.c16
-rw-r--r--vis-modes.c54
-rw-r--r--vis-prompt.c12
-rw-r--r--vis.h9
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, "<Enter>", &prompt_enter_binding);
- vis_window_mode_map(prompt, VIS_MODE_INSERT, "<Enter>", &prompt_enter_binding);
- vis_window_mode_map(prompt, VIS_MODE_VISUAL, "<Enter>", &prompt_enter_binding);
- vis_window_mode_map(prompt, VIS_MODE_NORMAL, "<Escape>", &prompt_esc_binding);
- vis_window_mode_map(prompt, VIS_MODE_INSERT, "<Up>", &prompt_up_binding);
- vis_window_mode_map(prompt, VIS_MODE_INSERT, "<Backspace>", &prompt_backspace_binding);
+ vis_window_mode_map(prompt, VIS_MODE_NORMAL, true, "<Enter>", &prompt_enter_binding);
+ vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "<Enter>", &prompt_enter_binding);
+ vis_window_mode_map(prompt, VIS_MODE_VISUAL, true, "<Enter>", &prompt_enter_binding);
+ vis_window_mode_map(prompt, VIS_MODE_NORMAL, true, "<Escape>", &prompt_esc_binding);
+ vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "<Up>", &prompt_up_binding);
+ vis_window_mode_map(prompt, VIS_MODE_INSERT, true, "<Backspace>", &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);