1
0
mirror of https://github.com/tmux/tmux.git synced 2025-03-25 15:28:49 +00:00

Make it easy to swap windows from choose-tree

I picked the new keys for this because of the similarity to switching vs
swapping tabs in a browser or other tabbed UI. There, Ctrl+PgUp switches
to one tab previous and Ctrl+Shift+PgUp swaps with the previous tab. So
I figured adding Shift to swap instead of move might be somewhat natural
here.

Some of the swapping code is copied from cmd-swap-window.c

Fixes 
This commit is contained in:
David Mandelberg 2025-03-18 19:11:45 -04:00
parent 3eb93383a3
commit 4d539951e0
7 changed files with 105 additions and 10 deletions

View File

@ -58,6 +58,7 @@ struct mode_tree_data {
mode_tree_menu_cb menucb; mode_tree_menu_cb menucb;
mode_tree_height_cb heightcb; mode_tree_height_cb heightcb;
mode_tree_key_cb keycb; mode_tree_key_cb keycb;
mode_tree_swap_cb swapcb;
struct mode_tree_list children; struct mode_tree_list children;
struct mode_tree_list saved; struct mode_tree_list saved;
@ -287,6 +288,35 @@ mode_tree_down(struct mode_tree_data *mtd, int wrap)
return (1); return (1);
} }
static void
mode_tree_swap(struct mode_tree_data *mtd, int direction)
{
u_int current_depth = mtd->line_list[mtd->current].depth;
u_int swap_with, swap_with_depth;
if (mtd->swapcb == NULL)
return;
/* Find the next line at the same depth with the same parent . */
swap_with = mtd->current;
do {
if (direction < 0 && swap_with < (u_int)-direction)
return;
if (direction > 0 && swap_with + direction >= mtd->line_size)
return;
swap_with += direction;
swap_with_depth = mtd->line_list[swap_with].depth;
} while (swap_with_depth > current_depth);
if (swap_with_depth != current_depth)
return;
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
mtd->line_list[swap_with].item->itemdata)) {
mtd->current = swap_with;
mode_tree_build(mtd);
}
}
void * void *
mode_tree_get_current(struct mode_tree_data *mtd) mode_tree_get_current(struct mode_tree_data *mtd)
{ {
@ -410,9 +440,9 @@ struct mode_tree_data *
mode_tree_start(struct window_pane *wp, struct args *args, mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb, mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
mode_tree_height_cb heightcb, mode_tree_key_cb keycb, void *modedata, mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
const struct menu_item *menu, const char **sort_list, u_int sort_size, mode_tree_swap_cb swapcb, void *modedata, const struct menu_item *menu,
struct screen **s) const char **sort_list, u_int sort_size, struct screen **s)
{ {
struct mode_tree_data *mtd; struct mode_tree_data *mtd;
const char *sort; const char *sort;
@ -455,6 +485,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mtd->menucb = menucb; mtd->menucb = menucb;
mtd->heightcb = heightcb; mtd->heightcb = heightcb;
mtd->keycb = keycb; mtd->keycb = keycb;
mtd->swapcb = swapcb;
TAILQ_INIT(&mtd->children); TAILQ_INIT(&mtd->children);
@ -1147,6 +1178,14 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
case 'n'|KEYC_CTRL: case 'n'|KEYC_CTRL:
mode_tree_down(mtd, 1); mode_tree_down(mtd, 1);
break; break;
case KEYC_UP|KEYC_SHIFT:
case 'K':
mode_tree_swap(mtd, -1);
break;
case KEYC_DOWN|KEYC_SHIFT:
case 'J':
mode_tree_swap(mtd, 1);
break;
case KEYC_PPAGE: case KEYC_PPAGE:
case 'b'|KEYC_CTRL: case 'b'|KEYC_CTRL:
for (i = 0; i < mtd->height; i++) { for (i = 0; i < mtd->height; i++) {

2
tmux.1
View File

@ -2715,6 +2715,8 @@ The following keys may be used in tree mode:
.It Li "Enter" Ta "Choose selected item" .It Li "Enter" Ta "Choose selected item"
.It Li "Up" Ta "Select previous item" .It Li "Up" Ta "Select previous item"
.It Li "Down" Ta "Select next item" .It Li "Down" Ta "Select next item"
.It Li "S-Up" Ta "Swap the current window with the previous one"
.It Li "S-Down" Ta "Swap the current window with the next one"
.It Li "+" Ta "Expand selected item" .It Li "+" Ta "Expand selected item"
.It Li "-" Ta "Collapse selected item" .It Li "-" Ta "Collapse selected item"
.It Li "M-+" Ta "Expand all items" .It Li "M-+" Ta "Expand all items"

6
tmux.h
View File

@ -3326,6 +3326,7 @@ typedef int (*mode_tree_search_cb)(void *, void *, const char *);
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code); typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
typedef u_int (*mode_tree_height_cb)(void *, u_int); typedef u_int (*mode_tree_height_cb)(void *, u_int);
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int); typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
typedef int (*mode_tree_swap_cb)(void *, void *);
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code); typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
u_int mode_tree_count_tagged(struct mode_tree_data *); u_int mode_tree_count_tagged(struct mode_tree_data *);
void *mode_tree_get_current(struct mode_tree_data *); void *mode_tree_get_current(struct mode_tree_data *);
@ -3340,8 +3341,9 @@ void mode_tree_up(struct mode_tree_data *, int);
int mode_tree_down(struct mode_tree_data *, int); int mode_tree_down(struct mode_tree_data *, int);
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *, struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb, mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb, void *, mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
const struct menu_item *, const char **, u_int, struct screen **); mode_tree_swap_cb, void *, const struct menu_item *, const char **,
u_int, struct screen **);
void mode_tree_zoom(struct mode_tree_data *, struct args *); void mode_tree_zoom(struct mode_tree_data *, struct args *);
void mode_tree_build(struct mode_tree_data *); void mode_tree_build(struct mode_tree_data *);
void mode_tree_free(struct mode_tree_data *); void mode_tree_free(struct mode_tree_data *);

