mirror of
https://github.com/tmux/tmux.git
synced 2024-12-25 02:48:47 +00:00
Validate command argument types (string or command list) and give more
useful error messages.
This commit is contained in:
parent
c6d6af4903
commit
03d173cbd8
85
arguments.c
85
arguments.c
@ -124,10 +124,11 @@ args_create(void)
|
|||||||
/* Parse arguments into a new argument set. */
|
/* Parse arguments into a new argument set. */
|
||||||
struct args *
|
struct args *
|
||||||
args_parse(const struct args_parse *parse, struct args_value *values,
|
args_parse(const struct args_parse *parse, struct args_value *values,
|
||||||
u_int count)
|
u_int count, char **cause)
|
||||||
{
|
{
|
||||||
struct args *args;
|
struct args *args;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
enum args_parse_type type;
|
||||||
struct args_value *value, *new;
|
struct args_value *value, *new;
|
||||||
u_char flag, argument;
|
u_char flag, argument;
|
||||||
const char *found, *string, *s;
|
const char *found, *string, *s;
|
||||||
@ -153,11 +154,13 @@ args_parse(const struct args_parse *parse, struct args_value *values,
|
|||||||
if (flag == '\0')
|
if (flag == '\0')
|
||||||
break;
|
break;
|
||||||
if (!isalnum(flag)) {
|
if (!isalnum(flag)) {
|
||||||
|
xasprintf(cause, "invalid flag -%c", flag);
|
||||||
args_free(args);
|
args_free(args);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
found = strchr(parse->template, flag);
|
found = strchr(parse->template, flag);
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
|
xasprintf(cause, "unknown flag -%c", flag);
|
||||||
args_free(args);
|
args_free(args);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -167,12 +170,22 @@ args_parse(const struct args_parse *parse, struct args_value *values,
|
|||||||
args_set(args, flag, NULL);
|
args_set(args, flag, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
new = xcalloc(1, sizeof *value);
|
new = xcalloc(1, sizeof *new);
|
||||||
if (*string != '\0') {
|
if (*string != '\0') {
|
||||||
new->type = ARGS_STRING;
|
new->type = ARGS_STRING;
|
||||||
new->string = xstrdup(string);
|
new->string = xstrdup(string);
|
||||||
} else {
|
} else {
|
||||||
if (i == count) {
|
if (i == count) {
|
||||||
|
xasprintf(cause,
|
||||||
|
"-%c expects an argument",
|
||||||
|
flag);
|
||||||
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (values[i].type != ARGS_STRING) {
|
||||||
|
xasprintf(cause,
|
||||||
|
"-%c argument must be a string",
|
||||||
|
flag);
|
||||||
args_free(args);
|
args_free(args);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -192,14 +205,60 @@ args_parse(const struct args_parse *parse, struct args_value *values,
|
|||||||
s = args_value_as_string(value);
|
s = args_value_as_string(value);
|
||||||
log_debug("%s: %u = %s", __func__, i, s);
|
log_debug("%s: %u = %s", __func__, i, s);
|
||||||
|
|
||||||
|
if (parse->cb != NULL) {
|
||||||
|
type = parse->cb(args, args->count, cause);
|
||||||
|
if (type == ARGS_PARSE_INVALID) {
|
||||||
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
type = ARGS_PARSE_STRING;
|
||||||
|
|
||||||
args->values = xrecallocarray(args->values,
|
args->values = xrecallocarray(args->values,
|
||||||
args->count, args->count + 1, sizeof *args->values);
|
args->count, args->count + 1, sizeof *args->values);
|
||||||
args_copy_value(&args->values[args->count++], value);
|
new = &args->values[args->count++];
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ARGS_PARSE_INVALID:
|
||||||
|
fatalx("unexpected argument type");
|
||||||
|
case ARGS_PARSE_STRING:
|
||||||
|
if (value->type != ARGS_STRING) {
|
||||||
|
xasprintf(cause,
|
||||||
|
"argument %u must be \"string\"",
|
||||||
|
args->count);
|
||||||
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
args_copy_value(new, value);
|
||||||
|
break;
|
||||||
|
case ARGS_PARSE_COMMANDS_OR_STRING:
|
||||||
|
args_copy_value(new, value);
|
||||||
|
break;
|
||||||
|
case ARGS_PARSE_COMMANDS:
|
||||||
|
if (value->type != ARGS_COMMANDS) {
|
||||||
|
xasprintf(cause,
|
||||||
|
"argument %u must be { commands }",
|
||||||
|
args->count);
|
||||||
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
args_copy_value(new, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((parse->lower != -1 && args->count < (u_int)parse->lower) ||
|
if (parse->lower != -1 && args->count < (u_int)parse->lower) {
|
||||||
(parse->upper != -1 && args->count > (u_int)parse->upper)) {
|
xasprintf(cause,
|
||||||
|
"too few arguments (need at least %u)",
|
||||||
|
parse->lower);
|
||||||
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (parse->upper != -1 && args->count > (u_int)parse->upper) {
|
||||||
|
xasprintf(cause,
|
||||||
|
"too many arguments (need at most %u)",
|
||||||
|
parse->upper);
|
||||||
args_free(args);
|
args_free(args);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -254,15 +313,25 @@ args_free(struct args *args)
|
|||||||
void
|
void
|
||||||
args_vector(struct args *args, int *argc, char ***argv)
|
args_vector(struct args *args, int *argc, char ***argv)
|
||||||
{
|
{
|
||||||
struct args_value *value;
|
char *s;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
*argc = 0;
|
*argc = 0;
|
||||||
*argv = NULL;
|
*argv = NULL;
|
||||||
|
|
||||||
for (i = 0; i < args->count; i++) {
|
for (i = 0; i < args->count; i++) {
|
||||||
value = &args->values[i];
|
switch (args->values[i].type) {
|
||||||
cmd_append_argv(argc, argv, args_value_as_string(value));
|
case ARGS_NONE:
|
||||||
|
break;
|
||||||
|
case ARGS_STRING:
|
||||||
|
cmd_append_argv(argc, argv, args->values[i].string);
|
||||||
|
break;
|
||||||
|
case ARGS_COMMANDS:
|
||||||
|
s = cmd_list_print(args->values[i].cmdlist, 0);
|
||||||
|
cmd_append_argv(argc, argv, s);
|
||||||
|
free(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +27,16 @@
|
|||||||
* Bind a key to a command.
|
* Bind a key to a command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmdq_item *);
|
static enum args_parse_type cmd_bind_key_args_parse(struct args *, u_int,
|
||||||
|
char **);
|
||||||
|
static enum cmd_retval cmd_bind_key_exec(struct cmd *,
|
||||||
|
struct cmdq_item *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_bind_key_entry = {
|
const struct cmd_entry cmd_bind_key_entry = {
|
||||||
.name = "bind-key",
|
.name = "bind-key",
|
||||||
.alias = "bind",
|
.alias = "bind",
|
||||||
|
|
||||||
.args = { "nrN:T:", 1, -1, NULL },
|
.args = { "nrN:T:", 1, -1, cmd_bind_key_args_parse },
|
||||||
.usage = "[-nr] [-T key-table] [-N note] key "
|
.usage = "[-nr] [-T key-table] [-N note] key "
|
||||||
"[command [arguments]]",
|
"[command [arguments]]",
|
||||||
|
|
||||||
@ -41,6 +44,15 @@ const struct cmd_entry cmd_bind_key_entry = {
|
|||||||
.exec = cmd_bind_key_exec
|
.exec = cmd_bind_key_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_bind_key_args_parse(__unused struct args *args, u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
if (idx == 1)
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
return (ARGS_PARSE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
* Prompt for command in client.
|
* Prompt for command in client.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static enum args_parse_type cmd_command_prompt_args_parse(struct args *,
|
||||||
|
u_int, char **);
|
||||||
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
|
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
|||||||
.name = "command-prompt",
|
.name = "command-prompt",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "1bFkiI:Np:t:T:", 0, 1, NULL },
|
.args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||||
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [-T type] [template]",
|
" [-T type] [template]",
|
||||||
|
|
||||||
@ -68,6 +70,13 @@ struct cmd_command_prompt_cdata {
|
|||||||
char **argv;
|
char **argv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_command_prompt_args_parse(__unused struct args *args, __unused u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
* Asks for confirmation before executing a command.
|
* Asks for confirmation before executing a command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static enum args_parse_type cmd_confirm_before_args_parse(struct args *,
|
||||||
|
u_int, char **);
|
||||||
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
|
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ const struct cmd_entry cmd_confirm_before_entry = {
|
|||||||
.name = "confirm-before",
|
.name = "confirm-before",
|
||||||
.alias = "confirm",
|
.alias = "confirm",
|
||||||
|
|
||||||
.args = { "bp:t:", 1, 1, NULL },
|
.args = { "bp:t:", 1, 1, cmd_confirm_before_args_parse },
|
||||||
.usage = "[-b] [-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
|
.usage = "[-b] [-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_TFLAG,
|
.flags = CMD_CLIENT_TFLAG,
|
||||||
@ -51,6 +53,13 @@ struct cmd_confirm_before_data {
|
|||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
* Display a menu on a client.
|
* Display a menu on a client.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static enum args_parse_type cmd_display_menu_args_parse(struct args *,
|
||||||
|
u_int, char **);
|
||||||
static enum cmd_retval cmd_display_menu_exec(struct cmd *,
|
static enum cmd_retval cmd_display_menu_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_display_popup_exec(struct cmd *,
|
static enum cmd_retval cmd_display_popup_exec(struct cmd *,
|
||||||
@ -37,7 +39,7 @@ const struct cmd_entry cmd_display_menu_entry = {
|
|||||||
.name = "display-menu",
|
.name = "display-menu",
|
||||||
.alias = "menu",
|
.alias = "menu",
|
||||||
|
|
||||||
.args = { "c:t:OT:x:y:", 1, -1, NULL },
|
.args = { "c:t:OT:x:y:", 1, -1, cmd_display_menu_args_parse },
|
||||||
.usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
|
.usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
|
||||||
"[-x position] [-y position] name key command ...",
|
"[-x position] [-y position] name key command ...",
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ const struct cmd_entry cmd_display_popup_entry = {
|
|||||||
.args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL },
|
.args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL },
|
||||||
.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] "
|
.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] "
|
||||||
CMD_TARGET_PANE_USAGE " [-w width] "
|
CMD_TARGET_PANE_USAGE " [-w width] "
|
||||||
"[-x position] [-y position] [command]",
|
"[-x position] [-y position] [shell-command]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@ -62,6 +64,30 @@ const struct cmd_entry cmd_display_popup_entry = {
|
|||||||
.exec = cmd_display_popup_exec
|
.exec = cmd_display_popup_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
|
||||||
|
{
|
||||||
|
u_int i = 0;
|
||||||
|
enum args_parse_type type = ARGS_PARSE_STRING;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
type = ARGS_PARSE_STRING;
|
||||||
|
if (i == idx)
|
||||||
|
break;
|
||||||
|
if (*args_string(args, i++) == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
type = ARGS_PARSE_STRING;
|
||||||
|
if (i++ == idx)
|
||||||
|
break;
|
||||||
|
|
||||||
|
type = ARGS_PARSE_COMMANDS_OR_STRING;
|
||||||
|
if (i++ == idx)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (type);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
|
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
|
||||||
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
* Display panes on a client.
|
* Display panes on a client.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static enum args_parse_type cmd_display_panes_args_parse(struct args *,
|
||||||
|
u_int, char **);
|
||||||
static enum cmd_retval cmd_display_panes_exec(struct cmd *,
|
static enum cmd_retval cmd_display_panes_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ const struct cmd_entry cmd_display_panes_entry = {
|
|||||||
.name = "display-panes",
|
.name = "display-panes",
|
||||||
.alias = "displayp",
|
.alias = "displayp",
|
||||||
|
|
||||||
.args = { "bd:Nt:", 0, 1, NULL },
|
.args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
|
||||||
.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
|
.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
|
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
|
||||||
@ -46,6 +48,13 @@ struct cmd_display_panes_data {
|
|||||||
struct args_command_state *state;
|
struct args_command_state *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||||
struct window_pane *wp)
|
struct window_pane *wp)
|
||||||
|
@ -29,7 +29,10 @@
|
|||||||
* Executes a tmux command if a shell command returns true or false.
|
* Executes a tmux command if a shell command returns true or false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *);
|
static enum args_parse_type cmd_if_shell_args_parse(struct args *, u_int,
|
||||||
|
char **);
|
||||||
|
static enum cmd_retval cmd_if_shell_exec(struct cmd *,
|
||||||
|
struct cmdq_item *);
|
||||||
|
|
||||||
static void cmd_if_shell_callback(struct job *);
|
static void cmd_if_shell_callback(struct job *);
|
||||||
static void cmd_if_shell_free(void *);
|
static void cmd_if_shell_free(void *);
|
||||||
@ -38,7 +41,7 @@ const struct cmd_entry cmd_if_shell_entry = {
|
|||||||
.name = "if-shell",
|
.name = "if-shell",
|
||||||
.alias = "if",
|
.alias = "if",
|
||||||
|
|
||||||
.args = { "bFt:", 2, 3, NULL },
|
.args = { "bFt:", 2, 3, cmd_if_shell_args_parse },
|
||||||
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
|
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
|
||||||
"[command]",
|
"[command]",
|
||||||
|
|
||||||
@ -56,6 +59,15 @@ struct cmd_if_shell_data {
|
|||||||
struct cmdq_item *item;
|
struct cmdq_item *item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_if_shell_args_parse(__unused struct args *args, u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
if (idx == 1 || idx == 2)
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
return (ARGS_PARSE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,10 @@
|
|||||||
* Runs a command without a window.
|
* Runs a command without a window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmdq_item *);
|
static enum args_parse_type cmd_run_shell_args_parse(struct args *, u_int,
|
||||||
|
char **);
|
||||||
|
static enum cmd_retval cmd_run_shell_exec(struct cmd *,
|
||||||
|
struct cmdq_item *);
|
||||||
|
|
||||||
static void cmd_run_shell_timer(int, short, void *);
|
static void cmd_run_shell_timer(int, short, void *);
|
||||||
static void cmd_run_shell_callback(struct job *);
|
static void cmd_run_shell_callback(struct job *);
|
||||||
@ -41,7 +44,7 @@ const struct cmd_entry cmd_run_shell_entry = {
|
|||||||
.name = "run-shell",
|
.name = "run-shell",
|
||||||
.alias = "run",
|
.alias = "run",
|
||||||
|
|
||||||
.args = { "bd:Ct:", 0, 1, NULL },
|
.args = { "bd:Ct:", 0, 1, cmd_run_shell_args_parse },
|
||||||
.usage = "[-bC] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
|
.usage = "[-bC] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
@ -62,6 +65,15 @@ struct cmd_run_shell_data {
|
|||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_run_shell_args_parse(struct args *args, __unused u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
if (args_has(args, 'C'))
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
return (ARGS_PARSE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_run_shell_print(struct job *job, const char *msg)
|
cmd_run_shell_print(struct job *job, const char *msg)
|
||||||
{
|
{
|
||||||
|
@ -27,13 +27,16 @@
|
|||||||
* Set an option.
|
* Set an option.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
|
static enum args_parse_type cmd_set_option_args_parse(struct args *,
|
||||||
|
u_int, char **);
|
||||||
|
static enum cmd_retval cmd_set_option_exec(struct cmd *,
|
||||||
|
struct cmdq_item *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_set_option_entry = {
|
const struct cmd_entry cmd_set_option_entry = {
|
||||||
.name = "set-option",
|
.name = "set-option",
|
||||||
.alias = "set",
|
.alias = "set",
|
||||||
|
|
||||||
.args = { "aFgopqst:uUw", 1, 2, NULL },
|
.args = { "aFgopqst:uUw", 1, 2, cmd_set_option_args_parse },
|
||||||
.usage = "[-aFgopqsuUw] " CMD_TARGET_PANE_USAGE " option [value]",
|
.usage = "[-aFgopqsuUw] " CMD_TARGET_PANE_USAGE " option [value]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
@ -46,7 +49,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
|
|||||||
.name = "set-window-option",
|
.name = "set-window-option",
|
||||||
.alias = "setw",
|
.alias = "setw",
|
||||||
|
|
||||||
.args = { "aFgoqt:u", 1, 2, NULL },
|
.args = { "aFgoqt:u", 1, 2, cmd_set_option_args_parse },
|
||||||
.usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
|
.usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
@ -59,7 +62,7 @@ const struct cmd_entry cmd_set_hook_entry = {
|
|||||||
.name = "set-hook",
|
.name = "set-hook",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "agpRt:uw", 1, 2, NULL },
|
.args = { "agpRt:uw", 1, 2, cmd_set_option_args_parse },
|
||||||
.usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
|
.usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
@ -68,6 +71,15 @@ const struct cmd_entry cmd_set_hook_entry = {
|
|||||||
.exec = cmd_set_option_exec
|
.exec = cmd_set_option_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum args_parse_type
|
||||||
|
cmd_set_option_args_parse(__unused struct args *args, u_int idx,
|
||||||
|
__unused char **cause)
|
||||||
|
{
|
||||||
|
if (idx == 1)
|
||||||
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
|
return (ARGS_PARSE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
10
cmd.c
10
cmd.c
@ -502,6 +502,7 @@ cmd_parse(struct args_value *values, u_int count, const char *file, u_int line,
|
|||||||
const struct cmd_entry *entry;
|
const struct cmd_entry *entry;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
struct args *args;
|
struct args *args;
|
||||||
|
char *error;
|
||||||
|
|
||||||
if (count == 0 || values[0].type != ARGS_STRING) {
|
if (count == 0 || values[0].type != ARGS_STRING) {
|
||||||
xasprintf(cause, "no command");
|
xasprintf(cause, "no command");
|
||||||
@ -511,11 +512,16 @@ cmd_parse(struct args_value *values, u_int count, const char *file, u_int line,
|
|||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
args = args_parse(&entry->args, values, count);
|
args = args_parse(&entry->args, values, count, &error);
|
||||||
if (args == NULL) {
|
if (args == NULL && error == NULL) {
|
||||||
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
|
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
if (args == NULL) {
|
||||||
|
xasprintf(cause, "command %s: %s", entry->name, error);
|
||||||
|
free(error);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
cmd = xcalloc(1, sizeof *cmd);
|
cmd = xcalloc(1, sizeof *cmd);
|
||||||
cmd->entry = entry;
|
cmd->entry = entry;
|
||||||
|
@ -634,8 +634,10 @@ key_bindings_init(void)
|
|||||||
|
|
||||||
for (i = 0; i < nitems(defaults); i++) {
|
for (i = 0; i < nitems(defaults); i++) {
|
||||||
pr = cmd_parse_from_string(defaults[i], NULL);
|
pr = cmd_parse_from_string(defaults[i], NULL);
|
||||||
if (pr->status != CMD_PARSE_SUCCESS)
|
if (pr->status != CMD_PARSE_SUCCESS) {
|
||||||
|
log_debug("%s", pr->error);
|
||||||
fatalx("bad default key: %s", defaults[i]);
|
fatalx("bad default key: %s", defaults[i]);
|
||||||
|
}
|
||||||
cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL));
|
cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL));
|
||||||
cmd_list_free(pr->cmdlist);
|
cmd_list_free(pr->cmdlist);
|
||||||
}
|
}
|
||||||
|
12
tmux.h
12
tmux.h
@ -1378,8 +1378,16 @@ struct args_value {
|
|||||||
struct args_entry;
|
struct args_entry;
|
||||||
RB_HEAD(args_tree, args_entry);
|
RB_HEAD(args_tree, args_entry);
|
||||||
|
|
||||||
|
/* Arguments parsing type. */
|
||||||
|
enum args_parse_type {
|
||||||
|
ARGS_PARSE_INVALID,
|
||||||
|
ARGS_PARSE_STRING,
|
||||||
|
ARGS_PARSE_COMMANDS_OR_STRING,
|
||||||
|
ARGS_PARSE_COMMANDS
|
||||||
|
};
|
||||||
|
|
||||||
/* Arguments parsing state. */
|
/* Arguments parsing state. */
|
||||||
typedef enum args_type (*args_parse_cb)(struct args *, u_int);
|
typedef enum args_parse_type (*args_parse_cb)(struct args *, u_int, char **);
|
||||||
struct args_parse {
|
struct args_parse {
|
||||||
const char *template;
|
const char *template;
|
||||||
int lower;
|
int lower;
|
||||||
@ -2201,7 +2209,7 @@ int tty_keys_next(struct tty *);
|
|||||||
void args_set(struct args *, u_char, struct args_value *);
|
void args_set(struct args *, u_char, struct args_value *);
|
||||||
struct args *args_create(void);
|
struct args *args_create(void);
|
||||||
struct args *args_parse(const struct args_parse *, struct args_value *,
|
struct args *args_parse(const struct args_parse *, struct args_value *,
|
||||||
u_int);
|
u_int, char **);
|
||||||
void args_vector(struct args *, int *, char ***);
|
void args_vector(struct args *, int *, char ***);
|
||||||
void args_free_value(struct args_value *);
|
void args_free_value(struct args_value *);
|
||||||
void args_free(struct args *);
|
void args_free(struct args *);
|
||||||
|
Loading…
Reference in New Issue
Block a user