diff --git a/Makefile b/Makefile index 86b28b60..0f7f403e 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ # $OpenBSD$ PROG= tmux -SRCS= attributes.c cfg.c client.c clock.c \ +SRCS= arguments.c attributes.c cfg.c client.c clock.c \ cmd-attach-session.c cmd-bind-key.c \ cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \ cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \ cmd-confirm-before.c cmd-copy-mode.c \ cmd-choose-buffer.c cmd-delete-buffer.c cmd-detach-client.c \ - cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \ + cmd-find-window.c cmd-has-session.c cmd-kill-pane.c \ cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \ cmd-last-pane.c cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \ cmd-list-clients.c cmd-list-commands.c cmd-list-keys.c \ diff --git a/arguments.c b/arguments.c new file mode 100644 index 00000000..ebd09580 --- /dev/null +++ b/arguments.c @@ -0,0 +1,222 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2010 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include "tmux.h" + +/* Create an arguments set with no flags. */ +struct args * +args_create(int argc, ...) +{ + struct args *args; + va_list ap; + int i; + + args = xcalloc(1, sizeof *args); + if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL) + fatal("bit_alloc failed"); + + args->argc = argc; + if (argc == 0) + args->argv = NULL; + else + args->argv = xcalloc(argc, sizeof **args->argv); + + va_start(ap, argc); + for (i = 0; i < argc; i++) + args->argv[i] = xstrdup(va_arg(ap, char *)); + va_end(ap); + + return (args); +} + +/* Parse an argv and argc into a new argument set. */ +struct args * +args_parse(const char *template, int argc, char **argv) +{ + struct args *args; + char *ptr; + int opt; + + args = xcalloc(1, sizeof *args); + if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL) + fatal("bit_alloc failed"); + + optreset = 1; + optind = 1; + + while ((opt = getopt(argc, argv, template)) != -1) { + if (opt < 0 || opt >= SCHAR_MAX) + continue; + if (opt == '?' || (ptr = strchr(template, opt)) == NULL) { + xfree(args->flags); + xfree(args); + return (NULL); + } + + bit_set(args->flags, opt); + if (ptr[1] == ':') { + if (args->values[opt] != NULL) + xfree(args->values[opt]); + args->values[opt] = xstrdup(optarg); + } + } + argc -= optind; + argv += optind; + + args->argc = argc; + args->argv = cmd_copy_argv(argc, argv); + + return (args); +} + +/* Free an arguments set. */ +void +args_free(struct args *args) +{ + u_int i; + + cmd_free_argv(args->argc, args->argv); + + for (i = 0; i < SCHAR_MAX; i++) { + if (args->values[i] != NULL) + xfree(args->values[i]); + } + + xfree(args->flags); + xfree(args); +} + +/* Print a set of arguments. */ +size_t +args_print(struct args *args, char *buf, size_t len) +{ + size_t off; + int i; + const char *quotes; + + /* There must be at least one byte at the start. */ + if (len == 0) + return (0); + off = 0; + + /* Process the flags first. */ + buf[off++] = '-'; + for (i = 0; i < SCHAR_MAX; i++) { + if (!bit_test(args->flags, i) || args->values[i] != NULL) + continue; + + if (off == len - 1) { + buf[off] = '\0'; + return (len); + } + buf[off++] = i; + buf[off] = '\0'; + } + if (off == 1) + buf[--off] = '\0'; + + /* Then the flags with arguments. */ + for (i = 0; i < SCHAR_MAX; i++) { + if (!bit_test(args->flags, i) || args->values[i] == NULL) + continue; + + if (off >= len) { + /* snprintf will have zero terminated. */ + return (len); + } + + if (strchr(args->values[i], ' ') != NULL) + quotes = "\""; + else + quotes = ""; + off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s", + off != 0 ? " " : "", i, quotes, args->values[i], quotes); + } + + /* And finally the argument vector. */ + for (i = 0; i < args->argc; i++) { + if (off >= len) { + /* snprintf will have zero terminated. */ + return (len); + } + + if (strchr(args->argv[i], ' ') != NULL) + quotes = "\""; + else + quotes = ""; + off += xsnprintf(buf + off, len - off, "%s%s%s%s", + off != 0 ? " " : "", quotes, args->argv[i], quotes); + } + + return (off); +} + +/* Return if an argument is present. */ +int +args_has(struct args *args, u_char ch) +{ + return (bit_test(args->flags, ch)); +} + +/* Set argument value. */ +void +args_set(struct args *args, u_char ch, const char *value) +{ + if (value != NULL) { + if (args->values[ch] != NULL) + xfree(args->values[ch]); + args->values[ch] = xstrdup(value); + } + bit_set(args->flags, ch); +} + +/* Get argument value. Will be NULL if it isn't present. */ +const char * +args_get(struct args *args, u_char ch) +{ + return (args->values[ch]); +} + +/* Convert an argument value to a number. */ +long long +args_strtonum(struct args *args, + u_char ch, long long minval, long long maxval, char **cause) +{ + const char *errstr; + long long ll; + + if (!args_has(args, ch)) { + *cause = xstrdup("missing"); + return (0); + } + + ll = strtonum(args->values[ch], minval, maxval, &errstr); + if (errstr != NULL) { + *cause = xstrdup(errstr); + return (0); + } + + *cause = NULL; + return (ll); +} diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 45a49f2b..f320056d 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -28,37 +28,37 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_attach_session_entry = { "attach-session", "attach", + "drt:", 0, 0, "[-dr] " CMD_TARGET_SESSION_USAGE, - CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, "dr", - cmd_target_init, - cmd_target_parse, - cmd_attach_session_exec, - cmd_target_free, - cmd_target_print + CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, + NULL, + NULL, + cmd_attach_session_exec }; int cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct client *c; - const char *update; - char *overrides, *cause; - u_int i; + struct args *args = self->args; + struct session *s; + struct client *c; + const char *update; + char *overrides, *cause; + u_int i; if (RB_EMPTY(&sessions)) { ctx->error(ctx, "no sessions"); return (-1); } - if ((s = cmd_find_session(ctx, data->target)) == NULL) + + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); if (ctx->cmdclient == NULL && ctx->curclient == NULL) return (0); if (ctx->cmdclient == NULL) { - if (cmd_check_flag(data->chflags, 'd')) { + if (args_has(self->args, 'd')) { /* * Can't use server_write_session in case attaching to * the same session as currently attached to. @@ -90,10 +90,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if (cmd_check_flag(data->chflags, 'r')) + if (args_has(self->args, 'r')) ctx->cmdclient->flags |= CLIENT_READONLY; - if (cmd_check_flag(data->chflags, 'd')) + if (args_has(self->args, 'd')) server_write_session(s, MSG_DETACH, NULL, 0); ctx->cmdclient->session = s; diff --git a/cmd-bind-key.c b/cmd-bind-key.c index 60887904..025f6c79 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -26,136 +26,87 @@ * Bind a key to a command, this recurses through cmd_*. */ -int cmd_bind_key_parse(struct cmd *, int, char **, char **); +int cmd_bind_key_check(struct args *); int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); -void cmd_bind_key_free(struct cmd *); -size_t cmd_bind_key_print(struct cmd *, char *, size_t); -int cmd_bind_key_table(struct cmd *, struct cmd_ctx *); - -struct cmd_bind_key_data { - int key; - int can_repeat; - struct cmd_list *cmdlist; - - int command_key; - char *tablename; - char *modecmd; -}; +int cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int); const struct cmd_entry cmd_bind_key_entry = { "bind-key", "bind", + "cnrt:", 1, -1, "[-cnr] [-t key-table] key command [arguments]", - 0, "", + 0, NULL, - cmd_bind_key_parse, - cmd_bind_key_exec, - cmd_bind_key_free, - cmd_bind_key_print + cmd_bind_key_check, + cmd_bind_key_exec }; int -cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) +cmd_bind_key_check(struct args *args) { - struct cmd_bind_key_data *data; - int opt, no_prefix = 0; - - self->data = data = xmalloc(sizeof *data); - data->can_repeat = 0; - data->cmdlist = NULL; - data->command_key = 0; - data->tablename = NULL; - data->modecmd = NULL; - - while ((opt = getopt(argc, argv, "cnrt:")) != -1) { - switch (opt) { - case 'c': - data->command_key = 1; - break; - case 'n': - no_prefix = 1; - break; - case 'r': - data->can_repeat = 1; - break; - case 't': - if (data->tablename == NULL) - data->tablename = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc < 1) - goto usage; - - if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) { - xasprintf(cause, "unknown key: %s", argv[0]); - goto error; - } - if (!no_prefix) - data->key |= KEYC_PREFIX; - - argc--; - argv++; - if (data->tablename != NULL) { - if (argc != 1) - goto usage; - data->modecmd = xstrdup(argv[0]); + if (args_has(args, 't')) { + if (args->argc != 1) + return (-1); } else { - if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL) - goto error; + if (args->argc < 2) + return (-1); + } + return (0); +} + +int +cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct args *args = self->args; + char *cause; + struct cmd_list *cmdlist; + int key; + + key = key_string_lookup_string(args->argv[0]); + if (key == KEYC_NONE) { + ctx->error(ctx, "unknown key: %s", args->argv[0]); + return (-1); } - return (0); + if (args_has(args, 't')) + return (cmd_bind_key_table(self, ctx, key)); -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); -} - -int -cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) -{ - struct cmd_bind_key_data *data = self->data; - - if (data == NULL) - return (0); - if (data->tablename != NULL) - return (cmd_bind_key_table(self, ctx)); - - key_bindings_add(data->key, data->can_repeat, data->cmdlist); - data->cmdlist->references++; + cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, &cause); + if (cmdlist == NULL) { + ctx->error(ctx, "%s", cause); + xfree(cause); + return (-1); + } + if (!args_has(args, 'n')) + key |= KEYC_PREFIX; + key_bindings_add(key, args_has(args, 'r'), cmdlist); return (0); } int -cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx) +cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) { - struct cmd_bind_key_data *data = self->data; + struct args *args = self->args; + const char *tablename; const struct mode_key_table *mtab; struct mode_key_binding *mbind, mtmp; enum mode_key_cmd cmd; - if ((mtab = mode_key_findtable(data->tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", data->tablename); + tablename = args_get(args, 't'); + if ((mtab = mode_key_findtable(tablename)) == NULL) { + ctx->error(ctx, "unknown key table: %s", tablename); return (-1); } - cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd); + cmd = mode_key_fromstring(mtab->cmdstr, args->argv[0]); if (cmd == MODEKEY_NONE) { - ctx->error(ctx, "unknown command: %s", data->modecmd); + ctx->error(ctx, "unknown command: %s", args->argv[0]); return (-1); } - mtmp.key = data->key & ~KEYC_PREFIX; - mtmp.mode = data->command_key ? 1 : 0; + mtmp.key = key; + mtmp.mode = !!args_has(args, 'c'); if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { mbind->cmd = cmd; return (0); @@ -167,45 +118,3 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx) SPLAY_INSERT(mode_key_tree, mtab->tree, mbind); return (0); } - -void -cmd_bind_key_free(struct cmd *self) -{ - struct cmd_bind_key_data *data = self->data; - - if (data->cmdlist != NULL) - cmd_list_free(data->cmdlist); - if (data->tablename != NULL) - xfree(data->tablename); - if (data->modecmd != NULL) - xfree(data->modecmd); - xfree(data); -} - -size_t -cmd_bind_key_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_bind_key_data *data = self->data; - size_t off = 0; - const char *skey; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - - if (off < len && data->command_key) - off += xsnprintf(buf + off, len - off, " -c"); - if (off < len && !(data->key & KEYC_PREFIX)) - off += xsnprintf(buf + off, len - off, " -n"); - if (off < len && data->can_repeat) - off += xsnprintf(buf + off, len - off, " -r"); - if (off < len && data->tablename != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->tablename); - if (off < len) { - skey = key_string_lookup_key(data->key & ~KEYC_PREFIX); - off += xsnprintf(buf + off, len - off, " %s ", skey); - } - if (off < len) - off += cmd_list_print(data->cmdlist, buf + off, len - off); - return (off); -} diff --git a/cmd-break-pane.c b/cmd-break-pane.c index d5f847fb..4c57a116 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -30,19 +30,18 @@ int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_break_pane_entry = { "break-pane", "breakp", - CMD_TARGET_PANE_USAGE " [-d]", - 0, "d", - cmd_target_init, - cmd_target_parse, - cmd_break_pane_exec, - cmd_target_free, - cmd_target_print + "dt:", 0, 0, + "[-d] " CMD_TARGET_PANE_USAGE, + 0, + NULL, + NULL, + cmd_break_pane_exec }; int cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct session *s; struct window_pane *wp; @@ -50,7 +49,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) char *cause; int base_idx; - if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL) + if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) return (-1); if (window_count_panes(wl->window) == 1) { @@ -74,7 +73,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) base_idx = options_get_number(&s->options, "base-index"); wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */ - if (!cmd_check_flag(data->chflags, 'd')) + if (!args_has(self->args, 'd')) session_select(s, wl->idx); server_redraw_session(s); diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index c711db42..6efbfe97 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -27,93 +27,30 @@ * Write the entire contents of a pane to a buffer. */ -int cmd_capture_pane_parse(struct cmd *, int, char **, char **); int cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *); -void cmd_capture_pane_free(struct cmd *); -void cmd_capture_pane_init(struct cmd *, int); -size_t cmd_capture_pane_print(struct cmd *, char *, size_t); - -struct cmd_capture_pane_data { - char *target; - int buffer; -}; const struct cmd_entry cmd_capture_pane_entry = { "capture-pane", "capturep", + "b:t:", 0, 0, "[-b buffer-index] [-t target-pane]", - 0, "", - cmd_capture_pane_init, - cmd_capture_pane_parse, - cmd_capture_pane_exec, - cmd_capture_pane_free, - cmd_capture_pane_print + 0, + NULL, + NULL, + cmd_capture_pane_exec }; -/* ARGSUSED */ -void -cmd_capture_pane_init(struct cmd *self, unused int arg) -{ - struct cmd_capture_pane_data *data; - - self->data = data = xmalloc(sizeof *data); - data->buffer = -1; - data->target = NULL; -} - -int -cmd_capture_pane_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_capture_pane_data *data; - const char *errstr; - int n, opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "b:t:")) != -1) { - switch (opt) { - case 'b': - if (data->buffer == -1) { - n = strtonum(optarg, 0, INT_MAX, &errstr); - if (errstr != NULL) { - xasprintf(cause, "buffer %s", errstr); - goto error; - } - data->buffer = n; - } - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); -} - int cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_capture_pane_data *data = self->data; - struct window_pane *wp; - char *buf, *line; - struct screen *s; - u_int i, limit; - size_t len, linelen; + struct args *args = self->args; + struct window_pane *wp; + char *buf, *line, *cause; + struct screen *s; + int buffer; + u_int i, limit; + size_t len, linelen; - if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); s = &wp->base; @@ -133,40 +70,24 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } limit = options_get_number(&global_options, "buffer-limit"); - if (data->buffer == -1) { + + if (!args_has(args, 'b')) { paste_add(&global_buffers, buf, len, limit); return (0); } - if (paste_replace(&global_buffers, data->buffer, buf, len) != 0) { - ctx->error(ctx, "no buffer %d", data->buffer); + + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + + if (paste_replace(&global_buffers, buffer, buf, len) != 0) { + ctx->error(ctx, "no buffer %d", buffer); xfree(buf); return (-1); } + return (0); } - -void -cmd_capture_pane_free(struct cmd *self) -{ - struct cmd_capture_pane_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - xfree(data); -} - -size_t -cmd_capture_pane_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_capture_pane_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->buffer != -1) - off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); - if (off < len && data->target != NULL) - off += xsnprintf(buf + off, len - off, " -t %s", data->target); - return (off); -} diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c index 32bf2f2d..c1093f92 100644 --- a/cmd-choose-buffer.c +++ b/cmd-choose-buffer.c @@ -33,24 +33,23 @@ void cmd_choose_buffer_free(void *); const struct cmd_entry cmd_choose_buffer_entry = { "choose-buffer", NULL, + "t:", 0, 1, CMD_TARGET_WINDOW_USAGE " [template]", - CMD_ARG01, "", - cmd_target_init, - cmd_target_parse, - cmd_choose_buffer_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_choose_buffer_exec }; struct cmd_choose_buffer_data { - struct client *client; - char *template; + struct client *client; + char *template; }; int cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_choose_buffer_data *cdata; struct winlink *wl; struct paste_buffer *pb; @@ -62,7 +61,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); if (paste_get_top(&global_buffers) == NULL) @@ -80,8 +79,8 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) } cdata = xmalloc(sizeof *cdata); - if (data->arg != NULL) - cdata->template = xstrdup(data->arg); + if (args->argc != 0) + cdata->template = xstrdup(args->argv[0]); else cdata->template = xstrdup("paste-buffer -b '%%'"); cdata->client = ctx->curclient; diff --git a/cmd-choose-client.c b/cmd-choose-client.c index cd5ab9ea..ac766ab5 100644 --- a/cmd-choose-client.c +++ b/cmd-choose-client.c @@ -33,13 +33,12 @@ void cmd_choose_client_free(void *); const struct cmd_entry cmd_choose_client_entry = { "choose-client", NULL, + "t:", 0, 1, CMD_TARGET_WINDOW_USAGE " [template]", - CMD_ARG01, "", - cmd_target_init, - cmd_target_parse, - cmd_choose_client_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_choose_client_exec }; struct cmd_choose_client_data { @@ -50,7 +49,7 @@ struct cmd_choose_client_data { int cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_choose_client_data *cdata; struct winlink *wl; struct client *c; @@ -61,7 +60,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) @@ -83,8 +82,8 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) } cdata = xmalloc(sizeof *cdata); - if (data->arg != NULL) - cdata->template = xstrdup(data->arg); + if (args->argc != 0) + cdata->template = xstrdup(args->argv[0]); else cdata->template = xstrdup("detach-client -t '%%'"); cdata->client = ctx->curclient; diff --git a/cmd-choose-session.c b/cmd-choose-session.c index cf36fe98..5aa0877b 100644 --- a/cmd-choose-session.c +++ b/cmd-choose-session.c @@ -33,13 +33,12 @@ void cmd_choose_session_free(void *); const struct cmd_entry cmd_choose_session_entry = { "choose-session", NULL, + "t:", 0, 1, CMD_TARGET_WINDOW_USAGE " [template]", - CMD_ARG01, "", - cmd_target_init, - cmd_target_parse, - cmd_choose_session_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_choose_session_exec }; struct cmd_choose_session_data { @@ -50,7 +49,7 @@ struct cmd_choose_session_data { int cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_choose_session_data *cdata; struct winlink *wl; struct session *s; @@ -63,7 +62,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) @@ -90,8 +89,8 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) } cdata = xmalloc(sizeof *cdata); - if (data->arg != NULL) - cdata->template = xstrdup(data->arg); + if (args->argc != 0) + cdata->template = xstrdup(args->argv[0]); else cdata->template = xstrdup("switch-client -t '%%'"); cdata->client = ctx->curclient; diff --git a/cmd-choose-window.c b/cmd-choose-window.c index 1bbe0dfe..a1280927 100644 --- a/cmd-choose-window.c +++ b/cmd-choose-window.c @@ -33,13 +33,12 @@ void cmd_choose_window_free(void *); const struct cmd_entry cmd_choose_window_entry = { "choose-window", NULL, + "t:", 0, 1, CMD_TARGET_WINDOW_USAGE " [template]", - CMD_ARG01, "", - cmd_target_init, - cmd_target_parse, - cmd_choose_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_choose_window_exec }; struct cmd_choose_window_data { @@ -51,7 +50,7 @@ struct cmd_choose_window_data { int cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_choose_window_data *cdata; struct session *s; struct winlink *wl, *wm; @@ -66,7 +65,7 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) } s = ctx->curclient->session; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) @@ -99,8 +98,8 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) } cdata = xmalloc(sizeof *cdata); - if (data->arg != NULL) - cdata->template = xstrdup(data->arg); + if (args->argc != 0) + cdata->template = xstrdup(args->argv[0]); else cdata->template = xstrdup("select-window -t '%%'"); cdata->session = s; diff --git a/cmd-clear-history.c b/cmd-clear-history.c index 9241485a..cf3da229 100644 --- a/cmd-clear-history.c +++ b/cmd-clear-history.c @@ -28,23 +28,22 @@ int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_clear_history_entry = { "clear-history", "clearhist", + "t:", 0, 0, CMD_TARGET_PANE_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_clear_history_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_clear_history_exec }; int cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct window_pane *wp; struct grid *gd; - if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); gd = wp->base.grid; diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c index 4df934f7..0dc151d1 100644 --- a/cmd-clock-mode.c +++ b/cmd-clock-mode.c @@ -28,22 +28,21 @@ int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_clock_mode_entry = { "clock-mode", NULL, + "t:", 0, 0, CMD_TARGET_PANE_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_clock_mode_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_clock_mode_exec }; int cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct window_pane *wp; - if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); window_pane_set_mode(wp, &window_clock_mode); diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index b76ea8d1..db50adc7 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -27,30 +27,21 @@ * Prompt for command in client. */ -void cmd_command_prompt_init(struct cmd *, int); -int cmd_command_prompt_parse(struct cmd *, int, char **, char **); -int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); -void cmd_command_prompt_free(struct cmd *); -size_t cmd_command_prompt_print(struct cmd *, char *, size_t); +void cmd_command_prompt_key_binding(struct cmd *, int); +int cmd_command_prompt_check(struct args *); +int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); -int cmd_command_prompt_callback(void *, const char *); -void cmd_command_prompt_cfree(void *); +int cmd_command_prompt_callback(void *, const char *); +void cmd_command_prompt_free(void *); const struct cmd_entry cmd_command_prompt_entry = { "command-prompt", NULL, + "p:t:", 0, 0, CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]", - 0, "", - cmd_command_prompt_init, - cmd_command_prompt_parse, - cmd_command_prompt_exec, - cmd_command_prompt_free, - cmd_command_prompt_print -}; - -struct cmd_command_prompt_data { - char *prompts; - char *target; - char *template; + 0, + cmd_command_prompt_key_binding, + NULL, + cmd_command_prompt_exec }; struct cmd_command_prompt_cdata { @@ -62,82 +53,39 @@ struct cmd_command_prompt_cdata { }; void -cmd_command_prompt_init(struct cmd *self, int key) +cmd_command_prompt_key_binding(struct cmd *self, int key) { - struct cmd_command_prompt_data *data; - - self->data = data = xmalloc(sizeof *data); - data->prompts = NULL; - data->target = NULL; - data->template = NULL; - switch (key) { case ',': - data->template = xstrdup("rename-window '%%'"); + self->args = args_create(1, "rename-window '%%'"); break; case '.': - data->template = xstrdup("move-window -t '%%'"); + self->args = args_create(1, "move-window -t '%%'"); break; case 'f': - data->template = xstrdup("find-window '%%'"); + self->args = args_create(1, "find-window '%%'"); break; case '\'': - data->template = xstrdup("select-window -t ':%%'"); - data->prompts = xstrdup("index"); + self->args = args_create(1, "select-window -t ':%%'"); + args_set(self->args, 'p', "index"); + break; + default: + self->args = args_create(0); break; } } -int -cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_command_prompt_data *data; - int opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "p:t:")) != -1) { - switch (opt) { - case 'p': - if (data->prompts == NULL) - data->prompts = xstrdup(optarg); - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0 && argc != 1) - goto usage; - - if (argc == 1) - data->template = xstrdup(argv[0]); - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - int cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_command_prompt_data *data = self->data; + struct args *args = self->args; + const char *prompts; struct cmd_command_prompt_cdata *cdata; struct client *c; char *prompt, *ptr; size_t n; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); if (c->prompt_string != NULL) @@ -150,63 +98,33 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) cdata->prompts = NULL; cdata->template = NULL; - if (data->template != NULL) - cdata->template = xstrdup(data->template); + if (args->argc != 0) + cdata->template = xstrdup(args->argv[0]); else cdata->template = xstrdup("%1"); - if (data->prompts != NULL) - cdata->prompts = xstrdup(data->prompts); - else if (data->template != NULL) { - n = strcspn(data->template, " ,"); - xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template); + + prompts = args_get(args, 'p'); + if (prompts != NULL) + cdata->prompts = xstrdup(prompts); + else if (args->argc != 0) { + n = strcspn(cdata->template, " ,"); + xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template); } else cdata->prompts = xstrdup(":"); cdata->next_prompt = cdata->prompts; ptr = strsep(&cdata->next_prompt, ","); - if (data->prompts == NULL) + if (prompts == NULL) prompt = xstrdup(ptr); else xasprintf(&prompt, "%s ", ptr); status_prompt_set(c, prompt, cmd_command_prompt_callback, - cmd_command_prompt_cfree, cdata, 0); + cmd_command_prompt_free, cdata, 0); xfree(prompt); return (0); } -void -cmd_command_prompt_free(struct cmd *self) -{ - struct cmd_command_prompt_data *data = self->data; - - if (data->prompts != NULL) - xfree(data->prompts); - if (data->target != NULL) - xfree(data->target); - if (data->template != NULL) - xfree(data->template); - xfree(data); -} - -size_t -cmd_command_prompt_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_command_prompt_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->prompts != NULL) - off += cmd_prarg(buf + off, len - off, " -p ", data->prompts); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - if (off < len && data->template != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->template); - return (off); -} - int cmd_command_prompt_callback(void *data, const char *s) { @@ -258,7 +176,7 @@ cmd_command_prompt_callback(void *data, const char *s) } void -cmd_command_prompt_cfree(void *data) +cmd_command_prompt_free(void *data) { struct cmd_command_prompt_cdata *cdata = data; diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index cdde81ac..b19d69d7 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -25,21 +25,20 @@ * Asks for confirmation before executing a command. */ +void cmd_confirm_before_key_binding(struct cmd *, int); int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *); -void cmd_confirm_before_init(struct cmd *, int); int cmd_confirm_before_callback(void *, const char *); void cmd_confirm_before_free(void *); const struct cmd_entry cmd_confirm_before_entry = { "confirm-before", "confirm", + "t:", 1, 1, CMD_TARGET_CLIENT_USAGE " command", - CMD_ARG1, "", - cmd_confirm_before_init, - cmd_target_parse, - cmd_confirm_before_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_confirm_before_key_binding, + NULL, + cmd_confirm_before_exec }; struct cmd_confirm_before_data { @@ -48,19 +47,17 @@ struct cmd_confirm_before_data { }; void -cmd_confirm_before_init(struct cmd *self, int key) +cmd_confirm_before_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - switch (key) { case '&': - data->arg = xstrdup("kill-window"); + self->args = args_create(1, "kill-window"); break; case 'x': - data->arg = xstrdup("kill-pane"); + self->args = args_create(1, "kill-pane"); + break; + default: + self->args = args_create(0); break; } } @@ -68,7 +65,7 @@ cmd_confirm_before_init(struct cmd *self, int key) int cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_confirm_before_data *cdata; struct client *c; char *buf, *cmd, *ptr; @@ -78,17 +75,17 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); - ptr = xstrdup(data->arg); + ptr = xstrdup(args->argv[0]); if ((cmd = strtok(ptr, " \t")) == NULL) cmd = ptr; xasprintf(&buf, "Confirm '%s'? (y/n) ", cmd); xfree(ptr); cdata = xmalloc(sizeof *cdata); - cdata->cmd = xstrdup(data->arg); + cdata->cmd = xstrdup(args->argv[0]); cdata->c = c; status_prompt_set(cdata->c, buf, cmd_confirm_before_callback, cmd_confirm_before_free, cdata, diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 3e858a33..b9290593 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -24,48 +24,40 @@ * Enter copy mode. */ -void cmd_copy_mode_init(struct cmd *, int); +void cmd_copy_mode_key_binding(struct cmd *, int); int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_copy_mode_entry = { "copy-mode", NULL, + "t:u", 0, 0, "[-u] " CMD_TARGET_PANE_USAGE, - 0, "u", - cmd_copy_mode_init, - cmd_target_parse, - cmd_copy_mode_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_copy_mode_key_binding, + NULL, + cmd_copy_mode_exec }; void -cmd_copy_mode_init(struct cmd *self, int key) +cmd_copy_mode_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - - switch (key) { - case KEYC_PPAGE: - cmd_set_flag(&data->chflags, 'u'); - break; - } + self->args = args_create(0); + if (key == KEYC_PPAGE) + args_set(self->args, 'u', NULL); } int cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct window_pane *wp; - if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); if (window_pane_set_mode(wp, &window_copy_mode) != 0) return (0); window_copy_init_from_pane(wp); - if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u')) + if (wp->mode == &window_copy_mode && args_has(self->args, 'u')) window_copy_pageup(wp); return (0); diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c index 0bfd77ae..3f0578ed 100644 --- a/cmd-delete-buffer.c +++ b/cmd-delete-buffer.c @@ -30,24 +30,35 @@ int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_delete_buffer_entry = { "delete-buffer", "deleteb", + "b:", 0, 0, CMD_BUFFER_USAGE, - 0, "", - cmd_buffer_init, - cmd_buffer_parse, - cmd_delete_buffer_exec, - cmd_buffer_free, - cmd_buffer_print + 0, + NULL, + NULL, + cmd_delete_buffer_exec }; int cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; + struct args *args = self->args; + char *cause; + int buffer; - if (data->buffer == -1) + if (!args_has(args, 'b')) { paste_free_top(&global_buffers); - else if (paste_free_index(&global_buffers, data->buffer) != 0) { - ctx->error(ctx, "no buffer %d", data->buffer); + return (0); + } + + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + + if (paste_free_index(&global_buffers, buffer) != 0) { + ctx->error(ctx, "no buffer %d", buffer); return (-1); } diff --git a/cmd-detach-client.c b/cmd-detach-client.c index a2288036..03789bd8 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -28,22 +28,21 @@ int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_detach_client_entry = { "detach-client", "detach", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - CMD_READONLY, "", - cmd_target_init, - cmd_target_parse, - cmd_detach_client_exec, - cmd_target_free, - cmd_target_print + CMD_READONLY, + NULL, + NULL, + cmd_detach_client_exec }; int cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct args *args = self->args; + struct client *c; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); server_write_client(c, MSG_DETACH, NULL, 0); diff --git a/cmd-display-message.c b/cmd-display-message.c index 8c42ee6d..baf6fb9d 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -30,33 +30,32 @@ int cmd_display_message_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_display_message_entry = { "display-message", "display", + "pt:", 0, 1, "[-p] " CMD_TARGET_CLIENT_USAGE " [message]", - CMD_ARG01, "p", - cmd_target_init, - cmd_target_parse, - cmd_display_message_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_display_message_exec }; int cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct client *c; const char *template; char *msg; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); - if (data->arg == NULL) + if (args->argc == 0) template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)"; else - template = data->arg; + template = args->argv[0]; msg = status_replace(c, NULL, template, time(NULL), 0); - if (cmd_check_flag(data->chflags, 'p')) + if (args_has(self->args, 'p')) ctx->print(ctx, "%s", msg); else status_message_set(c, "%s", msg); diff --git a/cmd-display-panes.c b/cmd-display-panes.c index 42ecbb9b..bc64b4b5 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -28,22 +28,21 @@ int cmd_display_panes_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_display_panes_entry = { "display-panes", "displayp", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_display_panes_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_display_panes_exec }; int cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct args *args = self->args; + struct client *c; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); server_set_identify(c); diff --git a/cmd-find-window.c b/cmd-find-window.c index 482d9243..6c3c48ce 100644 --- a/cmd-find-window.c +++ b/cmd-find-window.c @@ -34,13 +34,12 @@ void cmd_find_window_free(void *); const struct cmd_entry cmd_find_window_entry = { "find-window", "findw", + "t:", 1, 1, CMD_TARGET_WINDOW_USAGE " match-string", - CMD_ARG1, "", - cmd_target_init, - cmd_target_parse, - cmd_find_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_find_window_exec }; struct cmd_find_window_data { @@ -50,7 +49,7 @@ struct cmd_find_window_data { int cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_find_window_data *cdata; struct session *s; struct winlink *wl, *wm; @@ -58,7 +57,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) struct window_pane *wp; ARRAY_DECL(, u_int) list_idx; ARRAY_DECL(, char *) list_ctx; - char *sres, *sctx, *searchstr; + char *str, *sres, *sctx, *searchstr; u_int i, line; if (ctx->curclient == NULL) { @@ -67,13 +66,15 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) } s = ctx->curclient->session; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); + str = args->argv[0]; + ARRAY_INIT(&list_idx); ARRAY_INIT(&list_ctx); - xasprintf(&searchstr, "*%s*", data->arg); + xasprintf(&searchstr, "*%s*", str); RB_FOREACH(wm, winlinks, &s->windows) { i = 0; TAILQ_FOREACH(wp, &wm->window->panes, entry) { @@ -82,7 +83,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) if (fnmatch(searchstr, wm->window->name, 0) == 0) sctx = xstrdup(""); else { - sres = window_pane_search(wp, data->arg, &line); + sres = window_pane_search(wp, str, &line); if (sres == NULL && fnmatch(searchstr, wp->base.title, 0) != 0) continue; @@ -106,7 +107,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) xfree(searchstr); if (ARRAY_LENGTH(&list_idx) == 0) { - ctx->error(ctx, "no windows matching: %s", data->arg); + ctx->error(ctx, "no windows matching: %s", str); ARRAY_FREE(&list_idx); ARRAY_FREE(&list_ctx); return (-1); diff --git a/cmd-generic.c b/cmd-generic.c deleted file mode 100644 index 97e731c9..00000000 --- a/cmd-generic.c +++ /dev/null @@ -1,414 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2008 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include - -#include "tmux.h" - -int cmd_getopt(int, char **, const char *, const char *); -int cmd_parse_flags(int, const char *, uint64_t *); -size_t cmd_print_flags(char *, size_t, size_t, uint64_t); -int cmd_fill_argument(int, char **, char **, int, char **); - -size_t -cmd_prarg(char *buf, size_t len, const char *prefix, char *arg) -{ - if (strchr(arg, ' ') != NULL) - return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg)); - return (xsnprintf(buf, len, "%s%s", prefix, arg)); -} - -/* Append two flag strings together and call getopt. */ -int -cmd_getopt(int argc, char **argv, const char *flagstr, const char *chflagstr) -{ - char tmp[BUFSIZ]; - - if (strlcpy(tmp, flagstr, sizeof tmp) >= sizeof tmp) - fatalx("strlcpy overflow"); - if (strlcat(tmp, chflagstr, sizeof tmp) >= sizeof tmp) - fatalx("strlcat overflow"); - return (getopt(argc, argv, tmp)); -} - -/* Return if flag character is set. */ -int -cmd_check_flag(uint64_t chflags, int flag) -{ - if (flag >= 'A' && flag <= 'Z') - flag = 26 + flag - 'A'; - else if (flag >= 'a' && flag <= 'z') - flag = flag - 'a'; - else - return (0); - return ((chflags & (1ULL << flag)) != 0); -} - -/* Set flag character. */ -void -cmd_set_flag(uint64_t *chflags, int flag) -{ - if (flag >= 'A' && flag <= 'Z') - flag = 26 + flag - 'A'; - else if (flag >= 'a' && flag <= 'z') - flag = flag - 'a'; - else - return; - (*chflags) |= (1ULL << flag); -} - -/* If this option is expected, set it in chflags, otherwise return -1. */ -int -cmd_parse_flags(int opt, const char *chflagstr, uint64_t *chflags) -{ - if (strchr(chflagstr, opt) == NULL) - return (-1); - cmd_set_flag(chflags, opt); - return (0); -} - -/* Print the flags present in chflags. */ -size_t -cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags) -{ - u_char ch; - size_t boff = off; - - if (chflags == 0) - return (0); - off += xsnprintf(buf + off, len - off, " -"); - - for (ch = 0; ch < 26; ch++) { - if (cmd_check_flag(chflags, 'a' + ch)) - off += xsnprintf(buf + off, len - off, "%c", 'a' + ch); - if (cmd_check_flag(chflags, 'A' + ch)) - off += xsnprintf(buf + off, len - off, "%c", 'A' + ch); - } - return (off - boff); -} - -int -cmd_fill_argument(int flags, char **arg, char **arg2, int argc, char **argv) -{ - *arg = NULL; - *arg2 = NULL; - - if (flags & CMD_ARG1) { - if (argc != 1) - return (-1); - *arg = xstrdup(argv[0]); - return (0); - } - - if (flags & CMD_ARG01) { - if (argc != 0 && argc != 1) - return (-1); - if (argc == 1) - *arg = xstrdup(argv[0]); - return (0); - } - - if (flags & CMD_ARG2) { - if (argc != 2) - return (-1); - *arg = xstrdup(argv[0]); - *arg2 = xstrdup(argv[1]); - return (0); - } - - if (flags & CMD_ARG12) { - if (argc != 1 && argc != 2) - return (-1); - *arg = xstrdup(argv[0]); - if (argc == 2) - *arg2 = xstrdup(argv[1]); - return (0); - } - - if (argc != 0) - return (-1); - return (0); -} - -/* ARGSUSED */ -void -cmd_target_init(struct cmd *self, unused int key) -{ - struct cmd_target_data *data; - - self->data = data = xmalloc(sizeof *data); - data->chflags = 0; - data->target = NULL; - data->arg = NULL; - data->arg2 = NULL; -} - -int -cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_target_data *data; - const struct cmd_entry *entry = self->entry; - int opt; - - /* Don't use the entry version since it may be dependent on key. */ - cmd_target_init(self, 0); - data = self->data; - - while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) { - if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0) - continue; - switch (opt) { - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - - if (cmd_fill_argument( - self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0) - goto usage; - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - -void -cmd_target_free(struct cmd *self) -{ - struct cmd_target_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->arg != NULL) - xfree(data->arg); - if (data->arg2 != NULL) - xfree(data->arg2); - xfree(data); -} - -size_t -cmd_target_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_target_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - off += cmd_print_flags(buf, len, off, data->chflags); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - if (off < len && data->arg != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg); - if (off < len && data->arg2 != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg2); - return (off); -} - -/* ARGSUSED */ -void -cmd_srcdst_init(struct cmd *self, unused int key) -{ - struct cmd_srcdst_data *data; - - self->data = data = xmalloc(sizeof *data); - data->chflags = 0; - data->src = NULL; - data->dst = NULL; - data->arg = NULL; - data->arg2 = NULL; -} - -int -cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_srcdst_data *data; - const struct cmd_entry *entry = self->entry; - int opt; - - cmd_srcdst_init(self, 0); - data = self->data; - - while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) { - if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0) - continue; - switch (opt) { - case 's': - if (data->src == NULL) - data->src = xstrdup(optarg); - break; - case 't': - if (data->dst == NULL) - data->dst = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - - if (cmd_fill_argument( - self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0) - goto usage; - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - -void -cmd_srcdst_free(struct cmd *self) -{ - struct cmd_srcdst_data *data = self->data; - - if (data->src != NULL) - xfree(data->src); - if (data->dst != NULL) - xfree(data->dst); - if (data->arg != NULL) - xfree(data->arg); - if (data->arg2 != NULL) - xfree(data->arg2); - xfree(data); -} - -size_t -cmd_srcdst_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_srcdst_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - off += cmd_print_flags(buf, len, off, data->chflags); - if (off < len && data->src != NULL) - off += xsnprintf(buf + off, len - off, " -s %s", data->src); - if (off < len && data->dst != NULL) - off += xsnprintf(buf + off, len - off, " -t %s", data->dst); - if (off < len && data->arg != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg); - if (off < len && data->arg2 != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg2); - return (off); -} - -/* ARGSUSED */ -void -cmd_buffer_init(struct cmd *self, unused int key) -{ - struct cmd_buffer_data *data; - - self->data = data = xmalloc(sizeof *data); - data->chflags = 0; - data->buffer = -1; - data->arg = NULL; - data->arg2 = NULL; -} - -int -cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_buffer_data *data; - const struct cmd_entry *entry = self->entry; - int opt, n; - const char *errstr; - - cmd_buffer_init(self, 0); - data = self->data; - - while ((opt = cmd_getopt(argc, argv, "b:", entry->chflags)) != -1) { - if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0) - continue; - switch (opt) { - case 'b': - if (data->buffer == -1) { - n = strtonum(optarg, 0, INT_MAX, &errstr); - if (errstr != NULL) { - xasprintf(cause, "buffer %s", errstr); - goto error; - } - data->buffer = n; - } - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - - if (cmd_fill_argument( - self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0) - goto usage; - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); -} - -void -cmd_buffer_free(struct cmd *self) -{ - struct cmd_buffer_data *data = self->data; - - if (data->arg != NULL) - xfree(data->arg); - if (data->arg2 != NULL) - xfree(data->arg2); - xfree(data); -} - -size_t -cmd_buffer_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_buffer_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - off += cmd_print_flags(buf, len, off, data->chflags); - if (off < len && data->buffer != -1) - off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); - if (off < len && data->arg != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg); - if (off < len && data->arg2 != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->arg2); - return (off); -} diff --git a/cmd-has-session.c b/cmd-has-session.c index 00f171b7..d5d806a1 100644 --- a/cmd-has-session.c +++ b/cmd-has-session.c @@ -28,21 +28,20 @@ int cmd_has_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_has_session_entry = { "has-session", "has", + "t:", 0, 0, CMD_TARGET_SESSION_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_has_session_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_has_session_exec }; int cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; - if (cmd_find_session(ctx, data->target) == NULL) + if (cmd_find_session(ctx, args_get(args, 't')) == NULL) return (-1); return (0); diff --git a/cmd-if-shell.c b/cmd-if-shell.c index bf60fb23..b7671332 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -35,13 +35,12 @@ void cmd_if_shell_free(void *); const struct cmd_entry cmd_if_shell_entry = { "if-shell", "if", + "", 2, 2, "shell-command command", - CMD_ARG2, "", - cmd_target_init, - cmd_target_parse, - cmd_if_shell_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_if_shell_exec }; struct cmd_if_shell_data { @@ -52,12 +51,12 @@ struct cmd_if_shell_data { int cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_if_shell_data *cdata; struct job *job; cdata = xmalloc(sizeof *cdata); - cdata->cmd = xstrdup(data->arg2); + cdata->cmd = xstrdup(args->argv[1]); memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); if (ctx->cmdclient != NULL) @@ -66,7 +65,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) ctx->curclient->references++; job = job_add(NULL, 0, NULL, - data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata); + args->argv[0], cmd_if_shell_callback, cmd_if_shell_free, cdata); job_run(job); return (1); /* don't let client exit */ diff --git a/cmd-join-pane.c b/cmd-join-pane.c index d13c23e3..10b4dda3 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -28,139 +28,54 @@ * Join a pane into another (like split/swap/kill). */ -int cmd_join_pane_parse(struct cmd *, int, char **, char **); +void cmd_join_pane_key_binding(struct cmd *, int); int cmd_join_pane_exec(struct cmd *, struct cmd_ctx *); -void cmd_join_pane_free(struct cmd *); -void cmd_join_pane_init(struct cmd *, int); -size_t cmd_join_pane_print(struct cmd *, char *, size_t); - -struct cmd_join_pane_data { - char *src; - char *dst; - int flag_detached; - int flag_horizontal; - int percentage; - int size; -}; const struct cmd_entry cmd_join_pane_entry = { "join-pane", "joinp", + "dhvp:l:s:t:", 0, 0, "[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]", - 0, "", - cmd_join_pane_init, - cmd_join_pane_parse, - cmd_join_pane_exec, - cmd_join_pane_free, - cmd_join_pane_print + 0, + cmd_join_pane_key_binding, + NULL, + cmd_join_pane_exec }; void -cmd_join_pane_init(struct cmd *self, int key) +cmd_join_pane_key_binding(struct cmd *self, int key) { - struct cmd_join_pane_data *data; - - self->data = data = xmalloc(sizeof *data); - data->src = NULL; - data->dst = NULL; - data->flag_detached = 0; - data->flag_horizontal = 0; - data->percentage = -1; - data->size = -1; - switch (key) { case '%': - data->flag_horizontal = 1; + self->args = args_create(0); + args_set(self->args, 'h', NULL); break; - case '"': - data->flag_horizontal = 0; + default: + self->args = args_create(0); break; } } -int -cmd_join_pane_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_join_pane_data *data; - int opt; - const char *errstr; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "dhl:p:s:t:v")) != -1) { - switch (opt) { - case 'd': - data->flag_detached = 1; - break; - case 'h': - data->flag_horizontal = 1; - break; - case 's': - if (data->src == NULL) - data->src = xstrdup(optarg); - break; - case 't': - if (data->dst == NULL) - data->dst = xstrdup(optarg); - break; - case 'l': - if (data->percentage != -1 || data->size != -1) - break; - data->size = strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr != NULL) { - xasprintf(cause, "size %s", errstr); - goto error; - } - break; - case 'p': - if (data->size != -1 || data->percentage != -1) - break; - data->percentage = strtonum(optarg, 1, 100, &errstr); - if (errstr != NULL) { - xasprintf(cause, "percentage %s", errstr); - goto error; - } - break; - case 'v': - data->flag_horizontal = 0; - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0) - goto usage; - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); -} - int cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_join_pane_data *data = self->data; - struct session *dst_s; - struct winlink *src_wl, *dst_wl; - struct window *src_w, *dst_w; - struct window_pane *src_wp, *dst_wp; - int size, dst_idx; - enum layout_type type; - struct layout_cell *lc; + struct args *args = self->args; + struct session *dst_s; + struct winlink *src_wl, *dst_wl; + struct window *src_w, *dst_w; + struct window_pane *src_wp, *dst_wp; + char *cause; + int size, percentage, dst_idx; + enum layout_type type; + struct layout_cell *lc; - if ((dst_wl = cmd_find_pane(ctx, data->dst, &dst_s, &dst_wp)) == NULL) + dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp); + if (dst_wl == NULL) return (-1); dst_w = dst_wl->window; dst_idx = dst_wl->idx; - if ((src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp)) == NULL) + src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); + if (src_wl == NULL) return (-1); src_w = src_wl->window; @@ -170,17 +85,28 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } type = LAYOUT_TOPBOTTOM; - if (data->flag_horizontal) + if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; - if (data->size != -1) - size = data->size; - else if (data->percentage != -1) { + if (args_has(args, 's')) { + size = args_strtonum(args, 's', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "size %s", cause); + xfree(cause); + return (-1); + } + } else if (args_has(args, 'p')) { + percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "percentage %s", cause); + xfree(cause); + return (-1); + } if (type == LAYOUT_TOPBOTTOM) - size = (dst_wp->sy * data->percentage) / 100; + size = (dst_wp->sy * percentage) / 100; else - size = (dst_wp->sx * data->percentage) / 100; + size = (dst_wp->sx * percentage) / 100; } if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) { @@ -209,7 +135,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) server_redraw_window(src_w); server_redraw_window(dst_w); - if (!data->flag_detached) { + if (!args_has(args, 'd')) { window_set_active_pane(dst_w, src_wp); session_select(dst_s, dst_idx); server_redraw_session(dst_s); @@ -218,41 +144,3 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) return (0); } - -void -cmd_join_pane_free(struct cmd *self) -{ - struct cmd_join_pane_data *data = self->data; - - if (data->src != NULL) - xfree(data->src); - if (data->dst != NULL) - xfree(data->dst); - xfree(data); -} - -size_t -cmd_join_pane_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_join_pane_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_detached) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flag_horizontal) - off += xsnprintf(buf + off, len - off, " -h"); - if (off < len && data->size > 0) - off += xsnprintf(buf + off, len - off, " -l %d", data->size); - if (off < len && data->percentage > 0) { - off += xsnprintf( - buf + off, len - off, " -p %d", data->percentage); - } - if (off < len && data->src != NULL) - off += cmd_prarg(buf + off, len - off, " -s ", data->src); - if (off < len && data->dst != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->dst); - return (off); -} diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c index c48e4d4e..215c8ed7 100644 --- a/cmd-kill-pane.c +++ b/cmd-kill-pane.c @@ -30,23 +30,22 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_kill_pane_entry = { "kill-pane", "killp", + "at:", 0, 0, "[-a] " CMD_TARGET_PANE_USAGE, - 0, "a", - cmd_target_init, - cmd_target_parse, - cmd_kill_pane_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_kill_pane_exec }; int cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window_pane *loopwp, *nextwp, *wp; - if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) return (-1); if (window_count_panes(wl->window) == 1) { @@ -56,7 +55,7 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) return (0); } - if (cmd_check_flag(data->chflags, 'a')) { + if (args_has(self->args, 'a')) { loopwp = TAILQ_FIRST(&wl->window->panes); while (loopwp != NULL) { nextwp = TAILQ_NEXT(loopwp, entry); diff --git a/cmd-kill-server.c b/cmd-kill-server.c index 9e6ddb21..800563a4 100644 --- a/cmd-kill-server.c +++ b/cmd-kill-server.c @@ -31,13 +31,12 @@ int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_kill_server_entry = { "kill-server", NULL, + "", 0, 0, "", - 0, "", + 0, NULL, NULL, - cmd_kill_server_exec, - NULL, - NULL + cmd_kill_server_exec }; /* ARGSUSED */ diff --git a/cmd-kill-session.c b/cmd-kill-session.c index efd91801..086dbc67 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -31,22 +31,21 @@ int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_kill_session_entry = { "kill-session", NULL, + "t:", 0, 0, CMD_TARGET_SESSION_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_kill_session_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_kill_session_exec }; int cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; + struct args *args = self->args; + struct session *s; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); server_destroy_session(s); diff --git a/cmd-kill-window.c b/cmd-kill-window.c index aae1cc85..30f4c40e 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -28,22 +28,21 @@ int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_kill_window_entry = { "kill-window", "killw", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_kill_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_kill_window_exec }; int cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; + struct args *args = self->args; + struct winlink *wl; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); server_kill_window(wl->window); diff --git a/cmd-last-pane.c b/cmd-last-pane.c index b59843b7..f9f61495 100644 --- a/cmd-last-pane.c +++ b/cmd-last-pane.c @@ -28,23 +28,22 @@ int cmd_last_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_last_pane_entry = { "last-pane", "lastp", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_last_pane_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_last_pane_exec }; int cmd_last_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - struct window *w; + struct args *args = self->args; + struct winlink *wl; + struct window *w; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); w = wl->window; diff --git a/cmd-last-window.c b/cmd-last-window.c index 5f065ccb..209f367b 100644 --- a/cmd-last-window.c +++ b/cmd-last-window.c @@ -28,22 +28,21 @@ int cmd_last_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_last_window_entry = { "last-window", "last", + "t:", 0, 0, CMD_TARGET_SESSION_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_last_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_last_window_exec }; int cmd_last_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; + struct args *args = self->args; + struct session *s; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); if (session_last(s) == 0) diff --git a/cmd-link-window.c b/cmd-link-window.c index f8da27dd..a278fe34 100644 --- a/cmd-link-window.c +++ b/cmd-link-window.c @@ -30,31 +30,30 @@ int cmd_link_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_link_window_entry = { "link-window", "linkw", + "dks:t:", 0, 0, "[-dk] " CMD_SRCDST_WINDOW_USAGE, - 0, "dk", - cmd_srcdst_init, - cmd_srcdst_parse, - cmd_link_window_exec, - cmd_srcdst_free, - cmd_srcdst_print + 0, + NULL, + NULL, + cmd_link_window_exec }; int cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_srcdst_data *data = self->data; - struct session *src, *dst; - struct winlink *wl; - char *cause; - int idx, kflag, dflag; + struct args *args = self->args; + struct session *src, *dst; + struct winlink *wl; + char *cause; + int idx, kflag, dflag; - if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL) return (-1); - if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) + if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2) return (-1); - kflag = cmd_check_flag(data->chflags, 'k'); - dflag = cmd_check_flag(data->chflags, 'd'); + kflag = args_has(self->args, 'k'); + dflag = args_has(self->args, 'd'); if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { ctx->error(ctx, "can't link window: %s", cause); xfree(cause); diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c index efc86f97..d4ff9a22 100644 --- a/cmd-list-buffers.c +++ b/cmd-list-buffers.c @@ -30,13 +30,12 @@ int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_buffers_entry = { "list-buffers", "lsb", + "", 0, 0, "", - 0, "", + 0, NULL, NULL, - cmd_list_buffers_exec, - NULL, - NULL + cmd_list_buffers_exec }; /* ARGSUSED */ diff --git a/cmd-list-clients.c b/cmd-list-clients.c index 9c941b45..026f12a7 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -31,13 +31,12 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_clients_entry = { "list-clients", "lsc", + "", 0, 0, "", - 0, "", + 0, NULL, NULL, - cmd_list_clients_exec, - NULL, - NULL + cmd_list_clients_exec }; /* ARGSUSED */ diff --git a/cmd-list-commands.c b/cmd-list-commands.c index a5c98ea7..87901210 100644 --- a/cmd-list-commands.c +++ b/cmd-list-commands.c @@ -28,13 +28,12 @@ int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_commands_entry = { "list-commands", "lscm", + "", 0, 0, "", - 0, "", + 0, NULL, NULL, - cmd_list_commands_exec, - NULL, - NULL + cmd_list_commands_exec }; /* ARGSUSED */ diff --git a/cmd-list-keys.c b/cmd-list-keys.c index b60b4666..c6c391a2 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -32,26 +32,25 @@ int cmd_list_keys_table(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_keys_entry = { "list-keys", "lsk", + "t:", 0, 0, "[-t key-table]", - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_list_keys_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_list_keys_exec }; int cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct key_binding *bd; const char *key; char tmp[BUFSIZ]; size_t used; int width, keywidth; - if (data->target != NULL) + if (args_has(args, 't')) return (cmd_list_keys_table(self, ctx)); width = 0; @@ -95,14 +94,16 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) int cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; + const char *tablename; const struct mode_key_table *mtab; struct mode_key_binding *mbind; const char *key, *cmdstr, *mode; int width, keywidth; - if ((mtab = mode_key_findtable(data->target)) == NULL) { - ctx->error(ctx, "unknown key table: %s", data->target); + tablename = args_get(args, 't'); + if ((mtab = mode_key_findtable(tablename)) == NULL) { + ctx->error(ctx, "unknown key table: %s", tablename); return (-1); } diff --git a/cmd-list-panes.c b/cmd-list-panes.c index e96d596b..03fd7afd 100644 --- a/cmd-list-panes.c +++ b/cmd-list-panes.c @@ -30,19 +30,18 @@ int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_panes_entry = { "list-panes", "lsp", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_list_panes_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_list_panes_exec }; int cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window_pane *wp; struct grid *gd; @@ -50,7 +49,7 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx) u_int i, n; unsigned long long size; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); n = 0; diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c index e7aa22d7..6c0f2dae 100644 --- a/cmd-list-sessions.c +++ b/cmd-list-sessions.c @@ -30,13 +30,13 @@ int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_sessions_entry = { - "list-sessions", "ls", "", - 0, "", + "list-sessions", "ls", + "", 0, 0, + "", + 0, NULL, NULL, - cmd_list_sessions_exec, - NULL, - NULL + cmd_list_sessions_exec }; /* ARGSUSED */ diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 7a4a28c2..331b521a 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -30,24 +30,23 @@ int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_windows_entry = { "list-windows", "lsw", + "t:", 0, 0, CMD_TARGET_SESSION_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_list_windows_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_list_windows_exec }; int cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct winlink *wl; - char *layout; + struct args *args = self->args; + struct session *s; + struct winlink *wl; + char *layout; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); RB_FOREACH(wl, winlinks, &s->windows) { diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index 13413e4b..55a5cd14 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -35,41 +35,57 @@ void cmd_load_buffer_callback(struct client *, void *); const struct cmd_entry cmd_load_buffer_entry = { "load-buffer", "loadb", + "b:", 1, 1, CMD_BUFFER_USAGE " path", - CMD_ARG1, "", - cmd_buffer_init, - cmd_buffer_parse, - cmd_load_buffer_exec, - cmd_buffer_free, - cmd_buffer_print + 0, + NULL, + NULL, + cmd_load_buffer_exec }; int cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; - struct client *c = ctx->cmdclient; - FILE *f; - char *pdata, *new_pdata; - size_t psize; - u_int limit; - int ch; + struct args *args = self->args; + struct client *c = ctx->cmdclient; + FILE *f; + const char *path; + char *pdata, *new_pdata, *cause; + size_t psize; + u_int limit; + int ch, buffer; + int *buffer_ptr; - if (strcmp(data->arg, "-") == 0) { + if (!args_has(args, 'b')) + buffer = -1; + else { + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + } + + path = args->argv[0]; + if (strcmp(path, "-") == 0) { if (c == NULL) { - ctx->error(ctx, "%s: can't read from stdin", data->arg); + ctx->error(ctx, "%s: can't read from stdin", path); return (-1); } if (c->flags & CLIENT_TERMINAL) { - ctx->error(ctx, "%s: stdin is a tty", data->arg); + ctx->error(ctx, "%s: stdin is a tty", path); return (-1); } if (c->stdin_fd == -1) { - ctx->error(ctx, "%s: can't read from stdin", data->arg); + ctx->error(ctx, "%s: can't read from stdin", path); return (-1); } - c->stdin_data = &data->buffer; + buffer_ptr = xmalloc(sizeof *buffer_ptr); + *buffer_ptr = buffer; + + c->stdin_data = buffer_ptr; c->stdin_callback = cmd_load_buffer_callback; c->references++; @@ -77,8 +93,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) return (1); } - if ((f = fopen(data->arg, "rb")) == NULL) { - ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); + if ((f = fopen(path, "rb")) == NULL) { + ctx->error(ctx, "%s: %s", path, strerror(errno)); return (-1); } @@ -94,7 +110,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) pdata[psize++] = ch; } if (ferror(f)) { - ctx->error(ctx, "%s: read error", data->arg); + ctx->error(ctx, "%s: read error", path); goto error; } if (pdata != NULL) @@ -103,12 +119,12 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) fclose(f); limit = options_get_number(&global_options, "buffer-limit"); - if (data->buffer == -1) { + if (buffer == -1) { paste_add(&global_buffers, pdata, psize, limit); return (0); } - if (paste_replace(&global_buffers, data->buffer, pdata, psize) != 0) { - ctx->error(ctx, "no buffer %d", data->buffer); + if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { + ctx->error(ctx, "no buffer %d", buffer); return (-1); } @@ -125,10 +141,10 @@ error: void cmd_load_buffer_callback(struct client *c, void *data) { + int *buffer = data; char *pdata; size_t psize; u_int limit; - int *buffer = data; /* * Event callback has already checked client is not dead and reduced @@ -137,12 +153,10 @@ cmd_load_buffer_callback(struct client *c, void *data) c->flags |= CLIENT_EXIT; psize = EVBUFFER_LENGTH(c->stdin_event->input); - if (psize == 0) - return; - - pdata = malloc(psize + 1); - if (pdata == NULL) + if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) { + free(data); return; + } bufferevent_read(c->stdin_event, pdata, psize); pdata[psize] = '\0'; @@ -155,4 +169,6 @@ cmd_load_buffer_callback(struct client *c, void *data) c->stderr_event->output, "no buffer %d\n", *buffer); bufferevent_enable(c->stderr_event, EV_WRITE); } + + free (data); } diff --git a/cmd-lock-client.c b/cmd-lock-client.c index 607c9d22..bc5a1aa4 100644 --- a/cmd-lock-client.c +++ b/cmd-lock-client.c @@ -28,22 +28,21 @@ int cmd_lock_client_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_lock_client_entry = { "lock-client", "lockc", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_lock_client_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_lock_client_exec }; int cmd_lock_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct args *args = self->args; + struct client *c; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); server_lock_client(c); diff --git a/cmd-lock-server.c b/cmd-lock-server.c index b588e2b2..347cc128 100644 --- a/cmd-lock-server.c +++ b/cmd-lock-server.c @@ -32,13 +32,12 @@ int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_lock_server_entry = { "lock-server", "lock", + "", 0, 0, "", - 0, "", - NULL, - NULL, - cmd_lock_server_exec, + 0, NULL, NULL, + cmd_lock_server_exec }; /* ARGSUSED */ diff --git a/cmd-lock-session.c b/cmd-lock-session.c index 279ab655..4b75c973 100644 --- a/cmd-lock-session.c +++ b/cmd-lock-session.c @@ -28,22 +28,21 @@ int cmd_lock_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_lock_session_entry = { "lock-session", "locks", + "t:", 0, 0, CMD_TARGET_SESSION_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_lock_session_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_lock_session_exec }; int cmd_lock_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; + struct args *args = self->args; + struct session *s; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); server_lock_session(s); diff --git a/cmd-move-window.c b/cmd-move-window.c index 6105812a..ee3ba59c 100644 --- a/cmd-move-window.c +++ b/cmd-move-window.c @@ -30,31 +30,30 @@ int cmd_move_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_move_window_entry = { "move-window", "movew", + "dks:t:", 0, 0, "[-dk] " CMD_SRCDST_WINDOW_USAGE, - 0, "dk", - cmd_srcdst_init, - cmd_srcdst_parse, - cmd_move_window_exec, - cmd_srcdst_free, - cmd_srcdst_print + 0, + NULL, + NULL, + cmd_move_window_exec }; int cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_srcdst_data *data = self->data; - struct session *src, *dst; - struct winlink *wl; - char *cause; - int idx, kflag, dflag; + struct args *args = self->args; + struct session *src, *dst; + struct winlink *wl; + char *cause; + int idx, kflag, dflag; - if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL) return (-1); - if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) + if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2) return (-1); - kflag = cmd_check_flag(data->chflags, 'k'); - dflag = cmd_check_flag(data->chflags, 'd'); + kflag = args_has(self->args, 'k'); + dflag = args_has(self->args, 'd'); if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { ctx->error(ctx, "can't move window: %s", cause); xfree(cause); diff --git a/cmd-new-session.c b/cmd-new-session.c index 53a50bbb..d53e2692 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -29,119 +29,55 @@ * Create a new session and attach to the current terminal unless -d is given. */ -int cmd_new_session_parse(struct cmd *, int, char **, char **); +int cmd_new_session_check(struct args *); int cmd_new_session_exec(struct cmd *, struct cmd_ctx *); -void cmd_new_session_free(struct cmd *); -void cmd_new_session_init(struct cmd *, int); -size_t cmd_new_session_print(struct cmd *, char *, size_t); - -struct cmd_new_session_data { - char *target; - char *newname; - char *winname; - char *cmd; - int flag_detached; -}; const struct cmd_entry cmd_new_session_entry = { "new-session", "new", + "dn:s:t:", 0, 1, "[-d] [-n window-name] [-s session-name] [-t target-session] [command]", - CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, "", - cmd_new_session_init, - cmd_new_session_parse, - cmd_new_session_exec, - cmd_new_session_free, - cmd_new_session_print + CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, + NULL, + cmd_new_session_check, + cmd_new_session_exec }; -/* ARGSUSED */ -void -cmd_new_session_init(struct cmd *self, unused int arg) -{ - struct cmd_new_session_data *data; - - self->data = data = xmalloc(sizeof *data); - data->flag_detached = 0; - data->target = NULL; - data->newname = NULL; - data->winname = NULL; - data->cmd = NULL; -} - int -cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause) +cmd_new_session_check(struct args *args) { - struct cmd_new_session_data *data; - int opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "ds:t:n:")) != -1) { - switch (opt) { - case 'd': - data->flag_detached = 1; - break; - case 's': - if (data->newname == NULL) - data->newname = xstrdup(optarg); - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - case 'n': - if (data->winname == NULL) - data->winname = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0 && argc != 1) - goto usage; - - if (data->target != NULL && (argc == 1 || data->winname != NULL)) - goto usage; - - if (argc == 1) - data->cmd = xstrdup(argv[0]); - + if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) + return (-1); return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); } int cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_new_session_data *data = self->data; - struct session *s, *old_s, *groupwith; - struct window *w; - struct window_pane *wp; - struct environ env; - struct termios tio, *tiop; - struct passwd *pw; - const char *update, *cwd; - char *overrides, *cmd, *cause; - int detached, idx; - u_int sx, sy, i; + struct args *args = self->args; + struct session *s, *old_s, *groupwith; + struct window *w; + struct window_pane *wp; + struct environ env; + struct termios tio, *tiop; + struct passwd *pw; + const char *newname, *target, *update, *cwd; + char *overrides, *cmd, *cause; + int detached, idx; + u_int sx, sy, i; - if (data->newname != NULL && session_find(data->newname) != NULL) { - ctx->error(ctx, "duplicate session: %s", data->newname); + newname = args_get(args, 's'); + if (newname != NULL && session_find(newname) != NULL) { + ctx->error(ctx, "duplicate session: %s", newname); return (-1); } - groupwith = NULL; - if (data->target != NULL && - (groupwith = cmd_find_session(ctx, data->target)) == NULL) - return (-1); + target = args_get(args, 't'); + if (target != NULL) { + groupwith = cmd_find_session(ctx, target); + if (groupwith == NULL) + return (-1); + } else + groupwith = NULL; /* * There are three cases: @@ -162,7 +98,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) */ /* Set -d if no client. */ - detached = data->flag_detached; + detached = args_has(args, 'd'); if (ctx->cmdclient == NULL && ctx->curclient == NULL) detached = 1; @@ -228,10 +164,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) sy = 1; /* Figure out the command for the new window. */ - if (data->target != NULL) + if (target != NULL) cmd = NULL; - else if (data->cmd != NULL) - cmd = data->cmd; + else if (args->argc != 0) + cmd = args->argv[0]; else cmd = options_get_string(&global_s_options, "default-command"); @@ -243,8 +179,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) /* Create the new session. */ idx = -1 - options_get_number(&global_s_options, "base-index"); - s = session_create( - data->newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause); + s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause); if (s == NULL) { ctx->error(ctx, "create session failed: %s", cause); xfree(cause); @@ -253,11 +188,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) environ_free(&env); /* Set the initial window name if one given. */ - if (cmd != NULL && data->winname != NULL) { + if (cmd != NULL && args_has(args, 'n')) { w = s->curw->window; xfree(w->name); - w->name = xstrdup(data->winname); + w->name = xstrdup(args_get(args, 'n')); options_set_number(&w->options, "automatic-rename", 0); } @@ -316,39 +251,3 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) return (!detached); /* 1 means don't tell command client to exit */ } - -void -cmd_new_session_free(struct cmd *self) -{ - struct cmd_new_session_data *data = self->data; - - if (data->newname != NULL) - xfree(data->newname); - if (data->winname != NULL) - xfree(data->winname); - if (data->cmd != NULL) - xfree(data->cmd); - xfree(data); -} - -size_t -cmd_new_session_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_new_session_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_detached) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->winname != NULL) - off += cmd_prarg(buf + off, len - off, " -n ", data->winname); - if (off < len && data->newname != NULL) - off += cmd_prarg(buf + off, len - off, " -s ", data->newname); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - if (off < len && data->cmd != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->cmd); - return (off); -} diff --git a/cmd-new-window.c b/cmd-new-window.c index e17cdf1d..955f6449 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -26,115 +26,30 @@ * Create a new window. */ -int cmd_new_window_parse(struct cmd *, int, char **, char **); int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); -void cmd_new_window_free(struct cmd *); -void cmd_new_window_init(struct cmd *, int); -size_t cmd_new_window_print(struct cmd *, char *, size_t); - -struct cmd_new_window_data { - char *target; - char *name; - char *cmd; - int flag_insert_after; - int flag_detached; - int flag_kill; - int flag_print; -}; const struct cmd_entry cmd_new_window_entry = { "new-window", "neww", - "[-adkP] [-n window-name] [-t target-window] [command]", - 0, "", - cmd_new_window_init, - cmd_new_window_parse, - cmd_new_window_exec, - cmd_new_window_free, - cmd_new_window_print + "adkn:Pt:", 0, 1, + "[-adk] [-n window-name] [-t target-window] [command]", + 0, + NULL, + NULL, + cmd_new_window_exec }; -/* ARGSUSED */ -void -cmd_new_window_init(struct cmd *self, unused int arg) -{ - struct cmd_new_window_data *data; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->name = NULL; - data->cmd = NULL; - data->flag_insert_after = 0; - data->flag_detached = 0; - data->flag_kill = 0; - data->flag_print = 0; -} - -int -cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_new_window_data *data; - int opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "adkt:n:P")) != -1) { - switch (opt) { - case 'a': - data->flag_insert_after = 1; - break; - case 'd': - data->flag_detached = 1; - break; - case 'k': - data->flag_kill = 1; - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - case 'n': - if (data->name == NULL) - data->name = xstrdup(optarg); - break; - case 'P': - data->flag_print = 1; - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0 && argc != 1) - goto usage; - - if (argc == 1) - data->cmd = xstrdup(argv[0]); - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - int cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_new_window_data *data = self->data; - struct session *s; - struct winlink *wl; - char *cmd, *cwd, *cause; - int idx, last; + struct args *args = self->args; + struct session *s; + struct winlink *wl; + char *cmd, *cwd, *cause; + int idx, last, detached; - if (data == NULL) - return (0); - - if (data->flag_insert_after) { - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + if (args_has(args, 'a')) { + wl = cmd_find_window(ctx, args_get(args, 't'), &s); + if (wl == NULL) return (-1); idx = wl->idx + 1; @@ -155,14 +70,15 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) server_unlink_window(s, wl); } } else { - if ((idx = cmd_find_index(ctx, data->target, &s)) == -2) + if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2) return (-1); } + detached = args_has(args, 'd'); wl = NULL; if (idx != -1) wl = winlink_find_by_index(&s->windows, idx); - if (wl != NULL && data->flag_kill) { + if (wl != NULL && args_has(args, 'k')) { /* * Can't use session_detach as it will destroy session if this * makes it empty. @@ -173,14 +89,15 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) /* Force select/redraw if current. */ if (wl == s->curw) { - data->flag_detached = 0; + detached = 0; s->curw = NULL; } } - cmd = data->cmd; - if (cmd == NULL) + if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); + else + cmd = args->argv[0]; cwd = options_get_string(&s->options, "default-path"); if (*cwd == '\0') { if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) @@ -191,55 +108,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); - wl = session_new(s, data->name, cmd, cwd, idx, &cause); + wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); if (wl == NULL) { ctx->error(ctx, "create window failed: %s", cause); xfree(cause); return (-1); } - if (!data->flag_detached) { + if (!detached) { session_select(s, wl->idx); server_redraw_session_group(s); } else server_status_session_group(s); - if (data->flag_print) + if (args_has(args, 'P')) ctx->print(ctx, "%s:%u", s->name, wl->idx); return (0); } - -void -cmd_new_window_free(struct cmd *self) -{ - struct cmd_new_window_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->name != NULL) - xfree(data->name); - if (data->cmd != NULL) - xfree(data->cmd); - xfree(data); -} - -size_t -cmd_new_window_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_new_window_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_detached) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flag_print) - off += xsnprintf(buf + off, len - off, " -P"); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - if (off < len && data->name != NULL) - off += cmd_prarg(buf + off, len - off, " -n ", data->name); - if (off < len && data->cmd != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->cmd); - return (off); -} diff --git a/cmd-next-layout.c b/cmd-next-layout.c index aa033a83..bdd6f3e5 100644 --- a/cmd-next-layout.c +++ b/cmd-next-layout.c @@ -28,23 +28,22 @@ int cmd_next_layout_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_next_layout_entry = { "next-layout", "nextl", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_next_layout_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_next_layout_exec }; int cmd_next_layout_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - u_int layout; + struct args *args = self->args; + struct winlink *wl; + u_int layout; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); layout = layout_set_next(wl->window); diff --git a/cmd-next-window.c b/cmd-next-window.c index cc361b62..c9cb77a9 100644 --- a/cmd-next-window.c +++ b/cmd-next-window.c @@ -24,44 +24,39 @@ * Move to next window. */ -void cmd_next_window_init(struct cmd *, int); +void cmd_next_window_key_binding(struct cmd *, int); int cmd_next_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_next_window_entry = { "next-window", "next", + "at:", 0, 0, "[-a] " CMD_TARGET_SESSION_USAGE, - 0, "a", - cmd_next_window_init, - cmd_target_parse, - cmd_next_window_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_next_window_key_binding, + NULL, + cmd_next_window_exec }; void -cmd_next_window_init(struct cmd *self, int key) +cmd_next_window_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - + self->args = args_create(0); if (key == ('n' | KEYC_ESCAPE)) - cmd_set_flag(&data->chflags, 'a'); + args_set(self->args, 'a', NULL); } int cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - int activity; + struct args *args = self->args; + struct session *s; + int activity; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); activity = 0; - if (cmd_check_flag(data->chflags, 'a')) + if (args_has(self->args, 'a')) activity = 1; if (session_next(s, activity) == 0) diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index 439d7190..0d145c7d 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -28,132 +28,73 @@ * Paste paste buffer if present. */ -struct cmd_paste_buffer_data { - char *target; - int buffer; - - int flag_delete; - char *sepstr; -}; - -void cmd_paste_buffer_init(struct cmd *, int); -int cmd_paste_buffer_parse(struct cmd *, int, char **, char **); int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); + void cmd_paste_buffer_filter( - struct window_pane *, const char *, size_t, char *); -void cmd_paste_buffer_free(struct cmd *); -size_t cmd_paste_buffer_print(struct cmd *, char *, size_t); + struct window_pane *, const char *, size_t, const char *); const struct cmd_entry cmd_paste_buffer_entry = { "paste-buffer", "pasteb", + "db:rs:t:", 0, 0, "[-dr] [-s separator] [-b buffer-index] [-t target-pane]", - 0, "", - cmd_paste_buffer_init, - cmd_paste_buffer_parse, - cmd_paste_buffer_exec, - cmd_paste_buffer_free, - cmd_paste_buffer_print + 0, + NULL, + NULL, + cmd_paste_buffer_exec }; -/* ARGSUSED */ -void -cmd_paste_buffer_init(struct cmd *self, unused int arg) -{ - struct cmd_paste_buffer_data *data; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->buffer = -1; - data->flag_delete = 0; - data->sepstr = xstrdup("\r"); -} - -int -cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_paste_buffer_data *data; - int opt, n; - const char *errstr; - - cmd_paste_buffer_init(self, 0); - data = self->data; - - while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) { - switch (opt) { - case 'b': - if (data->buffer == -1) { - n = strtonum(optarg, 0, INT_MAX, &errstr); - if (errstr != NULL) { - xasprintf(cause, "buffer %s", errstr); - goto error; - } - data->buffer = n; - } - break; - case 'd': - data->flag_delete = 1; - break; - case 's': - if (data->sepstr != NULL) - xfree(data->sepstr); - data->sepstr = xstrdup(optarg); - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - case 'r': - if (data->sepstr != NULL) - xfree(data->sepstr); - data->sepstr = xstrdup("\n"); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); -} - int cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_paste_buffer_data *data = self->data; - struct window_pane *wp; - struct session *s; - struct paste_buffer *pb; + struct args *args = self->args; + struct window_pane *wp; + struct session *s; + struct paste_buffer *pb; + const char *sepstr; + char *cause; + int buffer; - if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) return (-1); - if (data->buffer == -1) - pb = paste_get_top(&global_buffers); + if (!args_has(args, 'b')) + buffer = -1; else { - pb = paste_get_index(&global_buffers, data->buffer); - if (pb == NULL) { - ctx->error(ctx, "no buffer %d", data->buffer); + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); return (-1); } } - if (pb != NULL) - cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr); + if (buffer == -1) + pb = paste_get_top(&global_buffers); + else { + pb = paste_get_index(&global_buffers, buffer); + if (pb == NULL) { + ctx->error(ctx, "no buffer %d", buffer); + return (-1); + } + } + + if (pb != NULL) { + sepstr = args_get(args, 's'); + if (sepstr == NULL) { + if (args_has(args, 'r')) + sepstr = "\n"; + else + sepstr = "\r"; + } + cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr); + } /* Delete the buffer if -d. */ - if (data->flag_delete) { - if (data->buffer == -1) + if (args_has(args, 'd')) { + if (buffer == -1) paste_free_top(&global_buffers); else - paste_free_index(&global_buffers, data->buffer); + paste_free_index(&global_buffers, buffer); } return (0); @@ -162,7 +103,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) /* Add bytes to a buffer and filter '\n' according to separator. */ void cmd_paste_buffer_filter( - struct window_pane *wp, const char *data, size_t size, char *sep) + struct window_pane *wp, const char *data, size_t size, const char *sep) { const char *end = data + size; const char *lf; @@ -179,46 +120,3 @@ cmd_paste_buffer_filter( if (end != data) bufferevent_write(wp->event, data, end - data); } - -void -cmd_paste_buffer_free(struct cmd *self) -{ - struct cmd_paste_buffer_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->sepstr != NULL) - xfree(data->sepstr); - xfree(data); -} - -size_t -cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_paste_buffer_data *data = self->data; - size_t off = 0; - char tmp[BUFSIZ]; - int r_flag; - - r_flag = 0; - if (data->sepstr != NULL) - r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0'); - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_delete) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && r_flag) - off += xsnprintf(buf + off, len - off, " -r"); - if (off < len && data->buffer != -1) - off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); - if (off < len && data->sepstr != NULL && !r_flag) { - strnvis( - tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL); - off += cmd_prarg(buf + off, len - off, " -s ", tmp); - } - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - return (off); -} diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c index d287d3b6..6284bf37 100644 --- a/cmd-pipe-pane.c +++ b/cmd-pipe-pane.c @@ -38,19 +38,18 @@ void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *); const struct cmd_entry cmd_pipe_pane_entry = { "pipe-pane", "pipep", + "ot:", 0, 1, CMD_TARGET_PANE_USAGE "[-o] [command]", - CMD_ARG01, "o", - cmd_target_init, - cmd_target_parse, - cmd_pipe_pane_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_pipe_pane_exec }; int cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct client *c; struct window_pane *wp; char *command; @@ -59,7 +58,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) if ((c = cmd_find_client(ctx, NULL)) == NULL) return (-1); - if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); /* Destroy the old pipe. */ @@ -71,7 +70,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } /* If no pipe command, that is enough. */ - if (data->arg == NULL || *data->arg == '\0') + if (args->argc == 0 || *args->argv[0] == '\0') return (0); /* @@ -80,7 +79,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) * * bind ^p pipep -o 'cat >>~/output' */ - if (cmd_check_flag(data->chflags, 'o') && old_fd != -1) + if (args_has(self->args, 'o') && old_fd != -1) return (0); /* Open the new pipe. */ @@ -114,7 +113,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) closefrom(STDERR_FILENO + 1); - command = status_replace(c, NULL, data->arg, time(NULL), 0); + command = status_replace(c, NULL, args->argv[0], time(NULL), 0); execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL); _exit(1); default: diff --git a/cmd-previous-layout.c b/cmd-previous-layout.c index 77e3ebbb..abe9e357 100644 --- a/cmd-previous-layout.c +++ b/cmd-previous-layout.c @@ -28,23 +28,22 @@ int cmd_previous_layout_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_previous_layout_entry = { "previous-layout", "prevl", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_previous_layout_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_previous_layout_exec }; int cmd_previous_layout_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - u_int layout; + struct args *args = self->args; + struct winlink *wl; + u_int layout; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); layout = layout_set_previous(wl->window); diff --git a/cmd-previous-window.c b/cmd-previous-window.c index 0357e76d..c3f60a29 100644 --- a/cmd-previous-window.c +++ b/cmd-previous-window.c @@ -24,44 +24,39 @@ * Move to previous window. */ -void cmd_previous_window_init(struct cmd *, int); +void cmd_previous_window_key_binding(struct cmd *, int); int cmd_previous_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_previous_window_entry = { "previous-window", "prev", + "at:", 0, 0, "[-a] " CMD_TARGET_SESSION_USAGE, - 0, "a", - cmd_previous_window_init, - cmd_target_parse, - cmd_previous_window_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_previous_window_key_binding, + NULL, + cmd_previous_window_exec }; void -cmd_previous_window_init(struct cmd *self, int key) +cmd_previous_window_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - + self->args = args_create(0); if (key == ('p' | KEYC_ESCAPE)) - cmd_set_flag(&data->chflags, 'a'); + args_set(self->args, 'a', NULL); } int cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - int activity; + struct args *args = self->args; + struct session *s; + int activity; - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); activity = 0; - if (cmd_check_flag(data->chflags, 'a')) + if (args_has(self->args, 'a')) activity = 1; if (session_previous(s, activity) == 0) diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 03662a85..5186dcb9 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -28,22 +28,21 @@ int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_refresh_client_entry = { "refresh-client", "refresh", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_refresh_client_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_refresh_client_exec }; int cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct args *args = self->args; + struct client *c; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); server_redraw_client(c); diff --git a/cmd-rename-session.c b/cmd-rename-session.c index bd9e787f..9ca43a7d 100644 --- a/cmd-rename-session.c +++ b/cmd-rename-session.c @@ -30,32 +30,33 @@ int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_rename_session_entry = { "rename-session", "rename", + "t:", 1, 1, CMD_TARGET_SESSION_USAGE " new-name", - CMD_ARG1, "", - cmd_target_init, - cmd_target_parse, - cmd_rename_session_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_rename_session_exec }; int cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; + struct args *args = self->args; + struct session *s; + const char *newname; - if (data->arg != NULL && session_find(data->arg) != NULL) { - ctx->error(ctx, "duplicate session: %s", data->arg); + newname = args->argv[0]; + if (session_find(newname) != NULL) { + ctx->error(ctx, "duplicate session: %s", newname); return (-1); } - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); RB_REMOVE(sessions, &sessions, s); xfree(s->name); - s->name = xstrdup(data->arg); + s->name = xstrdup(newname); RB_INSERT(sessions, &sessions, s); server_status_session(s); diff --git a/cmd-rename-window.c b/cmd-rename-window.c index 112bd299..5f4783dd 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -30,27 +30,26 @@ int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_rename_window_entry = { "rename-window", "renamew", + "t:", 1, 1, CMD_TARGET_WINDOW_USAGE " new-name", - CMD_ARG1, "", - cmd_target_init, - cmd_target_parse, - cmd_rename_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_rename_window_exec }; int cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct winlink *wl; + struct args *args = self->args; + struct session *s; + struct winlink *wl; - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) return (-1); xfree(wl->window->name); - wl->window->name = xstrdup(data->arg); + wl->window->name = xstrdup(args->argv[0]); options_set_number(&wl->window->options, "automatic-rename", 0); server_status_window(wl->window); diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index 73a5f820..1380b283 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -26,84 +26,90 @@ * Increase or decrease pane size. */ -void cmd_resize_pane_init(struct cmd *, int); +void cmd_resize_pane_key_binding(struct cmd *, int); int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_resize_pane_entry = { "resize-pane", "resizep", + "DLRt:U", 0, 1, "[-DLRU] " CMD_TARGET_PANE_USAGE " [adjustment]", - CMD_ARG01, "DLRU", - cmd_resize_pane_init, - cmd_target_parse, - cmd_resize_pane_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_resize_pane_key_binding, + NULL, + cmd_resize_pane_exec }; void -cmd_resize_pane_init(struct cmd *self, int key) +cmd_resize_pane_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - - if (key == (KEYC_UP | KEYC_CTRL)) - cmd_set_flag(&data->chflags, 'U'); - if (key == (KEYC_DOWN | KEYC_CTRL)) - cmd_set_flag(&data->chflags, 'D'); - if (key == (KEYC_LEFT | KEYC_CTRL)) - cmd_set_flag(&data->chflags, 'L'); - if (key == (KEYC_RIGHT | KEYC_CTRL)) - cmd_set_flag(&data->chflags, 'R'); - - if (key == (KEYC_UP | KEYC_ESCAPE)) { - cmd_set_flag(&data->chflags, 'U'); - data->arg = xstrdup("5"); - } - if (key == (KEYC_DOWN | KEYC_ESCAPE)) { - cmd_set_flag(&data->chflags, 'D'); - data->arg = xstrdup("5"); - } - if (key == (KEYC_LEFT | KEYC_ESCAPE)) { - cmd_set_flag(&data->chflags, 'L'); - data->arg = xstrdup("5"); - } - if (key == (KEYC_RIGHT | KEYC_ESCAPE)) { - cmd_set_flag(&data->chflags, 'R'); - data->arg = xstrdup("5"); + switch (key) { + case KEYC_UP | KEYC_CTRL: + self->args = args_create(0); + args_set(self->args, 'U', NULL); + break; + case KEYC_DOWN | KEYC_CTRL: + self->args = args_create(0); + args_set(self->args, 'D', NULL); + break; + case KEYC_LEFT | KEYC_CTRL: + self->args = args_create(0); + args_set(self->args, 'L', NULL); + break; + case KEYC_RIGHT | KEYC_CTRL: + self->args = args_create(0); + args_set(self->args, 'R', NULL); + break; + case KEYC_UP | KEYC_ESCAPE: + self->args = args_create(1, "5"); + args_set(self->args, 'U', NULL); + break; + case KEYC_DOWN | KEYC_ESCAPE: + self->args = args_create(1, "5"); + args_set(self->args, 'D', NULL); + break; + case KEYC_LEFT | KEYC_ESCAPE: + self->args = args_create(1, "5"); + args_set(self->args, 'L', NULL); + break; + case KEYC_RIGHT | KEYC_ESCAPE: + self->args = args_create(1, "5"); + args_set(self->args, 'R', NULL); + break; + default: + self->args = args_create(0); + break; } } int cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; const char *errstr; struct window_pane *wp; u_int adjust; - if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) return (-1); - if (data->arg == NULL) + if (args->argc == 0) adjust = 1; else { - adjust = strtonum(data->arg, 1, INT_MAX, &errstr); + adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); if (errstr != NULL) { - ctx->error(ctx, "adjustment %s: %s", errstr, data->arg); + ctx->error(ctx, "adjustment %s", errstr); return (-1); } } - if (cmd_check_flag(data->chflags, 'L')) + if (args_has(self->args, 'L')) layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust); - else if (cmd_check_flag(data->chflags, 'R')) + else if (args_has(self->args, 'R')) layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust); - else if (cmd_check_flag(data->chflags, 'U')) + else if (args_has(self->args, 'U')) layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust); - else if (cmd_check_flag(data->chflags, 'D')) + else if (args_has(self->args, 'D')) layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust); server_redraw_window(wl->window); diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c index 4c8235e7..30601fe5 100644 --- a/cmd-respawn-window.c +++ b/cmd-respawn-window.c @@ -30,31 +30,31 @@ int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_respawn_window_entry = { "respawn-window", "respawnw", + "kt:", 0, 1, "[-k] " CMD_TARGET_WINDOW_USAGE " [command]", - CMD_ARG01, "k", - cmd_target_init, - cmd_target_parse, - cmd_respawn_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_respawn_window_exec }; int cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window *w; struct window_pane *wp; struct session *s; struct environ env; + const char *cmd; char *cause; - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) return (-1); w = wl->window; - if (!cmd_check_flag(data->chflags, 'k')) { + if (!args_has(self->args, 'k')) { TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->fd == -1) continue; @@ -75,8 +75,11 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) window_destroy_panes(w); TAILQ_INSERT_HEAD(&w->panes, wp, entry); window_pane_resize(wp, w->sx, w->sy); - if (window_pane_spawn( - wp, data->arg, NULL, NULL, &env, s->tio, &cause) != 0) { + if (args->argc != 0) + cmd = args->argv[0]; + else + cmd = NULL; + if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) { ctx->error(ctx, "respawn window failed: %s", cause); xfree(cause); environ_free(&env); diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c index fbfba099..1d752e74 100644 --- a/cmd-rotate-window.c +++ b/cmd-rotate-window.c @@ -24,47 +24,42 @@ * Rotate the panes in a window. */ -void cmd_rotate_window_init(struct cmd *, int); +void cmd_rotate_window_key_binding(struct cmd *, int); int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_rotate_window_entry = { "rotate-window", "rotatew", + "Dt:U", 0, 0, "[-DU] " CMD_TARGET_WINDOW_USAGE, - 0, "DU", - cmd_rotate_window_init, - cmd_target_parse, - cmd_rotate_window_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_rotate_window_key_binding, + NULL, + cmd_rotate_window_exec }; void -cmd_rotate_window_init(struct cmd *self, int key) +cmd_rotate_window_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - + self->args = args_create(0); if (key == ('o' | KEYC_ESCAPE)) - cmd_set_flag(&data->chflags, 'D'); + args_set(self->args, 'D', NULL); } int cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window *w; struct window_pane *wp, *wp2; struct layout_cell *lc; u_int sx, sy, xoff, yoff; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); w = wl->window; - if (cmd_check_flag(data->chflags, 'D')) { + if (args_has(self->args, 'D')) { wp = TAILQ_LAST(&w->panes, window_panes); TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry); diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 7bfb8916..189eeac9 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -35,13 +35,12 @@ void cmd_run_shell_free(void *); const struct cmd_entry cmd_run_shell_entry = { "run-shell", "run", + "", 1, 1, "command", - CMD_ARG1, "", - cmd_target_init, - cmd_target_parse, - cmd_run_shell_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_run_shell_exec }; struct cmd_run_shell_data { @@ -52,12 +51,12 @@ struct cmd_run_shell_data { int cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct cmd_run_shell_data *cdata; struct job *job; cdata = xmalloc(sizeof *cdata); - cdata->cmd = xstrdup(data->arg); + cdata->cmd = xstrdup(args->argv[0]); memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); if (ctx->cmdclient != NULL) @@ -66,7 +65,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) ctx->curclient->references++; job = job_add(NULL, 0, NULL, - data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata); + args->argv[0], cmd_run_shell_callback, cmd_run_shell_free, cdata); job_run(job); return (1); /* don't let client exit */ diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c index 7a30d12b..6fd65696 100644 --- a/cmd-save-buffer.c +++ b/cmd-save-buffer.c @@ -32,56 +32,66 @@ int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_save_buffer_entry = { "save-buffer", "saveb", - "[-a] " CMD_BUFFER_USAGE " path", - CMD_ARG1, "a", - cmd_buffer_init, - cmd_buffer_parse, - cmd_save_buffer_exec, - cmd_buffer_free, - cmd_buffer_print + "ab:", 1, 1, + "[-a] " CMD_BUFFER_USAGE, + 0, + NULL, + NULL, + cmd_save_buffer_exec }; int cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; + struct args *args = self->args; + struct client *c = ctx->cmdclient; struct paste_buffer *pb; + const char *path; + char *cause; + int buffer; mode_t mask; FILE *f; - if (data->buffer == -1) { + if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { ctx->error(ctx, "no buffers"); return (-1); } } else { - pb = paste_get_index(&global_buffers, data->buffer); + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + + pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { - ctx->error(ctx, "no buffer %d", data->buffer); + ctx->error(ctx, "no buffer %d", buffer); return (-1); } } - if (strcmp(data->arg, "-") == 0) { - if (ctx->cmdclient == NULL) { - ctx->error(ctx, "%s: can't write to stdout", data->arg); + path = args->argv[0]; + if (strcmp(path, "-") == 0) { + if (c == NULL) { + ctx->error(ctx, "%s: can't write to stdout", path); return (-1); } - bufferevent_write( - ctx->cmdclient->stdout_event, pb->data, pb->size); + bufferevent_write(c->stdout_event, pb->data, pb->size); } else { mask = umask(S_IRWXG | S_IRWXO); - if (cmd_check_flag(data->chflags, 'a')) - f = fopen(data->arg, "ab"); + if (args_has(self->args, 'a')) + f = fopen(path, "ab"); else - f = fopen(data->arg, "wb"); + f = fopen(path, "wb"); umask(mask); if (f == NULL) { - ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); + ctx->error(ctx, "%s: %s", path, strerror(errno)); return (-1); } if (fwrite(pb->data, 1, pb->size, f) != pb->size) { - ctx->error(ctx, "%s: fwrite error", data->arg); + ctx->error(ctx, "%s: fwrite error", path); fclose(f); return (-1); } diff --git a/cmd-select-layout.c b/cmd-select-layout.c index 70f7125f..df977b0f 100644 --- a/cmd-select-layout.c +++ b/cmd-select-layout.c @@ -24,43 +24,40 @@ * Switch window to selected layout. */ -void cmd_select_layout_init(struct cmd *, int); +void cmd_select_layout_key_binding(struct cmd *, int); int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_select_layout_entry = { "select-layout", "selectl", + "t:", 0, 1, CMD_TARGET_WINDOW_USAGE " [layout-name]", - CMD_ARG01, "", - cmd_select_layout_init, - cmd_target_parse, - cmd_select_layout_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_select_layout_key_binding, + NULL, + cmd_select_layout_exec }; void -cmd_select_layout_init(struct cmd *self, int key) +cmd_select_layout_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - switch (key) { - case ('1' | KEYC_ESCAPE): - data->arg = xstrdup("even-horizontal"); + case '1' | KEYC_ESCAPE: + self->args = args_create(1, "even-horizontal"); break; - case ('2' | KEYC_ESCAPE): - data->arg = xstrdup("even-vertical"); + case '2' | KEYC_ESCAPE: + self->args = args_create(1, "even-vertical"); break; - case ('3' | KEYC_ESCAPE): - data->arg = xstrdup("main-horizontal"); + case '3' | KEYC_ESCAPE: + self->args = args_create(1, "main-horizontal"); break; - case ('4' | KEYC_ESCAPE): - data->arg = xstrdup("main-vertical"); + case '4' | KEYC_ESCAPE: + self->args = args_create(1, "main-vertical"); break; - case ('5' | KEYC_ESCAPE): - data->arg = xstrdup("tiled"); + case '5' | KEYC_ESCAPE: + self->args = args_create(1, "tiled"); + break; + default: + self->args = args_create(0); break; } } @@ -68,26 +65,32 @@ cmd_select_layout_init(struct cmd *self, int key) int cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - int layout; + struct args *args = self->args; + struct winlink *wl; + const char *layoutname; + int layout; - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (-1); - if (data->arg == NULL) { + if (args->argc == 0) layout = wl->window->lastlayout; - if (layout == -1) - return (0); - } else if ((layout = layout_set_lookup(data->arg)) != -1) { + else + layout = layout_set_lookup(args->argv[0]); + if (layout != -1) { layout = layout_set_select(wl->window, layout); ctx->info(ctx, "arranging in: %s", layout_set_name(layout)); - } else { - if (layout_parse(wl->window, data->arg) == -1) { - ctx->error(ctx, "can't set layout: %s", data->arg); + return (0); + } + + if (args->argc != 0) { + layoutname = args->argv[0]; + if (layout_parse(wl->window, layoutname) == -1) { + ctx->error(ctx, "can't set layout: %s", layoutname); return (-1); } - ctx->info(ctx, "arranging in: %s", data->arg); + ctx->info(ctx, "arranging in: %s", layoutname); + return (0); } return (0); diff --git a/cmd-select-pane.c b/cmd-select-pane.c index b5defa2e..a250bb6e 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -24,62 +24,57 @@ * Select pane. */ -void cmd_select_pane_init(struct cmd *, int); +void cmd_select_pane_key_binding(struct cmd *, int); int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_select_pane_entry = { "select-pane", "selectp", + "DLRt:U", 0, 0, "[-DLRU] " CMD_TARGET_PANE_USAGE, - 0, "DLRU", - cmd_select_pane_init, - cmd_target_parse, - cmd_select_pane_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_select_pane_key_binding, + NULL, + cmd_select_pane_exec }; void -cmd_select_pane_init(struct cmd *self, int key) +cmd_select_pane_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_target_init(self, key); - data = self->data; - + self->args = args_create(0); if (key == KEYC_UP) - cmd_set_flag(&data->chflags, 'U'); + args_set(self->args, 'U', NULL); if (key == KEYC_DOWN) - cmd_set_flag(&data->chflags, 'D'); + args_set(self->args, 'D', NULL); if (key == KEYC_LEFT) - cmd_set_flag(&data->chflags, 'L'); + args_set(self->args, 'L', NULL); if (key == KEYC_RIGHT) - cmd_set_flag(&data->chflags, 'R'); + args_set(self->args, 'R', NULL); if (key == 'o') - data->target = xstrdup(":.+"); + args_set(self->args, 't', ":.+"); } int cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window_pane *wp; - if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) + if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) return (-1); if (!window_pane_visible(wp)) { - ctx->error(ctx, "pane not visible: %s", data->target); + ctx->error(ctx, "pane not visible"); return (-1); } - if (cmd_check_flag(data->chflags, 'L')) + if (args_has(self->args, 'L')) wp = window_pane_find_left(wp); - else if (cmd_check_flag(data->chflags, 'R')) + else if (args_has(self->args, 'R')) wp = window_pane_find_right(wp); - else if (cmd_check_flag(data->chflags, 'U')) + else if (args_has(self->args, 'U')) wp = window_pane_find_up(wp); - else if (cmd_check_flag(data->chflags, 'D')) + else if (args_has(self->args, 'D')) wp = window_pane_find_down(wp); if (wp == NULL) { ctx->error(ctx, "pane not found"); diff --git a/cmd-select-window.c b/cmd-select-window.c index 6aeaad22..c414af3a 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -26,39 +26,38 @@ * Select window by index. */ -void cmd_select_window_init(struct cmd *, int); +void cmd_select_window_key_binding(struct cmd *, int); int cmd_select_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_select_window_entry = { "select-window", "selectw", + "t:", 0, 0, CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_select_window_init, - cmd_target_parse, - cmd_select_window_exec, - cmd_target_free, - cmd_target_print + 0, + cmd_select_window_key_binding, + NULL, + cmd_select_window_exec }; void -cmd_select_window_init(struct cmd *self, int key) +cmd_select_window_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; + char tmp[16]; - cmd_target_init(self, key); - data = self->data; + xsnprintf(tmp, sizeof tmp, ":%d", key - '0'); - xasprintf(&data->target, ":%d", key - '0'); + self->args = args_create(0); + args_set(self->args, 't', tmp); } int cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - struct session *s; + struct args *args = self->args; + struct winlink *wl; + struct session *s; - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) return (-1); if (session_select(s, wl->idx) == 0) diff --git a/cmd-send-keys.c b/cmd-send-keys.c index 3c680524..8181e563 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -26,128 +26,40 @@ * Send keys to client. */ -int cmd_send_keys_parse(struct cmd *, int, char **, char **); int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *); -void cmd_send_keys_free(struct cmd *); -size_t cmd_send_keys_print(struct cmd *, char *, size_t); - -struct cmd_send_keys_data { - char *target; - u_int nkeys; - int *keys; -}; const struct cmd_entry cmd_send_keys_entry = { "send-keys", "send", + "t:", 0, -1, "[-t target-pane] key ...", - 0, "", + 0, NULL, - cmd_send_keys_parse, - cmd_send_keys_exec, - cmd_send_keys_free, - cmd_send_keys_print + NULL, + cmd_send_keys_exec }; -int -cmd_send_keys_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_send_keys_data *data; - int opt, key; - char *s; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->nkeys = 0; - data->keys = NULL; - - while ((opt = getopt(argc, argv, "t:")) != -1) { - switch (opt) { - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc == 0) - goto usage; - - while (argc-- != 0) { - if ((key = key_string_lookup_string(*argv)) != KEYC_NONE) { - data->keys = xrealloc( - data->keys, data->nkeys + 1, sizeof *data->keys); - data->keys[data->nkeys++] = key; - } else { - for (s = *argv; *s != '\0'; s++) { - data->keys = xrealloc(data->keys, - data->nkeys + 1, sizeof *data->keys); - data->keys[data->nkeys++] = *s; - } - } - - argv++; - } - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - int cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_send_keys_data *data = self->data; - struct window_pane *wp; - struct session *s; - u_int i; + struct args *args = self->args; + struct window_pane *wp; + struct session *s; + const char *str; + int i, key; - if (data == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) return (-1); - if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL) - return (-1); + for (i = 0; i < args->argc; i++) { + str = args->argv[i]; - for (i = 0; i < data->nkeys; i++) - window_pane_key(wp, s, data->keys[i]); + if ((key = key_string_lookup_string(str)) != KEYC_NONE) { + window_pane_key(wp, s, key); + } else { + for (; *str != '\0'; str++) + window_pane_key(wp, s, *str); + } + } return (0); } - -void -cmd_send_keys_free(struct cmd *self) -{ - struct cmd_send_keys_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - xfree(data); -} - -size_t -cmd_send_keys_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_send_keys_data *data = self->data; - size_t off = 0; - u_int i; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - - for (i = 0; i < data->nkeys; i++) { - if (off >= len) - break; - off += xsnprintf(buf + off, - len - off, " %s", key_string_lookup_key(data->keys[i])); - } - return (off); -} diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index c7f7e9fa..398f440e 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -28,24 +28,23 @@ int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_send_prefix_entry = { "send-prefix", NULL, + "t:", 0, 0, CMD_TARGET_PANE_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_send_prefix_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_send_prefix_exec }; int cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct session *s; struct window_pane *wp; struct keylist *keylist; - if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL) + if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) return (-1); keylist = options_get_data(&s->options, "prefix"); diff --git a/cmd-server-info.c b/cmd-server-info.c index 51a42219..4bd65143 100644 --- a/cmd-server-info.c +++ b/cmd-server-info.c @@ -35,13 +35,12 @@ int cmd_server_info_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_server_info_entry = { "server-info", "info", + "", 0, 0, "", - 0, "", + 0, NULL, NULL, - cmd_server_info_exec, - NULL, - NULL + cmd_server_info_exec }; /* ARGSUSED */ diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index 376adb14..f31f8a06 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -30,36 +30,45 @@ int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_set_buffer_entry = { "set-buffer", "setb", + "b:", 1, 1, CMD_BUFFER_USAGE " data", - CMD_ARG1, "", - cmd_buffer_init, - cmd_buffer_parse, - cmd_set_buffer_exec, - cmd_buffer_free, - cmd_buffer_print + 0, + NULL, + NULL, + cmd_set_buffer_exec }; int cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; - u_int limit; - char *pdata; - size_t psize; + struct args *args = self->args; + u_int limit; + char *pdata, *cause; + size_t psize; + int buffer; limit = options_get_number(&global_options, "buffer-limit"); - pdata = xstrdup(data->arg); + pdata = xstrdup(args->argv[0]); psize = strlen(pdata); - if (data->buffer == -1) { + if (!args_has(args, 'b')) { paste_add(&global_buffers, pdata, psize, limit); return (0); } - if (paste_replace(&global_buffers, data->buffer, pdata, psize) != 0) { - ctx->error(ctx, "no buffer %d", data->buffer); + + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + + if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { + ctx->error(ctx, "no buffer %d", buffer); xfree(pdata); return (-1); } + return (0); } diff --git a/cmd-set-environment.c b/cmd-set-environment.c index fdd703c5..3075fb07 100644 --- a/cmd-set-environment.c +++ b/cmd-set-environment.c @@ -31,57 +31,63 @@ int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_set_environment_entry = { "set-environment", "setenv", + "grt:u", 1, 2, "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]", - CMD_ARG12, "gru", + 0, NULL, - cmd_target_parse, - cmd_set_environment_exec, - cmd_target_free, - cmd_target_print + NULL, + cmd_set_environment_exec }; int cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct environ *env; + struct args *args = self->args; + struct session *s; + struct environ *env; + const char *name, *value; - if (*data->arg == '\0') { + name = args->argv[0]; + if (*name == '\0') { ctx->error(ctx, "empty variable name"); return (-1); } - if (strchr(data->arg, '=') != NULL) { + if (strchr(name, '=') != NULL) { ctx->error(ctx, "variable name contains ="); return (-1); } - if (cmd_check_flag(data->chflags, 'g')) + if (args->argc < 1) + value = NULL; + else + value = args->argv[1]; + + if (args_has(self->args, 'g')) env = &global_environ; else { - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); env = &s->environ; } - if (cmd_check_flag(data->chflags, 'u')) { - if (data->arg2 != NULL) { + if (args_has(self->args, 'u')) { + if (value != NULL) { ctx->error(ctx, "can't specify a value with -u"); return (-1); } - environ_unset(env, data->arg); - } else if (cmd_check_flag(data->chflags, 'r')) { - if (data->arg2 != NULL) { + environ_unset(env, name); + } else if (args_has(self->args, 'r')) { + if (value != NULL) { ctx->error(ctx, "can't specify a value with -r"); return (-1); } - environ_set(env, data->arg, NULL); + environ_set(env, name, NULL); } else { - if (data->arg2 == NULL) { + if (value == NULL) { ctx->error(ctx, "no value specified"); return (-1); } - environ_set(env, data->arg, data->arg2); + environ_set(env, name, value); } return (0); diff --git a/cmd-set-option.c b/cmd-set-option.c index f15ce052..2aa99f10 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -30,40 +30,48 @@ int cmd_set_option_exec(struct cmd *, struct cmd_ctx *); int cmd_set_option_unset(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); int cmd_set_option_set(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_keys(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *, - const struct options_table_entry *, struct options *); + const struct options_table_entry *, struct options *, + const char *); const struct cmd_entry cmd_set_option_entry = { "set-option", "set", + "agst:uw", 1, 2, "[-agsuw] [-t target-session|target-window] option [value]", - CMD_ARG12, "agsuw", + 0, NULL, - cmd_target_parse, - cmd_set_option_exec, - cmd_target_free, - cmd_target_print + NULL, + cmd_set_option_exec }; int cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; const struct options_table_entry *table, *oe, *oe_loop; struct session *s; struct winlink *wl; @@ -71,61 +79,74 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) struct options *oo; struct jobs *jobs; struct job *job, *nextjob; + const char *optstr, *valstr; u_int i; int try_again; /* Work out the options tree and table to use. */ - if (cmd_check_flag(data->chflags, 's')) { + if (args_has(self->args, 's')) { oo = &global_options; table = server_options_table; - } else if (cmd_check_flag(data->chflags, 'w')) { + } else if (args_has(self->args, 'w')) { table = window_options_table; - if (cmd_check_flag(data->chflags, 'g')) + if (args_has(self->args, 'g')) oo = &global_w_options; else { - wl = cmd_find_window(ctx, data->target, NULL); + wl = cmd_find_window(ctx, args_get(args, 't'), NULL); if (wl == NULL) return (-1); oo = &wl->window->options; } } else { table = session_options_table; - if (cmd_check_flag(data->chflags, 'g')) + if (args_has(self->args, 'g')) oo = &global_s_options; else { - s = cmd_find_session(ctx, data->target); + s = cmd_find_session(ctx, args_get(args, 't')); if (s == NULL) return (-1); oo = &s->options; } } + /* Get the option name and value. */ + optstr = args->argv[0]; + if (*optstr == '\0') { + ctx->error(ctx, "invalid option"); + return (-1); + } + if (args->argc < 1) + valstr = NULL; + else + valstr = args->argv[1]; + /* Find the option table entry. */ oe = NULL; for (oe_loop = table; oe_loop->name != NULL; oe_loop++) { - if (strncmp(oe_loop->name, data->arg, strlen(data->arg)) != 0) + if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0) continue; + if (oe != NULL) { - ctx->error(ctx, "ambiguous option: %s", data->arg); + ctx->error(ctx, "ambiguous option: %s", optstr); return (-1); } oe = oe_loop; /* Bail now if an exact match. */ - if (strcmp(oe->name, data->arg) == 0) + if (strcmp(oe->name, optstr) == 0) break; } if (oe == NULL) { - ctx->error(ctx, "unknown option: %s", data->arg); + ctx->error(ctx, "unknown option: %s", optstr); return (-1); } /* Unset or set the option. */ - if (cmd_check_flag(data->chflags, 'u')) { - if (cmd_set_option_unset(self, ctx, oe, oo) != 0) + if (args_has(args, 'u')) { + if (cmd_set_option_unset(self, ctx, oe, oo, valstr) != 0) return (-1); } else { - if (cmd_set_option_set(self, ctx, oe, oo) != 0) + if (cmd_set_option_set(self, ctx, oe, oo, valstr) != 0) return (-1); } @@ -176,15 +197,15 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) /* Unset an option. */ int cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; - if (cmd_check_flag(data->chflags, 'g')) { + if (args_has(args, 'g')) { ctx->error(ctx, "can't unset global option: %s", oe->name); return (-1); } - if (data->arg2 != NULL) { + if (value != NULL) { ctx->error(ctx, "value passed to unset option: %s", oe->name); return (-1); } @@ -197,39 +218,38 @@ cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx, /* Set an option. */ int cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; struct options_entry *o; const char *s; - if (oe->type != OPTIONS_TABLE_FLAG && data->arg2 == NULL) { - ctx->error(ctx, "empty data->arg2"); + if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) { + ctx->error(ctx, "empty value"); return (-1); } o = NULL; switch (oe->type) { case OPTIONS_TABLE_STRING: - o = cmd_set_option_string(self, ctx, oe, oo); + o = cmd_set_option_string(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_NUMBER: - o = cmd_set_option_number(self, ctx, oe, oo); + o = cmd_set_option_number(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_KEYS: - o = cmd_set_option_keys(self, ctx, oe, oo); + o = cmd_set_option_keys(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_COLOUR: - o = cmd_set_option_colour(self, ctx, oe, oo); + o = cmd_set_option_colour(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_ATTRIBUTES: - o = cmd_set_option_attributes(self, ctx, oe, oo); + o = cmd_set_option_attributes(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_FLAG: - o = cmd_set_option_flag(self, ctx, oe, oo); + o = cmd_set_option_flag(self, ctx, oe, oo, value); break; case OPTIONS_TABLE_CHOICE: - o = cmd_set_option_choice(self, ctx, oe, oo); + o = cmd_set_option_choice(self, ctx, oe, oo, value); break; } if (o == NULL) @@ -243,37 +263,35 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx, /* Set a string option. */ struct options_entry * cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct options_entry *o; char *oldval, *newval; - if (cmd_check_flag(data->chflags, 'a')) { + if (args_has(args, 'a')) { oldval = options_get_string(oo, oe->name); - xasprintf(&newval, "%s%s", oldval, data->arg2); + xasprintf(&newval, "%s%s", oldval, value); } else - newval = data->arg2; + newval = xstrdup(value); o = options_set_string(oo, oe->name, "%s", newval); - if (newval != data->arg2) - xfree(newval); + xfree(newval); return (o); } /* Set a number option. */ struct options_entry * -cmd_set_option_number(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - long long ll; - const char *errstr; + long long ll; + const char *errstr; - ll = strtonum(data->arg2, oe->minimum, oe->maximum, &errstr); + ll = strtonum(value, oe->minimum, oe->maximum, &errstr); if (errstr != NULL) { - ctx->error(ctx, "value is %s: %s", errstr, data->arg2); + ctx->error(ctx, "value is %s: %s", errstr, value); return (NULL); } @@ -282,18 +300,17 @@ cmd_set_option_number(struct cmd *self, struct cmd_ctx *ctx, /* Set a keys option. */ struct options_entry * -cmd_set_option_keys(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_keys(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - struct keylist *keylist; - char *copy, *ptr, *s; - int key; + struct keylist *keylist; + char *copy, *ptr, *s; + int key; keylist = xmalloc(sizeof *keylist); ARRAY_INIT(keylist); - ptr = copy = xstrdup(data->arg2); + ptr = copy = xstrdup(value); while ((s = strsep(&ptr, ",")) != NULL) { if ((key = key_string_lookup_string(s)) == KEYC_NONE) { ctx->error(ctx, "unknown key: %s", s); @@ -310,14 +327,13 @@ cmd_set_option_keys(struct cmd *self, struct cmd_ctx *ctx, /* Set a colour option. */ struct options_entry * -cmd_set_option_colour(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_colour(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - int colour; + int colour; - if ((colour = colour_fromstring(data->arg2)) == -1) { - ctx->error(ctx, "bad colour: %s", data->arg2); + if ((colour = colour_fromstring(value)) == -1) { + ctx->error(ctx, "bad colour: %s", value); return (NULL); } @@ -326,14 +342,13 @@ cmd_set_option_colour(struct cmd *self, struct cmd_ctx *ctx, /* Set an attributes option. */ struct options_entry * -cmd_set_option_attributes(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_attributes(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - int attr; + int attr; - if ((attr = attributes_fromstring(data->arg2)) == -1) { - ctx->error(ctx, "bad attributes: %s", data->arg2); + if ((attr = attributes_fromstring(value)) == -1) { + ctx->error(ctx, "bad attributes: %s", value); return (NULL); } @@ -342,25 +357,24 @@ cmd_set_option_attributes(struct cmd *self, struct cmd_ctx *ctx, /* Set a flag option. */ struct options_entry * -cmd_set_option_flag(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - int flag; + int flag; - if (data->arg2 == NULL || *data->arg2 == '\0') + if (value == NULL || *value == '\0') flag = !options_get_number(oo, oe->name); else { - if ((data->arg2[0] == '1' && data->arg2[1] == '\0') || - strcasecmp(data->arg2, "on") == 0 || - strcasecmp(data->arg2, "yes") == 0) + if ((value[0] == '1' && value[1] == '\0') || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0) flag = 1; - else if ((data->arg2[0] == '0' && data->arg2[1] == '\0') || - strcasecmp(data->arg2, "off") == 0 || - strcasecmp(data->arg2, "no") == 0) + else if ((value[0] == '0' && value[1] == '\0') || + strcasecmp(value, "off") == 0 || + strcasecmp(value, "no") == 0) flag = 0; else { - ctx->error(ctx, "bad value: %s", data->arg2); + ctx->error(ctx, "bad value: %s", value); return (NULL); } } @@ -370,27 +384,26 @@ cmd_set_option_flag(struct cmd *self, struct cmd_ctx *ctx, /* Set a choice option. */ struct options_entry * -cmd_set_option_choice(struct cmd *self, struct cmd_ctx *ctx, - const struct options_table_entry *oe, struct options *oo) +cmd_set_option_choice(unused struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo, const char *value) { - struct cmd_target_data *data = self->data; - const char **choicep; - int n, choice = -1; + const char **choicep; + int n, choice = -1; n = 0; for (choicep = oe->choices; *choicep != NULL; choicep++) { n++; - if (strncmp(*choicep, data->arg2, strlen(data->arg2)) != 0) + if (strncmp(*choicep, value, strlen(value)) != 0) continue; if (choice != -1) { - ctx->error(ctx, "ambiguous value: %s", data->arg2); + ctx->error(ctx, "ambiguous value: %s", value); return (NULL); } choice = n - 1; } if (choice == -1) { - ctx->error(ctx, "unknown value: %s", data->arg2); + ctx->error(ctx, "unknown value: %s", value); return (NULL); } diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c index 559d6485..3a750476 100644 --- a/cmd-set-window-option.c +++ b/cmd-set-window-option.c @@ -28,20 +28,19 @@ int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_set_window_option_entry = { "set-window-option", "setw", + "agt:u", 1, 2, "[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]", - CMD_ARG12, "agu", + 0, NULL, - cmd_target_parse, - cmd_set_window_option_exec, - cmd_target_free, - cmd_target_print + NULL, + cmd_set_window_option_exec }; int cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; - cmd_set_flag(&data->chflags, 'w'); + args_set(args, 'w', NULL); return (cmd_set_option_entry.exec(self, ctx)); } diff --git a/cmd-show-buffer.c b/cmd-show-buffer.c index b6d0c231..256818f5 100644 --- a/cmd-show-buffer.c +++ b/cmd-show-buffer.c @@ -30,37 +30,44 @@ int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_buffer_entry = { "show-buffer", "showb", + "b:", 0, 0, CMD_BUFFER_USAGE, - 0, "", - cmd_buffer_init, - cmd_buffer_parse, - cmd_show_buffer_exec, - cmd_buffer_free, - cmd_buffer_print + 0, + NULL, + NULL, + cmd_show_buffer_exec }; int cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; + struct args *args = self->args; struct session *s; struct paste_buffer *pb; - char *in, *buf, *ptr; + int buffer; + char *in, *buf, *ptr, *cause; size_t size, len; u_int width; if ((s = cmd_find_session(ctx, NULL)) == NULL) return (-1); - if (data->buffer == -1) { + if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { ctx->error(ctx, "no buffers"); return (-1); } } else { - pb = paste_get_index(&global_buffers, data->buffer); + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "buffer %s", cause); + xfree(cause); + return (-1); + } + + pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { - ctx->error(ctx, "no buffer %d", data->buffer); + ctx->error(ctx, "no buffer %d", buffer); return (-1); } } diff --git a/cmd-show-environment.c b/cmd-show-environment.c index 6d0f364c..f52efbca 100644 --- a/cmd-show-environment.c +++ b/cmd-show-environment.c @@ -31,27 +31,26 @@ int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_environment_entry = { "show-environment", "showenv", + "gt:", 0, 0, "[-g] " CMD_TARGET_SESSION_USAGE, - 0, "g", - cmd_target_init, - cmd_target_parse, - cmd_show_environment_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_show_environment_exec }; int cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct session *s; - struct environ *env; - struct environ_entry *envent; + struct args *args = self->args; + struct session *s; + struct environ *env; + struct environ_entry *envent; - if (cmd_check_flag(data->chflags, 'g')) + if (args_has(self->args, 'g')) env = &global_environ; else { - if ((s = cmd_find_session(ctx, data->target)) == NULL) + if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL) return (-1); env = &s->environ; } diff --git a/cmd-show-messages.c b/cmd-show-messages.c index 84c2d6ce..5979e8c3 100644 --- a/cmd-show-messages.c +++ b/cmd-show-messages.c @@ -31,25 +31,24 @@ int cmd_show_messages_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_messages_entry = { "show-messages", "showmsgs", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_show_messages_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_show_messages_exec }; int cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; - struct message_entry *msg; - char *tim; - u_int i; + struct args *args = self->args; + struct client *c; + struct message_entry *msg; + char *tim; + u_int i; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) { diff --git a/cmd-show-options.c b/cmd-show-options.c index 02ca91e3..a36bebdf 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -31,19 +31,18 @@ int cmd_show_options_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_options_entry = { "show-options", "show", + "gst:w", 0, 0, "[-gsw] [-t target-session|target-window]", - 0, "gsw", - cmd_target_init, - cmd_target_parse, - cmd_show_options_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_show_options_exec }; int cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; const struct options_table_entry *table, *oe; struct session *s; struct winlink *wl; @@ -51,25 +50,25 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) struct options_entry *o; const char *optval; - if (cmd_check_flag(data->chflags, 's')) { + if (args_has(self->args, 's')) { oo = &global_options; table = server_options_table; - } else if (cmd_check_flag(data->chflags, 'w')) { + } else if (args_has(self->args, 'w')) { table = window_options_table; - if (cmd_check_flag(data->chflags, 'g')) + if (args_has(self->args, 'g')) oo = &global_w_options; else { - wl = cmd_find_window(ctx, data->target, NULL); + wl = cmd_find_window(ctx, args_get(args, 't'), NULL); if (wl == NULL) return (-1); oo = &wl->window->options; } } else { table = session_options_table; - if (cmd_check_flag(data->chflags, 'g')) + if (args_has(self->args, 'g')) oo = &global_s_options; else { - s = cmd_find_session(ctx, data->target); + s = cmd_find_session(ctx, args_get(args, 't')); if (s == NULL) return (-1); oo = &s->options; diff --git a/cmd-show-window-options.c b/cmd-show-window-options.c index b81f887c..4412499a 100644 --- a/cmd-show-window-options.c +++ b/cmd-show-window-options.c @@ -31,20 +31,19 @@ int cmd_show_window_options_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_window_options_entry = { "show-window-options", "showw", + "gt:", 0, 0, "[-g] " CMD_TARGET_WINDOW_USAGE, - 0, "g", - cmd_target_init, - cmd_target_parse, - cmd_show_window_options_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_show_window_options_exec }; int cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; - cmd_set_flag(&data->chflags, 'w'); + args_set(args, 'w', NULL); return (cmd_show_options_entry.exec(self, ctx)); } diff --git a/cmd-source-file.c b/cmd-source-file.c index 5ba7ed8b..aa05d362 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -24,80 +24,31 @@ * Sources a configuration file. */ -int cmd_source_file_parse(struct cmd *, int, char **, char **); int cmd_source_file_exec(struct cmd *, struct cmd_ctx *); -void cmd_source_file_free(struct cmd *); -void cmd_source_file_init(struct cmd *, int); -size_t cmd_source_file_print(struct cmd *, char *, size_t); - -struct cmd_source_file_data { - char *path; -}; const struct cmd_entry cmd_source_file_entry = { "source-file", "source", + "", 1, 1, "path", - 0, "", - cmd_source_file_init, - cmd_source_file_parse, - cmd_source_file_exec, - cmd_source_file_free, - cmd_source_file_print + 0, + NULL, + NULL, + cmd_source_file_exec }; -/* ARGSUSED */ -void -cmd_source_file_init(struct cmd *self, unused int arg) -{ - struct cmd_source_file_data *data; - - self->data = data = xmalloc(sizeof *data); - data->path = NULL; -} - -int -cmd_source_file_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_source_file_data *data; - int opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "")) != -1) { - switch (opt) { - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 1) - goto usage; - - data->path = xstrdup(argv[0]); - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - int cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_source_file_data *data = self->data; - struct causelist causes; - char *cause; - struct window_pane *wp; - int retval; - u_int i; + struct args *args = self->args; + struct causelist causes; + char *cause; + struct window_pane *wp; + int retval; + u_int i; ARRAY_INIT(&causes); - retval = load_cfg(data->path, ctx, &causes); + retval = load_cfg(args->argv[0], ctx, &causes); if (ARRAY_EMPTY(&causes)) return (retval); @@ -121,27 +72,3 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx) return (retval); } - -void -cmd_source_file_free(struct cmd *self) -{ - struct cmd_source_file_data *data = self->data; - - if (data->path != NULL) - xfree(data->path); - xfree(data); -} - -size_t -cmd_source_file_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_source_file_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->path != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->path); - return (off); -} diff --git a/cmd-split-window.c b/cmd-split-window.c index e9a6eb4e..b7be4078 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -28,142 +28,44 @@ * Split a window (add a new pane). */ -int cmd_split_window_parse(struct cmd *, int, char **, char **); +void cmd_split_window_key_binding(struct cmd *, int); int cmd_split_window_exec(struct cmd *, struct cmd_ctx *); -void cmd_split_window_free(struct cmd *); -void cmd_split_window_init(struct cmd *, int); -size_t cmd_split_window_print(struct cmd *, char *, size_t); - -struct cmd_split_window_data { - char *target; - char *cmd; - int flag_detached; - int flag_horizontal; - int flag_print; - int percentage; - int size; -}; const struct cmd_entry cmd_split_window_entry = { "split-window", "splitw", + "dl:hp:Pt:v", 0, 1, "[-dhvP] [-p percentage|-l size] [-t target-pane] [command]", - 0, "", - cmd_split_window_init, - cmd_split_window_parse, - cmd_split_window_exec, - cmd_split_window_free, - cmd_split_window_print + 0, + cmd_split_window_key_binding, + NULL, + cmd_split_window_exec }; void -cmd_split_window_init(struct cmd *self, int key) +cmd_split_window_key_binding(struct cmd *self, int key) { - struct cmd_split_window_data *data; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->cmd = NULL; - data->flag_detached = 0; - data->flag_horizontal = 0; - data->flag_print = 0; - data->percentage = -1; - data->size = -1; - - switch (key) { - case '%': - data->flag_horizontal = 1; - break; - case '"': - data->flag_horizontal = 0; - break; - } -} - -int -cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_split_window_data *data; - int opt; - const char *errstr; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "dhl:p:Pt:v")) != -1) { - switch (opt) { - case 'd': - data->flag_detached = 1; - break; - case 'h': - data->flag_horizontal = 1; - break; - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - case 'l': - if (data->percentage != -1 || data->size != -1) - break; - data->size = strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr != NULL) { - xasprintf(cause, "size %s", errstr); - goto error; - } - break; - case 'p': - if (data->size != -1 || data->percentage != -1) - break; - data->percentage = strtonum(optarg, 1, 100, &errstr); - if (errstr != NULL) { - xasprintf(cause, "percentage %s", errstr); - goto error; - } - break; - case 'P': - data->flag_print = 1; - break; - case 'v': - data->flag_horizontal = 0; - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0 && argc != 1) - goto usage; - - if (argc == 1) - data->cmd = xstrdup(argv[0]); - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - self->entry->free(self); - return (-1); + self->args = args_create(0); + if (key == '%') + args_set(self->args, 'h', NULL); } int cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_split_window_data *data = self->data; - struct session *s; - struct winlink *wl; - struct window *w; - struct window_pane *wp, *new_wp = NULL; - struct environ env; - char *cmd, *cwd, *cause; - const char *shell; - u_int hlimit, paneidx; - int size; - enum layout_type type; - struct layout_cell *lc; + struct args *args = self->args; + struct session *s; + struct winlink *wl; + struct window *w; + struct window_pane *wp, *new_wp = NULL; + struct environ env; + char *cmd, *cwd, *cause; + const char *shell; + u_int hlimit, paneidx; + int size, percentage; + enum layout_type type; + struct layout_cell *lc; - if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL) + if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) return (-1); w = wl->window; @@ -172,9 +74,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) environ_copy(&s->environ, &env); server_fill_environ(s, &env); - cmd = data->cmd; - if (cmd == NULL) + if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); + else + cmd = args->argv[0]; cwd = options_get_string(&s->options, "default-path"); if (*cwd == '\0') { if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) @@ -184,17 +87,28 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) } type = LAYOUT_TOPBOTTOM; - if (data->flag_horizontal) + if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; - if (data->size != -1) - size = data->size; - else if (data->percentage != -1) { + if (args_has(args, 's')) { + size = args_strtonum(args, 's', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "size %s", cause); + xfree(cause); + return (-1); + } + } else if (args_has(args, 'p')) { + percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause); + if (cause != NULL) { + ctx->error(ctx, "percentage %s", cause); + xfree(cause); + return (-1); + } if (type == LAYOUT_TOPBOTTOM) - size = (wp->sy * data->percentage) / 100; + size = (wp->sy * percentage) / 100; else - size = (wp->sx * data->percentage) / 100; + size = (wp->sx * percentage) / 100; } hlimit = options_get_number(&s->options, "history-limit"); @@ -214,7 +128,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) server_redraw_window(w); - if (!data->flag_detached) { + if (!args_has(args, 'd')) { window_set_active_pane(w, new_wp); session_select(s, wl->idx); server_redraw_session(s); @@ -223,7 +137,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) environ_free(&env); - if (data->flag_print) { + if (args_has(args, 'P')) { paneidx = window_pane_index(wl->window, new_wp); ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx); } @@ -237,43 +151,3 @@ error: xfree(cause); return (-1); } - -void -cmd_split_window_free(struct cmd *self) -{ - struct cmd_split_window_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->cmd != NULL) - xfree(data->cmd); - xfree(data); -} - -size_t -cmd_split_window_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_split_window_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_detached) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flag_horizontal) - off += xsnprintf(buf + off, len - off, " -h"); - if (off < len && data->flag_print) - off += xsnprintf(buf + off, len - off, " -P"); - if (off < len && data->size > 0) - off += xsnprintf(buf + off, len - off, " -l %d", data->size); - if (off < len && data->percentage > 0) { - off += xsnprintf( - buf + off, len - off, " -p %d", data->percentage); - } - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - if (off < len && data->cmd != NULL) - off += cmd_prarg(buf + off, len - off, " ", data->cmd); - return (off); -} diff --git a/cmd-start-server.c b/cmd-start-server.c index b93c9e6c..a69e77ea 100644 --- a/cmd-start-server.c +++ b/cmd-start-server.c @@ -28,13 +28,12 @@ int cmd_start_server_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_start_server_entry = { "start-server", "start", + "", 0, 0, "", - CMD_STARTSERVER, "", + CMD_STARTSERVER, NULL, NULL, - cmd_start_server_exec, - NULL, - NULL + cmd_start_server_exec }; /* ARGSUSED */ diff --git a/cmd-suspend-client.c b/cmd-suspend-client.c index b90121a0..2a4dac1b 100644 --- a/cmd-suspend-client.c +++ b/cmd-suspend-client.c @@ -31,22 +31,21 @@ int cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_suspend_client_entry = { "suspend-client", "suspendc", + "t:", 0, 0, CMD_TARGET_CLIENT_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_suspend_client_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_suspend_client_exec }; int cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct args *args = self->args; + struct client *c; - if ((c = cmd_find_client(ctx, data->target)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) return (-1); tty_stop_tty(&c->tty); diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c index bf4b048e..8e0662dd 100644 --- a/cmd-swap-pane.c +++ b/cmd-swap-pane.c @@ -26,66 +26,58 @@ * Swap two panes. */ -void cmd_swap_pane_init(struct cmd *, int); +void cmd_swap_pane_key_binding(struct cmd *, int); int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_swap_pane_entry = { "swap-pane", "swapp", + "dDs:t:U", 0, 0, "[-dDU] " CMD_SRCDST_PANE_USAGE, - 0, "dDU", - cmd_swap_pane_init, - cmd_srcdst_parse, - cmd_swap_pane_exec, - cmd_srcdst_free, - cmd_srcdst_print + 0, + cmd_swap_pane_key_binding, + NULL, + cmd_swap_pane_exec }; void -cmd_swap_pane_init(struct cmd *self, int key) +cmd_swap_pane_key_binding(struct cmd *self, int key) { - struct cmd_target_data *data; - - cmd_srcdst_init(self, key); - data = self->data; - + self->args = args_create(0); if (key == '{') - cmd_set_flag(&data->chflags, 'U'); + args_set(self->args, 'U', NULL); else if (key == '}') - cmd_set_flag(&data->chflags, 'D'); + args_set(self->args, 'D', NULL); } - int cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_srcdst_data *data = self->data; + struct args *args = self->args; struct winlink *src_wl, *dst_wl; struct window *src_w, *dst_w; struct window_pane *tmp_wp, *src_wp, *dst_wp; struct layout_cell *src_lc, *dst_lc; u_int sx, sy, xoff, yoff; - if (data == NULL) - return (0); - - if ((dst_wl = cmd_find_pane(ctx, data->dst, NULL, &dst_wp)) == NULL) + dst_wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &dst_wp); + if (dst_wl == NULL) return (-1); dst_w = dst_wl->window; - if (data->src == NULL) { + if (!args_has(args, 's')) { src_w = dst_w; - if (cmd_check_flag(data->chflags, 'D')) { + if (args_has(self->args, 'D')) { src_wp = TAILQ_NEXT(dst_wp, entry); if (src_wp == NULL) src_wp = TAILQ_FIRST(&dst_w->panes); - } else if (cmd_check_flag(data->chflags, 'U')) { + } else if (args_has(self->args, 'U')) { src_wp = TAILQ_PREV(dst_wp, window_panes, entry); if (src_wp == NULL) src_wp = TAILQ_LAST(&dst_w->panes, window_panes); } else return (0); } else { - src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp); + src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (-1); src_w = src_wl->window; @@ -121,7 +113,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) dst_wp->xoff = xoff; dst_wp->yoff = yoff; window_pane_resize(dst_wp, sx, sy); - if (!cmd_check_flag(data->chflags, 'd')) { + if (!args_has(self->args, 'd')) { if (src_w != dst_w) { window_set_active_pane(src_w, dst_wp); window_set_active_pane(dst_w, src_wp); diff --git a/cmd-swap-window.c b/cmd-swap-window.c index ab532eb0..7583bdff 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -30,27 +30,29 @@ int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_swap_window_entry = { "swap-window", "swapw", + "ds:t:", 0, 0, "[-d] " CMD_SRCDST_WINDOW_USAGE, - 0, "d", - cmd_srcdst_init, - cmd_srcdst_parse, - cmd_swap_window_exec, - cmd_srcdst_free, - cmd_srcdst_print + 0, + NULL, + NULL, + cmd_swap_window_exec }; int cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_srcdst_data *data = self->data; + struct args *args = self->args; + const char *target_src, *target_dst; struct session *src, *dst; struct session_group *sg_src, *sg_dst; struct winlink *wl_src, *wl_dst; struct window *w; - if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL) + target_src = args_get(args, 's'); + if ((wl_src = cmd_find_window(ctx, target_src, &src)) == NULL) return (-1); - if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL) + target_dst = args_get(args, 't'); + if ((wl_dst = cmd_find_window(ctx, target_dst, &dst)) == NULL) return (-1); sg_src = session_group_find(src); @@ -68,7 +70,7 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx) wl_dst->window = wl_src->window; wl_src->window = w; - if (!cmd_check_flag(data->chflags, 'd')) { + if (!args_has(self->args, 'd')) { session_select(dst, wl_dst->idx); if (src != dst) session_select(src, wl_src->idx); diff --git a/cmd-switch-client.c b/cmd-switch-client.c index d695ce42..66eae88b 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -27,138 +27,58 @@ * Switch client to a different session. */ -void cmd_switch_client_init(struct cmd *, int); -int cmd_switch_client_parse(struct cmd *, int, char **, char **); +void cmd_switch_client_key_binding(struct cmd *, int); int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *); -void cmd_switch_client_free(struct cmd *); -size_t cmd_switch_client_print(struct cmd *, char *, size_t); - -struct cmd_switch_client_data { - char *name; - char *target; - int flag_last; - int flag_next; - int flag_previous; -}; const struct cmd_entry cmd_switch_client_entry = { "switch-client", "switchc", + "lc:npt:", 0, 0, "[-lnp] [-c target-client] [-t target-session]", - 0, "", - cmd_switch_client_init, - cmd_switch_client_parse, - cmd_switch_client_exec, - cmd_switch_client_free, - cmd_switch_client_print + 0, + cmd_switch_client_key_binding, + NULL, + cmd_switch_client_exec }; void -cmd_switch_client_init(struct cmd *self, int key) +cmd_switch_client_key_binding(struct cmd *self, int key) { - struct cmd_switch_client_data *data; - - self->data = data = xmalloc(sizeof *data); - data->name = NULL; - data->target = NULL; - data->flag_last = 0; - data->flag_next = 0; - data->flag_previous = 0; - + self->args = args_create(0); switch (key) { case '(': - data->flag_previous = 1; + args_set(self->args, 'p', NULL); break; case ')': - data->flag_next = 1; + args_set(self->args, 'n', NULL); break; case 'L': - data->flag_last = 1; + args_set(self->args, 'l', NULL); break; } } -int -cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_switch_client_data *data; - int opt; - - self->entry->init(self, KEYC_NONE); - data = self->data; - - while ((opt = getopt(argc, argv, "c:lnpt:")) != -1) { - switch (opt) { - case 'c': - if (data->name == NULL) - data->name = xstrdup(optarg); - break; - case 'l': - if (data->flag_next || data->flag_previous || - data->target != NULL) - goto usage; - data->flag_last = 1; - break; - case 'n': - if (data->flag_previous || data->flag_last || - data->target != NULL) - goto usage; - data->flag_next = 1; - break; - case 'p': - if (data->flag_next || data->flag_last || - data->target != NULL) - goto usage; - data->flag_next = 1; - break; - case 't': - if (data->flag_next || data->flag_previous) - goto usage; - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0) - goto usage; - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - int cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_switch_client_data *data = self->data; - struct client *c; - struct session *s; + struct args *args = self->args; + struct client *c; + struct session *s; - if (data == NULL) - return (0); - - if ((c = cmd_find_client(ctx, data->name)) == NULL) + if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL) return (-1); s = NULL; - if (data->flag_next) { + if (args_has(args, 'n')) { if ((s = session_next_session(c->session)) == NULL) { ctx->error(ctx, "can't find next session"); return (-1); } - } else if (data->flag_previous) { + } else if (args_has(args, 'p')) { if ((s = session_previous_session(c->session)) == NULL) { ctx->error(ctx, "can't find previous session"); return (-1); } - } else if (data->flag_last) { + } else if (args_has(args, 'l')) { if (c->last_session != NULL && session_alive(c->last_session)) s = c->last_session; if (s == NULL) { @@ -166,7 +86,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } } else - s = cmd_find_session(ctx, data->target); + s = cmd_find_session(ctx, args_get(args, 't')); if (s == NULL) return (-1); @@ -181,37 +101,3 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx) return (0); } - -void -cmd_switch_client_free(struct cmd *self) -{ - struct cmd_switch_client_data *data = self->data; - - if (data->name != NULL) - xfree(data->name); - if (data->target != NULL) - xfree(data->target); - xfree(data); -} - -size_t -cmd_switch_client_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_switch_client_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return (off); - if (off < len && data->flag_last) - off += xsnprintf(buf + off, len - off, "%s", " -l"); - if (off < len && data->flag_next) - off += xsnprintf(buf + off, len - off, "%s", " -n"); - if (off < len && data->flag_previous) - off += xsnprintf(buf + off, len - off, "%s", " -p"); - if (off < len && data->name != NULL) - off += cmd_prarg(buf + off, len - off, " -c ", data->name); - if (off < len && data->target != NULL) - off += cmd_prarg(buf + off, len - off, " -t ", data->target); - return (off); -} diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index f95342b9..7dab5683 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -24,140 +24,80 @@ * Unbind key from command. */ -int cmd_unbind_key_parse(struct cmd *, int, char **, char **); +int cmd_unbind_key_check(struct args *); int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *); -void cmd_unbind_key_free(struct cmd *); -int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *); - -struct cmd_unbind_key_data { - int key; - - int flag_all; - int command_key; - char *tablename; -}; +int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int); const struct cmd_entry cmd_unbind_key_entry = { "unbind-key", "unbind", + "acnt:", 1, 1, "[-acn] [-t key-table] key", - 0, "", + 0, NULL, - cmd_unbind_key_parse, - cmd_unbind_key_exec, - cmd_unbind_key_free, - NULL + cmd_unbind_key_check, + cmd_unbind_key_exec }; int -cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause) +cmd_unbind_key_check(struct args *args) { - struct cmd_unbind_key_data *data; - int opt, no_prefix = 0; - - self->data = data = xmalloc(sizeof *data); - data->flag_all = 0; - data->command_key = 0; - data->tablename = NULL; - - while ((opt = getopt(argc, argv, "acnt:")) != -1) { - switch (opt) { - case 'a': - data->flag_all = 1; - break; - case 'c': - data->command_key = 1; - break; - case 'n': - no_prefix = 1; - break; - case 't': - if (data->tablename == NULL) - data->tablename = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (data->flag_all && (argc != 0 || data->tablename)) - goto usage; - if (!data->flag_all && argc != 1) - goto usage; - - if (!data->flag_all) { - data->key = key_string_lookup_string(argv[0]); - if (data->key == KEYC_NONE) { - xasprintf(cause, "unknown key: %s", argv[0]); - goto error; - } - if (!no_prefix) - data->key |= KEYC_PREFIX; - } - + if (args_has(args, 'a') && (args->argc != 0 || args_has(args, 't'))) + return (-1); return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - -error: - xfree(data); - return (-1); } int cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) { - struct cmd_unbind_key_data *data = self->data; - struct key_binding *bd; + struct args *args = self->args; + struct key_binding *bd; + int key; - if (data == NULL) - return (0); - if (data->flag_all) { + if (args_has(args, 'a')) { while (!SPLAY_EMPTY(&key_bindings)) { bd = SPLAY_ROOT(&key_bindings); SPLAY_REMOVE(key_bindings, &key_bindings, bd); cmd_list_free(bd->cmdlist); xfree(bd); } - } else { - if (data->tablename != NULL) - return (cmd_unbind_key_table(self, ctx)); - - key_bindings_remove(data->key); + return (0); } + key = key_string_lookup_string(args->argv[0]); + if (key == KEYC_NONE) { + ctx->error(ctx, "unknown key: %s", args->argv[0]); + return (-1); + } + + if (args_has(args, 't')) + return (cmd_unbind_key_table(self, ctx, key)); + + if (!args_has(args, 'n')) + key |= KEYC_PREFIX; + key_bindings_remove(key); return (0); } int -cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx) +cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key) { - struct cmd_unbind_key_data *data = self->data; + struct args *args = self->args; + const char *tablename; const struct mode_key_table *mtab; struct mode_key_binding *mbind, mtmp; - if ((mtab = mode_key_findtable(data->tablename)) == NULL) { - ctx->error(ctx, "unknown key table: %s", data->tablename); + tablename = args_get(args, 't'); + if ((mtab = mode_key_findtable(tablename)) == NULL) { + ctx->error(ctx, "unknown key table: %s", tablename); return (-1); } - mtmp.key = data->key & ~KEYC_PREFIX; - mtmp.mode = data->command_key ? 1 : 0; + mtmp.key = key; + mtmp.mode = !!args_has(args, 'c'); if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind); xfree(mbind); } return (0); } - -void -cmd_unbind_key_free(struct cmd *self) -{ - struct cmd_unbind_key_data *data = self->data; - - if (data->tablename != NULL) - xfree(data->tablename); - xfree(data); -} diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c index a7ca23da..2b44ea8a 100644 --- a/cmd-unlink-window.c +++ b/cmd-unlink-window.c @@ -28,26 +28,25 @@ int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_unlink_window_entry = { "unlink-window", "unlinkw", + "kt:", 0, 0, "[-k] " CMD_TARGET_WINDOW_USAGE, - 0, "k", - cmd_target_init, - cmd_target_parse, - cmd_unlink_window_exec, - cmd_target_free, - cmd_target_print + 0, + NULL, + NULL, + cmd_unlink_window_exec }; int cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; + struct args *args = self->args; struct winlink *wl; struct window *w; struct session *s, *s2; struct session_group *sg; u_int references; - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL) return (-1); w = wl->window; @@ -59,7 +58,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) } else references = 1; - if (!cmd_check_flag(data->chflags, 'k') && w->references == references) { + if (!args_has(self->args, 'k') && w->references == references) { ctx->error(ctx, "window is only linked to one session"); return (-1); } diff --git a/cmd.c b/cmd.c index cff10f9a..6c4a06f4 100644 --- a/cmd.c +++ b/cmd.c @@ -167,7 +167,7 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv) } char ** -cmd_copy_argv(int argc, char **argv) +cmd_copy_argv(int argc, char *const *argv) { char **new_argv; int i; @@ -201,8 +201,9 @@ cmd_parse(int argc, char **argv, char **cause) { const struct cmd_entry **entryp, *entry; struct cmd *cmd; + struct args *args; char s[BUFSIZ]; - int opt, ambiguous = 0; + int ambiguous = 0; *cause = NULL; if (argc == 0) { @@ -236,30 +237,19 @@ cmd_parse(int argc, char **argv, char **cause) return (NULL); } - optreset = 1; - optind = 1; - if (entry->parse == NULL) { - while ((opt = getopt(argc, argv, "")) != -1) { - switch (opt) { - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0) - goto usage; - } + args = args_parse(entry->args_template, argc, argv); + if (args == NULL) + goto usage; + if (entry->args_lower != -1 && args->argc < entry->args_lower) + goto usage; + if (entry->args_upper != -1 && args->argc > entry->args_upper) + goto usage; + if (entry->check != NULL && entry->check(args) != 0) + goto usage; cmd = xmalloc(sizeof *cmd); cmd->entry = entry; - cmd->data = NULL; - if (entry->parse != NULL) { - if (entry->parse(cmd, argc, argv, cause) != 0) { - xfree(cmd); - return (NULL); - } - } + cmd->args = args; return (cmd); ambiguous: @@ -277,6 +267,8 @@ ambiguous: return (NULL); usage: + if (args != NULL) + args_free(args); xasprintf(cause, "usage: %s %s", entry->name, entry->usage); return (NULL); } @@ -290,17 +282,27 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) void cmd_free(struct cmd *cmd) { - if (cmd->data != NULL && cmd->entry->free != NULL) - cmd->entry->free(cmd); + if (cmd->args != NULL) + args_free(cmd->args); xfree(cmd); } size_t cmd_print(struct cmd *cmd, char *buf, size_t len) { - if (cmd->entry->print == NULL) - return (xsnprintf(buf, len, "%s", cmd->entry->name)); - return (cmd->entry->print(cmd, buf, len)); + size_t off, used; + + off = xsnprintf(buf, len, "%s ", cmd->entry->name); + if (off < len) { + used = args_print(cmd->args, buf + off, len - off); + if (used == 0) + buf[off - 1] = '\0'; + else { + off += used; + buf[off] = '\0'; + } + } + return (off); } /* diff --git a/key-bindings.c b/key-bindings.c index 32e81e94..a3f7fb42 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -187,9 +187,10 @@ key_bindings_init(void) cmd = xmalloc(sizeof *cmd); cmd->entry = table[i].entry; - cmd->data = NULL; - if (cmd->entry->init != NULL) - cmd->entry->init(cmd, table[i].key); + if (cmd->entry->key_binding != NULL) + cmd->entry->key_binding(cmd, table[i].key); + else + cmd->args = args_create(0); TAILQ_INSERT_HEAD(&cmdlist->list, cmd, qentry); key_bindings_add( diff --git a/tmux.h b/tmux.h index 09999b00..3e6ecec2 100644 --- a/tmux.h +++ b/tmux.h @@ -1168,6 +1168,15 @@ struct client { }; ARRAY_DECL(clients, struct client *); +/* Parsed arguments. */ +struct args { + bitstr_t *flags; + char *values[SCHAR_MAX]; /* XXX This is awfully big. */ + + int argc; + char **argv; +}; + /* Key/command line command. */ struct cmd_ctx { /* @@ -1198,67 +1207,35 @@ struct cmd_ctx { }; struct cmd { - const struct cmd_entry *entry; - void *data; + const struct cmd_entry *entry; + struct args *args; - TAILQ_ENTRY(cmd) qentry; + TAILQ_ENTRY(cmd) qentry; }; struct cmd_list { - int references; - TAILQ_HEAD(, cmd) list; + int references; + TAILQ_HEAD(, cmd) list; }; struct cmd_entry { const char *name; const char *alias; + + const char *args_template; + int args_lower; + int args_upper; + const char *usage; #define CMD_STARTSERVER 0x1 #define CMD_CANTNEST 0x2 #define CMD_SENDENVIRON 0x4 -#define CMD_ARG1 0x8 -#define CMD_ARG01 0x10 -#define CMD_ARG2 0x20 -#define CMD_ARG12 0x40 -#define CMD_READONLY 0x80 +#define CMD_READONLY 0x8 int flags; - const char *chflags; - - void (*init)(struct cmd *, int); - int (*parse)(struct cmd *, int, char **, char **); + void (*key_binding)(struct cmd *, int); + int (*check)(struct args *); int (*exec)(struct cmd *, struct cmd_ctx *); - void (*free)(struct cmd *); - size_t (*print)(struct cmd *, char *, size_t); -}; - -/* Generic command data. */ -struct cmd_target_data { - uint64_t chflags; - - char *target; - - char *arg; - char *arg2; -}; - -struct cmd_srcdst_data { - uint64_t chflags; - - char *src; - char *dst; - - char *arg; - char *arg2; -}; - -struct cmd_buffer_data { - uint64_t chflags; - - int buffer; - - char *arg; - char *arg2; }; /* Key binding. */ @@ -1301,6 +1278,17 @@ struct options_table_entry { /* List of configuration causes. */ ARRAY_DECL(causelist, char *); +/* Common command usages. */ +#define CMD_TARGET_PANE_USAGE "[-t target-pane]" +#define CMD_TARGET_WINDOW_USAGE "[-t target-window]" +#define CMD_TARGET_SESSION_USAGE "[-t target-session]" +#define CMD_TARGET_CLIENT_USAGE "[-t target-client]" +#define CMD_SRCDST_PANE_USAGE "[-s src-pane] [-t dst-pane]" +#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]" +#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]" +#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]" +#define CMD_BUFFER_USAGE "[-b buffer-index]" + /* tmux.c */ extern struct options global_options; extern struct options global_s_options; @@ -1479,10 +1467,21 @@ char *paste_print(struct paste_buffer *, size_t); extern const char clock_table[14][5][5]; void clock_draw(struct screen_write_ctx *, int, int); +/* arguments.c */ +struct args *args_create(int, ...); +struct args *args_parse(const char *, int, char **); +void args_free(struct args *); +size_t args_print(struct args *, char *, size_t); +int args_has(struct args *, u_char); +void args_set(struct args *, u_char, const char *); +const char *args_get(struct args *, u_char); +long long args_strtonum( + struct args *, u_char, long long, long long, char **); + /* cmd.c */ int cmd_pack_argv(int, char **, char *, size_t); int cmd_unpack_argv(char *, size_t, int, char ***); -char **cmd_copy_argv(int, char **); +char **cmd_copy_argv(int, char *const *); void cmd_free_argv(int, char **); struct cmd *cmd_parse(int, char **, char **); int cmd_exec(struct cmd *, struct cmd_ctx *); @@ -1592,32 +1591,6 @@ size_t cmd_list_print(struct cmd_list *, char *, size_t); /* cmd-string.c */ int cmd_string_parse(const char *, struct cmd_list **, char **); -/* cmd-generic.c */ -size_t cmd_prarg(char *, size_t, const char *, char *); -int cmd_check_flag(uint64_t, int); -void cmd_set_flag(uint64_t *, int); -#define CMD_TARGET_PANE_USAGE "[-t target-pane]" -#define CMD_TARGET_WINDOW_USAGE "[-t target-window]" -#define CMD_TARGET_SESSION_USAGE "[-t target-session]" -#define CMD_TARGET_CLIENT_USAGE "[-t target-client]" -void cmd_target_init(struct cmd *, int); -int cmd_target_parse(struct cmd *, int, char **, char **); -void cmd_target_free(struct cmd *); -size_t cmd_target_print(struct cmd *, char *, size_t); -#define CMD_SRCDST_PANE_USAGE "[-s src-pane] [-t dst-pane]" -#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]" -#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]" -#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]" -void cmd_srcdst_init(struct cmd *, int); -int cmd_srcdst_parse(struct cmd *, int, char **, char **); -void cmd_srcdst_free(struct cmd *); -size_t cmd_srcdst_print(struct cmd *, char *, size_t); -#define CMD_BUFFER_USAGE "[-b buffer-index]" -void cmd_buffer_init(struct cmd *, int); -int cmd_buffer_parse(struct cmd *, int, char **, char **); -void cmd_buffer_free(struct cmd *); -size_t cmd_buffer_print(struct cmd *, char *, size_t); - /* client.c */ int client_main(int, char **, int);