diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-22 21:23:30 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-22 21:23:30 +0000 |
commit | 1d6863eed2f785c4e7ccf6f6019c14ed0210761e (patch) | |
tree | c4775c75b0ee781e280acc347bc4524ef6201d17 /usr.bin | |
parent | 27e86a37f7aa4330944f156b5d8c531ce1b9afb1 (diff) |
Tidy the target parsing code a bit and correct the behaviour so that as before
a string with no colon as a target window is first looked up as a window then
as a session, noted by Iain Morgan.
Also attempt to clarify the description of the target specification in the man
page.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/cmd.c | 144 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 44 |
2 files changed, 112 insertions, 76 deletions
diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index f7728ca6941..c5500af81f2 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.7 2009/07/17 18:45:08 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.8 2009/07/22 21:23:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -107,6 +107,7 @@ 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 *); +int cmd_lookup_index(struct session *, const char *, int *); struct cmd * cmd_parse(int argc, char **argv, char **cause) @@ -447,14 +448,15 @@ cmd_lookup_session(const char *name, int *ambiguous) } /* - * Lookup a window or return -1 if not found or ambigious. First try as an index - * and if invalid, use fnmatch or leading prefix. + * Lookup a window or return -1 if not found or ambigious. First try as an + * index and if invalid, use fnmatch or leading prefix. Return NULL but fill in + * idx if the window index is a valid number but there is now window with that + * index. */ 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; @@ -470,8 +472,7 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous) /* 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 (strcmp(name, wl->window->name) == 0) { if (wlfound != NULL) { *ambiguous = 1; return (NULL); @@ -485,9 +486,8 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous) /* 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 (strncmp(name, wl->window->name, strlen(name)) == 0 || + fnmatch(name, wl->window->name, 0) == 0) { if (wlfound != NULL) { *ambiguous = 1; return (NULL); @@ -501,6 +501,29 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous) return (NULL); } +/* + * Find a window index - if the window doesn't exist, check if it is a + * potential index and return it anyway. + */ +int +cmd_lookup_index(struct session *s, const char *name, int *ambiguous) +{ + struct winlink *wl; + const char *errstr; + u_int idx; + + if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL) + return (wl->idx); + if (*ambiguous) + return (-1); + + idx = strtonum(name, 0, INT_MAX, &errstr); + if (errstr == NULL) + return (idx); + + return (-1); +} + /* Find the target session or report an error and return NULL. */ struct session * cmd_find_session(struct cmd_ctx *ctx, const char *arg) @@ -570,21 +593,17 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) if (*arg == '\0') goto not_found; - /* Find the separating colon. If none, assume the current session. */ + /* Find the separating colon and split into window and 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); + goto no_colon; + winptr++; /* skip : */ + sessptr = xstrdup(arg); + *strchr(sessptr, ':') = '\0'; /* Try to lookup the session if present. */ - if (sessptr != NULL && *sessptr != '\0') { - if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) + if (*sessptr != '\0') { + if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) goto no_session; } if (sp != NULL) @@ -594,7 +613,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) * 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') + if (*winptr == '\0') wl = s->curw; else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) goto not_found; @@ -603,11 +622,26 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) xfree(sessptr); return (wl); +no_colon: + /* No colon in the string, first try as a window then as a session. */ + if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) { + if (ambiguous) + goto not_found; + if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL) + goto no_session; + wl = s->curw; + } + + if (sp != NULL) + *sp = s; + + return (wl); + no_session: if (ambiguous) - ctx->error(ctx, "multiple sessions: %s", sessptr); + ctx->error(ctx, "multiple sessions: %s", arg); else - ctx->error(ctx, "session not found: %s", sessptr); + ctx->error(ctx, "session not found: %s", arg); if (sessptr != NULL) xfree(sessptr); return (NULL); @@ -625,15 +659,14 @@ not_found: /* * 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). + * used when parsing an argument for a window target that may not exist (for + * example if 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; + const char *winptr; char *sessptr = NULL; int idx, ambiguous = 0; @@ -660,53 +693,56 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) /* 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); + goto no_colon; + winptr++; /* skip : */ + sessptr = xstrdup(arg); + *strchr(sessptr, ':') = '\0'; /* Try to lookup the session if present. */ if (sessptr != NULL && *sessptr != '\0') { - if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) + 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. + * Then work out the window. An empty string is a new 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 (*winptr == '\0') + idx = -1; + else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) { 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; + ctx->error(ctx, "invalid index: %s", arg); + idx = -2; + } if (sessptr != NULL) xfree(sessptr); return (idx); +no_colon: + /* No colon in the string, first try as a window then as a session. */ + if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) { + if (ambiguous) + goto not_found; + if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL) + goto no_session; + idx = -1; + } + + if (sp != NULL) + *sp = s; + + return (idx); + no_session: if (ambiguous) - ctx->error(ctx, "multiple sessions: %s", sessptr); + ctx->error(ctx, "multiple sessions: %s", arg); else - ctx->error(ctx, "session not found: %s", sessptr); + ctx->error(ctx, "session 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 5a0af9053e9..35e8a8c6bcb 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.42 2009/07/20 15:51:55 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.43 2009/07/22 21:23:29 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 20 2009 $ +.Dd $Mdocdate: July 22 2009 $ .Dt TMUX 1 .Os .Sh NAME @@ -544,36 +544,36 @@ is a prefix or for which it matches as an .Xr fnmatch 3 pattern. If a single match is found, it is used as the target session; multiple matches -produce an error +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 window , -where +.Em session Ns \&: Ns Em window . +.Em session +follows the same rules as for +.Ar target-session , +and .Em window -is a window index, for example mysession:1, or a window name, +is looked for in order: as a window index, for example mysession:1; as an exact +window name, such as mysession:mywindow; then as an .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 , -.Em index -or both may be omitted. -If +pattern or the start of a window name, such as mysession:mywin* or +mysession:mywin. +An empty window name specifies the next unused index if appropriate (for +example the +.Ic new-window +and +.Ic link-window +commands) +otherwise the current window in .Em session -is omitted, the same rules as for -.Ar target-session -are followed; if -.Em window -is not present, the current window for the given session is used. +is chosen. When the argument does not contain a colon, .Nm -first attempts to parse it as window index; if that fails, an attempt is made -to match a session or client name. +first attempts to parse it as window; if that fails, an attempt is made to +match a session. .Pp Multiple commands may be specified together as part of a .Em command sequence . |