From 632b5909af96861c881865afae8638a2fd072668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Wed, 14 Oct 2015 23:00:47 +0200 Subject: 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 l or even 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. --- editor.c | 9 +++++++++ editor.h | 3 +++ vis.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/editor.c b/editor.c index c07eed7..4484b0a 100644 --- a/editor.c +++ b/editor.c @@ -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); } diff --git a/editor.h b/editor.h index 87d9aeb..e7b5f0a 100644 --- a/editor.h +++ b/editor.h @@ -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); diff --git a/vis.c b/vis.c index 5057ab9..c4fbc29 100644 --- a/vis.c +++ b/vis.c @@ -2600,6 +2600,18 @@ static const char *keynext(const char *keys) { /* first try to parse a special key of the form */ 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++) { -- cgit v1.2.3