diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2015-10-14 23:00:47 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2015-10-14 23:17:15 +0200 |
| commit | 632b5909af96861c881865afae8638a2fd072668 (patch) | |
| tree | 22c745db9a95d6a8c999f0026a3d2e2301d95100 | |
| parent | fc8b564ab2a58cf5dd19dcaabd460b65bd5d444c (diff) | |
| download | vis-632b5909af96861c881865afae8638a2fd072668.tar.gz vis-632b5909af96861c881865afae8638a2fd072668.tar.xz | |
vis: introduce special keys which allow mappings to editor actions
Key bindings in vis are always recursive, hence mapping ~
to ~l will cause an infinite loop.
Instead vis supports special editor "keys" which map to
internal editor functions.
As an example one can thus map ~ to <vis-operator-case-swap>l
or even <vis-operator-case-swap><cursor-char-next>
Furthermore this makes it possible to completely unmap core
editor features such as operators, the corresponding funtionality
is still available via its corresponding special key.
| -rw-r--r-- | editor.c | 9 | ||||
| -rw-r--r-- | editor.h | 3 | ||||
| -rw-r--r-- | vis.c | 33 |
3 files changed, 44 insertions, 1 deletions
@@ -252,6 +252,14 @@ bool editor_mode_unmap(Mode *mode, const char *name) { return map_delete(mode->bindings, name); } +bool editor_action_register(Editor *ed, KeyAction *action) { + if (!ed->actions) + ed->actions = map_new(); + if (!ed->actions) + return false; + return map_put(ed->actions, action->name, action); +} + static void window_free(Win *win) { if (!win) return; @@ -430,6 +438,7 @@ void editor_free(Editor *ed) { ed->ui->free(ed->ui); map_free(ed->cmds); map_free(ed->options); + map_free(ed->actions); buffer_release(&ed->buffer_repeat); free(ed); } @@ -253,6 +253,7 @@ struct Editor { volatile sig_atomic_t cancel_filter; /* abort external command */ volatile sig_atomic_t sigbus; sigjmp_buf sigbus_jmpbuf; + Map *actions; /* built in special editor keys / commands */ }; Editor *editor_new(Ui*); @@ -266,6 +267,8 @@ bool editor_mode_bindings(Mode*, KeyBinding**); bool editor_mode_map(Mode*, const char *name, KeyBinding*); bool editor_mode_unmap(Mode*, const char *name); +bool editor_action_register(Editor*, KeyAction*); + /* these function operate on the currently focused window but make sure * that all windows which show the affected region are redrawn too. */ void editor_insert_key(Editor*, const char *data, size_t len); @@ -2600,6 +2600,18 @@ static const char *keynext(const char *keys) { /* first try to parse a special key of the form <Key> */ if (*keys == '<' && (next = termkey_strpkey(termkey, keys+1, &key, TERMKEY_FORMAT_VIM)) && *next == '>') return next+1; + if (*keys == '<') { + const char *start = keys + 1, *end = start; + while (*end && *end != '>') + end++; + if (end > start && end - start - 1 < 64 && *end == '>') { + char key[64]; + memcpy(key, start, end - start); + key[end - start] = '\0'; + if (map_get(vis->actions, key)) + return end + 1; + } + } while (!ISUTF8(*keys)) keys++; return termkey_strpkey(termkey, keys, &key, TERMKEY_FORMAT_VIM); @@ -2655,7 +2667,20 @@ static const char *keypress(const char *input) { } else if (prefix) { /* incomplete key binding? */ cur = end; } else { /* no keybinding */ - if (vis->mode->input) + KeyAction *action = NULL; + if (start[0] == '<' && end[-1] == '>') { + /* test for special editor key command */ + char tmp = end[-1]; + end[-1] = '\0'; + action = map_get(vis->actions, start+1); + end[-1] = tmp; + if (action) { + end = (char*)action->func(end, &action->arg); + if (!end) + break; + } + } + if (!action && vis->mode->input) vis->mode->input(start, end - start); start = cur = end; } @@ -2780,6 +2805,12 @@ int main(int argc, char *argv[]) { if (!editor_syntax_load(vis, syntaxes)) die("Could not load syntax highlighting definitions\n"); + for (int i = 0; i < LENGTH(vis_action); i++) { + KeyAction *action = &vis_action[i]; + if (!editor_action_register(vis, action)) + die("Could not register action: %s\n", action->name); + } + char *cmd = NULL; bool end_of_options = false; for (int i = 1; i < argc; i++) { |
