summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2010-06-21 01:46:37 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2010-06-21 01:46:37 +0000
commiteca92101cb7e08d7427eee989b3c1b75a481d077 (patch)
treee124aae4282869c4b807275b90a988176f7bb4a2
parentf2c6767bd66943273e2e2e2aed0648d412f50e13 (diff)
Extend the -t:+ and -t:- window targets for next and previous window to
accept an offset such as -t:+2. From Tiago Cunha.
-rw-r--r--usr.bin/tmux/cmd.c189
-rw-r--r--usr.bin/tmux/tmux.116
-rw-r--r--usr.bin/tmux/tmux.h4
-rw-r--r--usr.bin/tmux/window.c24
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)
{