From a7f2e23c04ef9d53c1fa3d597aae2f53c8ad595b Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 5 Jun 2015 08:14:16 +0000 Subject: [PATCH] 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. --- usr.bin/tmux/cmd-find.c | 94 +++++++++++++++++++++++-------------- usr.bin/tmux/key-bindings.c | 22 ++++----- usr.bin/tmux/tmux.1 | 15 +++++- 3 files changed, 84 insertions(+), 47 deletions(-) diff --git a/usr.bin/tmux/cmd-find.c b/usr.bin/tmux/cmd-find.c index dcfda1cf8f4..bdb91d34b5c 100644 --- a/usr.bin/tmux/cmd-find.c +++ b/usr.bin/tmux/cmd-find.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-find.c,v 1.8 2015/06/04 11:43:51 nicm Exp $ */ +/* $OpenBSD: cmd-find.c,v 1.9 2015/06/05 08:14:16 nicm Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -30,6 +30,8 @@ #define CMD_FIND_QUIET 0x2 #define CMD_FIND_WINDOW_INDEX 0x4 #define CMD_FIND_DEFAULT_MARKED 0x8 +#define CMD_FIND_EXACT_SESSION 0x10 +#define CMD_FIND_EXACT_WINDOW 0x20 enum cmd_find_type { CMD_FIND_PANE, @@ -381,6 +383,10 @@ cmd_find_get_session(struct cmd_find_state *fs, const char *session) if (fs->s != NULL) return (0); + /* Stop now if exact only. */ + if (fs->flags & CMD_FIND_EXACT_SESSION) + return (-1); + /* Otherwise look for prefix. */ s = NULL; 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; const char *errstr; - int idx, n; + int idx, n, exact; struct session *s; log_debug("%s: %s", __func__, window); + exact = (fs->flags & CMD_FIND_EXACT_WINDOW); /* Check for window ids starting with @. */ if (*window == '@') { @@ -469,7 +476,7 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window) } /* Try as an offset. */ - if (window[0] == '+' || window[0] == '-') { + if (!exact && window[0] == '+' || window[0] == '-') { if (window[1] != '\0') n = strtonum(window + 1, 1, INT_MAX, NULL); else @@ -499,43 +506,47 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window) } /* Try special characters. */ - if (strcmp(window, "!") == 0) { - fs->wl = TAILQ_FIRST(&fs->s->lastw); - if (fs->wl == NULL) - return (-1); - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - return (0); - } else if (strcmp(window, "^") == 0) { - fs->wl = RB_MIN(winlinks, &fs->s->windows); - if (fs->wl == NULL) - return (-1); - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - return (0); - } else if (strcmp(window, "$") == 0) { - fs->wl = RB_MAX(winlinks, &fs->s->windows); - if (fs->wl == NULL) - return (-1); - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - return (0); - } - - /* First see if this is a valid window index in this session. */ - idx = strtonum(window, 0, INT_MAX, &errstr); - if (errstr == NULL) { - if (fs->flags & CMD_FIND_WINDOW_INDEX) { - fs->idx = idx; + if (!exact) { + if (strcmp(window, "!") == 0) { + fs->wl = TAILQ_FIRST(&fs->s->lastw); + if (fs->wl == NULL) + return (-1); + fs->idx = fs->wl->idx; + fs->w = fs->wl->window; return (0); - } - fs->wl = winlink_find_by_index(&fs->s->windows, idx); - if (fs->wl != NULL) { + } else if (strcmp(window, "^") == 0) { + fs->wl = RB_MIN(winlinks, &fs->s->windows); + if (fs->wl == NULL) + return (-1); + fs->idx = fs->wl->idx; + fs->w = fs->wl->window; + return (0); + } else if (strcmp(window, "$") == 0) { + fs->wl = RB_MAX(winlinks, &fs->s->windows); + if (fs->wl == NULL) + return (-1); + fs->idx = fs->wl->idx; fs->w = fs->wl->window; return (0); } } + /* First see if this is a valid window index in this session. */ + if (window[0] != '+' && window[0] != '-') { + idx = strtonum(window, 0, INT_MAX, &errstr); + if (errstr == NULL) { + if (fs->flags & CMD_FIND_WINDOW_INDEX) { + fs->idx = idx; + return (0); + } + fs->wl = winlink_find_by_index(&fs->s->windows, idx); + if (fs->wl != NULL) { + fs->w = fs->wl->window; + return (0); + } + } + } + /* Look for exact matches, error if more than one. */ fs->wl = NULL; RB_FOREACH(wl, winlinks, &fs->s->windows) { @@ -551,6 +562,11 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window) return (0); } + + /* Stop now if exact only. */ + if (exact) + return (-1); + /* Try as the start of a window name, error if multiple. */ fs->wl = NULL; 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. */ if (session != NULL && *session == '\0') session = NULL; diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c index bcee036815b..2605e1afe58 100644 --- a/usr.bin/tmux/key-bindings.c +++ b/usr.bin/tmux/key-bindings.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key-bindings.c,v 1.49 2015/06/04 11:43:51 nicm Exp $ */ +/* $OpenBSD: key-bindings.c,v 1.50 2015/06/05 08:14:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -161,16 +161,16 @@ key_bindings_init(void) "bind , command-prompt -I'#W' \"rename-window '%%'\"", "bind - delete-buffer", "bind . command-prompt \"move-window -t '%%'\"", - "bind 0 select-window -t:0", - "bind 1 select-window -t:1", - "bind 2 select-window -t:2", - "bind 3 select-window -t:3", - "bind 4 select-window -t:4", - "bind 5 select-window -t:5", - "bind 6 select-window -t:6", - "bind 7 select-window -t:7", - "bind 8 select-window -t:8", - "bind 9 select-window -t:9", + "bind 0 select-window -t:=0", + "bind 1 select-window -t:=1", + "bind 2 select-window -t:=2", + "bind 3 select-window -t:=3", + "bind 4 select-window -t:=4", + "bind 5 select-window -t:=5", + "bind 6 select-window -t:=6", + "bind 7 select-window -t:=7", + "bind 8 select-window -t:=8", + "bind 9 select-window -t:=9", "bind : command-prompt", "bind \\; last-pane", "bind = choose-buffer", diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 7cff52f2ad7..9414db53b6e 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.434 2015/06/04 20:34:22 jmc Exp $ +.\" $OpenBSD: tmux.1,v 1.435 2015/06/05 08:14:16 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 4 2015 $ +.Dd $Mdocdate: June 5 2015 $ .Dt TMUX 1 .Os .Sh NAME @@ -404,6 +404,14 @@ An pattern which is matched against the session name. .El .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 produce an error. 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. .El .Pp +Like sessions, a +.Ql = +prefix will do an exact match only. An empty window name specifies the next unused index if appropriate (for example the .Ic new-window -- 2.20.1