vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

commit a9a003fb0496b178fe8f2e4561a6ad970c31ed82
parent 6bf3cfa47f7a09702693cd005eaa3760b7d24381
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Tue, 20 Dec 2016 22:07:50 +0100

vis: improve literal insertion via <C-v> in insert mode

Diffstat:
Mmain.c | 27++++++---------------------
Mvis.c | 42++++++++++++++++++++++++++++++++++++++++++
Mvis.h | 2++
3 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/main.c b/main.c @@ -1879,28 +1879,13 @@ static const char *insert_verbatim(Vis *vis, const char *keys, const Arg *arg) { const char *next = vis_keys_next(vis, keys); if (!next) return NULL; - size_t keylen = next - keys; - char key[keylen+1]; - memcpy(key, keys, keylen); - key[keylen] = '\0'; - - static const char *keysym[] = { - "<Enter>", "\n", - "<Tab>", "\t", - "<Backspace>", "\b", - "<Escape>", "\x1b", - "<DEL>", "\x7f", - NULL, - }; - - for (const char **k = keysym; k[0]; k += 2) { - if (strcmp(k[0], key) == 0) { - data = k[1]; - len = strlen(data); - keys = next; - break; - } + if ((rune = vis_keys_codepoint(vis, keys)) != (Rune)-1) { + len = runetochar(buf, &rune); + data = buf; + } else { + vis_info_show(vis, "Unknown key"); } + keys = next; } if (len > 0) diff --git a/vis.c b/vis.c @@ -865,6 +865,48 @@ const char *vis_keys_next(Vis *vis, const char *keys) { return keys; } +long vis_keys_codepoint(Vis *vis, const char *keys) { + long codepoint = -1; + const char *next; + TermKeyKey key; + TermKey *termkey = vis->ui->termkey_get(vis->ui); + + if (!keys[0]) + return -1; + if (keys[0] == '<' && !keys[1]) + return '<'; + + if (keys[0] == '<' && (next = termkey_strpkey(termkey, keys+1, &key, TERMKEY_FORMAT_VIM)) && *next == '>') + codepoint = (key.type == TERMKEY_TYPE_UNICODE) ? key.code.codepoint : -1; + else if ((next = termkey_strpkey(termkey, keys, &key, TERMKEY_FORMAT_VIM))) + codepoint = (key.type == TERMKEY_TYPE_UNICODE) ? key.code.codepoint : -1; + + if (codepoint != -1) { + if (key.modifiers == TERMKEY_KEYMOD_CTRL) + codepoint &= 0x1f; + return codepoint; + } + + if (!next || key.type != TERMKEY_TYPE_KEYSYM) + return -1; + + const int keysym[] = { + TERMKEY_SYM_ENTER, '\n', + TERMKEY_SYM_TAB, '\t', + TERMKEY_SYM_BACKSPACE, '\b', + TERMKEY_SYM_ESCAPE, 0x1b, + TERMKEY_SYM_DELETE, 0x7f, + 0, + }; + + for (const int *k = keysym; k[0]; k += 2) { + if (key.code.sym == k[0]) + return k[1]; + } + + return -1; +} + static void vis_keys_process(Vis *vis, size_t pos) { Buffer *buf = vis->keys; char *keys = buf->data + pos, *start = keys, *cur = keys, *end = keys; diff --git a/vis.h b/vis.h @@ -473,6 +473,8 @@ int vis_pipe_collect(Vis *vis, Filerange *range, const char *argv[], char **out, * following as will be processed by the input system. skips over special keys * such as <Enter> as well as pseudo keys registered via vis_action_register. */ const char *vis_keys_next(Vis*, const char *keys); +/* Tries to convert next symbolic key to a raw code point, returns -1 for unknown keys */ +long vis_keys_codepoint(Vis*, const char *keys); /* vis operates as a finite state machine (FSM), feeding keys from an input * queue (or a previously recorded macro) to key handling functions (see struct * KeyAction) which consume the input.