Support up, down, left, right movement through panes with -UDLR flags to

select-pane.

Also remove up- and down-pane: equivalent behaviour is now available
using -t :.+ and -t :.-.
This commit is contained in:
Nicholas Marriott 2010-03-15 22:03:38 +00:00
parent 4de04fac2c
commit aa8f9018ea
9 changed files with 201 additions and 149 deletions

5
TODO
View File

@ -125,11 +125,12 @@
- command to show status line information briefly when it is off - command to show status line information briefly when it is off
- some way to pad # stuff with spaces, #!2T maybe - some way to pad # stuff with spaces, #!2T maybe
- FreeBSD console problems - FreeBSD console problems
- + and - should be more powerful:
- wrap for windows like panes
- +2 -2 etc to move by two
For 1.3: For 1.3:
1 new input parser
2 move left/right/up/down around panes not just next/previous
3 why are alerts per-winlink? try per window? 3 why are alerts per-winlink? try per window?
4 audit of escape sequence support vs xterm 4 audit of escape sequence support vs xterm
5 double C-a should walk back over wrapped lines like C-e 5 double C-a should walk back over wrapped lines like C-e

View File

@ -1,60 +0,0 @@
/* $Id: cmd-down-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "tmux.h"
/*
* Move down a pane.
*/
int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_down_pane_entry = {
"down-pane", "downp",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_down_pane_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_NEXT(w->active, entry);
if (w->active == NULL)
w->active = TAILQ_FIRST(&w->panes);
} while (!window_pane_visible(w->active));
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (0);
}

View File

@ -1,4 +1,4 @@
/* $Id: cmd-select-pane.c,v 1.12 2010-01-05 23:52:37 tcunha Exp $ */ /* $Id: cmd-select-pane.c,v 1.13 2010-03-15 22:03:38 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,19 +24,40 @@
* Select pane. * Select pane.
*/ */
void cmd_select_pane_init(struct cmd *, int);
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = { const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp", "select-pane", "selectp",
CMD_TARGET_PANE_USAGE, "[-DLRU] " CMD_TARGET_PANE_USAGE,
0, "", 0, "DLRU",
cmd_target_init, cmd_select_pane_init,
cmd_target_parse, cmd_target_parse,
cmd_select_pane_exec, cmd_select_pane_exec,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
void
cmd_select_pane_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == KEYC_UP)
cmd_set_flag(&data->chflags, 'U');
if (key == KEYC_DOWN)
cmd_set_flag(&data->chflags, 'D');
if (key == KEYC_LEFT)
cmd_set_flag(&data->chflags, 'L');
if (key == KEYC_RIGHT)
cmd_set_flag(&data->chflags, 'R');
if (key == 'o')
data->target = xstrdup(":.+");
}
int int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
@ -51,6 +72,20 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->error(ctx, "pane not visible: %s", data->target); ctx->error(ctx, "pane not visible: %s", data->target);
return (-1); return (-1);
} }
if (cmd_check_flag(data->chflags, 'L'))
wp = window_pane_find_left(wp);
else if (cmd_check_flag(data->chflags, 'R'))
wp = window_pane_find_right(wp);
else if (cmd_check_flag(data->chflags, 'U'))
wp = window_pane_find_up(wp);
else if (cmd_check_flag(data->chflags, 'D'))
wp = window_pane_find_down(wp);
if (wp == NULL) {
ctx->error(ctx, "pane not found");
return (-1);
}
window_set_active_pane(wl->window, wp); window_set_active_pane(wl->window, wp);
server_status_window(wl->window); server_status_window(wl->window);
server_redraw_window_borders(wl->window); server_redraw_window_borders(wl->window);

View File

@ -1,60 +0,0 @@
/* $Id: cmd-up-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "tmux.h"
/*
* Move up a pane.
*/
int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_up_pane_entry = {
"up-pane", "upp",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_up_pane_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes);
} while (!window_pane_visible(w->active));
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (0);
}