View File

@ -350,7 +350,7 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_buffer_build, data->data = mode_tree_start(wp, args, window_buffer_build,
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL, window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
window_buffer_get_key, data, window_buffer_menu_items, window_buffer_get_key, NULL, data, window_buffer_menu_items,
window_buffer_sort_list, nitems(window_buffer_sort_list), &s); window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);

View File

@ -310,7 +310,7 @@ window_client_init(struct window_mode_entry *wme,
data->data = mode_tree_start(wp, args, window_client_build, data->data = mode_tree_start(wp, args, window_client_build,
window_client_draw, NULL, window_client_menu, NULL, window_client_draw, NULL, window_client_menu, NULL,
window_client_get_key, data, window_client_menu_items, window_client_get_key, NULL, data, window_client_menu_items,
window_client_sort_list, nitems(window_client_sort_list), &s); window_client_sort_list, nitems(window_client_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);

View File

@ -891,8 +891,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_customize_build, data->data = mode_tree_start(wp, args, window_customize_build,
window_customize_draw, NULL, window_customize_menu, window_customize_draw, NULL, window_customize_menu,
window_customize_height, NULL, data, window_customize_menu_items, window_customize_height, NULL, NULL, data,
NULL, 0, &s); window_customize_menu_items, NULL, 0, &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);
mode_tree_build(data->data); mode_tree_build(data->data);

View File

@ -902,6 +902,58 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line)
return (key); return (key);
} }
static int
window_tree_swap(void *cur_itemdata, void *other_itemdata)
{
struct window_tree_itemdata *cur = cur_itemdata;
struct window_tree_itemdata *other = other_itemdata;
struct session *cur_session, *other_session;
struct winlink *cur_winlink, *other_winlink;
struct window *cur_window, *other_window;
struct window_pane *cur_pane, *other_pane;
if (cur->type != other->type)
return (0);
if (cur->type != WINDOW_TREE_WINDOW)
return (0);
window_tree_pull_item(cur, &cur_session, &cur_winlink, &cur_pane);
window_tree_pull_item(other, &other_session, &other_winlink,
&other_pane);
if (cur_session != other_session)
return (0);
if (window_tree_sort->field != WINDOW_TREE_BY_INDEX &&
window_tree_cmp_window(&cur_winlink, &other_winlink) != 0) {
/*
* Swapping indexes would not swap positions in the tree, so
* prevent swapping to avoid confusing the user.
*/
return (0);
}
other_window = other_winlink->window;
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
cur_window = cur_winlink->window;
TAILQ_REMOVE(&cur_window->winlinks, cur_winlink, wentry);
other_winlink->window = cur_window;
TAILQ_INSERT_TAIL(&cur_window->winlinks, other_winlink, wentry);
cur_winlink->window = other_window;
TAILQ_INSERT_TAIL(&other_window->winlinks, cur_winlink, wentry);
if (cur_session->curw == cur_winlink)
session_set_current(cur_session, other_winlink);
else if (cur_session->curw == other_winlink)
session_set_current(cur_session, cur_winlink);
session_group_synchronize_from(cur_session);
server_redraw_session_group(cur_session);
recalculate_sizes();
return (1);
}
static struct screen * static struct screen *
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs, window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
struct args *args) struct args *args)
@ -940,7 +992,7 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_tree_build, data->data = mode_tree_start(wp, args, window_tree_build,
window_tree_draw, window_tree_search, window_tree_menu, NULL, window_tree_draw, window_tree_search, window_tree_menu, NULL,
window_tree_get_key, data, window_tree_menu_items, window_tree_get_key, window_tree_swap, data, window_tree_menu_items,
window_tree_sort_list, nitems(window_tree_sort_list), &s); window_tree_sort_list, nitems(window_tree_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);