From f9cfc764dd501e7ef5517735d797cb5e430545c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Fri, 3 Nov 2017 15:14:06 +0100 Subject: vis: take symbolic keys into account when evaluating key prefixes Previously `ci<` would have no immediate effect because in operator pending mode `i<` was wrongly treated as a powwible prefix of `i`. Fix #624 --- vis.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/vis.c b/vis.c index b1b9002..edf3f0c 100644 --- a/vis.c +++ b/vis.c @@ -1113,6 +1113,26 @@ bool vis_keys_utf8(Vis *vis, const char *keys, char utf8[static UTFmax+1]) { return true; } +typedef struct { + Vis *vis; + size_t len; // length of the prefix + int count; // how many bindings can complete this prefix + bool angle_bracket; // does the prefix end with '<' +} PrefixCompletion; + +static bool isprefix(const char *key, void *value, void *data) { + PrefixCompletion *completion = data; + if (!completion->angle_bracket) { + completion->count++; + } else { + const char *start = key + completion->len; + const char *end = vis_keys_next(completion->vis, start); + if (end && start + 1 == end) + completion->count++; + } + return completion->count == 1; +} + static void vis_keys_process(Vis *vis, size_t pos) { Buffer *buf = &vis->input_queue; char *keys = buf->data + pos, *start = keys, *cur = keys, *end = keys, *binding_end = keys;; @@ -1143,12 +1163,18 @@ static void vis_keys_process(Vis *vis, size_t pos) { binding = match; binding_end = end; } - /* "<" is never treated as a prefix because it - * is used to denote special key symbols */ - if (strcmp(start, "<")) { - prefix = (!match && map_contains(mode->bindings, start)) || - (match && !map_leaf(mode->bindings, start)); - } + + const Map *pmap = map_prefix(mode->bindings, start); + PrefixCompletion completions = { + .vis = vis, + .len = cur - start, + .count = 0, + .angle_bracket = !strcmp(cur, "<"), + }; + map_iterate(pmap, isprefix, &completions); + + prefix = (!match && completions.count > 0) || + ( match && completions.count > 1); } } -- cgit v1.2.3