diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-03-13 16:33:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-13 16:33:25 +0100 |
| commit | aa5ca34d4b84254c4f22787e671e34dcd376ad17 (patch) | |
| tree | f21cf7f58854dd741d6c91f6c49a323ec19dc3f7 | |
| parent | Fix debug-mode stack overflow on Windows (#4843) (diff) | |
| download | sl0ppij-aa5ca34d4b84254c4f22787e671e34dcd376ad17.tar.gz sl0ppij-aa5ca34d4b84254c4f22787e671e34dcd376ad17.tar.xz sl0ppij-aa5ca34d4b84254c4f22787e671e34dcd376ad17.zip | |
Add `--pane-id` and `--tab-id` to all relevant CLI commands (#4846)
* add missing pane-id and tab-id arguments to all cli actions
* rustfmt
* fix tests
* update e2e snapshots
* add pr
96 files changed, 4626 insertions, 233 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c35384a..74d64743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * fix: make sure clients are focused when atomically showing floating panes (https://github.com/zellij-org/zellij/pull/4834) * feat: allow configuring focus_follows_mouse and mouse_click_through (https://github.com/zellij-org/zellij/pull/4836) * fix: handle very large writes to the pty (https://github.com/zellij-org/zellij/pull/4818) +* feat: add --pane-id and --tab-id to all relevant CLI actions (https://github.com/zellij-org/zellij/pull/4846) ## [0.43.1] - 2025-08-08 diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_new_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_new_tab_plugin_command.snap index 59cf66f3..38ce1e9e 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_new_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_new_tab_plugin_command.snap @@ -37,6 +37,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), }, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_tab_with_index_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_tab_with_index_plugin_command.snap index c51575ed..28c62b2a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_tab_with_index_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__break_panes_to_tab_with_index_plugin_command.snap @@ -22,6 +22,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), }, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap index f376f4e6..7b31ca71 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap index 876de3d2..2b758c6a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap index 97528cac..b31bd2c5 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap index f20b4c65..e47bc89b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap @@ -15,6 +15,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap index af53bf2a..d76b1a2f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap @@ -15,6 +15,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap index b834fae6..f42fc911 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap @@ -14,6 +14,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_layout_plugin_command.snap index fa22e69d..a1a2c63c 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_layout_plugin_command.snap @@ -40,6 +40,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap index 1b0575e2..ec0711fa 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap index 3a062e7c..9c1483ed 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap index b6056657..413e183a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap @@ -21,6 +21,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap index 946656ce..cba3338c 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap @@ -17,6 +17,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap index a3b89e0e..251e585f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap index 2f9600c4..67166535 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap @@ -17,6 +17,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap index 7b12ea28..50806aec 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap index eb385864..a82b40a7 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap index f730b254..66727a92 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap @@ -15,6 +15,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap index 75b5dd62..7847f3bd 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap @@ -21,6 +21,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap index 323dd29b..a03ad540 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap index 43c28c07..e236fb9b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap index 704220a8..0de2f0f9 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap index 9beccaf4..e41284da 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap index 6f749f98..81b08d6c 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap @@ -31,6 +31,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap index 8a11021c..cd1466ae 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap @@ -83,6 +83,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap index 4e5076b1..eccf2bd0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap @@ -83,6 +83,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap index 3de5d347..c019c09e 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap index 47a7b8c1..603deaa8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap @@ -43,6 +43,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap index 023f92e8..6207efb3 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap @@ -41,6 +41,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap index 6dc703be..3089d85a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap @@ -42,6 +42,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap index 8b400575..9c1b42d6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap @@ -39,6 +39,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap index 66662754..675cac9a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap @@ -40,6 +40,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap index ac0cffca..a98b3e19 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap @@ -41,6 +41,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap index 16cb9276..aa308679 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap @@ -42,6 +42,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap index f80864c1..a895910a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap @@ -34,6 +34,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap index a8b46d9e..dfa6bcbf 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap @@ -35,6 +35,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__override_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__override_layout_plugin_command.snap index 0320d754..30e9d8ce 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__override_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__override_layout_plugin_command.snap @@ -2188,6 +2188,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap index 1d353741..b642064f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap index f36650ad..5f3a7d70 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap index 9c2e4f17..78bfe2ab 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap index 014f7cc4..bde1eaee 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap index 6baf42fb..2c279b00 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap @@ -36,6 +36,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap index 6d88c8d0..ff67468d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap @@ -26,6 +26,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap index 4c7953f5..b3fb351f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap @@ -38,6 +38,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap index 12b26384..19ecd531 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap @@ -17,6 +17,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap index c933f52e..3634bac2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap @@ -19,6 +19,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap index 94413d72..a43ab56a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap index cfb58f3f..3f536271 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap index b67d5e30..5b110d01 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap index 6c38598a..a76af090 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap index 90f7008d..c116da80 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap index 5f65db08..b63fe174 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap @@ -21,6 +21,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap index 5971b313..e9986253 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap @@ -17,6 +17,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap index 2f553d6c..531c882b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap @@ -24,6 +24,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap index 5f9f524c..90ad25e0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap @@ -23,6 +23,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap index c847c31b..0fab6fed 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap @@ -27,6 +27,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap index cbd966d3..056365a7 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap @@ -27,6 +27,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap index 3e1f9e71..6180f6fa 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap @@ -333,6 +333,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap index 93ca8b8a..69d8616b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap index ec786521..e2998b4d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap index c966e97a..f8fc7c47 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap index ad86b0d8..86104bb4 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap @@ -11,6 +11,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap index da58b12e..2c355cb5 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap index 9218fe37..870abd96 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap index 41665cf2..fc24b7f8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap @@ -12,6 +12,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap index 78e0286e..0a7ab0e9 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap @@ -19,6 +19,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_to_pane_id_plugin_command.snap index 7a1ccab1..9c071f78 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_to_pane_id_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_to_pane_id_plugin_command.snap @@ -20,6 +20,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap index 78e0286e..0a7ab0e9 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap @@ -19,6 +19,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_to_pane_id_plugin_command.snap index 90209815..1ee5dfad 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_to_pane_id_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_to_pane_id_plugin_command.snap @@ -19,6 +19,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index ea19402e..d6b3b48e 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -45,6 +45,7 @@ pub struct ActionCompletionResult { pub exit_status: Option<i32>, pub affected_pane_id: Option<PaneId>, pub affected_tab_id: Option<usize>, + pub error_message: Option<String>, } pub fn wait_for_action_completion( @@ -63,6 +64,7 @@ pub fn wait_for_action_completion( exit_status: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, } }, } @@ -82,6 +84,7 @@ pub fn wait_for_action_completion( exit_status: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, } }, } @@ -101,6 +104,7 @@ pub struct NotificationEnd { unblock_condition: Option<UnblockCondition>, affected_pane_id: Option<PaneId>, // optional payload of the pane id affected by this action affected_tab_id: Option<usize>, // optional payload of the tab id affected by this action + error_message: Option<String>, } impl Clone for NotificationEnd { @@ -112,6 +116,7 @@ impl Clone for NotificationEnd { unblock_condition: self.unblock_condition, affected_pane_id: self.affected_pane_id, affected_tab_id: self.affected_tab_id, + error_message: self.error_message.clone(), } } } @@ -124,6 +129,7 @@ impl NotificationEnd { unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, } } @@ -137,6 +143,7 @@ impl NotificationEnd { unblock_condition: Some(unblock_condition), affected_pane_id: None, affected_tab_id: None, + error_message: None, } } @@ -152,6 +159,10 @@ impl NotificationEnd { self.affected_tab_id = Some(tab_id); } + pub fn set_error_message(&mut self, message: String) { + self.error_message = Some(message); + } + pub fn unblock_condition(&self) -> Option<UnblockCondition> { self.unblock_condition } @@ -164,6 +175,7 @@ impl Drop for NotificationEnd { exit_status: self.exit_status, affected_pane_id: self.affected_pane_id, affected_tab_id: self.affected_tab_id, + error_message: self.error_message.take(), }; let _ = tx.send(result); } @@ -1795,9 +1807,232 @@ pub(crate) fn route_action( }) .with_context(err_context)?; }, + // Pane-targeting CLI-only variants + Action::ScrollUpByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ScrollUpWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ScrollDownByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ScrollDownWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ScrollToTopByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ScrollToTopWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ScrollToBottomByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ScrollToBottomWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::PageScrollUpByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::PageScrollUpWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::PageScrollDownByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::PageScrollDownWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::HalfPageScrollUpByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::HalfPageScrollUpWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::HalfPageScrollDownByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::HalfPageScrollDownWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ResizeByPaneId { + pane_id, + resize, + direction, + } => { + let resize_strategy = ResizeStrategy::new(resize, direction); + senders + .send_to_screen(ScreenInstruction::ResizeWithPaneId( + pane_id.into(), + resize_strategy, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::MovePaneByPaneId { pane_id, direction } => { + senders + .send_to_screen(ScreenInstruction::MovePaneWithPaneIdCli( + pane_id.into(), + direction, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::MovePaneBackwardsByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::MovePaneBackwardsWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ClearScreenByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ClearScreenWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::EditScrollbackByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::EditScrollbackWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ToggleFocusFullscreenByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::ToggleFullscreenWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::TogglePaneEmbedOrFloatingByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::TogglePaneEmbedOrFloatingWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::CloseFocusByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::CloseFocusWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::RenamePaneByPaneId { pane_id, name } => { + senders + .send_to_screen(ScreenInstruction::RenamePaneWithPaneId( + pane_id.into(), + name, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::UndoRenamePaneByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::UndoRenamePaneWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::TogglePanePinnedByPaneId { pane_id } => { + senders + .send_to_screen(ScreenInstruction::TogglePanePinnedWithPaneId( + pane_id.into(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + // Tab-targeting CLI-only variants + Action::UndoRenameTabByTabId { id } => { + senders + .send_to_screen(ScreenInstruction::UndoRenameTabWithTabId( + id as usize, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ToggleActiveSyncTabByTabId { id } => { + senders + .send_to_screen(ScreenInstruction::ToggleActiveSyncTabWithTabId( + id as usize, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::ToggleFloatingPanesByTabId { id } => { + senders + .send_to_screen(ScreenInstruction::ToggleFloatingPanesWithTabId( + id as usize, + default_shell.clone(), + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::PreviousSwapLayoutByTabId { id } => { + senders + .send_to_screen(ScreenInstruction::PreviousSwapLayoutWithTabId( + id as usize, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::NextSwapLayoutByTabId { id } => { + senders + .send_to_screen(ScreenInstruction::NextSwapLayoutWithTabId( + id as usize, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, + Action::MoveTabByTabId { id, direction } => { + senders + .send_to_screen(ScreenInstruction::MoveTabWithTabId( + id as usize, + direction, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, } let result = wait_for_action_completion(completion_rx, &action_name, wait_forever); - if let Some(exit_status) = result.exit_status { + if let Some(error_message) = &result.error_message { + if let Some(cli_client_id) = cli_client_id { + if let Some(ref os_input) = os_input { + let _ = os_input.send_to_client( + cli_client_id, + ServerToClientMsg::LogError { + lines: vec![error_message.clone()], + }, + ); + } + } + } else if let Some(exit_status) = result.exit_status { if let Some(cli_client_id) = cli_client_id { if let Some(ref os_input) = os_input { let _ = os_input.send_to_client( @@ -2857,6 +3092,7 @@ mod tests { exit_status: None, affected_pane_id: None, affected_tab_id: Some(123), + error_message: None, }; assert_eq!(result.affected_tab_id, Some(123)); diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 565aa8b9..0b90c7f9 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -700,6 +700,33 @@ pub enum ScreenInstruction { NotifyPaneClosedToSubscribers { pane_id: zellij_utils::data::PaneId, }, + // Pane-targeting CLI variants + ScrollUpWithPaneId(PaneId, Option<NotificationEnd>), + ScrollDownWithPaneId(PaneId, Option<NotificationEnd>), + ScrollToTopWithPaneId(PaneId, Option<NotificationEnd>), + ScrollToBottomWithPaneId(PaneId, Option<NotificationEnd>), + PageScrollUpWithPaneId(PaneId, Option<NotificationEnd>), + PageScrollDownWithPaneId(PaneId, Option<NotificationEnd>), + HalfPageScrollUpWithPaneId(PaneId, Option<NotificationEnd>), + HalfPageScrollDownWithPaneId(PaneId, Option<NotificationEnd>), + ResizeWithPaneId(PaneId, ResizeStrategy, Option<NotificationEnd>), + MovePaneWithPaneIdCli(PaneId, Option<Direction>, Option<NotificationEnd>), + MovePaneBackwardsWithPaneId(PaneId, Option<NotificationEnd>), + ClearScreenWithPaneId(PaneId, Option<NotificationEnd>), + EditScrollbackWithPaneId(PaneId, Option<NotificationEnd>), + ToggleFullscreenWithPaneId(PaneId, Option<NotificationEnd>), + TogglePaneEmbedOrFloatingWithPaneId(PaneId, Option<NotificationEnd>), + CloseFocusWithPaneId(PaneId, Option<NotificationEnd>), + RenamePaneWithPaneId(PaneId, Vec<u8>, Option<NotificationEnd>), + UndoRenamePaneWithPaneId(PaneId, Option<NotificationEnd>), + TogglePanePinnedWithPaneId(PaneId, Option<NotificationEnd>), + // Tab-targeting CLI variants + UndoRenameTabWithTabId(usize, Option<NotificationEnd>), + ToggleActiveSyncTabWithTabId(usize, Option<NotificationEnd>), + ToggleFloatingPanesWithTabId(usize, Option<TerminalAction>, Option<NotificationEnd>), + PreviousSwapLayoutWithTabId(usize, Option<NotificationEnd>), + NextSwapLayoutWithTabId(usize, Option<NotificationEnd>), + MoveTabWithTabId(usize, Direction, Option<NotificationEnd>), } impl From<&ScreenInstruction> for ScreenContext { @@ -975,6 +1002,61 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::NotifyPaneClosedToSubscribers { .. } => { ScreenContext::NotifyPaneClosedToSubscribers }, + // Pane-targeting CLI variants + ScreenInstruction::ScrollUpWithPaneId(..) => ScreenContext::ScrollUpWithPaneId, + ScreenInstruction::ScrollDownWithPaneId(..) => ScreenContext::ScrollDownWithPaneId, + ScreenInstruction::ScrollToTopWithPaneId(..) => ScreenContext::ScrollToTopWithPaneId, + ScreenInstruction::ScrollToBottomWithPaneId(..) => { + ScreenContext::ScrollToBottomWithPaneId + }, + ScreenInstruction::PageScrollUpWithPaneId(..) => ScreenContext::PageScrollUpWithPaneId, + ScreenInstruction::PageScrollDownWithPaneId(..) => { + ScreenContext::PageScrollDownWithPaneId + }, + ScreenInstruction::HalfPageScrollUpWithPaneId(..) => { + ScreenContext::HalfPageScrollUpWithPaneId + }, + ScreenInstruction::HalfPageScrollDownWithPaneId(..) => { + ScreenContext::HalfPageScrollDownWithPaneId + }, + ScreenInstruction::ResizeWithPaneId(..) => ScreenContext::ResizeWithPaneId, + ScreenInstruction::MovePaneWithPaneIdCli(..) => ScreenContext::MovePaneWithPaneIdCli, + ScreenInstruction::MovePaneBackwardsWithPaneId(..) => { + ScreenContext::MovePaneBackwardsWithPaneId + }, + ScreenInstruction::ClearScreenWithPaneId(..) => ScreenContext::ClearScreenWithPaneId, + ScreenInstruction::EditScrollbackWithPaneId(..) => { + ScreenContext::EditScrollbackWithPaneId + }, + ScreenInstruction::ToggleFullscreenWithPaneId(..) => { + ScreenContext::ToggleFullscreenWithPaneId + }, + ScreenInstruction::TogglePaneEmbedOrFloatingWithPaneId(..) => { + ScreenContext::TogglePaneEmbedOrFloatingWithPaneId + }, + ScreenInstruction::CloseFocusWithPaneId(..) => ScreenContext::CloseFocusWithPaneId, + ScreenInstruction::RenamePaneWithPaneId(..) => ScreenContext::RenamePaneWithPaneId, + ScreenInstruction::UndoRenamePaneWithPaneId(..) => { + ScreenContext::UndoRenamePaneWithPaneId + }, + ScreenInstruction::TogglePanePinnedWithPaneId(..) => { + ScreenContext::TogglePanePinnedWithPaneId + }, + // Tab-targeting CLI variants + ScreenInstruction::UndoRenameTabWithTabId(..) => ScreenContext::UndoRenameTabWithTabId, + ScreenInstruction::ToggleActiveSyncTabWithTabId(..) => { + ScreenContext::ToggleActiveSyncTabWithTabId + }, + ScreenInstruction::ToggleFloatingPanesWithTabId(..) => { + ScreenContext::ToggleFloatingPanesWithTabId + }, + ScreenInstruction::PreviousSwapLayoutWithTabId(..) => { + ScreenContext::PreviousSwapLayoutWithTabId + }, + ScreenInstruction::NextSwapLayoutWithTabId(..) => { + ScreenContext::NextSwapLayoutWithTabId + }, + ScreenInstruction::MoveTabWithTabId(..) => ScreenContext::MoveTabWithTabId, } } } @@ -2133,6 +2215,7 @@ impl Screen { let mut completion = completion; if let Some(c) = completion.as_mut() { c.set_exit_status(1); + c.set_error_message("Tab not found".to_string()); } drop(completion); }, @@ -2156,6 +2239,7 @@ impl Screen { let mut completion = completion; if let Some(c) = completion.as_mut() { c.set_exit_status(1); + c.set_error_message("Tab not found".to_string()); } drop(completion); }, @@ -2945,6 +3029,31 @@ impl Screen { Ok(()) } + pub fn move_tab_by_id(&mut self, tab_id: usize, direction: Direction) -> Result<()> { + if self.tabs.len() < 2 { + return Ok(()); + } + if let Some(tab) = self.tabs.get(&tab_id) { + let tab_pos = tab.position; + let swap_pos = match direction { + Direction::Left => { + if tab_pos == 0 { + self.tabs.len() - 1 + } else { + tab_pos - 1 + } + }, + Direction::Right => (tab_pos + 1) % self.tabs.len(), + _ => return Ok(()), + }; + self.switch_tabs(tab_pos, swap_pos); + self.log_and_report_session_state()?; + } else { + log::error!("Tab with id {} not found", tab_id); + } + Ok(()) + } + pub fn change_mode(&mut self, mut mode_info: ModeInfo, client_id: ClientId) -> Result<()> { if mode_info.session_name.as_ref() != Some(&self.session_name) { mode_info.session_name = Some(self.session_name.clone()); @@ -5019,116 +5128,148 @@ pub(crate) fn screen_thread_main( screen.render(None)?; screen.log_and_report_session_state()?; }, - ScreenInstruction::FocusNextPane( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.focus_next_pane(client_id) - ); - screen.render(None)?; + ScreenInstruction::FocusNextPane(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to change focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to change focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.focus_next_pane(client_id) + ); + screen.render(None)?; + } }, - ScreenInstruction::FocusPreviousPane( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.focus_previous_pane(client_id) - ); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::FocusPreviousPane(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to change focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to change focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.focus_previous_pane(client_id) + ); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusLeft( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.move_focus_left(client_id), - ? - ); - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusLeft(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.move_focus_left(client_id), + ? + ); + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusLeftOrPreviousTab( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - screen.move_focus_left_or_previous_tab(client_id)?; - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusLeftOrPreviousTab(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + screen.move_focus_left_or_previous_tab(client_id)?; + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusDown( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.move_focus_down(client_id), - ? - ); - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusDown(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.move_focus_down(client_id), + ? + ); + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusRight( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.move_focus_right(client_id), - ? - ); - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusRight(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.move_focus_right(client_id), + ? + ); + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusRightOrNextTab( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - screen.move_focus_right_or_next_tab(client_id)?; - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusRightOrNextTab(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + screen.move_focus_right_or_next_tab(client_id)?; + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, - ScreenInstruction::MoveFocusUp( - client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.move_focus_up(client_id), - ? - ); - screen.clear_bell_for_focused_pane(client_id); - screen.add_active_pane_to_group_if_marking(&client_id); - screen.render(None)?; - screen.log_and_report_session_state()?; + ScreenInstruction::MoveFocusUp(client_id, mut _completion_tx) => { + if screen.get_first_client_id().is_none() { + log::error!("No connected clients to move focus for"); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message("No connected clients to move focus for".to_string()); + } + } else { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab.move_focus_up(client_id), + ? + ); + screen.clear_bell_for_focused_pane(client_id); + screen.add_active_pane_to_group_if_marking(&client_id); + screen.render(None)?; + screen.log_and_report_session_state()?; + } }, ScreenInstruction::ClearScreen( client_id, @@ -8082,6 +8223,457 @@ pub(crate) fn screen_thread_main( ScreenInstruction::NotifyPaneClosedToSubscribers { pane_id } => { screen.notify_pane_closed_to_subscribers(pane_id); }, + // Pane-targeting CLI handlers + ScreenInstruction::ScrollUpWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.scroll_up_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::ScrollDownWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.scroll_down_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::ScrollToTopWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.scroll_to_top_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::ScrollToBottomWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.scroll_to_bottom_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::PageScrollUpWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.page_scroll_up_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::PageScrollDownWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.page_scroll_down_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::HalfPageScrollUpWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.half_page_scroll_up_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::HalfPageScrollDownWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.half_page_scroll_down_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::ResizeWithPaneId(pane_id, strategy, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.resize_by_pane_id(pane_id, strategy); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::MovePaneWithPaneIdCli(pane_id, direction, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.move_pane_by_pane_id(pane_id, direction); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::MovePaneBackwardsWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.move_pane_backwards_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::ClearScreenWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.clear_screen_by_pane_id(pane_id).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::EditScrollbackWithPaneId(pane_id, completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.edit_scrollback_for_pane_with_id(pane_id, completion_tx) + .non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + } + screen.render(None)?; + }, + ScreenInstruction::ToggleFullscreenWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.toggle_fullscreen_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::TogglePaneEmbedOrFloatingWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.toggle_pane_embed_or_floating_for_pane_id(pane_id, None) + .non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.log_and_report_session_state()?; + screen.render(None)?; + }, + ScreenInstruction::CloseFocusWithPaneId(pane_id, completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.close_pane_by_pane_id(pane_id, completion_tx) + .non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::RenamePaneWithPaneId(pane_id, name, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.rename_pane_by_pane_id(pane_id, name).non_fatal(); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::UndoRenamePaneWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.undo_rename_pane_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::TogglePanePinnedWithPaneId(pane_id, mut _completion_tx) => { + let all_tabs = screen.get_tabs_mut(); + let mut found = false; + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.toggle_pane_pinned_by_pane_id(pane_id); + found = true; + break; + } + } + if !found { + log::error!("Pane with id {:?} not found", pane_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Pane with id {:?} not found", pane_id)); + } + } + }, + // Tab-targeting CLI handlers + ScreenInstruction::UndoRenameTabWithTabId(tab_id, mut _completion_tx) => { + if let Some(tab) = screen.tabs.get_mut(&tab_id) { + if tab.name != tab.prev_name { + tab.name = tab.prev_name.clone(); + screen.log_and_report_session_state()?; + } + } else { + log::error!("Tab with id {} not found", tab_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Tab with id {} not found", tab_id)); + } + } + screen.render(None)?; + }, + ScreenInstruction::ToggleActiveSyncTabWithTabId(tab_id, mut _completion_tx) => { + if let Some(tab) = screen.tabs.get_mut(&tab_id) { + tab.toggle_sync_panes_is_active(); + } else { + log::error!("Tab with id {} not found", tab_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Tab with id {} not found", tab_id)); + } + } + screen.log_and_report_session_state()?; + screen.render(None)?; + }, + ScreenInstruction::ToggleFloatingPanesWithTabId( + tab_id, + default_shell, + mut completion_tx, + ) => { + if let Some(tab) = screen.tabs.get_mut(&tab_id) { + // Pass None as client_id so that if a new floating pane must be spawned, + // it targets this tab (via TabIndex) rather than the focused tab of some client. + tab.toggle_floating_panes(None, default_shell, completion_tx) + .non_fatal(); + } else { + log::error!("Tab with id {} not found", tab_id); + if let Some(ref mut c) = completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Tab with id {} not found", tab_id)); + } + drop(completion_tx); + } + screen.log_and_report_session_state()?; + screen.render(None)?; + }, + ScreenInstruction::PreviousSwapLayoutWithTabId(tab_id, mut _completion_tx) => { + if let Some(tab) = screen.tabs.get_mut(&tab_id) { + tab.previous_swap_layout().non_fatal(); + } else { + log::error!("Tab with id {} not found", tab_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Tab with id {} not found", tab_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::NextSwapLayoutWithTabId(tab_id, mut _completion_tx) => { + if let Some(tab) = screen.tabs.get_mut(&tab_id) { + tab.next_swap_layout().non_fatal(); + } else { + log::error!("Tab with id {} not found", tab_id); + if let Some(ref mut c) = _completion_tx { + c.set_exit_status(1); + c.set_error_message(format!("Tab with id {} not found", tab_id)); + } + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::MoveTabWithTabId(tab_id, direction, _completion_tx) => { + if pending_tab_ids.is_empty() { + screen.move_tab_by_id(tab_id, direction)?; + screen.render(None)?; + } else { + pending_events_waiting_for_tab.push(ScreenInstruction::MoveTabWithTabId( + tab_id, + direction, + _completion_tx, + )); + } + }, } } Ok(()) diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index bcefc510..b95567c1 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -5697,6 +5697,191 @@ impl Tab { .map(|p| p.position_and_size().stacked.is_some()) .unwrap_or(false) } + // --- Pane-targeting CLI methods --- + pub fn scroll_up_by_pane_id(&mut self, pane_id: PaneId) { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.scroll_up(1, fictitious_client_id); + } + } + pub fn scroll_down_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.scroll_down(1, fictitious_client_id); + if !pane.is_scrolled() { + if let PaneId::Terminal(raw_fd) = pane.pid() { + self.process_pending_vte_events(raw_fd)?; + } + } + } + Ok(()) + } + pub fn scroll_to_top_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.clear_scroll(); + if let Some(size) = pane.get_line_number() { + pane.scroll_up(size, fictitious_client_id); + } + } + Ok(()) + } + pub fn scroll_to_bottom_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.clear_scroll(); + if !pane.is_scrolled() { + if let PaneId::Terminal(raw_fd) = pane.pid() { + self.process_pending_vte_events(raw_fd)?; + } + } + } + Ok(()) + } + pub fn page_scroll_up_by_pane_id(&mut self, pane_id: PaneId) { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + let scroll_rows = pane.rows().max(1).saturating_sub(1); + pane.scroll_up(scroll_rows, fictitious_client_id); + } + } + pub fn page_scroll_down_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + let scroll_rows = pane.get_content_rows(); + pane.scroll_down(scroll_rows, fictitious_client_id); + if !pane.is_scrolled() { + if let PaneId::Terminal(raw_fd) = pane.pid() { + self.process_pending_vte_events(raw_fd)?; + } + } + } + Ok(()) + } + pub fn half_page_scroll_up_by_pane_id(&mut self, pane_id: PaneId) { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + let scroll_rows = (pane.rows().max(1).saturating_sub(1)) / 2; + pane.scroll_up(scroll_rows, fictitious_client_id); + } + } + pub fn half_page_scroll_down_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + let fictitious_client_id = 1; + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + let scroll_rows = (pane.rows().max(1).saturating_sub(1)) / 2; + pane.scroll_down(scroll_rows, fictitious_client_id); + if !pane.is_scrolled() { + if let PaneId::Terminal(raw_fd) = pane.pid() { + self.process_pending_vte_events(raw_fd)?; + } + } + } + Ok(()) + } + pub fn resize_by_pane_id(&mut self, pane_id: PaneId, strategy: ResizeStrategy) { + self.resize_pane_with_id(strategy, pane_id).non_fatal(); + } + pub fn move_pane_by_pane_id(&mut self, pane_id: PaneId, direction: Option<Direction>) { + if !self.has_selectable_panes() { + return; + } + if self.tiled_panes.fullscreen_is_active() { + return; + } + match direction { + Some(Direction::Left) => { + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane_left(pane_id); + self.swap_layouts.set_is_floating_damaged(); + self.set_force_render(); + } else { + self.tiled_panes.move_pane_left(pane_id); + } + }, + Some(Direction::Right) => { + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane_right(pane_id); + self.swap_layouts.set_is_floating_damaged(); + self.set_force_render(); + } else { + self.tiled_panes.move_pane_right(pane_id); + } + }, + Some(Direction::Up) => { + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane_up(pane_id); + self.swap_layouts.set_is_floating_damaged(); + self.set_force_render(); + } else { + self.tiled_panes.move_pane_up(pane_id); + } + }, + Some(Direction::Down) => { + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane_down(pane_id); + self.swap_layouts.set_is_floating_damaged(); + self.set_force_render(); + } else { + self.tiled_panes.move_pane_down(pane_id); + } + }, + None => { + let search_backwards = false; + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane(search_backwards, pane_id); + } else { + self.tiled_panes.move_pane(search_backwards, pane_id); + } + }, + } + } + pub fn move_pane_backwards_by_pane_id(&mut self, pane_id: PaneId) { + if !self.has_selectable_panes() { + return; + } + if self.tiled_panes.fullscreen_is_active() { + return; + } + let search_backwards = true; + if self.floating_panes.panes_contain(&pane_id) { + self.floating_panes.move_pane(search_backwards, pane_id); + } else { + self.tiled_panes.move_pane(search_backwards, pane_id); + } + } + pub fn clear_screen_by_pane_id(&mut self, pane_id: PaneId) -> Result<()> { + self.clear_screen_for_pane_id(pane_id); + Ok(()) + } + pub fn toggle_fullscreen_by_pane_id(&mut self, pane_id: PaneId) { + self.toggle_pane_fullscreen(pane_id); + } + pub fn close_pane_by_pane_id( + &mut self, + pane_id: PaneId, + completion_tx: Option<NotificationEnd>, + ) -> Result<()> { + self.close_pane(pane_id, false, None); + self.senders + .send_to_pty(PtyInstruction::ClosePane(pane_id, completion_tx))?; + Ok(()) + } + pub fn rename_pane_by_pane_id(&mut self, pane_id: PaneId, name: Vec<u8>) -> Result<()> { + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.rename(name); + } + Ok(()) + } + pub fn undo_rename_pane_by_pane_id(&mut self, pane_id: PaneId) { + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.load_pane_name(); + } + } + pub fn toggle_pane_pinned_by_pane_id(&mut self, pane_id: PaneId) { + if let Some(pane) = self.get_pane_with_id_mut(pane_id) { + pane.toggle_pinned(); + self.set_force_render(); + } + } } pub fn pane_info_for_pane( diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 00444c4a..363786f0 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -15340,3 +15340,250 @@ pub fn clearing_last_pane_bell_clears_tab_bell() { "tab_has_pending_bell should be false after last pane bell cleared" ); } + +// Category 5: pane-id-based operations + +#[test] +pub fn scroll_up_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.scroll_up_by_pane_id(pane_id); +} + +#[test] +pub fn scroll_down_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.scroll_down_by_pane_id(pane_id); +} + +#[test] +pub fn scroll_to_top_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.scroll_to_top_by_pane_id(pane_id); +} + +#[test] +pub fn scroll_to_bottom_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.scroll_to_bottom_by_pane_id(pane_id); +} + +#[test] +pub fn page_scroll_up_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.page_scroll_up_by_pane_id(pane_id); +} + +#[test] +pub fn page_scroll_down_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.page_scroll_down_by_pane_id(pane_id); +} + +#[test] +pub fn half_page_scroll_up_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.half_page_scroll_up_by_pane_id(pane_id); +} + +#[test] +pub fn half_page_scroll_down_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.half_page_scroll_down_by_pane_id(pane_id); +} + +#[test] +pub fn rename_pane_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.rename_pane_by_pane_id(pane_id, "new-name".as_bytes().to_vec()); +} + +#[test] +pub fn undo_rename_pane_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.rename_pane_by_pane_id(pane_id, "new-name".as_bytes().to_vec()); + tab.undo_rename_pane_by_pane_id(pane_id); +} + +#[test] +pub fn close_pane_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let stacked_resize = true; + let mut tab = create_new_tab(size, stacked_resize); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id, None, 1, None, None) + .unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 2); + tab.close_pane_by_pane_id(new_pane_id, None).unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 1); + assert!(!tab.has_pane_with_pid(&new_pane_id)); +} + +#[test] +pub fn resize_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id, None, 1, None, None) + .unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 2); + tab.resize_by_pane_id( + new_pane_id, + ResizeStrategy::new(Resize::Increase, Some(Direction::Down)), + ); +} + +#[test] +pub fn toggle_fullscreen_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id, None, 1, None, None) + .unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 2); + tab.toggle_fullscreen_by_pane_id(new_pane_id); +} + +#[test] +pub fn move_pane_by_pane_id_down() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id, None, 1, None, None) + .unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 2); + tab.move_pane_by_pane_id(new_pane_id, Some(Direction::Down)); +} + +#[test] +pub fn move_pane_backwards_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id, None, 1, None, None) + .unwrap(); + assert_eq!(tab.tiled_panes.panes.len(), 2); + tab.move_pane_backwards_by_pane_id(new_pane_id); +} + +#[test] +pub fn clear_screen_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.clear_screen_by_pane_id(pane_id); +} + +#[test] +pub fn toggle_pane_embed_or_floating_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + let _ = tab.toggle_pane_embed_or_floating_for_pane_id(pane_id, None); +} + +#[test] +pub fn toggle_pane_pinned_by_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(1); + assert!(tab.has_pane_with_pid(&pane_id)); + tab.toggle_pane_pinned_by_pane_id(pane_id); +} + +#[test] +pub fn scroll_up_nonexistent_pane_id_does_not_panic() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut tab = create_new_tab(size, true); + let pane_id = PaneId::Terminal(999); + assert!(!tab.has_pane_with_pid(&pane_id)); + tab.scroll_up_by_pane_id(pane_id); +} diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 49dbeb5d..1bbe2479 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -2233,6 +2233,7 @@ pub fn send_cli_resize_action_to_screen() { let resize_cli_action = CliAction::Resize { resize: Resize::Increase, direction: Some(Direction::Left), + pane_id: None, }; std::thread::sleep(std::time::Duration::from_millis(100)); // give time for the async render send_cli_action_to_server(&session_metadata, resize_cli_action, client_id); @@ -2404,6 +2405,7 @@ pub fn send_cli_move_pane_action() { ); let cli_action = CliAction::MovePane { direction: Some(Direction::Right), + pane_id: None, }; send_cli_action_to_server(&session_metadata, cli_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -2471,7 +2473,7 @@ pub fn send_cli_edit_scrollback_action() { PtyInstruction::Exit, pty_receiver ); - let cli_action = CliAction::EditScrollback; + let cli_action = CliAction::EditScrollback { pane_id: None }; let _ = mock_screen.to_screen.send(ScreenInstruction::PtyBytes( 0, "fill pane up with something".as_bytes().to_vec(), @@ -2523,7 +2525,7 @@ pub fn send_cli_scroll_up_action() { ServerInstruction::KillSession, server_receiver ); - let cli_action = CliAction::ScrollUp; + let cli_action = CliAction::ScrollUp { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2567,8 +2569,8 @@ pub fn send_cli_scroll_down_action() { ServerInstruction::KillSession, server_receiver ); - let scroll_up_cli_action = CliAction::ScrollUp; - let scroll_down_cli_action = CliAction::ScrollDown; + let scroll_up_cli_action = CliAction::ScrollUp { pane_id: None }; + let scroll_down_cli_action = CliAction::ScrollDown { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2614,8 +2616,8 @@ pub fn send_cli_scroll_to_bottom_action() { ServerInstruction::KillSession, server_receiver ); - let scroll_up_cli_action = CliAction::ScrollUp; - let scroll_to_bottom_action = CliAction::ScrollToBottom; + let scroll_up_cli_action = CliAction::ScrollUp { pane_id: None }; + let scroll_to_bottom_action = CliAction::ScrollToBottom { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2664,7 +2666,7 @@ pub fn send_cli_scroll_to_top_action() { ServerInstruction::KillSession, server_receiver ); - let scroll_to_top_action = CliAction::ScrollToTop; + let scroll_to_top_action = CliAction::ScrollToTop { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2706,7 +2708,7 @@ pub fn send_cli_page_scroll_up_action() { ServerInstruction::KillSession, server_receiver ); - let page_scroll_up_action = CliAction::PageScrollUp; + let page_scroll_up_action = CliAction::PageScrollUp { pane_id: None }; let mut pane_contents = String::new(); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for the async render for i in 0..20 { @@ -2748,8 +2750,8 @@ pub fn send_cli_page_scroll_down_action() { ServerInstruction::KillSession, server_receiver ); - let page_scroll_up_action = CliAction::PageScrollUp; - let page_scroll_down_action = CliAction::PageScrollDown; + let page_scroll_up_action = CliAction::PageScrollUp { pane_id: None }; + let page_scroll_down_action = CliAction::PageScrollDown { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2800,7 +2802,7 @@ pub fn send_cli_half_page_scroll_up_action() { ServerInstruction::KillSession, server_receiver ); - let half_page_scroll_up_action = CliAction::HalfPageScrollUp; + let half_page_scroll_up_action = CliAction::HalfPageScrollUp { pane_id: None }; let mut pane_contents = String::new(); for i in 0..20 { pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); @@ -2841,8 +2843,8 @@ pub fn send_cli_half_page_scroll_down_action() { ServerInstruction::KillSession, server_receiver ); - let half_page_scroll_up_action = CliAction::HalfPageScrollUp; - let half_page_scroll_down_action = CliAction::HalfPageScrollDown; + let half_page_scroll_up_action = CliAction::HalfPageScrollUp { pane_id: None }; + let half_page_scroll_down_action = CliAction::HalfPageScrollDown { pane_id: None }; let mut pane_contents = String::new(); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for the async render for i in 0..20 { @@ -2900,7 +2902,7 @@ pub fn send_cli_toggle_full_screen_action() { ServerInstruction::KillSession, server_receiver ); - let toggle_full_screen_action = CliAction::ToggleFullscreen; + let toggle_full_screen_action = CliAction::ToggleFullscreen { pane_id: None }; send_cli_action_to_server(&session_metadata, toggle_full_screen_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); mock_screen.teardown(vec![server_instruction, screen_thread]); @@ -2967,7 +2969,7 @@ pub fn send_cli_toggle_active_tab_sync_action() { PtyWriteInstruction::Exit, pty_writer_receiver ); - let cli_toggle_active_tab_sync_action = CliAction::ToggleActiveSyncTab; + let cli_toggle_active_tab_sync_action = CliAction::ToggleActiveSyncTab { tab_id: None }; let cli_write_action = CliAction::Write { bytes: vec![102, 111, 111], pane_id: None, @@ -3384,7 +3386,7 @@ pub fn send_cli_toggle_pane_embed_or_float() { ServerInstruction::KillSession, server_receiver ); - let toggle_pane_embed_or_floating = CliAction::TogglePaneEmbedOrFloating; + let toggle_pane_embed_or_floating = CliAction::TogglePaneEmbedOrFloating { pane_id: None }; // first time to float send_cli_action_to_server( &session_metadata, @@ -3435,8 +3437,8 @@ pub fn send_cli_toggle_floating_panes() { ServerInstruction::KillSession, server_receiver ); - let toggle_pane_embed_or_floating = CliAction::TogglePaneEmbedOrFloating; - let toggle_floating_panes = CliAction::ToggleFloatingPanes; + let toggle_pane_embed_or_floating = CliAction::TogglePaneEmbedOrFloating { pane_id: None }; + let toggle_floating_panes = CliAction::ToggleFloatingPanes { tab_id: None }; // float the focused pane send_cli_action_to_server(&session_metadata, toggle_pane_embed_or_floating, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -3476,7 +3478,7 @@ pub fn send_cli_close_pane_action() { ServerInstruction::KillSession, server_receiver ); - let close_pane_action = CliAction::ClosePane; + let close_pane_action = CliAction::ClosePane { pane_id: None }; send_cli_action_to_server(&session_metadata, close_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); mock_screen.teardown(vec![server_instruction, screen_thread]); @@ -3722,7 +3724,7 @@ pub fn send_cli_close_tab_action() { ServerInstruction::KillSession, server_receiver ); - let close_tab = CliAction::CloseTab; + let close_tab = CliAction::CloseTab { tab_id: None }; send_cli_action_to_server(&session_metadata, close_tab, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); mock_screen.teardown(vec![server_thread, screen_thread]); @@ -3760,6 +3762,7 @@ pub fn send_cli_rename_tab() { ); let rename_tab = CliAction::RenameTab { name: "new-tab-name".into(), + tab_id: None, }; send_cli_action_to_server(&session_metadata, rename_tab, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -3805,8 +3808,9 @@ pub fn send_cli_undo_rename_tab() { ); let rename_tab = CliAction::RenameTab { name: "new-tab-name".into(), + tab_id: None, }; - let undo_rename_tab = CliAction::UndoRenameTab; + let undo_rename_tab = CliAction::UndoRenameTab { tab_id: None }; // first rename the tab send_cli_action_to_server(&session_metadata, rename_tab, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -6088,3 +6092,845 @@ fn integration_subscriber_survives_after_regular_client_detach() { subscriber_msgs ); } + +// ========================================== +// Category 3: MockScreen end-to-end CLI tests +// ========================================== + +#[test] +pub fn send_cli_scroll_up_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ScrollUp { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ScrollUp with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_scroll_down_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ScrollDown { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ScrollDown with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_scroll_to_top_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ScrollToTop { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ScrollToTop with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_scroll_to_bottom_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ScrollToBottom { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ScrollToBottom with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_page_scroll_up_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::PageScrollUp { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "PageScrollUp with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_page_scroll_down_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::PageScrollDown { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "PageScrollDown with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_half_page_scroll_up_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::HalfPageScrollUp { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "HalfPageScrollUp with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_half_page_scroll_down_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::HalfPageScrollDown { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "HalfPageScrollDown with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_resize_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::Resize { + resize: Resize::Increase, + direction: Some(Direction::Left), + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "Resize with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_move_pane_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::MovePane { + direction: Some(Direction::Right), + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "MovePane with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_move_pane_backwards_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::MovePaneBackwards { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "MovePaneBackwards with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_clear_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::Clear { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "Clear with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_edit_scrollback_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::EditScrollback { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "EditScrollback with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_toggle_fullscreen_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ToggleFullscreen { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ToggleFullscreen with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_toggle_pane_embed_or_floating_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::TogglePaneEmbedOrFloating { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "TogglePaneEmbedOrFloating with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_close_pane_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let mut initial_layout = TiledPaneLayout::default(); + initial_layout.children_split_direction = SplitDirection::Vertical; + initial_layout.children = vec![TiledPaneLayout::default(), TiledPaneLayout::default()]; + let screen_thread = mock_screen.run(Some(initial_layout), vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ClosePane { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ClosePane with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_rename_pane_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::RenamePane { + name: "targeted-name".to_string(), + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "RenamePane with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_undo_rename_pane_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::UndoRenamePane { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "UndoRenamePane with pane_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_toggle_pane_pinned_with_pane_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::TogglePanePinned { + pane_id: Some("terminal_0".to_string()), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "TogglePanePinned with pane_id CLI action completed without errors" + ); +} + +// TAB-TARGETING MockScreen tests + +#[test] +pub fn send_cli_close_tab_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.new_tab(TiledPaneLayout::default()); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::CloseTab { tab_id: Some(1) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "CloseTab with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_rename_tab_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.new_tab(TiledPaneLayout::default()); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::RenameTab { + name: "targeted-tab".to_string(), + tab_id: Some(1), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "RenameTab with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_undo_rename_tab_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.new_tab(TiledPaneLayout::default()); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::UndoRenameTab { tab_id: Some(0) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "UndoRenameTab with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_toggle_active_sync_tab_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ToggleActiveSyncTab { tab_id: Some(0) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ToggleActiveSyncTab with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_toggle_floating_panes_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::ToggleFloatingPanes { tab_id: Some(0) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "ToggleFloatingPanes with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_previous_swap_layout_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::PreviousSwapLayout { tab_id: Some(0) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "PreviousSwapLayout with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_next_swap_layout_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::NextSwapLayout { tab_id: Some(0) }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "NextSwapLayout with tab_id CLI action completed without errors" + ); +} + +#[test] +pub fn send_cli_move_tab_with_tab_id() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(None, vec![]); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.new_tab(TiledPaneLayout::default()); + std::thread::sleep(std::time::Duration::from_millis(100)); + let cli_action = CliAction::MoveTab { + direction: Direction::Right, + tab_id: Some(0), + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_thread, screen_thread]); + assert!( + true, + "MoveTab with tab_id CLI action completed without errors" + ); +} + +// ========================================== +// Category 4: Direct Screen method tests +// ========================================== + +#[test] +pub fn move_tab_by_id_verifies_screen_state() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut screen = create_new_screen(size, true, true); + new_tab(&mut screen, 1, 0); + new_tab(&mut screen, 2, 1); + new_tab(&mut screen, 3, 2); + let original_pos_0 = screen.get_tab_by_id(0).unwrap().position; + let original_pos_1 = screen.get_tab_by_id(1).unwrap().position; + screen.move_tab_by_id(0, Direction::Right).expect("TEST"); + assert_eq!(screen.get_tab_by_id(0).unwrap().position, original_pos_1); + assert_eq!(screen.get_tab_by_id(1).unwrap().position, original_pos_0); +} diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap index 2a2c8a4f..742f2480 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: None, borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: None, borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap index b93701a2..21195f58 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: None, borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: None, borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap index 1c61a5c4..21f4b55d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: Some(Down), borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled { direction: Some(Down), borderless: None }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_in_place_with_close_replaced_pane.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_in_place_with_close_replaced_pane.snap index 35b8f9cb..bece1bab 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_in_place_with_close_replaced_pane.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_in_place_with_close_replaced_pane.snap @@ -30,6 +30,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap index 7b3226d9..3c2a1097 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap @@ -40,6 +40,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_in_place_with_close_replaced_pane.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_in_place_with_close_replaced_pane.snap index cb65be5b..44c00845 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_in_place_with_close_replaced_pane.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_in_place_with_close_replaced_pane.snap @@ -40,6 +40,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap index 3004bba7..7434e18c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", new_pane_instruction)" --- -Some(SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Tiled { direction: Some(Right), borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false)) +Some(SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Tiled { direction: Some(Right), borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap index 345421ea..0e62cd90 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled { direction: None, borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled { direction: None, borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap index e11a9f23..c9efed6d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Floating(Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None, borderless: Some(false) })), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Floating(Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None, borderless: Some(false) })), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap index 04dde5a4..2ebc8665 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled { direction: Some(Right), borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled { direction: Some(Right), borderless: Some(false) }, false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None, affected_tab_id: None, error_message: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_in_place_with_close_replaced_pane.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_in_place_with_close_replaced_pane.snap index 209981ae..fbdfc98c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_in_place_with_close_replaced_pane.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_in_place_with_close_replaced_pane.snap @@ -31,6 +31,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap index cd39bac6..2277cd57 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3568 -expression: "format!(\"{:#?}\", new_tab_instruction)" +expression: output --- NewTab( None, @@ -113,6 +112,7 @@ NewTab( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap index e38487fa..de7276ab 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap @@ -16,6 +16,7 @@ Some( unblock_condition: None, affected_pane_id: None, affected_tab_id: None, + error_message: None, }, ), ), diff --git a/zellij-utils/assets/prost_ipc/client_server_contract.rs b/zellij-utils/assets/prost_ipc/client_server_contract.rs index c7e58bf0..3496655c 100644 --- a/zellij-utils/assets/prost_ipc/client_server_contract.rs +++ b/zellij-utils/assets/prost_ipc/client_server_contract.rs @@ -119,7 +119,7 @@ pub struct RgbColor { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Action { - #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109")] + #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134")] pub action_type: ::core::option::Option<action::ActionType>, } /// Nested message and enum types in `Action`. @@ -345,6 +345,58 @@ pub mod action { SetPaneColor(super::SetPaneColorAction), #[prost(message, tag="109")] Paste(super::PasteAction), + /// Pane-targeting + #[prost(message, tag="110")] + ScrollUpByPaneId(super::ScrollUpByPaneIdAction), + #[prost(message, tag="111")] + ScrollDownByPaneId(super::ScrollDownByPaneIdAction), + #[prost(message, tag="112")] + ScrollToTopByPaneId(super::ScrollToTopByPaneIdAction), + #[prost(message, tag="113")] + ScrollToBottomByPaneId(super::ScrollToBottomByPaneIdAction), + #[prost(message, tag="114")] + PageScrollUpByPaneId(super::PageScrollUpByPaneIdAction), + #[prost(message, tag="115")] + PageScrollDownByPaneId(super::PageScrollDownByPaneIdAction), + #[prost(message, tag="116")] + HalfPageScrollUpByPaneId(super::HalfPageScrollUpByPaneIdAction), + #[prost(message, tag="117")] + HalfPageScrollDownByPaneId(super::HalfPageScrollDownByPaneIdAction), + #[prost(message, tag="118")] + ResizeByPaneId(super::ResizeByPaneIdAction), + #[prost(message, tag="119")] + MovePaneByPaneId(super::MovePaneByPaneIdAction), + #[prost(message, tag="120")] + MovePaneBackwardsByPaneId(super::MovePaneBackwardsByPaneIdAction), + #[prost(message, tag="121")] + ClearScreenByPaneId(super::ClearScreenByPaneIdAction), + #[prost(message, tag="122")] + EditScrollbackByPaneId(super::EditScrollbackByPaneIdAction), + #[prost(message, tag="123")] + ToggleFullscreenByPaneId(super::ToggleFullscreenByPaneIdAction), + #[prost(message, tag="124")] + TogglePaneEmbedOrFloatingByPaneId(super::TogglePaneEmbedOrFloatingByPaneIdAction), + #[prost(message, tag="125")] + CloseFocusByPaneId(super::CloseFocusByPaneIdAction), + #[prost(message, tag="126")] + RenamePaneByPaneId(super::RenamePaneByPaneIdAction), + #[prost(message, tag="127")] + UndoRenamePaneByPaneId(super::UndoRenamePaneByPaneIdAction), + #[prost(message, tag="128")] + TogglePanePinnedByPaneId(super::TogglePanePinnedByPaneIdAction), + /// Tab-targeting + #[prost(message, tag="129")] + UndoRenameTabByTabId(super::UndoRenameTabByTabIdAction), + #[prost(message, tag="130")] + ToggleActiveSyncTabByTabId(super::ToggleActiveSyncTabByTabIdAction), + #[prost(message, tag="131")] + ToggleFloatingPanesByTabId(super::ToggleFloatingPanesByTabIdAction), + #[prost(message, tag="132")] + PreviousSwapLayoutByTabId(super::PreviousSwapLayoutByTabIdAction), + #[prost(message, tag="133")] + NextSwapLayoutByTabId(super::NextSwapLayoutByTabIdAction), + #[prost(message, tag="134")] + MoveTabByTabId(super::MoveTabByTabIdAction), } } // Action message definitions (all 92 variants) @@ -1840,6 +1892,166 @@ pub struct Options { #[prost(bool, optional, tag="45")] pub mouse_click_through: ::core::option::Option<bool>, } +/// Pane-targeting action messages +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ScrollUpByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ScrollDownByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ScrollToTopByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ScrollToBottomByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PageScrollUpByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PageScrollDownByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HalfPageScrollUpByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HalfPageScrollDownByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResizeByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, + #[prost(message, optional, tag="2")] + pub resize_action: ::core::option::Option<ResizeAction>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MovePaneByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, + #[prost(enumeration="Direction", optional, tag="2")] + pub direction: ::core::option::Option<i32>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MovePaneBackwardsByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClearScreenByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EditScrollbackByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ToggleFullscreenByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TogglePaneEmbedOrFloatingByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CloseFocusByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RenamePaneByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, + #[prost(bytes="vec", tag="2")] + pub name: ::prost::alloc::vec::Vec<u8>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UndoRenamePaneByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TogglePanePinnedByPaneIdAction { + #[prost(message, optional, tag="1")] + pub pane_id: ::core::option::Option<PaneId>, +} +/// Tab-targeting action messages +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UndoRenameTabByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ToggleActiveSyncTabByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ToggleFloatingPanesByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PreviousSwapLayoutByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NextSwapLayoutByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveTabByTabIdAction { + #[prost(uint64, tag="1")] + pub id: u64, + #[prost(enumeration="Direction", tag="2")] + pub direction: i32, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum BareKey { diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 0d5e847c..005c8b66 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -723,6 +723,9 @@ pub enum CliAction { Resize { resize: Resize, direction: Option<Direction>, + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, }, /// Change focus to the next pane FocusNextPane, @@ -741,11 +744,22 @@ pub enum CliAction { /// [right|left|up|down] MovePane { direction: Option<Direction>, + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, }, /// Rotate the location of the previous pane backwards - MovePaneBackwards, + MovePaneBackwards { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Clear all buffers for a focused pane - Clear, + Clear { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Dumps the viewport and optionally scrollback of a pane to a file or STDOUT DumpScreen { /// File path to dump the pane content to. If omitted, prints to STDOUT. @@ -765,29 +779,73 @@ pub enum CliAction { /// Save the current session state to disk immediately SaveSession, /// Open the pane scrollback in your default editor - EditScrollback, + EditScrollback { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll up in the focused pane - ScrollUp, + ScrollUp { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll down in focus pane. - ScrollDown, + ScrollDown { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll down to bottom in focus pane. - ScrollToBottom, + ScrollToBottom { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll up to top in focus pane. - ScrollToTop, + ScrollToTop { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll up one page in focus pane. - PageScrollUp, + PageScrollUp { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll down one page in focus pane. - PageScrollDown, + PageScrollDown { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll up half page in focus pane. - HalfPageScrollUp, + HalfPageScrollUp { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Scroll down half page in focus pane. - HalfPageScrollDown, + HalfPageScrollDown { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Toggle between fullscreen focus pane and normal layout. - ToggleFullscreen, + ToggleFullscreen { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Toggle frames around panes in the UI TogglePaneFrames, /// Toggle between sending text commands to all panes on the current tab and normal mode. - ToggleActiveSyncTab, + ToggleActiveSyncTab { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, /// Open a new pane in the specified direction [right|down] /// If no direction is specified, will try to use the biggest available space. /// Returns: Created pane ID (format: terminal_<id> or plugin_<id>) @@ -969,9 +1027,17 @@ pub enum CliAction { input_mode: InputMode, }, /// Embed focused pane if floating or float focused pane if embedded - TogglePaneEmbedOrFloating, + TogglePaneEmbedOrFloating { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Toggle the visibility of all floating panes in the current Tab, open one if none exist - ToggleFloatingPanes, + ToggleFloatingPanes { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, /// Show all floating panes in the specified tab (or active tab if tab_id is not provided). /// /// Returns exit code 0 if state was changed, 2 if already visible, 1 if tab not found. @@ -987,19 +1053,34 @@ pub enum CliAction { tab_id: Option<usize>, }, /// Close the focused pane. - ClosePane, + ClosePane { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Renames the focused pane RenamePane { name: String, + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, }, /// Remove a previously set pane name - UndoRenamePane, + UndoRenamePane { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Go to the next tab. GoToNextTab, /// Go to the previous tab. GoToPreviousTab, /// Close the current tab. - CloseTab, + CloseTab { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, /// Go to tab with index [index] GoToTab { index: u32, @@ -1016,9 +1097,16 @@ pub enum CliAction { /// Renames the focused pane RenameTab { name: String, + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, }, /// Remove a previously set tab name - UndoRenameTab, + UndoRenameTab { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, /// Go to tab with stable ID GoToTabById { id: u64, @@ -1125,9 +1213,20 @@ pub enum CliAction { /// Move the focused tab in the specified direction. [right|left] MoveTab { direction: Direction, + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, + PreviousSwapLayout { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, + }, + NextSwapLayout { + /// Target a specific tab by ID + #[clap(short, long, value_parser)] + tab_id: Option<usize>, }, - PreviousSwapLayout, - NextSwapLayout, /// Override the layout of the active tab OverrideLayout { /// Path to the layout file @@ -1345,7 +1444,11 @@ tail -f /tmp/my-live-logfile | zellij action pipe --name logs --plugin https://e #[clap(short, long, value_parser)] json: bool, }, - TogglePanePinned, + TogglePanePinned { + /// Target a specific pane by ID (eg. terminal_1, plugin_2, or 3) + #[clap(short, long, value_parser)] + pane_id: Option<String>, + }, /// Stack pane ids /// Ids are a space separated list of pane ids. /// They should either be in the form of `terminal_<int>` (eg. terminal_1), `plugin_<int>` (eg. diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto index ec4f03a9..f93f2632 100644 --- a/zellij-utils/src/client_server_contract/common_types.proto +++ b/zellij-utils/src/client_server_contract/common_types.proto @@ -245,6 +245,33 @@ message Action { HideFloatingPanesAction hide_floating_panes = 107; SetPaneColorAction set_pane_color = 108; PasteAction paste = 109; + // Pane-targeting + ScrollUpByPaneIdAction scroll_up_by_pane_id = 110; + ScrollDownByPaneIdAction scroll_down_by_pane_id = 111; + ScrollToTopByPaneIdAction scroll_to_top_by_pane_id = 112; + ScrollToBottomByPaneIdAction scroll_to_bottom_by_pane_id = 113; + PageScrollUpByPaneIdAction page_scroll_up_by_pane_id = 114; + PageScrollDownByPaneIdAction page_scroll_down_by_pane_id = 115; + HalfPageScrollUpByPaneIdAction half_page_scroll_up_by_pane_id = 116; + HalfPageScrollDownByPaneIdAction half_page_scroll_down_by_pane_id = 117; + ResizeByPaneIdAction resize_by_pane_id = 118; + MovePaneByPaneIdAction move_pane_by_pane_id = 119; + MovePaneBackwardsByPaneIdAction move_pane_backwards_by_pane_id = 120; + ClearScreenByPaneIdAction clear_screen_by_pane_id = 121; + EditScrollbackByPaneIdAction edit_scrollback_by_pane_id = 122; + ToggleFullscreenByPaneIdAction toggle_fullscreen_by_pane_id = 123; + TogglePaneEmbedOrFloatingByPaneIdAction toggle_pane_embed_or_floating_by_pane_id = 124; + CloseFocusByPaneIdAction close_focus_by_pane_id = 125; + RenamePaneByPaneIdAction rename_pane_by_pane_id = 126; + UndoRenamePaneByPaneIdAction undo_rename_pane_by_pane_id = 127; + TogglePanePinnedByPaneIdAction toggle_pane_pinned_by_pane_id = 128; + // Tab-targeting + UndoRenameTabByTabIdAction undo_rename_tab_by_tab_id = 129; + ToggleActiveSyncTabByTabIdAction toggle_active_sync_tab_by_tab_id = 130; + ToggleFloatingPanesByTabIdAction toggle_floating_panes_by_tab_id = 131; + PreviousSwapLayoutByTabIdAction previous_swap_layout_by_tab_id = 132; + NextSwapLayoutByTabIdAction next_swap_layout_by_tab_id = 133; + MoveTabByTabIdAction move_tab_by_tab_id = 134; } } @@ -1146,3 +1173,32 @@ enum WebSharing { WEB_SHARING_OFF = 2; WEB_SHARING_DISABLED = 3; } + +// Pane-targeting action messages +message ScrollUpByPaneIdAction { PaneId pane_id = 1; } +message ScrollDownByPaneIdAction { PaneId pane_id = 1; } +message ScrollToTopByPaneIdAction { PaneId pane_id = 1; } +message ScrollToBottomByPaneIdAction { PaneId pane_id = 1; } +message PageScrollUpByPaneIdAction { PaneId pane_id = 1; } +message PageScrollDownByPaneIdAction { PaneId pane_id = 1; } +message HalfPageScrollUpByPaneIdAction { PaneId pane_id = 1; } +message HalfPageScrollDownByPaneIdAction { PaneId pane_id = 1; } +message ResizeByPaneIdAction { PaneId pane_id = 1; ResizeAction resize_action = 2; } +message MovePaneByPaneIdAction { PaneId pane_id = 1; optional Direction direction = 2; } +message MovePaneBackwardsByPaneIdAction { PaneId pane_id = 1; } +message ClearScreenByPaneIdAction { PaneId pane_id = 1; } +message EditScrollbackByPaneIdAction { PaneId pane_id = 1; } +message ToggleFullscreenByPaneIdAction { PaneId pane_id = 1; } +message TogglePaneEmbedOrFloatingByPaneIdAction { PaneId pane_id = 1; } +message CloseFocusByPaneIdAction { PaneId pane_id = 1; } +message RenamePaneByPaneIdAction { PaneId pane_id = 1; bytes name = 2; } +message UndoRenamePaneByPaneIdAction { PaneId pane_id = 1; } +message TogglePanePinnedByPaneIdAction { PaneId pane_id = 1; } + +// Tab-targeting action messages +message UndoRenameTabByTabIdAction { uint64 id = 1; } +message ToggleActiveSyncTabByTabIdAction { uint64 id = 1; } +message ToggleFloatingPanesByTabIdAction { uint64 id = 1; } +message PreviousSwapLayoutByTabIdAction { uint64 id = 1; } +message NextSwapLayoutByTabIdAction { uint64 id = 1; } +message MoveTabByTabIdAction { uint64 id = 1; Direction direction = 2; } diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 82016f7c..a07f4c84 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -418,6 +418,33 @@ pub enum ScreenContext { ClearPluginHighlights, SubscribeToPaneRenders, NotifyPaneClosedToSubscribers, + // Pane-targeting CLI variants + ScrollUpWithPaneId, + ScrollDownWithPaneId, + ScrollToTopWithPaneId, + ScrollToBottomWithPaneId, + PageScrollUpWithPaneId, + PageScrollDownWithPaneId, + HalfPageScrollUpWithPaneId, + HalfPageScrollDownWithPaneId, + ResizeWithPaneId, + MovePaneWithPaneIdCli, + MovePaneBackwardsWithPaneId, + ClearScreenWithPaneId, + EditScrollbackWithPaneId, + ToggleFullscreenWithPaneId, + TogglePaneEmbedOrFloatingWithPaneId, + CloseFocusWithPaneId, + RenamePaneWithPaneId, + UndoRenamePaneWithPaneId, + TogglePanePinnedWithPaneId, + // Tab-targeting CLI variants + UndoRenameTabWithTabId, + ToggleActiveSyncTabWithTabId, + ToggleFloatingPanesWithTabId, + PreviousSwapLayoutWithTabId, + NextSwapLayoutWithTabId, + MoveTabWithTabId, } /// Stack call representations corresponding to the different types of [`PtyInstruction`]s. diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index d56389c8..f26f6e9a 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -538,6 +538,88 @@ pub enum Action { }, TogglePaneInGroup, ToggleGroupMarking, + // Pane-targeting CLI-only variants + ScrollUpByPaneId { + pane_id: PaneId, + }, + ScrollDownByPaneId { + pane_id: PaneId, + }, + ScrollToTopByPaneId { + pane_id: PaneId, + }, + ScrollToBottomByPaneId { + pane_id: PaneId, + }, + PageScrollUpByPaneId { + pane_id: PaneId, + }, + PageScrollDownByPaneId { + pane_id: PaneId, + }, + HalfPageScrollUpByPaneId { + pane_id: PaneId, + }, + HalfPageScrollDownByPaneId { + pane_id: PaneId, + }, + ResizeByPaneId { + pane_id: PaneId, + resize: Resize, + direction: Option<Direction>, + }, + MovePaneByPaneId { + pane_id: PaneId, + direction: Option<Direction>, + }, + MovePaneBackwardsByPaneId { + pane_id: PaneId, + }, + ClearScreenByPaneId { + pane_id: PaneId, + }, + EditScrollbackByPaneId { + pane_id: PaneId, + }, + ToggleFocusFullscreenByPaneId { + pane_id: PaneId, + }, + TogglePaneEmbedOrFloatingByPaneId { + pane_id: PaneId, + }, + CloseFocusByPaneId { + pane_id: PaneId, + }, + RenamePaneByPaneId { + pane_id: PaneId, + name: Vec<u8>, + }, + UndoRenamePaneByPaneId { + pane_id: PaneId, + }, + TogglePanePinnedByPaneId { + pane_id: PaneId, + }, + // Tab-targeting CLI-only variants + UndoRenameTabByTabId { + id: u64, + }, + ToggleActiveSyncTabByTabId { + id: u64, + }, + ToggleFloatingPanesByTabId { + id: u64, + }, + PreviousSwapLayoutByTabId { + id: u64, + }, + NextSwapLayoutByTabId { + id: u64, + }, + MoveTabByTabId { + id: u64, + direction: Direction, + }, } impl Default for Action { @@ -691,8 +773,23 @@ impl Action { Ok(actions) }, - CliAction::Resize { resize, direction } => { - Ok(vec![Action::Resize { resize, direction }]) + CliAction::Resize { + resize, + direction, + pane_id, + } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ResizeByPaneId { + pane_id, + resize, + direction, + }]) + }, + None => Ok(vec![Action::Resize { resize, direction }]), }, CliAction::FocusNextPane => Ok(vec![Action::FocusNextPane]), CliAction::FocusPreviousPane => Ok(vec![Action::FocusPreviousPane]), @@ -700,10 +797,43 @@ impl Action { CliAction::MoveFocusOrTab { direction } => { Ok(vec![Action::MoveFocusOrTab { direction }]) }, - CliAction::MovePane { direction } => Ok(vec![Action::MovePane { direction }]), - CliAction::MovePaneBackwards => Ok(vec![Action::MovePaneBackwards]), - CliAction::MoveTab { direction } => Ok(vec![Action::MoveTab { direction }]), - CliAction::Clear => Ok(vec![Action::ClearScreen]), + CliAction::MovePane { direction, pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::MovePaneByPaneId { pane_id, direction }]) + }, + None => Ok(vec![Action::MovePane { direction }]), + }, + CliAction::MovePaneBackwards { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::MovePaneBackwardsByPaneId { pane_id }]) + }, + None => Ok(vec![Action::MovePaneBackwards]), + }, + CliAction::MoveTab { direction, tab_id } => match tab_id { + Some(id) => Ok(vec![Action::MoveTabByTabId { + id: id as u64, + direction, + }]), + None => Ok(vec![Action::MoveTab { direction }]), + }, + CliAction::Clear { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ClearScreenByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ClearScreen]), + }, CliAction::DumpScreen { path, full, @@ -735,18 +865,111 @@ impl Action { }, CliAction::DumpLayout => Ok(vec![Action::DumpLayout]), CliAction::SaveSession => Ok(vec![Action::SaveSession]), - CliAction::EditScrollback => Ok(vec![Action::EditScrollback]), - CliAction::ScrollUp => Ok(vec![Action::ScrollUp]), - CliAction::ScrollDown => Ok(vec![Action::ScrollDown]), - CliAction::ScrollToBottom => Ok(vec![Action::ScrollToBottom]), - CliAction::ScrollToTop => Ok(vec![Action::ScrollToTop]), - CliAction::PageScrollUp => Ok(vec![Action::PageScrollUp]), - CliAction::PageScrollDown => Ok(vec![Action::PageScrollDown]), - CliAction::HalfPageScrollUp => Ok(vec![Action::HalfPageScrollUp]), - CliAction::HalfPageScrollDown => Ok(vec![Action::HalfPageScrollDown]), - CliAction::ToggleFullscreen => Ok(vec![Action::ToggleFocusFullscreen]), + CliAction::EditScrollback { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::EditScrollbackByPaneId { pane_id }]) + }, + None => Ok(vec![Action::EditScrollback]), + }, + CliAction::ScrollUp { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ScrollUpByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ScrollUp]), + }, + CliAction::ScrollDown { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ScrollDownByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ScrollDown]), + }, + CliAction::ScrollToBottom { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ScrollToBottomByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ScrollToBottom]), + }, + CliAction::ScrollToTop { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ScrollToTopByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ScrollToTop]), + }, + CliAction::PageScrollUp { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::PageScrollUpByPaneId { pane_id }]) + }, + None => Ok(vec![Action::PageScrollUp]), + }, + CliAction::PageScrollDown { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::PageScrollDownByPaneId { pane_id }]) + }, + None => Ok(vec![Action::PageScrollDown]), + }, + CliAction::HalfPageScrollUp { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::HalfPageScrollUpByPaneId { pane_id }]) + }, + None => Ok(vec![Action::HalfPageScrollUp]), + }, + CliAction::HalfPageScrollDown { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::HalfPageScrollDownByPaneId { pane_id }]) + }, + None => Ok(vec![Action::HalfPageScrollDown]), + }, + CliAction::ToggleFullscreen { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::ToggleFocusFullscreenByPaneId { pane_id }]) + }, + None => Ok(vec![Action::ToggleFocusFullscreen]), + }, CliAction::TogglePaneFrames => Ok(vec![Action::TogglePaneFrames]), - CliAction::ToggleActiveSyncTab => Ok(vec![Action::ToggleActiveSyncTab]), + CliAction::ToggleActiveSyncTab { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::ToggleActiveSyncTabByTabId { id: id as u64 }]), + None => Ok(vec![Action::ToggleActiveSyncTab]), + }, CliAction::NewPane { direction, command, @@ -1007,36 +1230,90 @@ impl Action { }]) }, CliAction::SwitchMode { input_mode } => Ok(vec![Action::SwitchToMode { input_mode }]), - CliAction::TogglePaneEmbedOrFloating => Ok(vec![Action::TogglePaneEmbedOrFloating]), - CliAction::ToggleFloatingPanes => Ok(vec![Action::ToggleFloatingPanes]), + CliAction::TogglePaneEmbedOrFloating { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::TogglePaneEmbedOrFloatingByPaneId { pane_id }]) + }, + None => Ok(vec![Action::TogglePaneEmbedOrFloating]), + }, + CliAction::ToggleFloatingPanes { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::ToggleFloatingPanesByTabId { id: id as u64 }]), + None => Ok(vec![Action::ToggleFloatingPanes]), + }, CliAction::ShowFloatingPanes { tab_id } => { Ok(vec![Action::ShowFloatingPanes { tab_id }]) }, CliAction::HideFloatingPanes { tab_id } => { Ok(vec![Action::HideFloatingPanes { tab_id }]) }, - CliAction::ClosePane => Ok(vec![Action::CloseFocus]), - CliAction::RenamePane { name } => Ok(vec![ - Action::UndoRenamePane, - Action::PaneNameInput { - input: name.as_bytes().to_vec(), + CliAction::ClosePane { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::CloseFocusByPaneId { pane_id }]) }, - ]), - CliAction::UndoRenamePane => Ok(vec![Action::UndoRenamePane]), + None => Ok(vec![Action::CloseFocus]), + }, + CliAction::RenamePane { name, pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::RenamePaneByPaneId { + pane_id, + name: name.as_bytes().to_vec(), + }]) + }, + None => Ok(vec![ + Action::UndoRenamePane, + Action::PaneNameInput { + input: name.as_bytes().to_vec(), + }, + ]), + }, + CliAction::UndoRenamePane { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::UndoRenamePaneByPaneId { pane_id }]) + }, + None => Ok(vec![Action::UndoRenamePane]), + }, CliAction::GoToNextTab => Ok(vec![Action::GoToNextTab]), CliAction::GoToPreviousTab => Ok(vec![Action::GoToPreviousTab]), - CliAction::CloseTab => Ok(vec![Action::CloseTab]), + CliAction::CloseTab { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::CloseTabById { id: id as u64 }]), + None => Ok(vec![Action::CloseTab]), + }, CliAction::GoToTab { index } => Ok(vec![Action::GoToTab { index }]), CliAction::GoToTabName { name, create } => { Ok(vec![Action::GoToTabName { name, create }]) }, - CliAction::RenameTab { name } => Ok(vec![ - Action::TabNameInput { input: vec![0] }, - Action::TabNameInput { - input: name.as_bytes().to_vec(), - }, - ]), - CliAction::UndoRenameTab => Ok(vec![Action::UndoRenameTab]), + CliAction::RenameTab { name, tab_id } => match tab_id { + Some(id) => Ok(vec![Action::RenameTabById { + id: id as u64, + name, + }]), + None => Ok(vec![ + Action::TabNameInput { input: vec![0] }, + Action::TabNameInput { + input: name.as_bytes().to_vec(), + }, + ]), + }, + CliAction::UndoRenameTab { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::UndoRenameTabByTabId { id: id as u64 }]), + None => Ok(vec![Action::UndoRenameTab]), + }, CliAction::GoToTabById { id } => Ok(vec![Action::GoToTabById { id }]), CliAction::CloseTabById { id } => Ok(vec![Action::CloseTabById { id }]), CliAction::RenameTabById { id, name } => Ok(vec![Action::RenameTabById { id, name }]), @@ -1231,8 +1508,14 @@ impl Action { }]) } }, - CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]), - CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]), + CliAction::PreviousSwapLayout { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::PreviousSwapLayoutByTabId { id: id as u64 }]), + None => Ok(vec![Action::PreviousSwapLayout]), + }, + CliAction::NextSwapLayout { tab_id } => match tab_id { + Some(id) => Ok(vec![Action::NextSwapLayoutByTabId { id: id as u64 }]), + None => Ok(vec![Action::NextSwapLayout]), + }, CliAction::OverrideLayout { layout, layout_dir, @@ -1460,7 +1743,16 @@ impl Action { CliAction::CurrentTabInfo { json } => { Ok(vec![Action::CurrentTabInfo { output_json: json }]) }, - CliAction::TogglePanePinned => Ok(vec![Action::TogglePanePinned]), + CliAction::TogglePanePinned { pane_id } => match pane_id { + Some(pane_id_str) => { + let pane_id = PaneId::from_str(&pane_id_str) + .map_err(|_| format!( + "Malformed pane id: {pane_id_str}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)" + ))?; + Ok(vec![Action::TogglePanePinnedByPaneId { pane_id }]) + }, + None => Ok(vec![Action::TogglePanePinned]), + }, CliAction::StackPanes { pane_ids } => { let mut malformed_ids = vec![]; let pane_ids = pane_ids @@ -1855,4 +2147,852 @@ mod tests { let err = result.unwrap_err(); assert!(err.contains("Malformed pane id")); } + + // ============================================= + // Category 1: Pane-targeting tests + // ============================================= + + // 1. ScrollUp + #[test] + fn test_scroll_up_with_pane_id() { + let cli_action = CliAction::ScrollUp { + pane_id: Some("terminal_5".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollUpByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(5))); + }, + _ => panic!("Expected ScrollUpByPaneId action"), + } + } + + #[test] + fn test_scroll_up_without_pane_id() { + let cli_action = CliAction::ScrollUp { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ScrollUp)); + } + + // 2. ScrollDown + #[test] + fn test_scroll_down_with_pane_id() { + let cli_action = CliAction::ScrollDown { + pane_id: Some("terminal_2".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollDownByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(2))); + }, + _ => panic!("Expected ScrollDownByPaneId action"), + } + } + + #[test] + fn test_scroll_down_without_pane_id() { + let cli_action = CliAction::ScrollDown { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ScrollDown)); + } + + // 3. ScrollToTop + #[test] + fn test_scroll_to_top_with_pane_id() { + let cli_action = CliAction::ScrollToTop { + pane_id: Some("terminal_1".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollToTopByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(1))); + }, + _ => panic!("Expected ScrollToTopByPaneId action"), + } + } + + #[test] + fn test_scroll_to_top_without_pane_id() { + let cli_action = CliAction::ScrollToTop { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ScrollToTop)); + } + + // 4. ScrollToBottom + #[test] + fn test_scroll_to_bottom_with_pane_id() { + let cli_action = CliAction::ScrollToBottom { + pane_id: Some("terminal_4".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollToBottomByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(4))); + }, + _ => panic!("Expected ScrollToBottomByPaneId action"), + } + } + + #[test] + fn test_scroll_to_bottom_without_pane_id() { + let cli_action = CliAction::ScrollToBottom { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ScrollToBottom)); + } + + // 5. PageScrollUp + #[test] + fn test_page_scroll_up_with_pane_id() { + let cli_action = CliAction::PageScrollUp { + pane_id: Some("terminal_6".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::PageScrollUpByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(6))); + }, + _ => panic!("Expected PageScrollUpByPaneId action"), + } + } + + #[test] + fn test_page_scroll_up_without_pane_id() { + let cli_action = CliAction::PageScrollUp { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::PageScrollUp)); + } + + // 6. PageScrollDown + #[test] + fn test_page_scroll_down_with_pane_id() { + let cli_action = CliAction::PageScrollDown { + pane_id: Some("terminal_8".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::PageScrollDownByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(8))); + }, + _ => panic!("Expected PageScrollDownByPaneId action"), + } + } + + #[test] + fn test_page_scroll_down_without_pane_id() { + let cli_action = CliAction::PageScrollDown { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::PageScrollDown)); + } + + // 7. HalfPageScrollUp + #[test] + fn test_half_page_scroll_up_with_pane_id() { + let cli_action = CliAction::HalfPageScrollUp { + pane_id: Some("terminal_10".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::HalfPageScrollUpByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(10))); + }, + _ => panic!("Expected HalfPageScrollUpByPaneId action"), + } + } + + #[test] + fn test_half_page_scroll_up_without_pane_id() { + let cli_action = CliAction::HalfPageScrollUp { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::HalfPageScrollUp)); + } + + // 8. HalfPageScrollDown + #[test] + fn test_half_page_scroll_down_with_pane_id() { + let cli_action = CliAction::HalfPageScrollDown { + pane_id: Some("terminal_12".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::HalfPageScrollDownByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(12))); + }, + _ => panic!("Expected HalfPageScrollDownByPaneId action"), + } + } + + #[test] + fn test_half_page_scroll_down_without_pane_id() { + let cli_action = CliAction::HalfPageScrollDown { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::HalfPageScrollDown)); + } + + // 9. Resize + #[test] + fn test_resize_with_pane_id() { + let cli_action = CliAction::Resize { + resize: Resize::Increase, + direction: Some(Direction::Left), + pane_id: Some("terminal_3".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ResizeByPaneId { + pane_id, + resize, + direction, + } => { + assert!(matches!(pane_id, PaneId::Terminal(3))); + assert!(matches!(resize, Resize::Increase)); + assert!(matches!(direction, Some(Direction::Left))); + }, + _ => panic!("Expected ResizeByPaneId action"), + } + } + + #[test] + fn test_resize_without_pane_id() { + let cli_action = CliAction::Resize { + resize: Resize::Increase, + direction: Some(Direction::Left), + pane_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::Resize { resize, direction } => { + assert!(matches!(resize, Resize::Increase)); + assert!(matches!(direction, Some(Direction::Left))); + }, + _ => panic!("Expected Resize action"), + } + } + + // 10. MovePane + #[test] + fn test_move_pane_with_pane_id() { + let cli_action = CliAction::MovePane { + direction: Some(Direction::Right), + pane_id: Some("terminal_9".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::MovePaneByPaneId { pane_id, direction } => { + assert!(matches!(pane_id, PaneId::Terminal(9))); + assert!(matches!(direction, Some(Direction::Right))); + }, + _ => panic!("Expected MovePaneByPaneId action"), + } + } + + #[test] + fn test_move_pane_without_pane_id() { + let cli_action = CliAction::MovePane { + direction: Some(Direction::Right), + pane_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::MovePane { direction } => { + assert!(matches!(direction, Some(Direction::Right))); + }, + _ => panic!("Expected MovePane action"), + } + } + + // 11. MovePaneBackwards + #[test] + fn test_move_pane_backwards_with_pane_id() { + let cli_action = CliAction::MovePaneBackwards { + pane_id: Some("terminal_11".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::MovePaneBackwardsByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(11))); + }, + _ => panic!("Expected MovePaneBackwardsByPaneId action"), + } + } + + #[test] + fn test_move_pane_backwards_without_pane_id() { + let cli_action = CliAction::MovePaneBackwards { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::MovePaneBackwards)); + } + + // 12. Clear + #[test] + fn test_clear_with_pane_id() { + let cli_action = CliAction::Clear { + pane_id: Some("terminal_14".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ClearScreenByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(14))); + }, + _ => panic!("Expected ClearScreenByPaneId action"), + } + } + + #[test] + fn test_clear_without_pane_id() { + let cli_action = CliAction::Clear { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ClearScreen)); + } + + // 13. EditScrollback + #[test] + fn test_edit_scrollback_with_pane_id() { + let cli_action = CliAction::EditScrollback { + pane_id: Some("terminal_15".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::EditScrollbackByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(15))); + }, + _ => panic!("Expected EditScrollbackByPaneId action"), + } + } + + #[test] + fn test_edit_scrollback_without_pane_id() { + let cli_action = CliAction::EditScrollback { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::EditScrollback)); + } + + // 14. ToggleFullscreen + #[test] + fn test_toggle_fullscreen_with_pane_id() { + let cli_action = CliAction::ToggleFullscreen { + pane_id: Some("terminal_16".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ToggleFocusFullscreenByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(16))); + }, + _ => panic!("Expected ToggleFocusFullscreenByPaneId action"), + } + } + + #[test] + fn test_toggle_fullscreen_without_pane_id() { + let cli_action = CliAction::ToggleFullscreen { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ToggleFocusFullscreen)); + } + + // 15. TogglePaneEmbedOrFloating + #[test] + fn test_toggle_pane_embed_or_floating_with_pane_id() { + let cli_action = CliAction::TogglePaneEmbedOrFloating { + pane_id: Some("terminal_17".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::TogglePaneEmbedOrFloatingByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(17))); + }, + _ => panic!("Expected TogglePaneEmbedOrFloatingByPaneId action"), + } + } + + #[test] + fn test_toggle_pane_embed_or_floating_without_pane_id() { + let cli_action = CliAction::TogglePaneEmbedOrFloating { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::TogglePaneEmbedOrFloating)); + } + + // 16. ClosePane + #[test] + fn test_close_pane_with_pane_id() { + let cli_action = CliAction::ClosePane { + pane_id: Some("terminal_18".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::CloseFocusByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(18))); + }, + _ => panic!("Expected CloseFocusByPaneId action"), + } + } + + #[test] + fn test_close_pane_without_pane_id() { + let cli_action = CliAction::ClosePane { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::CloseFocus)); + } + + // 17. RenamePane + #[test] + fn test_rename_pane_with_pane_id() { + let cli_action = CliAction::RenamePane { + name: "my-pane".to_string(), + pane_id: Some("terminal_19".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::RenamePaneByPaneId { pane_id, name } => { + assert!(matches!(pane_id, PaneId::Terminal(19))); + assert_eq!(name, &"my-pane".as_bytes().to_vec()); + }, + _ => panic!("Expected RenamePaneByPaneId action"), + } + } + + #[test] + fn test_rename_pane_without_pane_id() { + let cli_action = CliAction::RenamePane { + name: "my-pane".to_string(), + pane_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 2); + assert!(matches!(actions[0], Action::UndoRenamePane)); + assert!(matches!(actions[1], Action::PaneNameInput { .. })); + } + + // 18. UndoRenamePane + #[test] + fn test_undo_rename_pane_with_pane_id() { + let cli_action = CliAction::UndoRenamePane { + pane_id: Some("terminal_20".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::UndoRenamePaneByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(20))); + }, + _ => panic!("Expected UndoRenamePaneByPaneId action"), + } + } + + #[test] + fn test_undo_rename_pane_without_pane_id() { + let cli_action = CliAction::UndoRenamePane { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::UndoRenamePane)); + } + + // 19. TogglePanePinned + #[test] + fn test_toggle_pane_pinned_with_pane_id() { + let cli_action = CliAction::TogglePanePinned { + pane_id: Some("terminal_21".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::TogglePanePinnedByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(21))); + }, + _ => panic!("Expected TogglePanePinnedByPaneId action"), + } + } + + #[test] + fn test_toggle_pane_pinned_without_pane_id() { + let cli_action = CliAction::TogglePanePinned { pane_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::TogglePanePinned)); + } + + // Extra pane tests + #[test] + fn test_scroll_up_with_plugin_pane_id() { + let cli_action = CliAction::ScrollUp { + pane_id: Some("plugin_3".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollUpByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Plugin(3))); + }, + _ => panic!("Expected ScrollUpByPaneId action with plugin pane id"), + } + } + + #[test] + fn test_scroll_up_with_bare_integer_pane_id() { + let cli_action = CliAction::ScrollUp { + pane_id: Some("7".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ScrollUpByPaneId { pane_id } => { + assert!(matches!(pane_id, PaneId::Terminal(7))); + }, + _ => panic!("Expected ScrollUpByPaneId action with bare integer pane id"), + } + } + + #[test] + fn test_scroll_up_with_invalid_pane_id() { + let cli_action = CliAction::ScrollUp { + pane_id: Some("invalid_id".to_string()), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_err()); + let err = result.unwrap_err(); + assert!(err.contains("Malformed pane id")); + } + + // ============================================= + // Category 1: Tab-targeting tests + // ============================================= + + // 20. CloseTab + #[test] + fn test_close_tab_with_tab_id() { + let cli_action = CliAction::CloseTab { tab_id: Some(5) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::CloseTabById { id } => { + assert_eq!(*id, 5u64); + }, + _ => panic!("Expected CloseTabById action"), + } + } + + #[test] + fn test_close_tab_without_tab_id() { + let cli_action = CliAction::CloseTab { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::CloseTab)); + } + + // 21. RenameTab + #[test] + fn test_rename_tab_with_tab_id() { + let cli_action = CliAction::RenameTab { + name: "my-tab".to_string(), + tab_id: Some(3), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::RenameTabById { id, name } => { + assert_eq!(*id, 3u64); + assert_eq!(name, "my-tab"); + }, + _ => panic!("Expected RenameTabById action"), + } + } + + #[test] + fn test_rename_tab_without_tab_id() { + let cli_action = CliAction::RenameTab { + name: "my-tab".to_string(), + tab_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 2); + assert!(matches!(actions[0], Action::TabNameInput { .. })); + assert!(matches!(actions[1], Action::TabNameInput { .. })); + } + + // 22. UndoRenameTab + #[test] + fn test_undo_rename_tab_with_tab_id() { + let cli_action = CliAction::UndoRenameTab { tab_id: Some(7) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::UndoRenameTabByTabId { id } => { + assert_eq!(*id, 7u64); + }, + _ => panic!("Expected UndoRenameTabByTabId action"), + } + } + + #[test] + fn test_undo_rename_tab_without_tab_id() { + let cli_action = CliAction::UndoRenameTab { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::UndoRenameTab)); + } + + // 23. ToggleActiveSyncTab + #[test] + fn test_toggle_active_sync_tab_with_tab_id() { + let cli_action = CliAction::ToggleActiveSyncTab { tab_id: Some(2) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ToggleActiveSyncTabByTabId { id } => { + assert_eq!(*id, 2u64); + }, + _ => panic!("Expected ToggleActiveSyncTabByTabId action"), + } + } + + #[test] + fn test_toggle_active_sync_tab_without_tab_id() { + let cli_action = CliAction::ToggleActiveSyncTab { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ToggleActiveSyncTab)); + } + + // 24. ToggleFloatingPanes + #[test] + fn test_toggle_floating_panes_with_tab_id() { + let cli_action = CliAction::ToggleFloatingPanes { tab_id: Some(4) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::ToggleFloatingPanesByTabId { id } => { + assert_eq!(*id, 4u64); + }, + _ => panic!("Expected ToggleFloatingPanesByTabId action"), + } + } + + #[test] + fn test_toggle_floating_panes_without_tab_id() { + let cli_action = CliAction::ToggleFloatingPanes { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::ToggleFloatingPanes)); + } + + // 25. PreviousSwapLayout + #[test] + fn test_previous_swap_layout_with_tab_id() { + let cli_action = CliAction::PreviousSwapLayout { tab_id: Some(6) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::PreviousSwapLayoutByTabId { id } => { + assert_eq!(*id, 6u64); + }, + _ => panic!("Expected PreviousSwapLayoutByTabId action"), + } + } + + #[test] + fn test_previous_swap_layout_without_tab_id() { + let cli_action = CliAction::PreviousSwapLayout { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::PreviousSwapLayout)); + } + + // 26. NextSwapLayout + #[test] + fn test_next_swap_layout_with_tab_id() { + let cli_action = CliAction::NextSwapLayout { tab_id: Some(8) }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::NextSwapLayoutByTabId { id } => { + assert_eq!(*id, 8u64); + }, + _ => panic!("Expected NextSwapLayoutByTabId action"), + } + } + + #[test] + fn test_next_swap_layout_without_tab_id() { + let cli_action = CliAction::NextSwapLayout { tab_id: None }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], Action::NextSwapLayout)); + } + + // 27. MoveTab + #[test] + fn test_move_tab_with_tab_id() { + let cli_action = CliAction::MoveTab { + direction: Direction::Right, + tab_id: Some(10), + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::MoveTabByTabId { id, direction } => { + assert_eq!(*id, 10u64); + assert!(matches!(direction, Direction::Right)); + }, + _ => panic!("Expected MoveTabByTabId action"), + } + } + + #[test] + fn test_move_tab_without_tab_id() { + let cli_action = CliAction::MoveTab { + direction: Direction::Right, + tab_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::MoveTab { direction } => { + assert!(matches!(direction, Direction::Right)); + }, + _ => panic!("Expected MoveTab action"), + } + } } diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs index 17860407..11948521 100644 --- a/zellij-utils/src/ipc/protobuf_conversion.rs +++ b/zellij-utils/src/ipc/protobuf_conversion.rs @@ -780,35 +780,143 @@ impl From<crate::input::actions::Action> { fn from(action: crate::input::actions::Action) -> Self { use crate::client_server_contract::client_server_contract::{ - action::ActionType, BreakPaneAction, BreakPaneLeftAction, BreakPaneRightAction, - ChangeFloatingPaneCoordinatesAction, ClearScreenAction, CliPipeAction, - CloseFocusAction, ClosePluginPaneAction, CloseTabAction, CloseTabByIdAction, - CloseTerminalPaneAction, ConfirmAction, CopyAction, CurrentTabInfoAction, DenyAction, - DetachAction, DumpLayoutAction, DumpScreenAction, EditFileAction, EditScrollbackAction, - FocusNextPaneAction, FocusPluginPaneWithIdAction, FocusPreviousPaneAction, - FocusTerminalPaneWithIdAction, GoToNextTabAction, GoToPreviousTabAction, GoToTabAction, - GoToTabByIdAction, GoToTabNameAction, HalfPageScrollDownAction, HalfPageScrollUpAction, - HideFloatingPanesAction, KeybindPipeAction, LaunchOrFocusPluginAction, - LaunchPluginAction, ListClientsAction, ListPanesAction, ListTabsAction, - MouseEventAction, MoveFocusAction, MoveFocusOrTabAction, MovePaneAction, - MovePaneBackwardsAction, MoveTabAction, NewBlockingPaneAction, NewFloatingPaneAction, - NewFloatingPluginPaneAction, NewInPlacePaneAction, NewInPlacePluginPaneAction, - NewPaneAction, NewStackedPaneAction, NewTabAction, NewTiledPaneAction, - NewTiledPluginPaneAction, NextSwapLayoutAction, NoOpAction, OverrideLayoutAction, - PageScrollDownAction, PageScrollUpAction, PaneIdWithPlugin, PaneNameInputAction, - PasteAction, PreviousSwapLayoutAction, QueryTabNamesAction, QuitAction, - RenamePluginPaneAction, RenameSessionAction, RenameTabAction, RenameTabByIdAction, - RenameTerminalPaneAction, ResizeAction, RunAction, SaveSessionAction, ScrollDownAction, - ScrollDownAtAction, ScrollToBottomAction, ScrollToTopAction, ScrollUpAction, - ScrollUpAtAction, SearchAction, SearchInputAction, SearchToggleOptionAction, - SetPaneBorderlessAction, SetPaneColorAction, ShowFloatingPanesAction, - SkipConfirmAction, StackPanesAction, StartOrReloadPluginAction, SwitchFocusAction, - SwitchModeForAllClientsAction, SwitchSessionAction, SwitchToModeAction, - TabNameInputAction, ToggleActiveSyncTabAction, ToggleFloatingPanesAction, - ToggleFocusFullscreenAction, ToggleGroupMarkingAction, ToggleMouseModeAction, - TogglePaneBorderlessAction, TogglePaneEmbedOrFloatingAction, TogglePaneFramesAction, - TogglePaneInGroupAction, TogglePanePinnedAction, ToggleTabAction, UndoRenamePaneAction, - UndoRenameTabAction, WriteAction, WriteCharsAction, WriteCharsToPaneIdAction, + action::ActionType, + BreakPaneAction, + BreakPaneLeftAction, + BreakPaneRightAction, + ChangeFloatingPaneCoordinatesAction, + ClearScreenAction, + ClearScreenByPaneIdAction, + CliPipeAction, + CloseFocusAction, + CloseFocusByPaneIdAction, + ClosePluginPaneAction, + CloseTabAction, + CloseTabByIdAction, + CloseTerminalPaneAction, + ConfirmAction, + CopyAction, + CurrentTabInfoAction, + DenyAction, + DetachAction, + DumpLayoutAction, + DumpScreenAction, + EditFileAction, + EditScrollbackAction, + EditScrollbackByPaneIdAction, + FocusNextPaneAction, + FocusPluginPaneWithIdAction, + FocusPreviousPaneAction, + FocusTerminalPaneWithIdAction, + GoToNextTabAction, + GoToPreviousTabAction, + GoToTabAction, + GoToTabByIdAction, + GoToTabNameAction, + HalfPageScrollDownAction, + HalfPageScrollDownByPaneIdAction, + HalfPageScrollUpAction, + HalfPageScrollUpByPaneIdAction, + HideFloatingPanesAction, + KeybindPipeAction, + LaunchOrFocusPluginAction, + LaunchPluginAction, + ListClientsAction, + ListPanesAction, + ListTabsAction, + MouseEventAction, + MoveFocusAction, + MoveFocusOrTabAction, + MovePaneAction, + MovePaneBackwardsAction, + MovePaneBackwardsByPaneIdAction, + MovePaneByPaneIdAction, + MoveTabAction, + MoveTabByTabIdAction, + NewBlockingPaneAction, + NewFloatingPaneAction, + NewFloatingPluginPaneAction, + NewInPlacePaneAction, + NewInPlacePluginPaneAction, + NewPaneAction, + NewStackedPaneAction, + NewTabAction, + NewTiledPaneAction, + NewTiledPluginPaneAction, + NextSwapLayoutAction, + NextSwapLayoutByTabIdAction, + NoOpAction, + OverrideLayoutAction, + PageScrollDownAction, + PageScrollDownByPaneIdAction, + PageScrollUpAction, + PageScrollUpByPaneIdAction, + PaneIdWithPlugin, + PaneNameInputAction, + PasteAction, + PreviousSwapLayoutAction, + PreviousSwapLayoutByTabIdAction, + QueryTabNamesAction, + QuitAction, + RenamePaneByPaneIdAction, + RenamePluginPaneAction, + RenameSessionAction, + RenameTabAction, + RenameTabByIdAction, + RenameTerminalPaneAction, + ResizeAction, + ResizeByPaneIdAction, + RunAction, + SaveSessionAction, + ScrollDownAction, + ScrollDownAtAction, + ScrollDownByPaneIdAction, + ScrollToBottomAction, + ScrollToBottomByPaneIdAction, + ScrollToTopAction, + ScrollToTopByPaneIdAction, + ScrollUpAction, + ScrollUpAtAction, + // Pane-targeting + ScrollUpByPaneIdAction, + SearchAction, + SearchInputAction, + SearchToggleOptionAction, + SetPaneBorderlessAction, + SetPaneColorAction, + ShowFloatingPanesAction, + SkipConfirmAction, + StackPanesAction, + StartOrReloadPluginAction, + SwitchFocusAction, + SwitchModeForAllClientsAction, + SwitchSessionAction, + SwitchToModeAction, + TabNameInputAction, + ToggleActiveSyncTabAction, + ToggleActiveSyncTabByTabIdAction, + ToggleFloatingPanesAction, + ToggleFloatingPanesByTabIdAction, + ToggleFocusFullscreenAction, + ToggleFullscreenByPaneIdAction, + ToggleGroupMarkingAction, + ToggleMouseModeAction, + TogglePaneBorderlessAction, + TogglePaneEmbedOrFloatingAction, + TogglePaneEmbedOrFloatingByPaneIdAction, + TogglePaneFramesAction, + TogglePaneInGroupAction, + TogglePanePinnedAction, + TogglePanePinnedByPaneIdAction, + ToggleTabAction, + UndoRenamePaneAction, + UndoRenamePaneByPaneIdAction, + UndoRenameTabAction, + // Tab-targeting + UndoRenameTabByTabIdAction, + WriteAction, + WriteCharsAction, + WriteCharsToPaneIdAction, WriteToPaneIdAction, }; use std::collections::HashMap; @@ -1472,6 +1580,134 @@ impl From<crate::input::actions::Action> bg, }) }, + // Pane-targeting CLI-only variants + crate::input::actions::Action::ScrollUpByPaneId { pane_id } => { + ActionType::ScrollUpByPaneId(ScrollUpByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ScrollDownByPaneId { pane_id } => { + ActionType::ScrollDownByPaneId(ScrollDownByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ScrollToTopByPaneId { pane_id } => { + ActionType::ScrollToTopByPaneId(ScrollToTopByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ScrollToBottomByPaneId { pane_id } => { + ActionType::ScrollToBottomByPaneId(ScrollToBottomByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::PageScrollUpByPaneId { pane_id } => { + ActionType::PageScrollUpByPaneId(PageScrollUpByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::PageScrollDownByPaneId { pane_id } => { + ActionType::PageScrollDownByPaneId(PageScrollDownByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::HalfPageScrollUpByPaneId { pane_id } => { + ActionType::HalfPageScrollUpByPaneId(HalfPageScrollUpByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::HalfPageScrollDownByPaneId { pane_id } => { + ActionType::HalfPageScrollDownByPaneId(HalfPageScrollDownByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ResizeByPaneId { + pane_id, + resize, + direction, + } => ActionType::ResizeByPaneId(ResizeByPaneIdAction { + pane_id: Some(pane_id.into()), + resize_action: Some(ResizeAction { + resize: resize_to_proto_i32(resize), + direction: direction.map(|d| direction_to_proto_i32(d)), + }), + }), + crate::input::actions::Action::MovePaneByPaneId { pane_id, direction } => { + ActionType::MovePaneByPaneId(MovePaneByPaneIdAction { + pane_id: Some(pane_id.into()), + direction: direction.map(|d| direction_to_proto_i32(d)), + }) + }, + crate::input::actions::Action::MovePaneBackwardsByPaneId { pane_id } => { + ActionType::MovePaneBackwardsByPaneId(MovePaneBackwardsByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ClearScreenByPaneId { pane_id } => { + ActionType::ClearScreenByPaneId(ClearScreenByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::EditScrollbackByPaneId { pane_id } => { + ActionType::EditScrollbackByPaneId(EditScrollbackByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::ToggleFocusFullscreenByPaneId { pane_id } => { + ActionType::ToggleFullscreenByPaneId(ToggleFullscreenByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::TogglePaneEmbedOrFloatingByPaneId { pane_id } => { + ActionType::TogglePaneEmbedOrFloatingByPaneId( + TogglePaneEmbedOrFloatingByPaneIdAction { + pane_id: Some(pane_id.into()), + }, + ) + }, + crate::input::actions::Action::CloseFocusByPaneId { pane_id } => { + ActionType::CloseFocusByPaneId(CloseFocusByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::RenamePaneByPaneId { pane_id, name } => { + ActionType::RenamePaneByPaneId(RenamePaneByPaneIdAction { + pane_id: Some(pane_id.into()), + name, + }) + }, + crate::input::actions::Action::UndoRenamePaneByPaneId { pane_id } => { + ActionType::UndoRenamePaneByPaneId(UndoRenamePaneByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + crate::input::actions::Action::TogglePanePinnedByPaneId { pane_id } => { + ActionType::TogglePanePinnedByPaneId(TogglePanePinnedByPaneIdAction { + pane_id: Some(pane_id.into()), + }) + }, + // Tab-targeting CLI-only variants + crate::input::actions::Action::UndoRenameTabByTabId { id } => { + ActionType::UndoRenameTabByTabId(UndoRenameTabByTabIdAction { id }) + }, + crate::input::actions::Action::ToggleActiveSyncTabByTabId { id } => { + ActionType::ToggleActiveSyncTabByTabId(ToggleActiveSyncTabByTabIdAction { id }) + }, + crate::input::actions::Action::ToggleFloatingPanesByTabId { id } => { + ActionType::ToggleFloatingPanesByTabId(ToggleFloatingPanesByTabIdAction { id }) + }, + crate::input::actions::Action::PreviousSwapLayoutByTabId { id } => { + ActionType::PreviousSwapLayoutByTabId(PreviousSwapLayoutByTabIdAction { id }) + }, + crate::input::actions::Action::NextSwapLayoutByTabId { id } => { + ActionType::NextSwapLayoutByTabId(NextSwapLayoutByTabIdAction { id }) + }, + crate::input::actions::Action::MoveTabByTabId { id, direction } => { + ActionType::MoveTabByTabId(MoveTabByTabIdAction { + id, + direction: direction_to_proto_i32(direction), + }) + }, }; Self { @@ -2180,6 +2416,197 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action> bg: set_pane_color_action.bg, }) }, + // Pane-targeting CLI-only variants + ActionType::ScrollUpByPaneId(a) => { + Ok(crate::input::actions::Action::ScrollUpByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ScrollUpByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ScrollDownByPaneId(a) => { + Ok(crate::input::actions::Action::ScrollDownByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ScrollDownByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ScrollToTopByPaneId(a) => { + Ok(crate::input::actions::Action::ScrollToTopByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ScrollToTopByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ScrollToBottomByPaneId(a) => { + Ok(crate::input::actions::Action::ScrollToBottomByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ScrollToBottomByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::PageScrollUpByPaneId(a) => { + Ok(crate::input::actions::Action::PageScrollUpByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("PageScrollUpByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::PageScrollDownByPaneId(a) => { + Ok(crate::input::actions::Action::PageScrollDownByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("PageScrollDownByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::HalfPageScrollUpByPaneId(a) => { + Ok(crate::input::actions::Action::HalfPageScrollUpByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("HalfPageScrollUpByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::HalfPageScrollDownByPaneId(a) => { + Ok(crate::input::actions::Action::HalfPageScrollDownByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("HalfPageScrollDownByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ResizeByPaneId(a) => { + let resize_action = a + .resize_action + .ok_or_else(|| anyhow!("ResizeByPaneId missing resize_action"))?; + let resize = proto_i32_to_resize(resize_action.resize)?; + let direction = resize_action + .direction + .map(|d| proto_i32_to_direction(d)) + .transpose()?; + Ok(crate::input::actions::Action::ResizeByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ResizeByPaneId missing pane_id"))? + .try_into()?, + resize, + direction, + }) + }, + ActionType::MovePaneByPaneId(a) => { + let direction = a.direction.map(|d| proto_i32_to_direction(d)).transpose()?; + Ok(crate::input::actions::Action::MovePaneByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("MovePaneByPaneId missing pane_id"))? + .try_into()?, + direction, + }) + }, + ActionType::MovePaneBackwardsByPaneId(a) => { + Ok(crate::input::actions::Action::MovePaneBackwardsByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("MovePaneBackwardsByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ClearScreenByPaneId(a) => { + Ok(crate::input::actions::Action::ClearScreenByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ClearScreenByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::EditScrollbackByPaneId(a) => { + Ok(crate::input::actions::Action::EditScrollbackByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("EditScrollbackByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::ToggleFullscreenByPaneId(a) => Ok( + crate::input::actions::Action::ToggleFocusFullscreenByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("ToggleFullscreenByPaneId missing pane_id"))? + .try_into()?, + }, + ), + ActionType::TogglePaneEmbedOrFloatingByPaneId(a) => Ok( + crate::input::actions::Action::TogglePaneEmbedOrFloatingByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| { + anyhow!("TogglePaneEmbedOrFloatingByPaneId missing pane_id") + })? + .try_into()?, + }, + ), + ActionType::CloseFocusByPaneId(a) => { + Ok(crate::input::actions::Action::CloseFocusByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("CloseFocusByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::RenamePaneByPaneId(a) => { + Ok(crate::input::actions::Action::RenamePaneByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("RenamePaneByPaneId missing pane_id"))? + .try_into()?, + name: a.name, + }) + }, + ActionType::UndoRenamePaneByPaneId(a) => { + Ok(crate::input::actions::Action::UndoRenamePaneByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("UndoRenamePaneByPaneId missing pane_id"))? + .try_into()?, + }) + }, + ActionType::TogglePanePinnedByPaneId(a) => { + Ok(crate::input::actions::Action::TogglePanePinnedByPaneId { + pane_id: a + .pane_id + .ok_or_else(|| anyhow!("TogglePanePinnedByPaneId missing pane_id"))? + .try_into()?, + }) + }, + // Tab-targeting CLI-only variants + ActionType::UndoRenameTabByTabId(a) => { + Ok(crate::input::actions::Action::UndoRenameTabByTabId { id: a.id }) + }, + ActionType::ToggleActiveSyncTabByTabId(a) => { + Ok(crate::input::actions::Action::ToggleActiveSyncTabByTabId { id: a.id }) + }, + ActionType::ToggleFloatingPanesByTabId(a) => { + Ok(crate::input::actions::Action::ToggleFloatingPanesByTabId { id: a.id }) + }, + ActionType::PreviousSwapLayoutByTabId(a) => { + Ok(crate::input::actions::Action::PreviousSwapLayoutByTabId { id: a.id }) + }, + ActionType::NextSwapLayoutByTabId(a) => { + Ok(crate::input::actions::Action::NextSwapLayoutByTabId { id: a.id }) + }, + ActionType::MoveTabByTabId(a) => { + let direction = proto_i32_to_direction(a.direction)?; + Ok(crate::input::actions::Action::MoveTabByTabId { + id: a.id, + direction, + }) + }, } } } diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs index b4dbb163..3202f28a 100644 --- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs +++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs @@ -3076,6 +3076,230 @@ fn test_client_messages() { pane_ids: vec![PaneId::Terminal(1)], scrollback: Some(0), }); + // Pane-targeting roundtrips + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ScrollUpByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ScrollUpByPaneId { + pane_id: PaneId::Plugin(5), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ScrollDownByPaneId { + pane_id: PaneId::Terminal(2), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ScrollToTopByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ScrollToBottomByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::PageScrollUpByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::PageScrollDownByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::HalfPageScrollUpByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::HalfPageScrollDownByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ResizeByPaneId { + pane_id: PaneId::Terminal(1), + resize: Resize::Increase, + direction: Some(Direction::Left), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ResizeByPaneId { + pane_id: PaneId::Terminal(1), + resize: Resize::Decrease, + direction: None, + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::MovePaneByPaneId { + pane_id: PaneId::Terminal(3), + direction: Some(Direction::Up), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::MovePaneByPaneId { + pane_id: PaneId::Terminal(3), + direction: None, + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::MovePaneBackwardsByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ClearScreenByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::EditScrollbackByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ToggleFocusFullscreenByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::TogglePaneEmbedOrFloatingByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::CloseFocusByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::RenamePaneByPaneId { + pane_id: PaneId::Terminal(1), + name: "test-name".as_bytes().to_vec(), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::UndoRenamePaneByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::TogglePanePinnedByPaneId { + pane_id: PaneId::Terminal(1), + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + // Tab-targeting roundtrips + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::UndoRenameTabByTabId { id: 5 }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ToggleActiveSyncTabByTabId { id: 2 }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::ToggleFloatingPanesByTabId { id: 0 }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::PreviousSwapLayoutByTabId { id: 1 }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::NextSwapLayoutByTabId { id: 3 }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::MoveTabByTabId { + id: 1, + direction: Direction::Left, + }, + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); } fn test_server_messages() { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index aef9d881..9117bee5 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -1065,8 +1065,33 @@ impl TryFrom<Action> for ProtobufAction { | Action::Paste { .. } | Action::GoToTabById { .. } | Action::CloseTabById { .. } - | Action::RenameTabById { .. } => { - Err("WriteToPaneId, WriteCharsToPaneId, Paste, GoToTabById, CloseTabById, and RenameTabById are CLI-only actions, not available in keybindings") + | Action::RenameTabById { .. } + | Action::ScrollUpByPaneId { .. } + | Action::ScrollDownByPaneId { .. } + | Action::ScrollToTopByPaneId { .. } + | Action::ScrollToBottomByPaneId { .. } + | Action::PageScrollUpByPaneId { .. } + | Action::PageScrollDownByPaneId { .. } + | Action::HalfPageScrollUpByPaneId { .. } + | Action::HalfPageScrollDownByPaneId { .. } + | Action::ResizeByPaneId { .. } + | Action::MovePaneByPaneId { .. } + | Action::MovePaneBackwardsByPaneId { .. } + | Action::ClearScreenByPaneId { .. } + | Action::EditScrollbackByPaneId { .. } + | Action::ToggleFocusFullscreenByPaneId { .. } + | Action::TogglePaneEmbedOrFloatingByPaneId { .. } + | Action::CloseFocusByPaneId { .. } + | Action::RenamePaneByPaneId { .. } + | Action::UndoRenamePaneByPaneId { .. } + | Action::TogglePanePinnedByPaneId { .. } + | Action::UndoRenameTabByTabId { .. } + | Action::ToggleActiveSyncTabByTabId { .. } + | Action::ToggleFloatingPanesByTabId { .. } + | Action::PreviousSwapLayoutByTabId { .. } + | Action::NextSwapLayoutByTabId { .. } + | Action::MoveTabByTabId { .. } => { + Err("These are CLI-only actions, not available in keybindings") }, Action::SwitchToMode { input_mode } => { let input_mode: ProtobufInputMode = input_mode.try_into()?; @@ -1157,14 +1182,12 @@ impl TryFrom<Action> for ProtobufAction { let dump_to_stdout = file_path.is_none(); Ok(ProtobufAction { name: ProtobufActionName::DumpScreen as i32, - optional_payload: Some(OptionalPayload::DumpScreenPayload( - DumpScreenPayload { - file_path: file_path.unwrap_or_default(), - include_scrollback, - pane_id: pane_id.and_then(|p| p.try_into().ok()), - dump_to_stdout, - }, - )), + optional_payload: Some(OptionalPayload::DumpScreenPayload(DumpScreenPayload { + file_path: file_path.unwrap_or_default(), + include_scrollback, + pane_id: pane_id.and_then(|p| p.try_into().ok()), + dump_to_stdout, + })), }) }, Action::EditScrollback => Ok(ProtobufAction { |
