diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/cmd.c | 189 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 16 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 4 | ||||
-rw-r--r-- | usr.bin/tmux/window.c | 24 |
4 files changed, 164 insertions, 69 deletions
diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index 07b728a478a..7b2cc08f634 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.40 2010/05/05 23:24:23 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.41 2010/06/21 01:46:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -538,7 +538,7 @@ 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. Return NULL but fill in - * idx if the window index is a valid number but there is now window with that + * idx if the window index is a valid number but there is no window with that * index. */ struct winlink * @@ -660,6 +660,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) const char *winptr; char *sessptr = NULL; int ambiguous = 0; + int n = 1; /* * Find the current session. There must always be a current session, if @@ -705,11 +706,21 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) wl = s->curw; else if (winptr[0] == '!' && winptr[1] == '\0') wl = TAILQ_FIRST(&s->lastw); - else if (winptr[0] == '+' && winptr[1] == '\0') - wl = winlink_next(s->curw); - else if (winptr[0] == '-' && winptr[1] == '\0') - wl = winlink_previous(s->curw); - else + else if (winptr[0] == '+' || winptr[0] == '-') { + if (winptr[1] != '\0') + n = strtonum(winptr + 1, 1, INT_MAX, NULL); + if (n == 0) + wl = cmd_lookup_window(s, winptr, &ambiguous); + else { + if (winptr[0] == '+') + wl = winlink_next_by_number(s->curw, n); + else + wl = winlink_previous_by_number(s->curw, n); + /* Search by name before giving up. */ + if (wl == NULL) + wl = cmd_lookup_window(s, winptr, &ambiguous); + } + } else wl = cmd_lookup_window(s, winptr, &ambiguous); if (wl == NULL) goto not_found; @@ -726,25 +737,41 @@ no_colon: if (arg[0] == '!' && arg[1] == '\0') { if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) goto not_found; - } else if (arg[0] == '+' && arg[1] == '\0') { - if ((wl = winlink_next(s->curw)) == NULL) - goto not_found; - } else if (arg[0] == '-' && arg[1] == '\0') { - if ((wl = winlink_previous(s->curw)) == NULL) - goto not_found; - } else 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; - } + } else if (arg[0] == '+' || arg[0] == '-') { + if (arg[1] != '\0') + n = strtonum(arg + 1, 1, INT_MAX, NULL); + if (n == 0) + wl = cmd_lookup_window(s, arg, &ambiguous); + else { + if (arg[0] == '+') + wl = winlink_next_by_number(s->curw, n); + else + wl = winlink_previous_by_number(s->curw, n); + /* Search by name before giving up. */ + if (wl == NULL) + wl = cmd_lookup_window(s, arg, &ambiguous); + } + if (wl == NULL) + goto lookup_session; + } else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) + goto lookup_session; if (sp != NULL) *sp = s; return (wl); +lookup_session: + if (ambiguous) + goto not_found; + if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL) + goto no_session; + + if (sp != NULL) + *sp = s; + + return (s->curw); + no_session: if (ambiguous) ctx->error(ctx, "multiple sessions: %s", arg); @@ -778,6 +805,7 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) const char *winptr; char *sessptr = NULL; int idx, ambiguous = 0; + int n = 1; /* * Find the current session. There must always be a current session, if @@ -825,20 +853,23 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp) if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) goto not_found; idx = wl->idx; - } else if (winptr[0] == '+' && winptr[1] == '\0') { - if (s->curw->idx == INT_MAX) - goto not_found; - idx = s->curw->idx + 1; - } else if (winptr[0] == '-' && winptr[1] == '\0') { - if (s->curw->idx == 0) - goto not_found; - idx = s->curw->idx - 1; - } else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) { - if (ambiguous) - goto not_found; - ctx->error(ctx, "invalid index: %s", arg); - idx = -2; - } + } else if (winptr[0] == '+' || winptr[0] == '-') { + if (winptr[1] != '\0') + n = strtonum(winptr + 1, 1, INT_MAX, NULL); + if (winptr[0] == '+' && s->curw->idx == INT_MAX) + idx = cmd_lookup_index(s, winptr, &ambiguous); + else if (winptr[0] == '-' && s->curw->idx == 0) + idx = cmd_lookup_index(s, winptr, &ambiguous); + else if (n == 0) + idx = cmd_lookup_index(s, winptr, &ambiguous); + else if (winptr[0] == '+') + idx = s->curw->idx + n; + else + idx = s->curw->idx - n; + if (idx < 0) + goto invalid_index; + } else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) + goto invalid_index; if (sessptr != NULL) xfree(sessptr); @@ -853,27 +884,40 @@ no_colon: if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) goto not_found; idx = wl->idx; - } else if (arg[0] == '+' && arg[1] == '\0') { - if (s->curw->idx == INT_MAX) - goto not_found; - idx = s->curw->idx + 1; - } else if (arg[0] == '-' && arg[1] == '\0') { - if (s->curw->idx == 0) - goto not_found; - idx = s->curw->idx - 1; - } else 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; - } + } else if (arg[0] == '+' || arg[0] == '-') { + if (arg[1] != '\0') + n = strtonum(arg + 1, 1, INT_MAX, NULL); + if (arg[0] == '+' && s->curw->idx == INT_MAX) + idx = cmd_lookup_index(s, arg, &ambiguous); + else if (arg[0] == '-' && s->curw->idx == 0) + idx = cmd_lookup_index(s, arg, &ambiguous); + else if (n == 0) + idx = cmd_lookup_index(s, arg, &ambiguous); + else if (arg[0] == '+') + idx = s->curw->idx + n; + else + idx = s->curw->idx - n; + if (idx < 0) + goto lookup_session; + } else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) + goto lookup_session; if (sp != NULL) *sp = s; return (idx); +lookup_session: + if (ambiguous) + goto not_found; + if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL) + goto no_session; + + if (sp != NULL) + *sp = s; + + return (-1); + no_session: if (ambiguous) ctx->error(ctx, "multiple sessions: %s", arg); @@ -883,6 +927,15 @@ no_session: xfree(sessptr); return (-2); +invalid_index: + if (ambiguous) + goto not_found; + ctx->error(ctx, "invalid index: %s", arg); + + if (sessptr != NULL) + xfree(sessptr); + return (-2); + not_found: if (ambiguous) ctx->error(ctx, "multiple windows: %s", arg); @@ -907,7 +960,7 @@ cmd_find_pane(struct cmd_ctx *ctx, struct layout_cell *lc; const char *period, *errstr; char *winptr, *paneptr; - u_int idx; + u_int idx, n = 1; /* Get the current session. */ if ((s = cmd_current_session(ctx)) == NULL) { @@ -939,7 +992,27 @@ cmd_find_pane(struct cmd_ctx *ctx, paneptr = winptr + (period - arg) + 1; if (*paneptr == '\0') *wpp = wl->window->active; - else { + else if (paneptr[0] == '+' || paneptr[0] == '-') { + if (paneptr[1] != '\0') + n = strtonum(paneptr + 1, 1, INT_MAX, NULL); + idx = window_pane_index(wl->window, wl->window->active); + if (paneptr[0] == '+' && idx == INT_MAX) + *wpp = TAILQ_FIRST(&wl->window->panes); + else if (paneptr[0] == '-' && idx == 0) + *wpp = TAILQ_LAST(&wl->window->panes, window_panes); + else if (n == 0) + *wpp = wl->window->active; + else if (paneptr[0] == '+') + *wpp = window_pane_at_index(wl->window, idx + n); + else + *wpp = window_pane_at_index(wl->window, idx - n); + if (paneptr[0] == '+' && *wpp == NULL) + *wpp = TAILQ_FIRST(&wl->window->panes); + else if (paneptr[0] == '-' && *wpp == NULL) + *wpp = TAILQ_LAST(&wl->window->panes, window_panes); + else if (*wpp == NULL) + goto error; + } else { idx = strtonum(paneptr, 0, INT_MAX, &errstr); if (errstr != NULL) goto lookup_string; @@ -952,20 +1025,6 @@ cmd_find_pane(struct cmd_ctx *ctx, return (wl); lookup_string: - /* Try as next or previous pane. */ - if (paneptr[0] == '+' && paneptr[1] == '\0') { - *wpp = TAILQ_NEXT(wl->window->active, entry); - if (*wpp == NULL) - *wpp = TAILQ_FIRST(&wl->window->panes); - return (wl); - } - if (paneptr[0] == '-' && paneptr[1] == '\0') { - *wpp = TAILQ_PREV(wl->window->active, window_panes, entry); - if (*wpp == NULL) - *wpp = TAILQ_LAST(&wl->window->panes, window_panes); - return (wl); - } - /* Try pane string description. */ if ((lc = layout_find_string(wl->window, paneptr)) == NULL) { ctx->error(ctx, "can't find pane: %s", paneptr); diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 18e268f0916..a9901e4f44a 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.176 2010/06/14 23:04:44 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.177 2010/06/21 01:46:36 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -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 14 2010 $ +.Dd $Mdocdate: June 21 2010 $ .Dt TMUX 1 .Os .Sh NAME @@ -428,6 +428,18 @@ One of the strings .Em bottom-right may be used instead of a pane index. .Pp +The special characters +.Ql + +and +.Ql - +may be followed by an offset, for example: +.Bd -literal -offset indent +select-window -t:+2 +.Ed +.Pp +When dealing with a session that doesn't contain sequential window indexes, +they will be correctly skipped. +.Pp .Ar shell-command arguments are .Xr sh 1 diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 8a1601b448b..7bdf4e054ab 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.226 2010/06/21 01:27:46 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.227 2010/06/21 01:46:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1799,6 +1799,8 @@ struct winlink *winlink_add(struct winlinks *, struct window *, int); void winlink_remove(struct winlinks *, struct winlink *); struct winlink *winlink_next(struct winlink *); struct winlink *winlink_previous(struct winlink *); +struct winlink *winlink_next_by_number(struct winlink *, int); +struct winlink *winlink_previous_by_number(struct winlink *, int); void winlink_stack_push(struct winlink_stack *, struct winlink *); void winlink_stack_remove(struct winlink_stack *, struct winlink *); int window_index(struct window *, u_int *); diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c index b0ae5694919..48e4e645ab5 100644 --- a/usr.bin/tmux/window.c +++ b/usr.bin/tmux/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.51 2010/05/23 19:42:19 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.52 2010/06/21 01:46:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -172,6 +172,28 @@ winlink_previous(struct winlink *wl) return (RB_PREV(winlinks, wwl, wl)); } +struct winlink * +winlink_next_by_number(struct winlink *wl, int n) +{ + for (; n > 0; n--) { + if ((wl = RB_NEXT(winlinks, wwl, wl)) == NULL) + break; + } + + return (wl); +} + +struct winlink * +winlink_previous_by_number(struct winlink *wl, int n) +{ + for (; n > 0; n--) { + if ((wl = RB_PREV(winlinks, wwl, wl)) == NULL) + break; + } + + return (wl); +} + void winlink_stack_push(struct winlink_stack *stack, struct winlink *wl) { |