1
0
mirror of https://github.com/tmux/tmux.git synced 2025-03-30 19:48:48 +00:00

Add S-Up and S-Down to move windows in tree mode. From David Mandelberg

in GitHub issue 4415.
This commit is contained in:
nicm 2025-03-21 13:36:42 +00:00
parent b7d640e764
commit a541be3951
7 changed files with 109 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++) {

6
tmux.1
View File

@ -2713,6 +2713,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"
@ -5942,6 +5944,7 @@ The following variables are available, where appropriate:
.It Li "command_list_name" Ta "" Ta "Command name if listing commands" .It Li "command_list_name" Ta "" Ta "Command name if listing commands"
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands" .It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
.It Li "config_files" Ta "" Ta "List of configuration files loaded" .It Li "config_files" Ta "" Ta "List of configuration files loaded"
.It Li "cursor_blinking" Ta "" Ta "1 if the cursor is blinking"
.It Li "copy_cursor_hyperlink" Ta "" Ta "Hyperlink under cursor in copy mode" .It Li "copy_cursor_hyperlink" Ta "" Ta "Hyperlink under cursor in copy mode"
.It Li "copy_cursor_line" Ta "" Ta "Line the cursor is on in copy mode" .It Li "copy_cursor_line" Ta "" Ta "Line the cursor is on in copy mode"
.It Li "copy_cursor_word" Ta "" Ta "Word under cursor in copy mode" .It Li "copy_cursor_word" Ta "" Ta "Word under cursor in copy mode"
@ -5949,7 +5952,10 @@ The following variables are available, where appropriate:
.It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode" .It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode"
.It Li "current_file" Ta "" Ta "Current configuration file" .It Li "current_file" Ta "" Ta "Current configuration file"
.It Li "cursor_character" Ta "" Ta "Character at cursor in pane" .It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
.It Li "cursor_colour" Ta "" Ta "Cursor colour in pane"
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag" .It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
.It Li "cursor_shape" Ta "" Ta "Cursor shape in pane"
.It Li "cursor_very_visible" Ta "" Ta "1 if the cursor is in very visible mode"
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane" .It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
.It Li "cursor_y" Ta "" Ta "Cursor Y position in pane" .It Li "cursor_y" Ta "" Ta "Cursor Y position in pane"
.It Li "history_bytes" Ta "" Ta "Number of bytes in window history" .It Li "history_bytes" Ta "" Ta "Number of bytes in window history"

6
tmux.h
View File

@ -3276,6 +3276,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 *);
@ -3290,8 +3291,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);