diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-13 17:47:47 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-13 17:47:47 +0000 |
commit | c2c663e118deaaeb506c6b6fdd8d7c672ce0c680 (patch) | |
tree | d096eba061c552bc79881ce87d35a568697dc746 | |
parent | 05c6d0668eda3213f427d840f5f588636d06a4d2 (diff) |
Tidy up and improve target (-t) argument parsing:
- move the code back into cmd.c and merge with the existing functions where
possible;
- accept "-tttyp0" as well as "-t/dev/ttyp0" for clients;
- when looking up session names, try an exact match first, and if that fails
look for it as an fnmatch pattern and then as the start of a name - if more
that one session matches an error is given; so if there is one session called
"mysession", -tmysession, -tmysess, -tmysess* are equivalent but if there
is also "mysession2", the last two are errors;
- similarly for windows, if the argument is not a valid index or exact window
name match, try it against the window names as an fnmatch pattern and a
prefix.
-rw-r--r-- | usr.bin/tmux/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/tmux/arg.c | 194 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-link-window.c | 15 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-move-window.c | 15 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-new-window.c | 14 | ||||
-rw-r--r-- | usr.bin/tmux/cmd.c | 422 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 45 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 11 |
8 files changed, 414 insertions, 306 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile index 88bff2ff7ec..ddcc1479e99 100644 --- a/usr.bin/tmux/Makefile +++ b/usr.bin/tmux/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.5 2009/07/09 15:47:49 nicm Exp $ +# $OpenBSD: Makefile,v 1.6 2009/07/13 17:47:46 nicm Exp $ PROG= tmux -SRCS= arg.c attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \ +SRCS= attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \ client-msg.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 \ diff --git a/usr.bin/tmux/arg.c b/usr.bin/tmux/arg.c deleted file mode 100644 index e45a5887a0e..00000000000 --- a/usr.bin/tmux/arg.c +++ /dev/null @@ -1,194 +0,0 @@ -/* $OpenBSD: arg.c,v 1.2 2009/06/02 11:18:59 ray Exp $ */ - -/* - * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> - * - * 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 <sys/types.h> - -#include <fnmatch.h> -#include <stdlib.h> -#include <string.h> - -#include "tmux.h" - -struct client *arg_lookup_client(const char *); -struct session *arg_lookup_session(const char *); - -struct client * -arg_lookup_client(const char *name) -{ - struct client *c; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && strcmp(name, c->tty.path) == 0) - return (c); - } - - return (NULL); -} - -struct session * -arg_lookup_session(const char *name) -{ - struct session *s, *newest = NULL; - struct timeval *tv; - u_int i; - - tv = NULL; - for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { - s = ARRAY_ITEM(&sessions, i); - if (s == NULL || fnmatch(name, s->name, 0) != 0) - continue; - - if (tv == NULL || timercmp(&s->tv, tv, >)) { - newest = s; - tv = &s->tv; - } - } - - return (newest); -} - -struct client * -arg_parse_client(const char *arg) -{ - struct client *c; - char *arg2; - size_t n; - - if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) { - arg2 = xstrdup(arg); - - /* Trim a trailing : if any from the argument. */ - n = strlen(arg2); - if (n && arg2[n - 1] == ':') - arg2[n - 1] = '\0'; - - /* Try and look up the client name. */ - c = arg_lookup_client(arg2); - xfree(arg2); - return (c); - } - - return (NULL); -} - -struct session * -arg_parse_session(const char *arg) -{ - struct session *s; - struct client *c; - char *arg2; - size_t n; - - if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) { - arg2 = xstrdup(arg); - - /* Trim a trailing : if any from the argument. */ - n = strlen(arg2); - if (n && arg2[n - 1] == ':') - arg2[n - 1] = '\0'; - - /* See if the argument matches a session. */ - if ((s = arg_lookup_session(arg2)) != NULL) { - xfree(arg2); - return (s); - } - - /* If not try a client. */ - if ((c = arg_lookup_client(arg2)) != NULL) { - xfree(arg2); - return (c->session); - } - - xfree(arg2); - } - - return (NULL); -} - -int -arg_parse_window(const char *arg, struct session **s, int *idx) -{ - char *arg2, *ptr; - const char *errstr; - - *idx = -1; - - /* Handle no argument or a single :. */ - if (arg == NULL || (arg[0] == ':' && arg[1] == '\0')) { - *s = arg_parse_session(NULL); - return (0); - } - - /* Find the separator if any. */ - arg2 = xstrdup(arg); - ptr = strrchr(arg2, ':'); - - /* - * If it is first, this means no session name, so use current session - * and try to convert the rest as index. - */ - if (ptr == arg2) { - *idx = strtonum(ptr + 1, 0, INT_MAX, &errstr); - if (errstr != NULL) { - xfree(arg2); - return (1); - } - - xfree(arg2); - *s = arg_parse_session(NULL); - return (0); - } - - /* If missing, try as an index, else look up immediately. */ - if (ptr == NULL) { - *idx = strtonum(arg2, 0, INT_MAX, &errstr); - if (errstr == NULL) { - /* This is good as an index; use current session. */ - xfree(arg2); - *s = arg_parse_session(NULL); - return (0); - } - - *idx = -1; - goto lookup; - } - - /* If last, strip it and look up as a session. */ - if (ptr[1] == '\0') { - *ptr = '\0'; - goto lookup; - } - - /* Present but not first and not last. Break and convert both. */ - *ptr = '\0'; - *idx = strtonum(ptr + 1, 0, INT_MAX, &errstr); - if (errstr != NULL) { - xfree(arg2); - return (1); - } - -lookup: - /* Look up as session. */ - *s = arg_parse_session(arg2); - xfree(arg2); - if (*s == NULL) - return (1); - return (0); -} diff --git a/usr.bin/tmux/cmd-link-window.c b/usr.bin/tmux/cmd-link-window.c index 32144859fcf..29d18ab88a0 100644 --- a/usr.bin/tmux/cmd-link-window.c +++ b/usr.bin/tmux/cmd-link-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-link-window.c,v 1.1 2009/06/01 22:58:49 nicm Exp $ */ +/* $OpenBSD: cmd-link-window.c,v 1.2 2009/07/13 17:47:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -52,19 +52,8 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL) return (-1); - - if (arg_parse_window(data->dst, &dst, &idx) != 0) { - ctx->error(ctx, "bad window: %s", data->dst); - return (-1); - } - if (dst == NULL) - dst = ctx->cursession; - if (dst == NULL) - dst = cmd_current_session(ctx); - if (dst == NULL) { - ctx->error(ctx, "session not found: %s", data->dst); + if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) return (-1); - } wl_dst = NULL; if (idx != -1) diff --git a/usr.bin/tmux/cmd-move-window.c b/usr.bin/tmux/cmd-move-window.c index bde3ed61380..b818beaa141 100644 --- a/usr.bin/tmux/cmd-move-window.c +++ b/usr.bin/tmux/cmd-move-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-move-window.c,v 1.1 2009/06/01 22:58:49 nicm Exp $ */ +/* $OpenBSD: cmd-move-window.c,v 1.2 2009/07/13 17:47:46 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -54,19 +54,8 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL) return (-1); - - if (arg_parse_window(data->dst, &dst, &idx) != 0) { - ctx->error(ctx, "bad window: %s", data->dst); - return (-1); - } - if (dst == NULL) - dst = ctx->cursession; - if (dst == NULL) - dst = cmd_current_session(ctx); - if (dst == NULL) { - ctx->error(ctx, "session not found: %s", data->dst); + if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) return (-1); - } wl_dst = NULL; if (idx != -1) diff --git a/usr.bin/tmux/cmd-new-window.c b/usr.bin/tmux/cmd-new-window.c index fe0729f71cd..eefbebe7e29 100644 --- a/usr.bin/tmux/cmd-new-window.c +++ b/usr.bin/tmux/cmd-new-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-new-window.c,v 1.2 2009/07/07 06:58:49 nicm Exp $ */ +/* $OpenBSD: cmd-new-window.c,v 1.3 2009/07/13 17:47:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -126,18 +126,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) if (data == NULL) return (0); - if (arg_parse_window(data->target, &s, &idx) != 0) { - ctx->error(ctx, "bad window: %s", data->target); + if ((idx = cmd_find_index(ctx, data->target, &s)) == -2) return (-1); - } - if (s == NULL) - s = ctx->cursession; - if (s == NULL) - s = cmd_current_session(ctx); - if (s == NULL) { - ctx->error(ctx, "session not found: %s", data->target); - return (-1); - } wl = NULL; if (idx != -1) diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index b4cdd0ec5d8..1ac380ffd34 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.4 2009/07/09 15:47:49 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.5 2009/07/13 17:47:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -19,6 +19,8 @@ #include <sys/types.h> #include <sys/time.h> +#include <fnmatch.h> +#include <paths.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -100,6 +102,11 @@ const struct cmd_entry *cmd_table[] = { NULL }; +struct session *cmd_newest_session(void); +struct client *cmd_lookup_client(const char *); +struct session *cmd_lookup_session(const char *, int *); +struct winlink *cmd_lookup_window(struct session *, const char *, int *); + struct cmd * cmd_parse(int argc, char **argv, char **cause) { @@ -294,106 +301,421 @@ cmd_recv_string(struct buffer *b) return (s); } +/* + * Figure out the current session. Use: 1) the current session, if the command + * context has one; 2) the session specified in the TMUX variable from the + * environment (as passed from the client); 3) the newest session. + */ struct session * cmd_current_session(struct cmd_ctx *ctx) { struct msg_command_data *data = ctx->msgdata; - struct timeval *tv; - struct session *s, *newest = NULL; - u_int i; + struct session *s; if (ctx->cursession != NULL) return (ctx->cursession); if (data != NULL && data->pid != -1) { - if (data->pid != getpid()) { - ctx->error(ctx, "wrong server: %ld", (long) data->pid); + if (data->pid != getpid()) return (NULL); - } - if (data->idx > ARRAY_LENGTH(&sessions)) { - ctx->error(ctx, "index out of range: %d", data->idx); + if (data->idx > ARRAY_LENGTH(&sessions)) return (NULL); - } - if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) { - ctx->error(ctx, "session doesn't exist: %u", data->idx); + if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) return (NULL); - } return (s); } - tv = NULL; + return (cmd_newest_session()); +} + +/* Find the newest session. */ +struct session * +cmd_newest_session(void) +{ + struct session *s, *snewest; + struct timeval *tv = NULL; + u_int i; + + snewest = NULL; for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { - s = ARRAY_ITEM(&sessions, i); - if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) { - newest = ARRAY_ITEM(&sessions, i); + if ((s = ARRAY_ITEM(&sessions, i)) == NULL) + continue; + + if (tv == NULL || timercmp(&s->tv, tv, >)) { + snewest = s; tv = &s->tv; } } - return (newest); + + return (snewest); } +/* Find the target client or report an error and return NULL. */ struct client * cmd_find_client(struct cmd_ctx *ctx, const char *arg) { struct client *c; + char *tmparg; + size_t arglen; + /* A NULL argument means the current client. */ if (arg == NULL) - c = ctx->curclient; - else { - if ((c = arg_parse_client(arg)) == NULL) { - if (arg != NULL) - ctx->error(ctx, "client not found: %s", arg); - else - ctx->error(ctx, "no client found"); + return (ctx->curclient); + tmparg = xstrdup(arg); + + /* Trim a single trailing colon if any. */ + arglen = strlen(tmparg); + if (arglen != 0 && tmparg[arglen - 1] == ':') + tmparg[arglen - 1] = '\0'; + + /* Find the client, if any. */ + c = cmd_lookup_client(tmparg); + + /* If no client found, report an error. */ + if (c == NULL) + ctx->error(ctx, "client not found: %s", tmparg); + + xfree(tmparg); + return (c); +} + +/* + * Lookup a client by device path. Either of a full match and a match without a + * leading _PATH_DEV ("/dev/") is accepted. + */ +struct client * +cmd_lookup_client(const char *name) +{ + struct client *c; + const char *path; + u_int i; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + if ((c = ARRAY_ITEM(&clients, i)) == NULL) + continue; + path = c->tty.path; + + /* Check for exact matches. */ + if (strcmp(name, path) == 0) + return (c); + + /* Check without leading /dev if present. */ + if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0) + continue; + if (strcmp(name, path + (sizeof _PATH_DEV) - 1) == 0) + return (c); + } + + return (NULL); +} + +/* Lookup a session by name. If no session is found, NULL is returned. */ +struct session * +cmd_lookup_session(const char *name, int *ambiguous) +{ + struct session *s, *sfound; + u_int i; + + *ambiguous = 0; + + /* + * Look for matches. Session names must be unique so an exact match + * can't be ambigious and can just be returned. + */ + sfound = NULL; + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + if ((s = ARRAY_ITEM(&sessions, i)) == NULL) + continue; + + /* Check for an exact match and return it if found. */ + if (strcmp(name, s->name) == 0) + return (s); + + /* Then check for pattern matches. */ + if (strncmp(name, s->name, strlen(name)) == 0 || + fnmatch(name, s->name, 0) == 0) { + if (sfound != NULL) { + *ambiguous = 1; + return (NULL); + } + sfound = s; } } - return (c); + + return (sfound); } +/* + * Lookup a window or return -1 if not found or ambigious. First try as an index + * and if invalid, use fnmatch or leading prefix. + */ +struct winlink * +cmd_lookup_window(struct session *s, const char *name, int *ambiguous) +{ + struct winlink *wl, *wlfound; + struct window *w; + const char *errstr; + u_int idx; + + *ambiguous = 0; + + /* First see if this is a valid window index in this session. */ + idx = strtonum(name, 0, INT_MAX, &errstr); + if (errstr == NULL) { + if ((wl = winlink_find_by_index(&s->windows, idx)) != NULL) + return (wl); + } + + /* Look for exact matches, error if more than one. */ + wlfound = NULL; + RB_FOREACH(wl, winlinks, &s->windows) { + w = wl->window; + if (strcmp(name, w->name) == 0) { + if (wlfound != NULL) { + *ambiguous = 1; + return (NULL); + } + wlfound = wl; + } + } + if (wlfound != NULL) + return (wlfound); + + /* Now look for pattern matches, again error if multiple. */ + wlfound = NULL; + RB_FOREACH(wl, winlinks, &s->windows) { + w = wl->window; + if (strncmp(name, w->name, strlen(name)) == 0 || + fnmatch(name, w->name, 0) == 0) { + if (wlfound != NULL) { + *ambiguous = 1; + return (NULL); + } + wlfound = wl; + } + } + if (wlfound != NULL) + return (wlfound); + + return (NULL); +} + +/* Find the target session or report an error and return NULL. */ struct session * cmd_find_session(struct cmd_ctx *ctx, const char *arg) { struct session *s; + struct client *c; + char *tmparg; + size_t arglen; + int ambiguous; + /* A NULL argument means the current session. */ if (arg == NULL) - s = cmd_current_session(ctx); - else { - if ((s = arg_parse_session(arg)) == NULL) { - if (arg != NULL) - ctx->error(ctx, "session not found: %s", arg); - else - ctx->error(ctx, "no session found"); - } + return (cmd_current_session(ctx)); + tmparg = xstrdup(arg); + + /* Trim a single trailing colon if any. */ + arglen = strlen(tmparg); + if (arglen != 0 && tmparg[arglen - 1] == ':') + tmparg[arglen - 1] = '\0'; + + /* Find the session, if any. */ + s = cmd_lookup_session(tmparg, &ambiguous); + + /* If it doesn't, try to match it as a client. */ + if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL) + s = c->session; + + /* If no session found, report an error. */ + if (s == NULL) { + if (ambiguous) + ctx->error(ctx, "more than one session: %s", tmparg); + else + ctx->error(ctx, "session not found: %s", tmparg); } + + xfree(tmparg); return (s); } +/* Find the target session and window or report an error and return NULL. */ struct winlink * cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) { struct session *s; struct winlink *wl; - int idx; - - wl = NULL; - if (arg_parse_window(arg, &s, &idx) != 0) { - ctx->error(ctx, "bad window: %s", arg); + const char *winptr; + char *sessptr = NULL; + int ambiguous = 0; + + /* + * Find the current session. There must always be a current session, if + * it can't be found, report an error. + */ + if ((s = cmd_current_session(ctx)) == NULL) { + ctx->error(ctx, "can't establish current session"); return (NULL); } - if (s == NULL) - s = ctx->cursession; - if (s == NULL) - s = cmd_current_session(ctx); - if (s == NULL) - return (NULL); + + /* A NULL argument means the current session and window. */ + if (arg == NULL) { + if (sp != NULL) + *sp = s; + return (s->curw); + } + + /* Time to look at the argument. If it is empty, that is an error. */ + if (*arg == '\0') + goto not_found; + + /* Find the separating colon. If none, assume the current session. */ + winptr = strchr(arg, ':'); + if (winptr == NULL) + winptr = xstrdup(arg); + else { + winptr++; /* skip : */ + sessptr = xstrdup(arg); + *strchr(sessptr, ':') = '\0'; + } + + log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr); + + /* Try to lookup the session if present. */ + if (sessptr != NULL && *sessptr != '\0') { + if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) + goto no_session; + } if (sp != NULL) *sp = s; - if (idx == -1) + /* + * Then work out the window. An empty string is the current window, + * otherwise try to look it up in the session. + */ + if (winptr == NULL || *winptr == '\0') wl = s->curw; - else - wl = winlink_find_by_index(&s->windows, idx); - if (wl == NULL) - ctx->error(ctx, "window not found: %s:%d", s->name, idx); + else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) + goto not_found; + + if (sessptr != NULL) + xfree(sessptr); return (wl); + +no_session: + if (ambiguous) + ctx->error(ctx, "multiple sessions: %s", sessptr); + else + ctx->error(ctx, "session not found: %s", sessptr); + if (sessptr != NULL) + xfree(sessptr); + return (NULL); + +not_found: + if (ambiguous) + ctx->error(ctx, "multiple windows: %s", arg); + else + ctx->error(ctx, "window not found: %s", arg); + if (sessptr != NULL) + xfree(sessptr); + return (NULL); +} + +/* + * Find the target session and window index, whether or not it exists in the + * session. Return -2 on error or -1 if no window index is specified. This is + * used when parsing an argument for a window target that may not be exist (for + * example it is going to be created). + */ +int +cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) +{ + struct session *s; + struct winlink *wl; + const char *winptr, *errstr; + char *sessptr = NULL; + int idx, ambiguous = 0; + + /* + * Find the current session. There must always be a current session, if + * it can't be found, report an error. + */ + if ((s = cmd_current_session(ctx)) == NULL) { + ctx->error(ctx, "can't establish current session"); + return (NULL); + } + + /* A NULL argument means the current session and "no window" (-1). */ + if (arg == NULL) { + if (sp != NULL) + *sp = s; + return (-1); + } + + /* Time to look at the argument. If it is empty, that is an error. */ + if (*arg == '\0') + goto not_found; + + /* Find the separating colon. If none, assume the current session. */ + winptr = strchr(arg, ':'); + if (winptr == NULL) + winptr = xstrdup(arg); + else { + winptr++; /* skip : */ + sessptr = xstrdup(arg); + *strchr(sessptr, ':') = '\0'; + } + + log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr); + + /* Try to lookup the session if present. */ + if (sessptr != NULL && *sessptr != '\0') { + if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) + goto no_session; + } + if (sp != NULL) + *sp = s; + + /* + * Then work out the window. No : means "no window" (-1), an empty + * string is the current window, otherwise try to look it up in the + * session. + */ + if (winptr == NULL) + idx = -1; + else if (*winptr == '\0') + idx = s->curw->idx; + else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) { + if (ambiguous) + goto not_found; + /* Don't care it doesn't exist if this is a valid index. */ + idx = strtonum(winptr, 0, INT_MAX, &errstr); + if (errstr != NULL) { + ctx->error(ctx, "index %s: %s", errstr, winptr); + idx = -2; + } + } else + idx = wl->idx; + + if (sessptr != NULL) + xfree(sessptr); + return (idx); + +no_session: + if (ambiguous) + ctx->error(ctx, "multiple sessions: %s", sessptr); + else + ctx->error(ctx, "session not found: %s", sessptr); + if (sessptr != NULL) + xfree(sessptr); + return (-2); + +not_found: + if (ambiguous) + ctx->error(ctx, "multiple windows: %s", arg); + else + ctx->error(ctx, "window not found: %s", arg); + if (sessptr != NULL) + xfree(sessptr); + return (-2); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index d52574444ff..8b9d2306501 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.28 2009/07/12 23:45:03 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.29 2009/07/13 17:47:46 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -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: July 12 2009 $ +.Dd $Mdocdate: July 13 2009 $ .Dt TMUX 1 .Os .Sh NAME @@ -500,8 +500,14 @@ These specify the client, session or window which a command should affect. .Ar target-client is the name of the .Xr pty 4 -file to which the client is connected, for example +file to which the client is connected, for example either of +.Pa /dev/ttyp1 +or +.Pa ttyp1 +for the client attached to .Pa /dev/ttyp1 . +If no client is specified, the current client is chosen, if possible, or an +error is reported. Clients may be listed with the .Ic list-clients command. @@ -509,23 +515,32 @@ command. .Ar target-session is either the name of a session (as listed by the .Ic list-sessions -command) or the name of a client, +command) or the name of a client with the same syntax as .Ar target-client , in which case the session attached to the client is used. -An +When looking for the session name, +.Nm +initially searches for an exact match; if none is found, the session names +are checked for any for which +.Ar target-session +is a prefix or for which it matches as an .Xr fnmatch 3 -pattern may be used to match the session name. -If a session is omitted when required, -.Nm tmux -attempts to use the current session; if no current session is available, the -most recently created is chosen. -If no client is specified, the current client is chosen, if possible, or an -error is reported. +pattern. +If a single match is found, it is used as the target session; multiple matches +produce an error +If a session is omitted, the current session is used if available; if no +current session is available, the most recently created is chosen. .Pp .Ar target-window specifies a window in the form -.Em session Ns \&: Ns Em index , -for example mysession:1. +.Em session Ns \&: Ns Em window , +where +.Em window +is a window index, for example mysession:1, or a window name, +.Xr fnmatch 3 +pattern, or prefix, such as mysession:mywin[0-3]. +If the latter, the window is looked up in a similar fashion to session name +searches described above. The session is in the same form as for .Ar target-session . .Em session , @@ -536,7 +551,7 @@ If is omitted, the same rules as for .Ar target-session are followed; if -.Em index +.Em window is not present, the current window for the given session is used. When the argument does not contain a colon, .Nm diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 6264ace2c87..4eb3aa3aa17 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.25 2009/07/13 10:43:52 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.26 2009/07/13 17:47:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1076,11 +1076,6 @@ int paste_replace(struct paste_stack *, u_int, char *); /* clock.c */ void clock_draw(struct screen_write_ctx *, u_int, int); -/* arg.c */ -struct client *arg_parse_client(const char *); -struct session *arg_parse_session(const char *); -int arg_parse_window(const char *, struct session **, int *); - /* cmd.c */ struct cmd *cmd_parse(int, char **, char **); int cmd_exec(struct cmd *, struct cmd_ctx *); @@ -1094,7 +1089,9 @@ struct session *cmd_current_session(struct cmd_ctx *); struct client *cmd_find_client(struct cmd_ctx *, const char *); struct session *cmd_find_session(struct cmd_ctx *, const char *); struct winlink *cmd_find_window( - struct cmd_ctx *, const char *, struct session **); + struct cmd_ctx *, const char *, struct session **); +int cmd_find_index( + struct cmd_ctx *, const char *, struct session **); extern const struct cmd_entry *cmd_table[]; extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_bind_key_entry; |