From e4f1fbd0085f30be0945ff3c8220184b0b473906 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 3 Mar 2012 09:19:40 +0000 Subject: [PATCH] Sync OpenBSD patchset 1035: Add move-pane command (like join-pane but allows the same window). Also -b flag to join-pane and move-pane to place the pane to the left or above. From George Nachman. --- cmd-join-pane.c | 35 +++++++++++++++++++++++++++++------ cmd-split-window.c | 2 +- cmd.c | 1 + layout.c | 33 ++++++++++++++++++++++++--------- tmux.1 | 24 +++++++++++++++++++++++- tmux.h | 3 ++- 6 files changed, 80 insertions(+), 18 deletions(-) diff --git a/cmd-join-pane.c b/cmd-join-pane.c index cb30687b..c87c5331 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -1,6 +1,7 @@ /* $Id$ */ /* + * Copyright (c) 2011 George Nachman * Copyright (c) 2009 Nicholas Marriott * * Permission to use, copy, modify, and distribute this software for any @@ -24,22 +25,34 @@ #include "tmux.h" /* - * Join a pane into another (like split/swap/kill). + * Join or move a pane into another (like split/swap/kill). */ void cmd_join_pane_key_binding(struct cmd *, int); int cmd_join_pane_exec(struct cmd *, struct cmd_ctx *); +int join_pane(struct cmd *, struct cmd_ctx *, int); + const struct cmd_entry cmd_join_pane_entry = { "join-pane", "joinp", - "dhvp:l:s:t:", 0, 0, - "[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]", + "bdhvp:l:s:t:", 0, 0, + "[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]", 0, cmd_join_pane_key_binding, NULL, cmd_join_pane_exec }; +const struct cmd_entry cmd_move_pane_entry = { + "move-pane", "movep", + "bdhvp:l:s:t:", 0, 0, + "[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]", + 0, + NULL, + NULL, + cmd_join_pane_exec +}; + void cmd_join_pane_key_binding(struct cmd *self, int key) { @@ -56,6 +69,12 @@ cmd_join_pane_key_binding(struct cmd *self, int key) int cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + return join_pane(self, ctx, self->entry == &cmd_join_pane_entry); +} + +int +join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) { struct args *args = self->args; struct session *dst_s; @@ -78,10 +97,14 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); src_w = src_wl->window; - if (src_w == dst_w) { + if (not_same_window && src_w == dst_w) { ctx->error(ctx, "can't join a pane to its own window"); return (-1); } + if (!not_same_window && src_wp == dst_wp) { + ctx->error(ctx, "source and target panes must be different"); + return (-1); + } type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) @@ -107,8 +130,8 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) else size = (dst_wp->sx * percentage) / 100; } - - if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) { + lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b')); + if (lc == NULL) { ctx->error(ctx, "create pane failed: pane too small"); return (-1); } diff --git a/cmd-split-window.c b/cmd-split-window.c index 7bbef7b6..1bf54e5f 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -112,7 +112,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; - if ((lc = layout_split_pane(wp, type, size)) == NULL) { + if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) { cause = xstrdup("pane too small"); goto error; } diff --git a/cmd.c b/cmd.c index 09b368da..2763a603 100644 --- a/cmd.c +++ b/cmd.c @@ -67,6 +67,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_lock_client_entry, &cmd_lock_server_entry, &cmd_lock_session_entry, + &cmd_move_pane_entry, &cmd_move_window_entry, &cmd_new_session_entry, &cmd_new_window_entry, diff --git a/layout.c b/layout.c index eada12a8..430a52f7 100644 --- a/layout.c +++ b/layout.c @@ -616,9 +616,10 @@ layout_assign_pane(struct layout_cell *lc, struct window_pane *wp) * split. This must be followed by layout_assign_pane before much else happens! **/ struct layout_cell * -layout_split_pane(struct window_pane *wp, enum layout_type type, int size) +layout_split_pane( + struct window_pane *wp, enum layout_type type, int size, int insert_before) { - struct layout_cell *lc, *lcparent, *lcnew; + struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2; u_int sx, sy, xoff, yoff, size1, size2; lc = wp->layout_cell; @@ -650,8 +651,12 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size) */ /* Create the new child cell. */ - lcnew = layout_create_cell(lc->parent); - TAILQ_INSERT_AFTER(&lc->parent->cells, lc, lcnew, entry); + lcparent = lc->parent; + lcnew = layout_create_cell(lcparent); + if (insert_before) + TAILQ_INSERT_BEFORE(lc, lcnew, entry); + else + TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry); } else { /* * Otherwise create a new parent and insert it. @@ -672,7 +677,17 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size) /* Create the new child cell. */ lcnew = layout_create_cell(lcparent); - TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry); + if (insert_before) + TAILQ_INSERT_HEAD(&lcparent->cells, lcnew, entry); + else + TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry); + } + if (insert_before) { + lc1 = lcnew; + lc2 = lc; + } else { + lc1 = lc; + lc2 = lcnew; } /* Set new cell sizes. size is the target size or -1 for middle split, @@ -689,8 +704,8 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size) else if (size2 > sx - 2) size2 = sx - 2; size1 = sx - 1 - size2; - layout_set_size(lc, size1, sy, xoff, yoff); - layout_set_size(lcnew, size2, sy, xoff + lc->sx + 1, yoff); + layout_set_size(lc1, size1, sy, xoff, yoff); + layout_set_size(lc2, size2, sy, xoff + lc1->sx + 1, yoff); break; case LAYOUT_TOPBOTTOM: if (size < 0) @@ -702,8 +717,8 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size) else if (size2 > sy - 2) size2 = sy - 2; size1 = sy - 1 - size2; - layout_set_size(lc, sx, size1, xoff, yoff); - layout_set_size(lcnew, sx, size2, xoff, yoff + lc->sy + 1); + layout_set_size(lc1, sx, size1, xoff, yoff); + layout_set_size(lc2, sx, size2, xoff, yoff + lc1->sy + 1); break; default: fatalx("bad layout type"); diff --git a/tmux.1 b/tmux.1 index 252d40bc..a241e621 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1109,7 +1109,7 @@ choice list is shown. This command only works from inside .Nm . .It Xo Ic join-pane -.Op Fl dhv +.Op Fl bdhv .Oo Fl l .Ar size | .Fl p Ar percentage Oc @@ -1126,6 +1126,12 @@ and creating a new pane, split it and move into the space. This can be used to reverse .Ic break-pane . +The +.Fl b +option causes +.Ar src-pane +to be joined to left of or above +.Ar dst-pane . .It Xo Ic kill-pane .Op Fl a .Op Fl t Ar target-pane @@ -1214,6 +1220,22 @@ For the meaning of the flag, see the .Sx FORMATS section. +.It Xo Ic move-pane +.Op Fl bdhv +.Oo Fl l +.Ar size | +.Fl p Ar percentage Oc +.Op Fl s Ar src-pane +.Op Fl t Ar dst-pane +.Xc +.D1 (alias: Ic movep ) +Like +.Ic join-pane , +but +.Ar src-pane +and +.Ar dst-pane +may belong to the same window. .It Xo Ic move-window .Op Fl dk .Op Fl s Ar src-window diff --git a/tmux.h b/tmux.h index 28bc0c0b..4a24e880 100644 --- a/tmux.h +++ b/tmux.h @@ -1601,6 +1601,7 @@ extern const struct cmd_entry cmd_load_buffer_entry; extern const struct cmd_entry cmd_lock_client_entry; extern const struct cmd_entry cmd_lock_server_entry; extern const struct cmd_entry cmd_lock_session_entry; +extern const struct cmd_entry cmd_move_pane_entry; extern const struct cmd_entry cmd_move_window_entry; extern const struct cmd_entry cmd_new_session_entry; extern const struct cmd_entry cmd_new_window_entry; @@ -1995,7 +1996,7 @@ void layout_resize_pane_mouse( struct client *c, struct mouse_event *mouse); void layout_assign_pane(struct layout_cell *, struct window_pane *); struct layout_cell *layout_split_pane( - struct window_pane *, enum layout_type, int); + struct window_pane *, enum layout_type, int, int); void layout_close_pane(struct window_pane *); /* layout-custom.c */