void buffer_truncate_ts (Buffer* buffer) { assert(NULL != buffer); assert(NULL != buffer->mutex); pthread_mutex_lock(buffer->mutex); buffer_truncate(buffer); pthread_mutex_unlock(buffer->mutex); }
void vis_keys_feed(Vis *vis, const char *input) { if (!input) return; if (vis->recording) macro_append(vis->recording, input); if (vis->macro_operator) macro_append(vis->macro_operator, input); if (!buffer_append0(vis->keys, input)) buffer_truncate(vis->keys); /* if we are being called from within a keyhandler then appending * the new keys to the end of the input queue is enough. they will * be interpreted once the key handler returns and control reaches * back to the vis_keys_process function. */ if (!vis->keyhandler) vis_keys_process(vis); }
const char *vis_keys_push(Vis *vis, const char *input) { if (!input) return NULL; if (vis->recording) macro_append(vis->recording, input); if (vis->macro_operator) macro_append(vis->macro_operator, input); if (!buffer_append0(&vis->input_queue, input)) { buffer_truncate(&vis->input_queue); return NULL; } return vis_keys_raw(vis, &vis->input_queue, input); }
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); }