Make it so that if a window or session target is prefixed with an =,

only an exact name or index match is accepted, no special character,
prefix match, or fnmatch.
This commit is contained in:
nicm 2015-06-05 08:14:16 +00:00
parent 6b2129696f
commit 4219939c10
3 changed files with 80 additions and 43 deletions

View File

@ -30,6 +30,8 @@
#define CMD_FIND_QUIET 0x2 #define CMD_FIND_QUIET 0x2
#define CMD_FIND_WINDOW_INDEX 0x4 #define CMD_FIND_WINDOW_INDEX 0x4
#define CMD_FIND_DEFAULT_MARKED 0x8 #define CMD_FIND_DEFAULT_MARKED 0x8
#define CMD_FIND_EXACT_SESSION 0x10
#define CMD_FIND_EXACT_WINDOW 0x20
enum cmd_find_type { enum cmd_find_type {
CMD_FIND_PANE, CMD_FIND_PANE,
@ -381,6 +383,10 @@ cmd_find_get_session(struct cmd_find_state *fs, const char *session)
if (fs->s != NULL) if (fs->s != NULL)
return (0); return (0);
/* Stop now if exact only. */
if (fs->flags & CMD_FIND_EXACT_SESSION)
return (-1);
/* Otherwise look for prefix. */ /* Otherwise look for prefix. */
s = NULL; s = NULL;
RB_FOREACH(s_loop, sessions, &sessions) { RB_FOREACH(s_loop, sessions, &sessions) {
@ -455,10 +461,11 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
{ {
struct winlink *wl; struct winlink *wl;
const char *errstr; const char *errstr;
int idx, n; int idx, n, exact;
struct session *s; struct session *s;
log_debug("%s: %s", __func__, window); log_debug("%s: %s", __func__, window);
exact = (fs->flags & CMD_FIND_EXACT_WINDOW);
/* Check for window ids starting with @. */ /* Check for window ids starting with @. */
if (*window == '@') { if (*window == '@') {
@ -469,7 +476,7 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
} }
/* Try as an offset. */ /* Try as an offset. */
if (window[0] == '+' || window[0] == '-') { if (!exact && window[0] == '+' || window[0] == '-') {
if (window[1] != '\0') if (window[1] != '\0')
n = strtonum(window + 1, 1, INT_MAX, NULL); n = strtonum(window + 1, 1, INT_MAX, NULL);
else else
@ -499,40 +506,44 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
} }
/* Try special characters. */ /* Try special characters. */
if (strcmp(window, "!") == 0) { if (!exact) {
fs->wl = TAILQ_FIRST(&fs->s->lastw); if (strcmp(window, "!") == 0) {
if (fs->wl == NULL) fs->wl = TAILQ_FIRST(&fs->s->lastw);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
} else if (strcmp(window, "^") == 0) { return (0);
fs->wl = RB_MIN(winlinks, &fs->s->windows); } else if (strcmp(window, "^") == 0) {
if (fs->wl == NULL) fs->wl = RB_MIN(winlinks, &fs->s->windows);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
} else if (strcmp(window, "$") == 0) { return (0);
fs->wl = RB_MAX(winlinks, &fs->s->windows); } else if (strcmp(window, "$") == 0) {
if (fs->wl == NULL) fs->wl = RB_MAX(winlinks, &fs->s->windows);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
return (0);
}
} }
/* First see if this is a valid window index in this session. */ /* First see if this is a valid window index in this session. */
idx = strtonum(window, 0, INT_MAX, &errstr); if (window[0] != '+' && window[0] != '-') {
if (errstr == NULL) { idx = strtonum(window, 0, INT_MAX, &errstr);
if (fs->flags & CMD_FIND_WINDOW_INDEX) { if (errstr == NULL) {
fs->idx = idx; if (fs->flags & CMD_FIND_WINDOW_INDEX) {
return (0); fs->idx = idx;
} return (0);
fs->wl = winlink_find_by_index(&fs->s->windows, idx); }
if (fs->wl != NULL) { fs->wl = winlink_find_by_index(&fs->s->windows, idx);
fs->w = fs->wl->window; if (fs->wl != NULL) {
return (0); fs->w = fs->wl->window;
return (0);
}
} }
} }
@ -551,6 +562,11 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
return (0); return (0);
} }
/* Stop now if exact only. */
if (exact)
return (-1);
/* Try as the start of a window name, error if multiple. */ /* Try as the start of a window name, error if multiple. */
fs->wl = NULL; fs->wl = NULL;
RB_FOREACH(wl, winlinks, &fs->s->windows) { RB_FOREACH(wl, winlinks, &fs->s->windows) {
@ -868,6 +884,16 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
} }
} }
/* Set exact match flags. */
if (session != NULL && *session == '=') {
session++;
fs.flags |= CMD_FIND_EXACT_SESSION;
}
if (window != NULL && *window == '=') {
window++;
fs.flags |= CMD_FIND_EXACT_WINDOW;
}
/* Empty is the same as NULL. */ /* Empty is the same as NULL. */
if (session != NULL && *session == '\0') if (session != NULL && *session == '\0')
session = NULL; session = NULL;

View File

@ -161,16 +161,16 @@ key_bindings_init(void)
"bind , command-prompt -I'#W' \"rename-window '%%'\"", "bind , command-prompt -I'#W' \"rename-window '%%'\"",
"bind - delete-buffer", "bind - delete-buffer",
"bind . command-prompt \"move-window -t '%%'\"", "bind . command-prompt \"move-window -t '%%'\"",
"bind 0 select-window -t:0", "bind 0 select-window -t:=0",
"bind 1 select-window -t:1", "bind 1 select-window -t:=1",
"bind 2 select-window -t:2", "bind 2 select-window -t:=2",
"bind 3 select-window -t:3", "bind 3 select-window -t:=3",
"bind 4 select-window -t:4", "bind 4 select-window -t:=4",
"bind 5 select-window -t:5", "bind 5 select-window -t:=5",
"bind 6 select-window -t:6", "bind 6 select-window -t:=6",
"bind 7 select-window -t:7", "bind 7 select-window -t:=7",
"bind 8 select-window -t:8", "bind 8 select-window -t:=8",
"bind 9 select-window -t:9", "bind 9 select-window -t:=9",
"bind : command-prompt", "bind : command-prompt",
"bind \\; last-pane", "bind \\; last-pane",
"bind = choose-buffer", "bind = choose-buffer",

11
tmux.1
View File

@ -404,6 +404,14 @@ An
pattern which is matched against the session name. pattern which is matched against the session name.
.El .El
.Pp .Pp
If the session name is prefixed with a
.Ql = : ,
only an exact match is accepted (so
.Ql =mysess
will only match exactly
.Ql mysess ,
not
.Ql mysession ) .
If a single session is found, it is used as the target session; multiple matches If a single session 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
@ -440,6 +448,9 @@ As an
pattern matched against the window name. pattern matched against the window name.
.El .El
.Pp .Pp
Like sessions, a
.Ql =
prefix will do an exact match only.
An empty window name specifies the next unused index if appropriate (for An empty window name specifies the next unused index if appropriate (for
example the example the
.Ic new-window .Ic new-window