/* Dispatch actions according to program flags (NOT commands or * command options). */ static void cli_context_flag_dispatch (cli_context_t *ctx, gint in_argc, gchar **in_argv) { command_t *cmd; gboolean check; GOptionEntry 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. */ cmd = command_new (flagdefs, in_argc + 1, in_argv - 1); if (!cmd) { /* An error message has already been printed, so we just return. */ return; } if (command_flag_boolean_get (cmd, "help", &check) && check) { if (command_arg_count (cmd) >= 1) { help_command (ctx, cli_context_command_names (ctx), command_argv_get (cmd), command_arg_count (cmd), 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 (cmd, "version", &check) && check) { g_printf (_("XMMS2 CLI version " XMMS_VERSION "\n")); g_printf (_("Copyright (C) 2008-2014 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 (ctx, cli_context_command_names (ctx), in_argv, in_argc, CMD_TYPE_COMMAND); } command_free (cmd); }
gboolean cli_help (cli_context_t *ctx, command_t *cmd) { cmd_type_t cmdtype; GList *names; gint num_args; gboolean alias; num_args = command_arg_count (cmd); if (command_flag_boolean_get (cmd, "alias", &alias) && alias) { names = cli_context_alias_names (ctx); cmdtype = CMD_TYPE_ALIAS; } else { names = cli_context_command_names (ctx); cmdtype = CMD_TYPE_COMMAND; } /* No argument, display the list of commands */ if (num_args == 0) { help_list (names, NULL, cmdtype); } else { help_command (ctx, names, command_argv_get (cmd), num_args, cmdtype); } /* No data pending */ return FALSE; }
gboolean cli_jump (cli_context_t *ctx, command_t *cmd) { xmmsc_connection_t *conn = cli_context_xmms_sync (ctx); xmmsv_t *query; gboolean backward = FALSE; playlist_positions_t *positions; command_flag_boolean_get (cmd, "backward", &backward); /* Select by positions */ if (command_arg_positions_get (cmd, 0, &positions, cli_context_current_position (ctx))) { gint pos; if (playlist_positions_get_single (positions, &pos)) { XMMS_CALL_CHAIN (XMMS_CALL_P (xmmsc_playlist_set_next, conn, pos), XMMS_CALL_P (xmmsc_playback_tickle, conn)); } else { g_printf (_("Cannot jump to several positions!\n")); } playlist_positions_free (positions); /* Select by pattern */ } else if (command_arg_pattern_get (cmd, 0, &query, TRUE)) { query = xmmsv_coll_intersect_with_playlist (query, XMMS_ACTIVE_PLAYLIST); XMMS_CALL_CHAIN (XMMS_CALL_P (xmmsc_coll_query_ids, conn, query, NULL, 0, 0), FUNC_CALL_P (cli_jump_relative, ctx, (backward ? -1 : 1), XMMS_PREV_VALUE)); xmmsv_unref (query); } return FALSE; }
static void cli_context_command_dispatch (cli_context_t *ctx, gint in_argc, gchar **in_argv) { command_action_t *action; command_trie_match_type_t match; gint argc; gchar *tmp_argv[in_argc+1]; gchar **argv; /* The arguments will be updated by command_trie_find and * init_context_from_args, so we make a copy. */ memcpy (tmp_argv, in_argv, in_argc * sizeof (gchar *)); tmp_argv[in_argc] = NULL; argc = in_argc; argv = tmp_argv; /* This updates argv and argc so that they start at the first non-command * token. */ match = cli_context_find_command (ctx, &argv, &argc, &action); if (match == COMMAND_TRIE_MATCH_ACTION) { gboolean help; gboolean need_io; command_t *cmd; /* 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. */ cmd = command_new (action->argdefs, argc + 1, argv - 1); if (cmd) { if (command_flag_boolean_get (cmd, "help", &help) && help) { /* Help flag passed, bypass action and show help */ /* FIXME(g): select aliasnames list if it's an alias */ help_command (ctx, cli_context_command_names (ctx), in_argv, in_argc, CMD_TYPE_COMMAND); } else if (cli_context_command_runnable (ctx, action)) { /* All fine, run the command */ command_name_set (cmd, action->name); cli_context_loop_suspend (ctx); need_io = action->callback (ctx, cmd); if (!need_io) { cli_context_loop_resume (ctx); } } command_free (cmd); } } else { /* Call help to print the "no such command" error */ help_command (ctx, cli_context_command_names (ctx), in_argv, in_argc, CMD_TYPE_COMMAND); } }
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); } }
static gboolean cmd_flag_pos_get_playlist (cli_context_t *ctx, command_t *cmd, gint *pos, const gchar *playlist) { gboolean next, at_isset; gint at; gint tmp = -1; at_isset = command_flag_int_get (cmd, "at", &at); command_flag_boolean_get (cmd, "next", &next); if (next && at_isset) { g_printf (_("Error: --next and --at are mutually exclusive!\n")); return FALSE; } else if (next) { playlist_currpos_get (ctx, playlist, &tmp); if (tmp == -1) { /* no current position, next == append */ if (!playlist_length_get (ctx, playlist, pos)) { return FALSE; } } else { *pos = tmp + 1; } } else if (at_isset) { if (!playlist_length_get (ctx, playlist, &tmp)) { return FALSE; } if (at == 0 || (at > 0 && at > tmp + 1)) { g_printf (_("Error: specified position is outside the playlist!\n")); return FALSE; } else { *pos = at - 1; /* playlist ids start at 0 */ } } else { /* default to append */ playlist_length_get (ctx, playlist, pos); } return TRUE; }