diff --git a/cmd-break-pane.c b/cmd-break-pane.c index 880ee7f5..87892d73 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -34,8 +34,8 @@ const struct cmd_entry cmd_break_pane_entry = { .name = "break-pane", .alias = "breakp", - .args = { "dPF:n:s:t:", 0, 0 }, - .usage = "[-dP] [-F format] [-n window-name] [-s src-pane] " + .args = { "adPF:n:s:t:", 0, 0 }, + .usage = "[-adP] [-F format] [-n window-name] [-s src-pane] " "[-t dst-window]", .source = { 's', CMD_FIND_PANE, 0 }, @@ -63,17 +63,31 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item) const char *template; char *cp; - if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) { - cmdq_error(item, "index %d already in use", idx); - return (CMD_RETURN_ERROR); - } - - if (window_count_panes(w) == 1) { - cmdq_error(item, "can't break with only one pane"); - return (CMD_RETURN_ERROR); + if (args_has(args, 'a')) { + if (target->wl != NULL) + idx = winlink_shuffle_up(dst_s, target->wl); + else + idx = winlink_shuffle_up(dst_s, dst_s->curw); + if (idx == -1) + return (CMD_RETURN_ERROR); } server_unzoom_window(w); + if (window_count_panes(w) == 1) { + if (server_link_window(src_s, wl, dst_s, idx, 0, + !args_has(args, 'd'), &cause) != 0) { + cmdq_error(item, "%s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + server_unlink_window(src_s, wl); + return (CMD_RETURN_NORMAL); + } + if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) { + cmdq_error(item, "index in use: %d", idx); + return (CMD_RETURN_ERROR); + } + TAILQ_REMOVE(&w->panes, wp, entry); window_lost_pane(w, wp); layout_close_pane(wp); diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 6583db75..2e4bec50 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -49,8 +49,8 @@ const struct cmd_entry cmd_move_pane_entry = { .name = "move-pane", .alias = "movep", - .args = { "bdhvp:l:s:t:", 0, 0 }, - .usage = "[-bdhv] [-l size] " CMD_SRCDST_PANE_USAGE, + .args = { "bdfhvp:l:s:t:", 0, 0 }, + .usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE, .source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED }, .target = { 't', CMD_FIND_PANE, 0 }, @@ -71,16 +71,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; char *cause = NULL; - int size, percentage, dst_idx, not_same_window; + int size, percentage, dst_idx; int flags; enum layout_type type; struct layout_cell *lc; - if (cmd_get_entry(self) == &cmd_join_pane_entry) - not_same_window = 1; - else - not_same_window = 0; - dst_s = target->s; dst_wl = target->wl; dst_wp = target->wp; @@ -93,11 +88,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) src_w = src_wl->window; server_unzoom_window(src_w); - if (not_same_window && src_w == dst_w) { - cmdq_error(item, "can't join a pane to its own window"); - return (CMD_RETURN_ERROR); - } - if (!not_same_window && src_wp == dst_wp) { + if (src_wp == dst_wp) { cmdq_error(item, "source and target panes must be different"); return (CMD_RETURN_ERROR); } diff --git a/cmd-move-window.c b/cmd-move-window.c index eb6f4f1a..94b6c950 100644 --- a/cmd-move-window.c +++ b/cmd-move-window.c @@ -63,9 +63,9 @@ cmd_move_window_exec(struct cmd *self, struct cmdq_item *item) struct cmd_find_state *source = cmdq_get_source(item); struct cmd_find_state target; const char *tflag = args_get(args, 't'); - struct session *src; + struct session *src = source->s; struct session *dst; - struct winlink *wl; + struct winlink *wl = source->wl; char *cause; int idx, kflag, dflag, sflag; @@ -83,9 +83,7 @@ cmd_move_window_exec(struct cmd *self, struct cmdq_item *item) if (cmd_find_target(&target, item, tflag, CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX) != 0) return (CMD_RETURN_ERROR); - src = source->s; dst = target.s; - wl = source->wl; idx = target.idx; kflag = args_has(args, 'k'); @@ -93,12 +91,16 @@ cmd_move_window_exec(struct cmd *self, struct cmdq_item *item) sflag = args_has(args, 's'); if (args_has(args, 'a')) { - if ((idx = winlink_shuffle_up(dst, dst->curw)) == -1) + if (target.wl != NULL) + idx = winlink_shuffle_up(dst, target.wl); + else + idx = winlink_shuffle_up(dst, dst->curw); + if (idx == -1) return (CMD_RETURN_ERROR); } if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { - cmdq_error(item, "can't link window: %s", cause); + cmdq_error(item, "%s", cause); free(cause); return (CMD_RETURN_ERROR); } diff --git a/mode-tree.c b/mode-tree.c index 0177d618..783ffcfa 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -256,8 +256,8 @@ mode_tree_expand_current(struct mode_tree_data *mtd) } } -void -mode_tree_set_current(struct mode_tree_data *mtd, uint64_t tag) +static int +mode_tree_get_tag(struct mode_tree_data *mtd, uint64_t tag, u_int *found) { u_int i; @@ -266,15 +266,41 @@ mode_tree_set_current(struct mode_tree_data *mtd, uint64_t tag) break; } if (i != mtd->line_size) { - mtd->current = i; + *found = i; + return (1); + } + return (0); +} + +void +mode_tree_expand(struct mode_tree_data *mtd, uint64_t tag) +{ + u_int found; + + if (!mode_tree_get_tag(mtd, tag, &found)) + return; + if (!mtd->line_list[found].item->expanded) { + mtd->line_list[found].item->expanded = 1; + mode_tree_build(mtd); + } +} + +int +mode_tree_set_current(struct mode_tree_data *mtd, uint64_t tag) +{ + u_int found; + + if (mode_tree_get_tag(mtd, tag, &found)) { + mtd->current = found; if (mtd->current > mtd->height - 1) mtd->offset = mtd->current - mtd->height + 1; else mtd->offset = 0; - } else { - mtd->current = 0; - mtd->offset = 0; + return (1); } + mtd->current = 0; + mtd->offset = 0; + return (0); } u_int diff --git a/tmux.1 b/tmux.1 index 9cd120a4..6a77a273 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1714,7 +1714,7 @@ from which the layout was originally defined. Commands related to windows and panes are as follows: .Bl -tag -width Ds .It Xo Ic break-pane -.Op Fl dP +.Op Fl adP .Op Fl F Ar format .Op Fl n Ar window-name .Op Fl s Ar src-pane @@ -1725,6 +1725,10 @@ Break .Ar src-pane off from its containing window to make it the only pane in .Ar dst-window . +With +.Fl a , +the window is moved to the next index up (following windows +are moved if necessary). If .Fl d is given, the new window does not become the current window. @@ -1873,12 +1877,15 @@ The following keys may be used in tree mode: .It Li "<" Ta "Scroll list of previews left" .It Li ">" Ta "Scroll list of previews right" .It Li "C-s" Ta "Search by name" +.It Li "m" Ta "Set the marked pane" +.It Li "M" Ta "Clear the marked pane" .It Li "n" Ta "Repeat last search" .It Li "t" Ta "Toggle if item is tagged" .It Li "T" Ta "Tag no items" .It Li "C-t" Ta "Tag all items" .It Li "\&:" Ta "Run a command for each tagged item" .It Li "f" Ta "Enter a format to filter items" +.It Li "H" Ta "Jump to the starting pane" .It Li "O" Ta "Change sort field" .It Li "r" Ta "Reverse sort order" .It Li "v" Ta "Toggle preview" @@ -2125,19 +2132,14 @@ See the .Sx FORMATS section. .It Xo Ic move-pane -.Op Fl bdhv +.Op Fl bdfhv .Op Fl l Ar size .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. +Does the same as +.Ic join-pane . .It Xo Ic move-window .Op Fl ardk .Op Fl s Ar src-window diff --git a/tmux.h b/tmux.h index 6b604f26..f95726d5 100644 --- a/tmux.h +++ b/tmux.h @@ -2623,7 +2623,8 @@ typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code); u_int mode_tree_count_tagged(struct mode_tree_data *); void *mode_tree_get_current(struct mode_tree_data *); void mode_tree_expand_current(struct mode_tree_data *); -void mode_tree_set_current(struct mode_tree_data *, uint64_t); +void mode_tree_expand(struct mode_tree_data *, uint64_t); +int mode_tree_set_current(struct mode_tree_data *, uint64_t); void mode_tree_each_tagged(struct mode_tree_data *, mode_tree_each_cb, struct client *, key_code, int); void mode_tree_down(struct mode_tree_data *, int); diff --git a/window-tree.c b/window-tree.c index 3bb2af34..095520e2 100644 --- a/window-tree.c +++ b/window-tree.c @@ -37,9 +37,11 @@ static void window_tree_key(struct window_mode_entry *, #define WINDOW_TREE_DEFAULT_FORMAT \ "#{?pane_format," \ - "#{pane_current_command} \"#{pane_title}\"" \ + "#{?pane_marked,#[reverse],}" \ + "#{pane_current_command}#{?pane_active,*,}#{?pane_marked,M,} \"#{pane_title}\"" \ "," \ "#{?window_format," \ + "#{?window_marked_flag,#[reverse],}" \ "#{window_name}#{window_flags} " \ "(#{window_panes} panes)" \ "#{?#{==:#{window_panes},1}, \"#{pane_title}\",}" \ @@ -56,6 +58,7 @@ static void window_tree_key(struct window_mode_entry *, static const struct menu_item window_tree_menu_items[] = { { "Select", '\r', NULL }, { "Expand", KEYC_RIGHT, NULL }, + { "Mark", 'm', NULL }, { "", KEYC_NONE, NULL }, { "Tag", 't', NULL }, { "Tag All", '\024', NULL }, @@ -1170,7 +1173,7 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, struct window_tree_modedata *data = wme->data; struct window_tree_itemdata *item, *new_item; char *name, *prompt = NULL; - struct cmd_find_state fs; + struct cmd_find_state fs, *fsp = &data->fs; int finished; u_int tagged, x, y, idx; struct session *ns; @@ -1192,6 +1195,21 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, case '>': data->offset++; break; + case 'H': + mode_tree_expand(data->data, (uint64_t)fsp->s); + mode_tree_expand(data->data, (uint64_t)fsp->wl); + if (!mode_tree_set_current(data->data, (uint64_t)wme->wp)) + mode_tree_set_current(data->data, (uint64_t)fsp->wl); + break; + case 'm': + window_tree_pull_item(item, &ns, &nwl, &nwp); + server_set_marked(ns, nwl, nwp); + mode_tree_build(data->data); + break; + case 'M': + server_clear_marked(); + mode_tree_build(data->data); + break; case 'x': window_tree_pull_item(item, &ns, &nwl, &nwp); switch (item->type) {