22
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.137 2010-01-22 17:28:34 tcunha Exp $ */ /* $Id: cmd.c,v 1.138 2010-03-15 22:03:38 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -44,7 +44,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_detach_client_entry, &cmd_detach_client_entry,
&cmd_display_message_entry, &cmd_display_message_entry,
&cmd_display_panes_entry, &cmd_display_panes_entry,
&cmd_down_pane_entry,
&cmd_find_window_entry, &cmd_find_window_entry,
&cmd_has_session_entry, &cmd_has_session_entry,
&cmd_if_shell_entry, &cmd_if_shell_entry,
@ -108,7 +107,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_switch_client_entry, &cmd_switch_client_entry,
&cmd_unbind_key_entry, &cmd_unbind_key_entry,
&cmd_unlink_window_entry, &cmd_unlink_window_entry,
&cmd_up_pane_entry,
NULL NULL
}; };
@ -954,15 +952,29 @@ cmd_find_pane(struct cmd_ctx *ctx,
return (wl); return (wl);
lookup_string: 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. */ /* Try pane string description. */
if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) { if ((lc = layout_find_string(wl->window, paneptr)) == NULL) {
ctx->error(ctx, "can't find pane: %s", paneptr); ctx->error(ctx, "can't find pane: %s", paneptr);
goto error; goto error;
} }
*wpp = lc->wp; *wpp = lc->wp;
xfree(winptr); xfree(winptr);
return (s->curw); return (wl);
no_period: no_period:
/* Try as a pane number alone. */ /* Try as a pane number alone. */

View File

@ -1,4 +1,4 @@
/* $Id: key-bindings.c,v 1.88 2010-02-08 18:27:34 tcunha Exp $ */ /* $Id: key-bindings.c,v 1.89 2010-03-15 22:03:38 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -136,7 +136,7 @@ key_bindings_init(void)
{ 'i', 0, &cmd_display_message_entry }, { 'i', 0, &cmd_display_message_entry },
{ 'l', 0, &cmd_last_window_entry }, { 'l', 0, &cmd_last_window_entry },
{ 'n', 0, &cmd_next_window_entry }, { 'n', 0, &cmd_next_window_entry },
{ 'o', 0, &cmd_down_pane_entry }, { 'o', 0, &cmd_select_pane_entry },
{ 'p', 0, &cmd_previous_window_entry }, { 'p', 0, &cmd_previous_window_entry },
{ 'q', 0, &cmd_display_panes_entry }, { 'q', 0, &cmd_display_panes_entry },
{ 'r', 0, &cmd_refresh_client_entry }, { 'r', 0, &cmd_refresh_client_entry },
@ -155,8 +155,10 @@ key_bindings_init(void)
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry }, { 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
{ 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry }, { 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry },
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry }, { 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
{ KEYC_UP, 0, &cmd_up_pane_entry }, { KEYC_UP, 1, &cmd_select_pane_entry },
{ KEYC_DOWN, 0, &cmd_down_pane_entry }, { KEYC_DOWN, 1, &cmd_select_pane_entry },
{ KEYC_LEFT, 1, &cmd_select_pane_entry },
{ KEYC_RIGHT, 1, &cmd_select_pane_entry },
{ KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, { KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
{ KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, { KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
{ KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, { KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },

32
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.237 2010-03-08 15:02:07 tcunha Exp $ .\" $Id: tmux.1,v 1.238 2010-03-15 22:03:38 nicm Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -336,6 +336,11 @@ If neither a colon nor period appears,
first attempts to use the argument as a pane index; if that fails, it is looked first attempts to use the argument as a pane index; if that fails, it is looked
up as for up as for
.Ar target-window . .Ar target-window .
A
.Ql +
or
.Ql -
indicate the next or previous pane index, respectively.
One of the strings One of the strings
.Em top , .Em top ,
.Em bottom , .Em bottom ,
@ -727,10 +732,8 @@ command (bound to
and and
.Ql C-right .Ql C-right
by default), the current pane may be changed with the by default), the current pane may be changed with the
.Ic up-pane .Ic select-pane
and command and the
.Ic down-pane
commands and the
.Ic rotate-window .Ic rotate-window
and and
.Ic swap-pane .Ic swap-pane
@ -859,9 +862,6 @@ While the indicator is on screen, a pane may be selected with the
to to
.Ql 9 .Ql 9
keys. keys.
.It Ic down-pane Op Fl t Ar target-pane
.D1 (alias: Ic downp )
Change the active pane to the next pane (higher index).
.It Xo Ic find-window .It Xo Ic find-window
.Op Fl t Ar target-window .Op Fl t Ar target-window
.Ar match-string .Ar match-string
@ -1103,12 +1103,23 @@ Choose a specific layout for a window.
If If
.Ar layout-name .Ar layout-name
is not given, the last layout used (if any) is reapplied. is not given, the last layout used (if any) is reapplied.
.It Ic select-pane Op Fl t Ar target-pane .It Xo Ic select-pane
.Op Fl DLRU
.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic selectp ) .D1 (alias: Ic selectp )
Make pane Make pane
.Ar target-pane .Ar target-pane
the active pane in window the active pane in window
.Ar target-window . .Ar target-window .
If one of
.Fl D ,
.Fl L ,
.Fl R ,
or
.Fl U
is used, respectively the pane below, to the left, to the right, or above the
target pane is used.
.It Ic select-window Op Fl t Ar target-window .It Ic select-window Op Fl t Ar target-window
.D1 (alias: Ic selectw ) .D1 (alias: Ic selectw )
Select the window at Select the window at
@ -1184,9 +1195,6 @@ if
.Fl k .Fl k
is specified and the window is linked to only one session, it is unlinked and is specified and the window is linked to only one session, it is unlinked and
destroyed. destroyed.
.It Ic up-pane Op Fl t Ar target-pane
.D1 (alias: Ic upp )
Change the active pane to the previous pane (lower index).
.El .El
.Sh KEY BINDINGS .Sh KEY BINDINGS
.Nm .Nm

6
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.548 2010-03-15 12:51:23 nicm Exp $ */ /* $Id: tmux.h,v 1.549 2010-03-15 22:03:38 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -1831,6 +1831,10 @@ void window_pane_mouse(struct window_pane *,
int window_pane_visible(struct window_pane *); int window_pane_visible(struct window_pane *);
char *window_pane_search( char *window_pane_search(
struct window_pane *, const char *, u_int *); struct window_pane *, const char *, u_int *);
struct window_pane *window_pane_find_up(struct window_pane *);
struct window_pane *window_pane_find_down(struct window_pane *);
struct window_pane *window_pane_find_left(struct window_pane *);
struct window_pane *window_pane_find_right(struct window_pane *);
/* layout.c */ /* layout.c */
struct layout_cell *layout_create_cell(struct layout_cell *); struct layout_cell *layout_create_cell(struct layout_cell *);

