mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +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:
		
							
								
								
									
										142
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								cmd.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										42
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								tmux.1
									
									
									
									
									
								
							@@ -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 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 Ns \&: Ns Em window .
 | 
			
		||||
.Em session
 | 
			
		||||
is omitted, the same rules as for
 | 
			
		||||
.Ar target-session
 | 
			
		||||
are followed; if
 | 
			
		||||
follows the same rules as for
 | 
			
		||||
.Ar target-session ,
 | 
			
		||||
and
 | 
			
		||||
.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,
 | 
			
		||||
.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 .
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user