Sync OpenBSD patchset 164:

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.
pull/1/head
Tiago Cunha 2009-07-23 13:06:31 +00:00
parent c84145751a
commit fb0301f8b8
2 changed files with 112 additions and 76 deletions

144
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.106 2009-07-21 13:07:50 nicm Exp $ */ /* $Id: cmd.c,v 1.107 2009-07-23 13:06:31 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -106,6 +106,7 @@ struct session *cmd_newest_session(void);
struct client *cmd_lookup_client(const char *); struct client *cmd_lookup_client(const char *);
struct session *cmd_lookup_session(const char *, int *); struct session *cmd_lookup_session(const char *, int *);
struct winlink *cmd_lookup_window(struct 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 * struct cmd *
cmd_parse(int argc, char **argv, char **cause) cmd_parse(int argc, char **argv, char **cause)
@ -446,14 +447,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 * Lookup a window or return -1 if not found or ambigious. First try as an
* and if invalid, use fnmatch or leading prefix. * 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 * struct winlink *
cmd_lookup_window(struct session *s, const char *name, int *ambiguous) cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
{ {
struct winlink *wl, *wlfound; struct winlink *wl, *wlfound;
struct window *w;
const char *errstr; const char *errstr;
u_int idx; u_int idx;
@ -469,8 +471,7 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
/* Look for exact matches, error if more than one. */ /* Look for exact matches, error if more than one. */
wlfound = NULL; wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; if (strcmp(name, wl->window->name) == 0) {
if (strcmp(name, w->name) == 0) {
if (wlfound != NULL) { if (wlfound != NULL) {
*ambiguous = 1; *ambiguous = 1;
return (NULL); return (NULL);
@ -484,9 +485,8 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
/* Now look for pattern matches, again error if multiple. */ /* Now look for pattern matches, again error if multiple. */
wlfound = NULL; wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; if (strncmp(name, wl->window->name, strlen(name)) == 0 ||
if (strncmp(name, w->name, strlen(name)) == 0 || fnmatch(name, wl->window->name, 0) == 0) {
fnmatch(name, w->name, 0) == 0) {
if (wlfound != NULL) { if (wlfound != NULL) {
*ambiguous = 1; *ambiguous = 1;
return (NULL); return (NULL);
@ -500,6 +500,29 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
return (NULL); 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. */ /* Find the target session or report an error and return NULL. */
struct session * struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg) cmd_find_session(struct cmd_ctx *ctx, const char *arg)
@ -569,21 +592,17 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
if (*arg == '\0') if (*arg == '\0')
goto not_found; 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, ':'); winptr = strchr(arg, ':');
if (winptr == NULL) if (winptr == NULL)
winptr = xstrdup(arg); goto no_colon;
else { winptr++; /* skip : */
winptr++; /* skip : */ sessptr = xstrdup(arg);
sessptr = xstrdup(arg); *strchr(sessptr, ':') = '\0';
*strchr(sessptr, ':') = '\0';
}
log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr);
/* Try to lookup the session if present. */ /* Try to lookup the session if present. */
if (sessptr != NULL && *sessptr != '\0') { if (*sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session; goto no_session;
} }
if (sp != NULL) if (sp != NULL)
@ -593,7 +612,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, * Then work out the window. An empty string is the current window,
* otherwise try to look it up in the session. * otherwise try to look it up in the session.
*/ */
if (winptr == NULL || *winptr == '\0') if (*winptr == '\0')
wl = s->curw; wl = s->curw;
else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL)
goto not_found; goto not_found;
@ -602,11 +621,26 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
xfree(sessptr); xfree(sessptr);
return (wl); 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: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", sessptr); ctx->error(ctx, "multiple sessions: %s", arg);
else else
ctx->error(ctx, "session not found: %s", sessptr); ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL) if (sessptr != NULL)
xfree(sessptr); xfree(sessptr);
return (NULL); return (NULL);
@ -624,15 +658,14 @@ not_found:
/* /*
* Find the target session and window index, whether or not it exists in the * 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 * 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 * used when parsing an argument for a window target that may not exist (for
* example it is going to be created). * example if it is going to be created).
*/ */
int int
cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{ {
struct session *s; struct session *s;
struct winlink *wl; const char *winptr;
const char *winptr, *errstr;
char *sessptr = NULL; char *sessptr = NULL;
int idx, ambiguous = 0; int idx, ambiguous = 0;
@ -659,53 +692,56 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
/* Find the separating colon. If none, assume the current session. */ /* Find the separating colon. If none, assume the current session. */
winptr = strchr(arg, ':'); winptr = strchr(arg, ':');
if (winptr == NULL) if (winptr == NULL)
winptr = xstrdup(arg); goto no_colon;
else { winptr++; /* skip : */
winptr++; /* skip : */ sessptr = xstrdup(arg);
sessptr = xstrdup(arg); *strchr(sessptr, ':') = '\0';
*strchr(sessptr, ':') = '\0';
}
log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr);
/* Try to lookup the session if present. */ /* Try to lookup the session if present. */
if (sessptr != NULL && *sessptr != '\0') { if (sessptr != NULL && *sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL) if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session; goto no_session;
} }
if (sp != NULL) if (sp != NULL)
*sp = s; *sp = s;
/* /*
* Then work out the window. No : means "no window" (-1), an empty * Then work out the window. An empty string is a new window otherwise
* string is the current window, otherwise try to look it up in the * try to look it up in the session.
* session.
*/ */
if (winptr == NULL) if (*winptr == '\0')
idx = -1; idx = -1;
else if (*winptr == '\0') else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
idx = s->curw->idx;
else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) {
if (ambiguous) if (ambiguous)
goto not_found; goto not_found;
/* Don't care it doesn't exist if this is a valid index. */ ctx->error(ctx, "invalid index: %s", arg);
idx = strtonum(winptr, 0, INT_MAX, &errstr); idx = -2;
if (errstr != NULL) { }
ctx->error(ctx, "index %s: %s", errstr, winptr);
idx = -2;
}
} else
idx = wl->idx;
if (sessptr != NULL) if (sessptr != NULL)
xfree(sessptr); xfree(sessptr);
return (idx); 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: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", sessptr); ctx->error(ctx, "multiple sessions: %s", arg);
else else
ctx->error(ctx, "session not found: %s", sessptr); ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL) if (sessptr != NULL)
xfree(sessptr); xfree(sessptr);
return (-2); return (-2);

44
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.128 2009-07-20 17:08:48 tcunha Exp $ .\" $Id: tmux.1,v 1.129 2009-07-23 13:06:31 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -544,36 +544,36 @@ is a prefix or for which it matches as an
.Xr fnmatch 3 .Xr fnmatch 3
pattern. pattern.
If a single match is found, it is used as the target session; multiple matches 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 If a session is omitted, the current session is used if available; if no
current session is available, the most recently created is chosen. current session is available, the most recently created is chosen.
.Pp .Pp
.Ar target-window .Ar target-window
specifies a window in the form specifies a window in the form
.Em session Ns \&: Ns Em window , .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 ,
.Em index
or both may be omitted.
If
.Em session .Em session
is omitted, the same rules as for follows the same rules as for
.Ar target-session .Ar target-session ,
are followed; if and
.Em window .Em window
is not present, the current window for the given session is used. 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 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 chosen.
When the argument does not contain a colon, When the argument does not contain a colon,
.Nm .Nm
first attempts to parse it as window index; if that fails, an attempt is made first attempts to parse it as window; if that fails, an attempt is made to
to match a session or client name. match a session.
.Pp .Pp
Multiple commands may be specified together as part of a Multiple commands may be specified together as part of a
.Em command sequence . .Em command sequence .