Commit 30bbacf8 authored by Andrew Price's avatar Andrew Price
Browse files

Implement tab completion for mw.command.foo

Also fix and simplify the implementation of mw.command

Fixes #34
parent 6663b8fc
Loading
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include "intl.h"
#include "userio.h"

#include "js.h"
#include "alias.h"
alias *alias_list = NULL;
alias *bind_list = NULL;
@@ -176,24 +177,33 @@ char *list_bind(const char *text, int state)
char *list_bind_rl(const char *text, int state)
{
	static alias *bind;
	static int js_idx;
	static int len;
	char		*name;
	char *completion;
	const char *name;

	if (state == 0)
	{
	if (state == 0) {
		bind = bind_list;
		js_idx = 0;
		len = strlen(text);
		len--;
	}

	text++;

	while (bind != NULL)
	{
	while (bind != NULL) {
		name = bind->from;
		bind = bind->next;
		if ((len == 0) || !strncasecmp(name, text, len))
			return dupstr(name, ",");
		if ((len == 0) || !strncasecmp(name, text, len)) {
			asprintf(&completion, ",%s", name);
			return completion;
		}
	}
	while ((name = js_command_name_get(js_idx++)) != NULL) {
		if ((len == 0) || !strncasecmp(name, text, len)) {
			asprintf(&completion, ",%s", name);
			return completion;
		}
	}
	return NULL;
}
+29 −48
Original line number Diff line number Diff line
@@ -1132,51 +1132,6 @@ static void define_store_object(const char *name)
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
}

static duk_ret_t js_command_get(duk_context *cx)
{
	const char *key = duk_get_string(cx, 1);

	duk_push_this(cx);
	(void)duk_get_prop_string(cx, -1, key);
	return 1;
}

static duk_ret_t js_command_set(duk_context *cx)
{
	(void)duk_require_string(cx, 1);
	duk_require_callable(cx, 2);

	duk_push_this(cx); /* Target object */
	duk_dup(cx, 1); /* Command name */
	duk_dup(cx, 2); /* Handler */
	duk_def_prop(cx, -3, DUK_DEFPROP_HAVE_VALUE|DUK_DEFPROP_SET_CONFIGURABLE);
	return 0;
}

static duk_ret_t js_command_has(duk_context *cx)
{
	const char *key = duk_get_string(cx, 1);

	duk_push_this(cx);
	return duk_has_prop_string(cx, -1, key);
}

static duk_ret_t js_command_delete(duk_context *cx)
{
	const char *key = duk_get_string(cx, 1);

	duk_push_this(cx);
	return duk_del_prop_string(cx, -1, key);
}

static const duk_function_list_entry command_handlers[] = {
	{ "get", js_command_get, 3 },
	{ "set", js_command_set, 4 },
	{ "has", js_command_has, 2 },
	{ "deleteProperty", js_command_delete, 2 },
	{ NULL, NULL, 0 }
};

/* The owning object must be at the top of the stack when calling this */
static void define_command_object(void)
{
@@ -1184,16 +1139,14 @@ static void define_command_object(void)
	duk_push_string(ctx, "command"); /* To be used by duk_def_prop() below */
	duk_push_object(ctx); /* command object */
	duk_push_object(ctx); /* Handler object */
	duk_put_function_list(ctx, -1, command_handlers);
	duk_push_proxy(ctx, 0); /* Stack is now [ "command", proxy ] */

	/* Define the command object in the parent object */
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
}

int js_handle_command(const char *name, int argc, const char **argv)
static int js_push_command_object(void)
{
	duk_require_stack(ctx, argc + 5);
	if (!duk_get_global_string(ctx, "mw")) {
		fprintf(stderr, "mwjs error: failed to lookup mw namespace\n");
		duk_pop(ctx);
@@ -1208,6 +1161,15 @@ int js_handle_command(const char *name, int argc, const char **argv)
		fprintf(stderr, "mwjs error: 'mw.command' is not an object\n");
		return -1;
	}
	return 0;
}

int js_handle_command(const char *name, int argc, const char **argv)
{
	duk_require_stack(ctx, argc + 5);
	if (js_push_command_object())
		return -1;

	if (!duk_get_prop_string(ctx, -1, name)) {
		duk_pop_3(ctx);
		return 1;
@@ -1228,6 +1190,25 @@ int js_handle_command(const char *name, int argc, const char **argv)
	return 0;
}

const char *js_command_name_get(int x)
{
	char *name = NULL;
	int i = 0;

	if (js_push_command_object())
		return NULL;

	duk_enum(ctx, -1, 0);
	while (name == NULL && duk_next(ctx, -1, 0)) {
		const char *str = duk_get_string(ctx, -1);
		if (i++ == x)
			name = strdup(str);
		duk_pop(ctx);
	}
	duk_pop(ctx);
	return name;
}

/* The owning object must be at the top of the stack when calling this */
static void define_func(const char *name, duk_c_function func, int nargs)
{
+2 −0
Original line number Diff line number Diff line
@@ -24,4 +24,6 @@ enum bindtype {
	K_BIND_INPUT
};

const char *js_command_name_get(int x);

#endif /* JS_H */