aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-11-03 15:14:06 +0100
committerMarc André Tanner <mat@brain-dump.org>2017-11-04 14:57:14 +0100
commitf9cfc764dd501e7ef5517735d797cb5e430545c3 (patch)
tree42fc0222210e72f6e84dc496378171f1a2e7eb74
parent67abeacf796cf795795b9bb1bf29c738e75b5f51 (diff)
downloadvis-f9cfc764dd501e7ef5517735d797cb5e430545c3.tar.gz
vis-f9cfc764dd501e7ef5517735d797cb5e430545c3.tar.xz
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<Tab>`. Fix #624
-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);
}
}