예제 #1
0
파일: vis.c 프로젝트: ewqasd200g/vis
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;
}
예제 #2
0
파일: vis.c 프로젝트: tycho/vis
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);
}