static void vis_keys_process(Vis *vis) { Buffer *buf = vis->keys; char *keys = buf->data, *start = keys, *cur = keys, *end; bool prefix = false, unknown_key = false; KeyBinding *binding = NULL; vis->keyhandler = true; while (cur && *cur) { if (!(end = (char*)vis_keys_next(vis, cur))) { unknown_key = true; goto out; } char tmp = *end; *end = '\0'; prefix = false; binding = NULL; for (Mode *mode = vis->mode; mode && !binding && !prefix; mode = mode->parent) { for (int global = 0; global < 2 && !binding && !prefix; global++) { Mode *mode_local = global || !vis->win ? mode : &vis->win->modes[mode->id]; if (!mode_local->bindings) continue; binding = map_get(mode_local->bindings, start); /* "<" is never treated as a prefix because it is used to denote * special key symbols */ if (strcmp(cur, "<")) prefix = !binding && map_contains(mode_local->bindings, start); } } *end = tmp; if (binding) { /* exact match */ if (binding->action) { end = (char*)binding->action->func(vis, end, &binding->action->arg); if (!end) break; start = cur = end; } else if (binding->alias) { buffer_put0(buf, end); buffer_prepend0(buf, binding->alias); start = cur = buf->data; } } else if (prefix) { /* incomplete key binding? */ cur = end; } else { /* no keybinding */ KeyAction *action = NULL; if (start[0] == '<' && end[-1] == '>') { /* test for special editor key command */ char tmp = end[-1]; end[-1] = '\0'; action = map_get(vis->actions, start+1); end[-1] = tmp; if (action) { end = (char*)action->func(vis, end, &action->arg); if (!end) break; } } if (!action && vis->mode->input) vis->mode->input(vis, start, end - start); start = cur = end; } } out: if (unknown_key) buffer_truncate(buf); else buffer_put0(buf, start); vis->keyhandler = false; }
static const char *vis_keys_raw(Vis *vis, Buffer *buf, const char *input) { char *keys = buf->data, *start = keys, *cur = keys, *end; bool prefix = false; KeyBinding *binding = NULL; while (cur && *cur) { if (!(end = (char*)vis_keys_next(vis, cur))) goto err; // XXX: can't parse key this should never happen char tmp = *end; *end = '\0'; prefix = false; binding = NULL; for (Mode *mode = vis->mode; mode && !binding && !prefix; mode = mode->parent) { for (int global = 0; global < 2 && !binding && !prefix; global++) { Mode *mode_local = global ? mode : &vis->win->modes[mode->id]; if (!mode_local->bindings) continue; binding = map_get(mode_local->bindings, start); /* "<" is never treated as a prefix because it is used to denote * special key symbols */ if (strcmp(cur, "<")) prefix = !binding && map_contains(mode_local->bindings, start); } } *end = tmp; vis->keys = buf; if (binding) { /* exact match */ if (binding->action) { end = (char*)binding->action->func(vis, end, &binding->action->arg); if (!end) break; start = cur = end; } else if (binding->alias) { buffer_put0(buf, end); buffer_prepend0(buf, binding->alias); start = cur = buf->data; } } else if (prefix) { /* incomplete key binding? */ cur = end; } else { /* no keybinding */ KeyAction *action = NULL; if (start[0] == '<' && end[-1] == '>') { /* test for special editor key command */ char tmp = end[-1]; end[-1] = '\0'; action = map_get(vis->actions, start+1); end[-1] = tmp; if (action) { end = (char*)action->func(vis, end, &action->arg); if (!end) break; } } if (!action && vis->mode->input) vis->mode->input(vis, start, end - start); start = cur = end; } } vis->keys = NULL; buffer_put0(buf, start); return input + (start - keys); err: vis->keys = NULL; buffer_truncate(buf); return input + strlen(input); }