diff options
| -rw-r--r-- | vis.c | 38 |
1 files changed, 32 insertions, 6 deletions
@@ -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); } } |
