Пример #1
0
/* Dispatch actions according to program flags (NOT commands or
 * command options).
 */
void
flag_dispatch (cli_infos_t *infos, gint in_argc, gchar **in_argv)
{
	command_context_t *ctx;
	gboolean check;

	argument_t flagdefs[] = {
		{ "help",    'h', 0, G_OPTION_ARG_NONE, NULL,
		             _("Display this help and exit."), NULL },
		{ "version", 'v', 0, G_OPTION_ARG_NONE, NULL,
		             _("Output version information and exit."), NULL },
		{ NULL }
	};

	/* Include one command token as a workaround for the bug that
	 * the option parser does not parse commands starting with a
	 * flag properly (e.g. "-p foo arg1"). Will be skipped by the
	 * command utils. */
	ctx = init_context_from_args (flagdefs, in_argc + 1, in_argv - 1);

	if (!ctx) {
		/* An error message has already been printed, so we just return. */
		return;
	}

	if (command_flag_boolean_get (ctx, "help", &check) && check) {
		if (ctx->argc > 1) {
			help_command (infos, infos->cmdnames, ctx->argv + 1, ctx->argc - 1,
			              CMD_TYPE_COMMAND);
		} else {
			/* FIXME: explain -h and -v flags here (reuse help_command code?) */
			g_printf (_("usage: xmms2 [<command> [args]]\n\n"));
			g_printf (_("XMMS2 CLI, the awesome command-line XMMS2 client from the future, "
			          "v" XMMS_VERSION ".\n\n"));
			g_printf (_("If given a command, runs it inline and exit.\n"));
			g_printf (_("If not, enters a shell-like interface to execute commands.\n\n"));
			g_printf (_("Type 'help <command>' for detailed help about a command.\n"));
		}
	} else if (command_flag_boolean_get (ctx, "version", &check) && check) {
		g_printf (_("XMMS2 CLI version " XMMS_VERSION "\n"));
		g_printf (_("Copyright (C) 2008 XMMS2 Team\n"));
		g_printf (_("This is free software; see the source for copying conditions.\n"));
		g_printf (_("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
		          "PARTICULAR PURPOSE.\n"));
		/* FIXME: compiled against? use RL_READLINE_VERSION? */
		g_printf (_(" Using readline version %s\n"), rl_library_version);
	} else {
		/* Call help to print the "no such command" error */
		/* FIXME: Could be a more helpful "invalid flag"?*/
		help_command (infos, infos->cmdnames, in_argv, in_argc, CMD_TYPE_COMMAND);
	}

	command_context_free (ctx);
}
Пример #2
0
void
command_dispatch (cli_infos_t *infos, gint in_argc, gchar **in_argv)
{
	command_action_t *action;
	command_trie_match_type_t match;
	gint argc;
	gchar **argv;

	gboolean auto_complete;

	/* The arguments will be updated by command_trie_find. */
	argc = in_argc;
	argv = in_argv;
	auto_complete = configuration_get_boolean (infos->config,
	                                           "AUTO_UNIQUE_COMPLETE");
	match = command_trie_find (infos->commands, &argv, &argc,
	                            auto_complete, &action);

	if (match == COMMAND_TRIE_MATCH_ACTION) {

		gboolean help;
		gboolean need_io;
		command_context_t *ctx;

		/* Include one command token as a workaround for the bug that
		 * the option parser does not parse commands starting with a
		 * flag properly (e.g. "-p foo arg1"). Will be skipped by the
		 * command utils. */
		ctx = init_context_from_args (action->argdefs, argc + 1, argv - 1);
		ctx->name = g_strdup (action->name);

		if (command_flag_boolean_get (ctx, "help", &help) && help) {
			/* Help flag passed, bypass action and show help */
			/* FIXME(g): select aliasnames list if it's an alias */
			help_command (infos, infos->cmdnames, in_argv, in_argc, CMD_TYPE_COMMAND);
		} else if (command_runnable (infos, action)) {
			/* All fine, run the command */
			cli_infos_loop_suspend (infos);
			need_io = action->callback (infos, ctx);
			if (!need_io) {
				cli_infos_loop_resume (infos);
			}
		}

		command_context_free (ctx);
	} else {
		/* Call help to print the "no such command" error */
		help_command (infos, infos->cmdnames, in_argv, in_argc, CMD_TYPE_COMMAND);
	}
}
Пример #3
0
/* Parse the argv array with GOptionContext, using the given argument
 * definitions, and return a command context structure containing
 * argument values.
 * Note: The lib doesn't like argv starting with a flag, so keep a
 * token before that to avoid problems.
 *
 * The passed argv should be an array of length argc+1. (So that a terminating
 * NULL-pointer can be added in argv[argc].)
 */
