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.
This commit is contained in:
Nicholas Marriott 2009-07-13 17:47:46 +00:00
parent 359285928b
commit 023d8d38ec
8 changed files with 406 additions and 298 deletions

View File

@ -1,7 +1,7 @@
# $OpenBSD$ # $OpenBSD$
PROG= tmux 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 \ 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-break-pane.c cmd-choose-session.c cmd-choose-window.c \
cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \ cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \

194
arg.c
View File

@ -1,194 +0,0 @@
/* $OpenBSD$ */
/*
* 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);
}

View File

@ -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) if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); 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);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)

View File

@ -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) if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); 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);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)

View File

@ -126,18 +126,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (arg_parse_window(data->target, &s, &idx) != 0) { if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
ctx->error(ctx, "bad window: %s", data->target);
return (-1); 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; wl = NULL;
if (idx != -1) if (idx != -1)

420
cmd.c
View File

@ -19,6 +19,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <fnmatch.h>
#include <paths.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -100,6 +102,11 @@ const struct cmd_entry *cmd_table[] = {
NULL 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 * struct cmd *
cmd_parse(int argc, char **argv, char **cause) cmd_parse(int argc, char **argv, char **cause)
{ {
@ -294,106 +301,421 @@ cmd_recv_string(struct buffer *b)
return (s); 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 * struct session *
cmd_current_session(struct cmd_ctx *ctx) cmd_current_session(struct cmd_ctx *ctx)
{ {
struct msg_command_data *data = ctx->msgdata; struct msg_command_data *data = ctx->msgdata;
struct timeval *tv; struct session *s;
struct session *s, *newest = NULL;
u_int i;
if (ctx->cursession != NULL) if (ctx->cursession != NULL)
return (ctx->cursession); return (ctx->cursession);
if (data != NULL && data->pid != -1) { if (data != NULL && data->pid != -1) {
if (data->pid != getpid()) { if (data->pid != getpid())
ctx->error(ctx, "wrong server: %ld", (long) data->pid);
return (NULL); return (NULL);
} if (data->idx > ARRAY_LENGTH(&sessions))
if (data->idx > ARRAY_LENGTH(&sessions)) {
ctx->error(ctx, "index out of range: %d", data->idx);
return (NULL); return (NULL);
} if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
ctx->error(ctx, "session doesn't exist: %u", data->idx);
return (NULL); return (NULL);
}
return (s); 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++) { for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i); if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) { continue;
newest = ARRAY_ITEM(&sessions, i);
if (tv == NULL || timercmp(&s->tv, tv, >)) {
snewest = s;
tv = &s->tv; tv = &s->tv;
} }
} }
return (newest);
return (snewest);
} }
/* Find the target client or report an error and return NULL. */
struct client * struct client *
cmd_find_client(struct cmd_ctx *ctx, const char *arg) cmd_find_client(struct cmd_ctx *ctx, const char *arg)
{ {
struct client *c; struct client *c;
char *tmparg;
size_t arglen;
/* A NULL argument means the current client. */
if (arg == NULL) if (arg == NULL)
c = ctx->curclient; return (ctx->curclient);
else { tmparg = xstrdup(arg);
if ((c = arg_parse_client(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "client not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no client found"); 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); 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 (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 * struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg) cmd_find_session(struct cmd_ctx *ctx, const char *arg)
{ {
struct session *s; struct session *s;
struct client *c;
char *tmparg;
size_t arglen;
int ambiguous;
/* A NULL argument means the current session. */
if (arg == NULL) if (arg == NULL)
s = cmd_current_session(ctx); return (cmd_current_session(ctx));
else { tmparg = xstrdup(arg);
if ((s = arg_parse_session(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "session not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no session found"); 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); return (s);
} }
/* Find the target session and window or report an error and return NULL. */
struct winlink * struct winlink *
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
int idx; const char *winptr;
char *sessptr = NULL;
int ambiguous = 0;
wl = NULL; /*
if (arg_parse_window(arg, &s, &idx) != 0) { * Find the current session. There must always be a current session, if
ctx->error(ctx, "bad window: %s", arg); * 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); return (NULL);
} }
if (s == NULL)
s = ctx->cursession; /* A NULL argument means the current session and window. */
if (s == NULL) if (arg == NULL) {
s = cmd_current_session(ctx); if (sp != NULL)
if (s == NULL) *sp = s;
return (NULL); 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) if (sp != NULL)
*sp = s; *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; wl = s->curw;
else else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL)
wl = winlink_find_by_index(&s->windows, idx); goto not_found;
if (wl == NULL)
ctx->error(ctx, "window not found: %s:%d", s->name, idx); if (sessptr != NULL)
xfree(sessptr);
return (wl); 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);
} }

41
tmux.1
View File

@ -500,8 +500,14 @@ These specify the client, session or window which a command should affect.
.Ar target-client .Ar target-client
is the name of the is the name of the
.Xr pty 4 .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 . .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 Clients may be listed with the
.Ic list-clients .Ic list-clients
command. command.
@ -509,23 +515,32 @@ command.
.Ar target-session .Ar target-session
is either the name of a session (as listed by the is either the name of a session (as listed by the
.Ic list-sessions .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 , .Ar target-client ,
in which case the session attached to the client is used. 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 .Xr fnmatch 3
pattern may be used to match the session name. pattern.
If a session is omitted when required, If a single match is found, it is used as the target session; multiple matches
.Nm tmux produce an error
attempts to use the current session; if no current session is available, the If a session is omitted, the current session is used if available; if no
most recently created is chosen. 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.
.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 index , .Em session Ns \&: Ns Em window ,
for example mysession:1. 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 The session is in the same form as for
.Ar target-session . .Ar target-session .
.Em session , .Em session ,
@ -536,7 +551,7 @@ If
is omitted, the same rules as for is omitted, the same rules as for
.Ar target-session .Ar target-session
are followed; if are followed; if
.Em index .Em window
is not present, the current window for the given session is used. is not present, the current window for the given session is used.
When the argument does not contain a colon, When the argument does not contain a colon,
.Nm .Nm

9
tmux.h
View File

@ -1076,11 +1076,6 @@ int paste_replace(struct paste_stack *, u_int, char *);
/* clock.c */ /* clock.c */
void clock_draw(struct screen_write_ctx *, u_int, int); 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 */ /* cmd.c */
struct cmd *cmd_parse(int, char **, char **); struct cmd *cmd_parse(int, char **, char **);
int cmd_exec(struct cmd *, struct cmd_ctx *); 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 client *cmd_find_client(struct cmd_ctx *, const char *);
struct session *cmd_find_session(struct cmd_ctx *, const char *); struct session *cmd_find_session(struct cmd_ctx *, const char *);
struct winlink *cmd_find_window( 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_table[];
extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_bind_key_entry;