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
- some way to pad # stuff with spaces, #!2T maybe
- FreeBSD console problems
- + and - should be more powerful:
- wrap for windows like panes
- +2 -2 etc to move by two
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?
4 audit of escape sequence support vs xterm
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>
@ -24,19 +24,40 @@
* Select pane.
*/
void cmd_select_pane_init(struct cmd *, int);
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
CMD_TARGET_PANE_USAGE,
0, "",
cmd_target_init,
"[-DLRU] " CMD_TARGET_PANE_USAGE,
0, "DLRU",
cmd_select_pane_init,
cmd_target_parse,
cmd_select_pane_exec,
cmd_target_free,
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
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);
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);
server_status_window(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>
@ -44,7 +44,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_detach_client_entry,
&cmd_display_message_entry,
&cmd_display_panes_entry,
&cmd_down_pane_entry,
&cmd_find_window_entry,
&cmd_has_session_entry,
&cmd_if_shell_entry,
@ -108,7 +107,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_switch_client_entry,
&cmd_unbind_key_entry,
&cmd_unlink_window_entry,
&cmd_up_pane_entry,
NULL
};
@ -954,15 +952,29 @@ 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(s->curw->window, paneptr)) == NULL) {
if ((lc = layout_find_string(wl->window, paneptr)) == NULL) {
ctx->error(ctx, "can't find pane: %s", paneptr);
goto error;
}
*wpp = lc->wp;
xfree(winptr);
return (s->curw);
return (wl);
no_period:
/* 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>
@ -136,7 +136,7 @@ key_bindings_init(void)
{ 'i', 0, &cmd_display_message_entry },
{ 'l', 0, &cmd_last_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 },
{ 'q', 0, &cmd_display_panes_entry },
{ 'r', 0, &cmd_refresh_client_entry },
@ -155,8 +155,10 @@ key_bindings_init(void)
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
{ 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry },
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
{ KEYC_UP, 0, &cmd_up_pane_entry },
{ KEYC_DOWN, 0, &cmd_down_pane_entry },
{ KEYC_UP, 1, &cmd_select_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_DOWN | 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>
.\"
@ -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
up as for
.Ar target-window .
A
.Ql +
or
.Ql -
indicate the next or previous pane index, respectively.
One of the strings
.Em top ,
.Em bottom ,
@ -727,10 +732,8 @@ command (bound to
and
.Ql C-right
by default), the current pane may be changed with the
.Ic up-pane
and
.Ic down-pane
commands and the
.Ic select-pane
command and the
.Ic rotate-window
and
.Ic swap-pane
@ -859,9 +862,6 @@ While the indicator is on screen, a pane may be selected with the
to
.Ql 9
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
.Op Fl t Ar target-window
.Ar match-string
@ -1103,12 +1103,23 @@ Choose a specific layout for a window.
If
.Ar layout-name
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 )
Make pane
.Ar target-pane
the active pane in 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
.D1 (alias: Ic selectw )
Select the window at
@ -1184,9 +1195,6 @@ if
.Fl k
is specified and the window is linked to only one session, it is unlinked and
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
.Sh KEY BINDINGS
.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>
@ -1831,6 +1831,10 @@ void window_pane_mouse(struct window_pane *,
int window_pane_visible(struct window_pane *);
char *window_pane_search(
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 */
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>
@ -834,3 +834,113 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
xfree(newsearchstr);
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);
}