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

select-pane.

Also REMOVE the up- and down-pane commands: equivalent behaviour is now
available using -t :.+ and -t :.-.
pull/1/head
Nicholas Marriott 2010-03-22 19:07:52 +00:00
parent 021037c419
commit 6f04866044
9 changed files with 194 additions and 143 deletions

View File

@ -6,7 +6,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \ cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \
cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \ cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \
cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \ cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \
cmd-delete-buffer.c cmd-detach-client.c cmd-down-pane.c \ cmd-delete-buffer.c cmd-detach-client.c \
cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \ cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \
cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \ cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \
cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \ cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \
@ -28,7 +28,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
cmd-run-shell.c cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \ cmd-run-shell.c cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \
cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \ cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \
cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \ cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \
cmd-up-pane.c cmd-display-message.c cmd-display-panes.c \ cmd-display-message.c cmd-display-panes.c \
cmd-pipe-pane.c cmd-capture-pane.c cmd.c \ cmd-pipe-pane.c cmd-capture-pane.c cmd.c \
colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \ colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \
imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \ imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \

View File

@ -1,60 +0,0 @@
/* $OpenBSD$ */
/*
* 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

@ -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 @@
/* $OpenBSD$ */
/*
* 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);
}

20
cmd.c
View File

@ -45,7 +45,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,
@ -109,7 +108,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
}; };
@ -955,15 +953,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

@ -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 },

30
tmux.1
View File

@ -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

4
tmux.h
View File

@ -1832,6 +1832,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 *);

110
window.c
View File

@ -827,3 +827,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);
}