static command_context_t *
init_context_from_args (argument_t *argdefs, gint argc, gchar **argv)
{
	command_context_t *ctx;
	GOptionContext *context;
	GError *error = NULL;
	gint i;

	ctx = command_context_init (argc, argv);

	for (i = 0; argdefs && argdefs[i].long_name; ++i) {
		command_argument_t *arg = g_new (command_argument_t, 1);

		switch (argdefs[i].arg) {
		case G_OPTION_ARG_NONE:
			arg->type = COMMAND_ARGUMENT_TYPE_BOOLEAN;
			arg->value.vbool = FALSE;
			argdefs[i].arg_data = &arg->value.vbool;
			break;

		case G_OPTION_ARG_INT:
			arg->type = COMMAND_ARGUMENT_TYPE_INT;
			arg->value.vint = -1;
			argdefs[i].arg_data = &arg->value.vint;
			break;

		case G_OPTION_ARG_STRING:
			arg->type = COMMAND_ARGUMENT_TYPE_STRING;
			arg->value.vstring = NULL;
			argdefs[i].arg_data = &arg->value.vstring;
			break;

		case G_OPTION_ARG_STRING_ARRAY:
			arg->type = COMMAND_ARGUMENT_TYPE_STRING_ARRAY;
			arg->value.vstringv = NULL;
			argdefs[i].arg_data = &arg->value.vstringv;
			break;

		default:
			g_printf (_("Trying to register a flag '%s' of invalid type!"),
			          argdefs[i].long_name);
			break;
		}

		g_hash_table_insert (ctx->flags,
		                     g_strdup (argdefs[i].long_name), arg);
	}

	context = g_option_context_new (NULL);
	g_option_context_set_help_enabled (context, FALSE);  /* runs exit(0)! */
	g_option_context_set_ignore_unknown_options (context, TRUE);
	g_option_context_add_main_entries (context, argdefs, NULL);
	g_option_context_parse (context, &ctx->argc, &ctx->argv, &error);
	g_option_context_free (context);

	if (error) {
		g_printf (_("Error: %s\n"), error->message);
		g_error_free (error);
		command_context_free (ctx);
		return NULL;
	}

	/* strip --, check for unknown options before it */
	/* FIXME: We do not parse options elsewhere, do we? */
	for (i = 0; i < ctx->argc; i++) {
		if (strcmp (ctx->argv[i], "--") == 0) {
			break;
		}
		if (ctx->argv[i][0] == '-' && ctx->argv[i][1] != '\0' &&
		    !(ctx->argv[i][1] >= '0' && ctx->argv[i][1] <= '9')) {

			g_printf (_("Error: Unknown option '%s'\n"), ctx->argv[i]);
			command_context_free (ctx);
			return NULL;
		}
	}
	if (i != ctx->argc) {
		for (i++; i < ctx->argc; i++) {
			argv[i-1] = argv[i];
		}
		ctx->argc--;
	}

	/* Some functions rely on NULL-termination. */
	ctx->argv[ctx->argc] = NULL;
	return ctx;
}