mirror of
https://github.com/tmux/tmux.git
synced 2025-01-15 05:09:04 +00:00
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.
This commit is contained in:
parent
dd4a3b24fc
commit
f7df0bac96
120
cmd.c
120
cmd.c
@ -107,6 +107,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)
|
||||||
@ -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
|
* 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;
|
||||||
|
|
||||||
@ -470,8 +472,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);
|
||||||
@ -485,9 +486,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);
|
||||||
@ -501,6 +501,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)
|
||||||
@ -570,20 +593,16 @@ 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;
|
||||||
}
|
}
|
||||||
@ -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,
|
* 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;
|
||||||
@ -603,11 +622,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);
|
||||||
@ -625,15 +659,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;
|
||||||
|
|
||||||
@ -660,14 +693,10 @@ 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') {
|
||||||
@ -678,35 +707,42 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
|
|||||||
*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);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
ctx->error(ctx, "index %s: %s", errstr, winptr);
|
|
||||||
idx = -2;
|
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);
|
||||||
|
42
tmux.1
42
tmux.1
@ -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 .
|
||||||
|
Loading…
Reference in New Issue
Block a user