From 8d3b726396d3f5124d31a792a5f3358357f2e105 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Tue, 22 Jun 2010 23:29:05 +0000 Subject: [PATCH] Sync OpenBSD patchset 725: Extend the -t:+ and -t:- window targets for next and previous window to accept an offset such as -t:+2. From Tiago Cunha. --- cmd.c | 189 ++++++++++++++++++++++++++++++++++++------------------- tmux.1 | 16 ++++- tmux.h | 4 +- window.c | 24 ++++++- 4 files changed, 164 insertions(+), 69 deletions(-) diff --git a/cmd.c b/cmd.c index 079cf5e8..a9a3a629 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.139 2010-05-14 14:33:39 tcunha Exp $ */ +/* $Id: cmd.c,v 1.140 2010-06-22 23:29:05 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -537,7 +537,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 * @@ -659,6 +659,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 @@ -704,11 +705,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; @@ -725,25 +736,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); @@ -777,6 +804,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 @@ -824,20 +852,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); @@ -852,27 +883,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); @@ -882,6 +926,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); @@ -906,7 +959,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) { @@ -938,7 +991,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; @@ -951,20 +1024,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/tmux.1 b/tmux.1 index 90a5bd50..850c7e74 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $Id: tmux.1,v 1.258 2010-06-15 20:24:52 tcunha Exp $ +.\" $Id: tmux.1,v 1.259 2010-06-22 23:29:05 tcunha 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 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/tmux.h b/tmux.h index 7184296d..6bad49b3 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.562 2010-06-22 23:26:18 tcunha Exp $ */ +/* $Id: tmux.h,v 1.563 2010-06-22 23:29:05 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1798,6 +1798,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/window.c b/window.c index 9e6a3500..d02178c1 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.132 2010-05-22 21:56:04 micahcowan Exp $ */ +/* $Id: window.c,v 1.133 2010-06-22 23:29:05 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -170,6 +170,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) {