112
window.c
View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.127 2010-03-15 12:51:23 nicm Exp $ */ /* $Id: window.c,v 1.128 2010-03-15 22:03:38 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -834,3 +834,113 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
xfree(newsearchstr); xfree(newsearchstr);
return (msg); return (msg);
} }
/* Find the pane directly above another. */
struct window_pane *
window_pane_find_up(struct window_pane *wp)
{
struct window_pane *wp2;
u_int left, top;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
top = wp->yoff;
if (top == 0)
top = wp->window->sy + 1;
left = wp->xoff;
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (!window_pane_visible(wp2))
continue;
if (wp2->yoff + wp2->sy + 1 != top)
continue;
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
return (wp2);
}
return (NULL);
}
/* Find the pane directly below another. */
struct window_pane *
window_pane_find_down(struct window_pane *wp)
{
struct window_pane *wp2;
u_int left, bottom;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
bottom = wp->yoff + wp->sy + 1;
if (bottom >= wp->window->sy)
bottom = 0;
left = wp->xoff;
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (!window_pane_visible(wp2))
continue;
if (wp2->yoff != bottom)
continue;
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
return (wp2);
}
return (NULL);
}
/*
* Find the pane directly to the left of another, adjacent to the left side and
* containing the top edge.
*/
struct window_pane *
window_pane_find_left(struct window_pane *wp)
{
struct window_pane *wp2;
u_int left, top;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
left = wp->xoff;
if (left == 0)
left = wp->window->sx + 1;
top = wp->yoff;
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (!window_pane_visible(wp2))
continue;
if (wp2->xoff + wp2->sx + 1 != left)
continue;
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
return (wp2);
}
return (NULL);
}
/*
* Find the pane directly to the right of another, that is adjacent to the
* right edge and including the top edge.
*/
struct window_pane *
window_pane_find_right(struct window_pane *wp)
{
struct window_pane *wp2;
u_int right, top;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
right = wp->xoff + wp->sx + 1;
if (right >= wp->window->sx)
right = 0;
top = wp->yoff;
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (!window_pane_visible(wp2))
continue;
if (wp2->xoff != right)
continue;
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
return (wp2);
}
return (NULL);
}