diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-24 19:53:38 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-24 19:53:38 +0000 |
commit | 80107f99da3b67201c712344950c91128c136b23 (patch) | |
tree | 623f84ed3392417fc769ee596cf48331531533b6 /usr.bin/tmux | |
parent | 38c599a96818f72492019b9f38af1421b37c2e65 (diff) |
Add support for custom command aliases, this is an array option which
contains items of the form "alias=command". This is consulted when an
unknown command is parsed.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r-- | usr.bin/tmux/client.c | 17 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-string.c | 84 | ||||
-rw-r--r-- | usr.bin/tmux/cmd.c | 70 | ||||
-rw-r--r-- | usr.bin/tmux/key-bindings.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/options-table.c | 9 | ||||
-rw-r--r-- | usr.bin/tmux/pty.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 28 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 3 |
8 files changed, 166 insertions, 53 deletions
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c index bc617d545b9..ad7f3bf7b49 100644 --- a/usr.bin/tmux/client.c +++ b/usr.bin/tmux/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.119 2017/01/23 10:09:43 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.120 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -252,16 +252,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags, * flag. */ cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause); - if (cmdlist == NULL) { - fprintf(stderr, "%s\n", cause); - return (1); - } - cmdflags &= ~CMD_STARTSERVER; - TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { - if (cmd->entry->flags & CMD_STARTSERVER) - cmdflags |= CMD_STARTSERVER; + if (cmdlist != NULL) { + TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { + if (cmd->entry->flags & CMD_STARTSERVER) + cmdflags |= CMD_STARTSERVER; + } + cmd_list_free(cmdlist); } - cmd_list_free(cmdlist); } /* Create client process structure (starts logging). */ diff --git a/usr.bin/tmux/cmd-string.c b/usr.bin/tmux/cmd-string.c index b0565e62235..a86181e3a66 100644 --- a/usr.bin/tmux/cmd-string.c +++ b/usr.bin/tmux/cmd-string.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-string.c,v 1.27 2017/01/16 14:52:25 nicm Exp $ */ +/* $OpenBSD: cmd-string.c,v 1.28 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -54,17 +54,15 @@ cmd_string_ungetc(size_t *p) (*p)--; } -struct cmd_list * -cmd_string_parse(const char *s, const char *file, u_int line, char **cause) +int +cmd_string_split(const char *s, int *rargc, char ***rargv) { - size_t p = 0; - int ch, i, argc = 0; - char **argv = NULL, *buf = NULL, *t; - const char *whitespace, *equals; - size_t len = 0; - struct cmd_list *cmdlist = NULL; + size_t p = 0; + int ch, argc = 0, append = 0; + char **argv = NULL, *buf = NULL, *t; + const char *whitespace, *equals; + size_t len = 0; - *cause = NULL; for (;;) { ch = cmd_string_getc(s, &p); switch (ch) { @@ -115,43 +113,67 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause) argc--; memmove(argv, argv + 1, argc * (sizeof *argv)); } - if (argc == 0) - goto out; - - cmdlist = cmd_list_parse(argc, argv, file, line, cause); - goto out; + goto done; case '~': - if (buf == NULL) { - t = cmd_string_expand_tilde(s, &p); - if (t == NULL) - goto error; - cmd_string_copy(&buf, t, &len); + if (buf != NULL) { + append = 1; break; } - /* FALLTHROUGH */ + t = cmd_string_expand_tilde(s, &p); + if (t == NULL) + goto error; + cmd_string_copy(&buf, t, &len); + break; default: + append = 1; + break; + } + if (append) { if (len >= SIZE_MAX - 2) goto error; - buf = xrealloc(buf, len + 1); buf[len++] = ch; - break; } + append = 0; } -error: - xasprintf(cause, "invalid or unknown command: %s", s); +done: + *rargc = argc; + *rargv = argv; -out: free(buf); + return (0); - if (argv != NULL) { - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); - } +error: + if (argv != NULL) + cmd_free_argv(argc, argv); + free(buf); + return (-1); +} +struct cmd_list * +cmd_string_parse(const char *s, const char *file, u_int line, char **cause) +{ + struct cmd_list *cmdlist = NULL; + int argc; + char **argv; + + *cause = NULL; + if (cmd_string_split(s, &argc, &argv) != 0) + goto error; + if (argc != 0) { + cmdlist = cmd_list_parse(argc, argv, file, line, cause); + if (cmdlist == NULL) { + cmd_free_argv(argc, argv); + goto error; + } + } + cmd_free_argv(argc, argv); return (cmdlist); + +error: + xasprintf(cause, "invalid or unknown command: %s", s); + return (NULL); } static void diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index 1079167d1ea..b38ff48abeb 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.134 2017/01/16 14:52:25 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.135 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -308,21 +308,74 @@ cmd_stringify_argv(int argc, char **argv) return (buf); } +static int +cmd_try_alias(int *argc, char ***argv) +{ + struct options_entry *o; + int old_argc = *argc, new_argc; + char **old_argv = *argv, **new_argv; + u_int size, idx; + int i; + size_t wanted; + const char *s, *cp = NULL; + + o = options_get_only(global_options, "command-alias"); + if (o == NULL || options_array_size(o, &size) == -1 || size == 0) + return (-1); + + wanted = strlen(old_argv[0]); + for (idx = 0; idx < size; idx++) { + s = options_array_get(o, idx); + if (s == NULL) + continue; + + cp = strchr(s, '='); + if (cp == NULL || (size_t)(cp - s) != wanted) + continue; + if (strncmp(old_argv[0], s, wanted) == 0) + break; + } + if (idx == size) + return (-1); + + if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0) + return (-1); + + *argc = new_argc + old_argc - 1; + *argv = xcalloc((*argc) + 1, sizeof **argv); + + for (i = 0; i < new_argc; i++) + (*argv)[i] = xstrdup(new_argv[i]); + for (i = 1; i < old_argc; i++) + (*argv)[new_argc + i - 1] = xstrdup(old_argv[i]); + + log_debug("alias: %s=%s", old_argv[0], cp + 1); + for (i = 0; i < *argc; i++) + log_debug("alias: argv[%d] = %s", i, (*argv)[i]); + + cmd_free_argv(new_argc, new_argv); + return (0); +} + struct cmd * cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) { + const char *name; const struct cmd_entry **entryp, *entry; struct cmd *cmd; struct args *args; char s[BUFSIZ]; - int ambiguous = 0; + int ambiguous, allocated = 0; *cause = NULL; if (argc == 0) { xasprintf(cause, "no command"); return (NULL); } + name = argv[0]; +retry: + ambiguous = 0; entry = NULL; for (entryp = cmd_table; *entryp != NULL; entryp++) { if ((*entryp)->alias != NULL && @@ -342,10 +395,17 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) if (strcmp(entry->name, argv[0]) == 0) break; } + if ((ambiguous || entry == NULL) && + server_proc != NULL && + !allocated && + cmd_try_alias(&argc, &argv) == 0) { + allocated = 1; + goto retry; + } if (ambiguous) goto ambiguous; if (entry == NULL) { - xasprintf(cause, "unknown command: %s", argv[0]); + xasprintf(cause, "unknown command: %s", name); return (NULL); } @@ -365,6 +425,8 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) cmd->file = xstrdup(file); cmd->line = line; + if (allocated) + cmd_free_argv(argc, argv); return (cmd); ambiguous: @@ -378,7 +440,7 @@ ambiguous: break; } s[strlen(s) - 2] = '\0'; - xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s); + xasprintf(cause, "ambiguous command: %s, could be: %s", name, s); return (NULL); usage: diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c index af0bf7bb1dc..a627342ab59 100644 --- a/usr.bin/tmux/key-bindings.c +++ b/usr.bin/tmux/key-bindings.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key-bindings.c,v 1.71 2017/01/16 14:52:25 nicm Exp $ */ +/* $OpenBSD: key-bindings.c,v 1.72 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -383,7 +383,7 @@ key_bindings_init(void) for (i = 0; i < nitems(defaults); i++) { cmdlist = cmd_string_parse(defaults[i], "<default>", i, &cause); if (cmdlist == NULL) - fatalx("bad default key"); + fatalx("bad default key: %s", defaults[i]); cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0)); cmd_list_free(cmdlist); } diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c index a6a8eec4222..52fc4f3c249 100644 --- a/usr.bin/tmux/options-table.c +++ b/usr.bin/tmux/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.82 2017/01/16 14:52:25 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.83 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -65,6 +65,13 @@ const struct options_table_entry options_table[] = { .default_num = 20 }, + { .name = "command-alias", + .type = OPTIONS_TABLE_ARRAY, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "split-pane=split-window," + "splitp=split-window" + }, + { .name = "default-terminal", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, diff --git a/usr.bin/tmux/pty.c b/usr.bin/tmux/pty.c index 108aaa18b9e..61778866b11 100644 --- a/usr.bin/tmux/pty.c +++ b/usr.bin/tmux/pty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pty.c,v 1.1 2017/01/23 10:09:43 nicm Exp $ */ +/* $OpenBSD: pty.c,v 1.2 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -45,7 +45,7 @@ pty_fork(int ptmfd, int *fd, char *name, size_t namelen, struct winsize *ws) struct ptmget ptm; pid_t pid; - if ((ioctl(ptmfd, PTMGET, &ptm) == -1)) + if (ioctl(ptmfd, PTMGET, &ptm) == -1) return (-1); strlcpy(name, ptm.sn, namelen); diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index ab3d3d5fc84..768fb3b7a46 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.525 2017/01/13 10:12:12 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.526 2017/01/24 19:53:37 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 13 2017 $ +.Dd $Mdocdate: January 24 2017 $ .Dt TMUX 1 .Os .Sh NAME @@ -2410,6 +2410,30 @@ Available server options are: Set the number of buffers; as new buffers are added to the top of the stack, old ones are removed from the bottom if necessary to maintain this maximum length. +.It Xo Ic command-alias[] +.Ar name=value +.Xc +This is an array of custom aliases for commands. +If an unknown command matches +.Ar name , +it is replaced with +.Ar value . +For example, after: +.Pp +.Dl set -s command-alias[2] zoom='resize-pane -Z' +.Pp +Using: +.Pp +.Dl zoom -t:.1 +.Pp +Is equivalent to: +.Pp +.Dl resize-pane -Z -t:.1 +.Pp +Note that aliases are expanded when a command is parsed rather than when it is +executed, so binding an alias with +.Ic bind-key +will bind the expanded form. .It Ic default-terminal Ar terminal Set the default terminal for new windows created in this session - the default value of the diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index b718cb59c1d..680f889360c 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.703 2017/01/24 19:11:46 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.704 2017/01/24 19:53:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1828,6 +1828,7 @@ void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...); void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...); /* cmd-string.c */ +int cmd_string_split(const char *, int *, char ***); struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **); /* cmd-wait-for.c */ |