aboutsummaryrefslogtreecommitdiff
path: root/vis.c
diff options
context:
space:
mode:
Diffstat (limited to 'vis.c')
-rw-r--r--vis.c38
1 files 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);
}
}