diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2016-01-13 10:12:38 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2016-01-13 21:38:20 +0100 |
| commit | d81c8d760848899dccd6f1a7e47cedb8c3afb0bf (patch) | |
| tree | 3ae0e1b45639968f9b55c1f80cd94f8134544774 | |
| parent | 2c0d472e87625000c71626fc965e7d1060f4ac7d (diff) | |
| download | vis-d81c8d760848899dccd6f1a7e47cedb8c3afb0bf.tar.gz vis-d81c8d760848899dccd6f1a7e47cedb8c3afb0bf.tar.xz | |
vis: add infrastructure to support per window key bindings
| -rw-r--r-- | vis-core.h | 1 | ||||
| -rw-r--r-- | vis-modes.c | 33 | ||||
| -rw-r--r-- | vis.c | 32 | ||||
| -rw-r--r-- | vis.h | 2 |
4 files changed, 52 insertions, 16 deletions
@@ -119,6 +119,7 @@ struct Win { View *view; /* currently displayed part of underlying text */ RingBuffer *jumplist; /* LRU jump management */ ChangeList changelist; /* state for iterating through least recently changes */ + Mode modes[VIS_MODE_LAST]; /* overlay mods used for per window key bindings */ Win *prev, *next; /* neighbouring windows */ }; diff --git a/vis-modes.c b/vis-modes.c index 8e245a3..0b85ed7 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -20,14 +20,35 @@ void mode_set(Vis *vis, Mode *new_mode) { vis->win->ui->draw_status(vis->win->ui); } -bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *key, const KeyBinding *binding) { - Mode *mode = mode_get(vis, modeid); - return mode && map_put(mode->bindings, key, binding); +static bool mode_map(Mode *mode, const char *key, const KeyBinding *binding) { + if (!mode) + return false; + if (!mode->bindings) { + mode->bindings = map_new(); + if (!mode->bindings) + return false; + } + return 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_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_mode_unmap(Vis *vis, enum VisMode modeid, const char *key) { - Mode *mode = mode_get(vis, modeid); - return mode && map_delete(mode->bindings, 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); } /** mode switching event handlers */ @@ -150,6 +150,8 @@ static void window_free(Win *win) { if (vis && vis->ui) vis->ui->window_free(win->ui); view_free(win->view); + for (size_t i = 0; i < LENGTH(win->modes); i++) + map_free(win->modes[i].bindings); ringbuf_free(win->jumplist); free(win); } @@ -174,6 +176,8 @@ static Win *window_new_file(Vis *vis, File *file) { vis->windows = win; vis->win = win; vis->ui->window_focus(win->ui); + for (size_t i = 0; i < LENGTH(win->modes); i++) + win->modes[i].parent = &vis_modes[i]; if (vis->event && vis->event->win_open) vis->event->win_open(vis, win); return win; @@ -199,6 +203,12 @@ bool vis_window_split(Win *original) { Win *win = window_new_file(original->vis, original->file); if (!win) return false; + for (size_t i = 0; i < LENGTH(win->modes); i++) { + if (original->modes[i].bindings) + win->modes[i].bindings = map_new(); + if (win->modes[i].bindings) + map_copy(win->modes[i].bindings, original->modes[i].bindings); + } win->file = original->file; win->file->refcount++; view_syntax_set(win->view, view_syntax_get(original->view)); @@ -296,11 +306,6 @@ Vis *vis_new(Ui *ui, VisEvent *event) { vis->ui->init(vis->ui, vis); vis->tabwidth = 8; vis->expandtab = false; - for (int i = 0; i < VIS_MODE_LAST; i++) { - Mode *mode = &vis_modes[i]; - if (!(mode->bindings = map_new())) - goto err; - } if (!(vis->prompt = calloc(1, sizeof(Win)))) goto err; if (!(vis->prompt->file = calloc(1, sizeof(File)))) @@ -341,10 +346,8 @@ void vis_free(Vis *vis) { map_free(vis->options); map_free(vis->actions); buffer_release(&vis->input_queue); - for (int i = 0; i < VIS_MODE_LAST; i++) { - Mode *mode = &vis_modes[i]; - map_free(mode->bindings); - } + for (int i = 0; i < VIS_MODE_LAST; i++) + map_free(vis_modes[i].bindings); free(vis); } @@ -694,7 +697,16 @@ static const char *vis_keys_raw(Vis *vis, Buffer *buf, const char *input) { prefix = false; binding = NULL; - for (Mode *mode = vis->mode; mode && !binding && !prefix; mode = mode->parent) { + Mode *mode = vis->mode; + for (size_t i = 0; i < LENGTH(vis->win->modes); i++) { + if (mode == &vis_modes[i]) { + if (vis->win->modes[i].bindings) + mode = &vis->win->modes[i]; + break; + } + } + + for (; mode && !binding && !prefix; mode = mode->parent) { binding = map_get(mode->bindings, start); /* "<" is never treated as a prefix because it is used to denote * special key symbols */ @@ -134,8 +134,10 @@ 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: 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); /* get the current mode's status line indicator */ const char *vis_mode_status(Vis*); /* associates the special pseudo key <keyaction->name> with the given key action. |
