aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-06-29 18:10:59 +0200
committerGitHub <noreply@github.com>2026-06-29 18:10:59 +0200
commit245f5141c9bb7eb91f003efac4defc94470243fd (patch)
tree52ae6d003366f97e41c8a1450602aef63c8fdca2
parentfeat: reload config on theme change (#5135) (diff)
downloadsl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.gz
sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.xz
sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.zip
Title frames (#5318)
* initial implementation * improve single line title design * hint text plugin infra * add proto regen task * display alt text in status bar * don't display text with full frames * style alt hover text * fix + style control own pane hover * make multiplayer indications responsive * update snapshots * plugin api * single pane as tab * better scroll styling * fix tests * tab-bar plus hover * plugin surface tests * integration tests * adjust all integration tests * reduce hover noise * add pane id to in place * more integration tests * style: rustfmt * update plugin assets * update assets and snapshots * add pr
-rw-r--r--CHANGELOG.md1
-rw-r--r--default-plugins/fixture-plugin-for-tests/src/main.rs5
-rw-r--r--default-plugins/status-bar/src/main.rs94
-rw-r--r--default-plugins/status-bar/src/one_line_ui.rs492
-rw-r--r--default-plugins/tab-bar/src/line.rs74
-rw-r--r--default-plugins/tab-bar/src/main.rs49
-rw-r--r--default-plugins/tab-bar/src/tab.rs13
-rw-r--r--src/main.rs2
-rw-r--r--src/tests/e2e/cases.rs18
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap47
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap46
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap48
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap46
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap46
-rw-r--r--xtask/src/build.rs15
-rw-r--r--xtask/src/flags.rs6
-rw-r--r--xtask/src/main.rs1
-rw-r--r--zellij-integration-tests/src/harness.rs6
-rw-r--r--zellij-integration-tests/src/runner.rs1
-rw-r--r--zellij-integration-tests/src/test_env.rs1
-rw-r--r--zellij-integration-tests/tests/app.rs5
-rw-r--r--zellij-integration-tests/tests/basic.rs8
-rw-r--r--zellij-integration-tests/tests/cli.rs10
-rw-r--r--zellij-integration-tests/tests/clients.rs30
-rw-r--r--zellij-integration-tests/tests/misc.rs2
-rw-r--r--zellij-integration-tests/tests/modes.rs12
-rw-r--r--zellij-integration-tests/tests/mouse.rs4
-rw-r--r--zellij-integration-tests/tests/panes.rs165
-rw-r--r--zellij-integration-tests/tests/resize.rs4
-rw-r--r--zellij-integration-tests/tests/resurrection.rs4
-rw-r--r--zellij-integration-tests/tests/scroll.rs36
-rw-r--r--zellij-integration-tests/tests/search.rs38
-rw-r--r--zellij-integration-tests/tests/set_pane_frame_style.rs120
-rw-r--r--zellij-integration-tests/tests/single_pane_tab_title.rs128
-rw-r--r--zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap26
-rw-r--r--zellij-integration-tests/tests/snapshots/basic__resize_pane.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap26
-rw-r--r--zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap2
-rw-r--r--zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap2
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__lock_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap41
-rw-r--r--zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap19
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__close_pane.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap2
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap36
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap28
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap28
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap28
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap36
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap4
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap26
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap36
-rw-r--r--zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap38
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap29
-rw-r--r--zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap26
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap6
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap6
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap6
-rw-r--r--zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap48
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__close_tab.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap27
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap46
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap25
-rw-r--r--zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap18
-rw-r--r--zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap28
-rw-r--r--zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap28
-rw-r--r--zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap7
-rw-r--r--zellij-integration-tests/tests/tabs.rs9
-rw-r--r--zellij-integration-tests/tests/title_frame_hints.rs233
-rw-r--r--zellij-integration-tests/tests/title_frame_mouse.rs158
-rw-r--r--zellij-integration-tests/tests/title_frame_scroll.rs58
-rw-r--r--zellij-server/src/lib.rs4
-rw-r--r--zellij-server/src/panes/floating_panes/mod.rs1
-rw-r--r--zellij-server/src/panes/terminal_pane.rs10
-rw-r--r--zellij-server/src/panes/tiled_panes/mod.rs87
-rw-r--r--zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs6
-rw-r--r--zellij-server/src/plugins/mod.rs5
-rw-r--r--zellij-server/src/plugins/unit/plugin_tests.rs232
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap29
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap21
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap21
-rw-r--r--zellij-server/src/plugins/wasm_bridge.rs2
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs39
-rw-r--r--zellij-server/src/route.rs21
-rw-r--r--zellij-server/src/screen.rs77
-rw-r--r--zellij-server/src/tab/layout_applier.rs17
-rw-r--r--zellij-server/src/tab/mod.rs230
-rw-r--r--zellij-server/src/tab/mouse_handler.rs82
-rw-r--r--zellij-server/src/tab/unit/layout_applier_tests.rs9
-rw-r--r--zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap16
-rw-r--r--zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap10
-rw-r--r--zellij-server/src/tab/unit/tab_integration_tests.rs27
-rw-r--r--zellij-server/src/tab/unit/tab_tests.rs9
-rw-r--r--zellij-server/src/ui/hint_text.rs303
-rw-r--r--zellij-server/src/ui/mod.rs1
-rw-r--r--zellij-server/src/ui/pane_boundaries_frame.rs402
-rw-r--r--zellij-server/src/ui/pane_contents_and_ui.rs8
-rw-r--r--zellij-server/src/unit/screen_tests.rs25
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap1
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap6
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap2
-rw-r--r--zellij-tile/src/shim.rs21
-rw-r--r--zellij-tile/src/ui_components/text.rs12
-rwxr-xr-xzellij-utils/assets/plugins/about.wasmbin1480015 -> 1514076 bytes
-rwxr-xr-xzellij-utils/assets/plugins/compact-bar.wasmbin1672767 -> 1706211 bytes
-rwxr-xr-xzellij-utils/assets/plugins/configuration.wasmbin1539390 -> 1570529 bytes
-rwxr-xr-xzellij-utils/assets/plugins/fixture-plugin-for-tests.wasmbin1626945 -> 1667362 bytes
-rwxr-xr-xzellij-utils/assets/plugins/layout-manager.wasmbin1822121 -> 1854570 bytes
-rwxr-xr-xzellij-utils/assets/plugins/link.wasmbin1261935 -> 1291115 bytes
-rwxr-xr-xzellij-utils/assets/plugins/mobile.wasmbin1505278 -> 1584657 bytes
-rwxr-xr-xzellij-utils/assets/plugins/multiple-select.wasmbin1476362 -> 1510648 bytes
-rwxr-xr-xzellij-utils/assets/plugins/plugin-manager.wasmbin1438666 -> 1470625 bytes
-rwxr-xr-xzellij-utils/assets/plugins/session-manager.wasmbin1605727 -> 1692291 bytes
-rwxr-xr-xzellij-utils/assets/plugins/share.wasmbin1434349 -> 1467285 bytes
-rwxr-xr-xzellij-utils/assets/plugins/status-bar.wasmbin1621222 -> 1659571 bytes
-rwxr-xr-xzellij-utils/assets/plugins/strider.wasmbin1630868 -> 1668558 bytes
-rwxr-xr-xzellij-utils/assets/plugins/tab-bar.wasmbin1547574 -> 1725835 bytes
-rw-r--r--zellij-utils/assets/prost/api.action.rs13
-rw-r--r--zellij-utils/assets/prost/api.event.rs71
-rw-r--r--zellij-utils/assets/prost/api.pane_frame_style.rs29
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs27
-rw-r--r--zellij-utils/assets/prost/generated_plugin_api.rs3
-rw-r--r--zellij-utils/assets/prost_ipc/client_server_contract.rs12
-rw-r--r--zellij-utils/src/cli.rs19
-rw-r--r--zellij-utils/src/client_server_contract/common_types.proto5
-rw-r--r--zellij-utils/src/data.rs15
-rw-r--r--zellij-utils/src/errors.rs2
-rw-r--r--zellij-utils/src/input/actions.rs111
-rw-r--r--zellij-utils/src/input/mod.rs1
-rw-r--r--zellij-utils/src/input/options.rs78
-rw-r--r--zellij-utils/src/ipc/protobuf_conversion.rs31
-rw-r--r--zellij-utils/src/ipc/tests/roundtrip_tests.rs23
-rw-r--r--zellij-utils/src/kdl/mod.rs79
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap7
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap7
-rw-r--r--zellij-utils/src/plugin_api/action.proto7
-rw-r--r--zellij-utils/src/plugin_api/action.rs42
-rw-r--r--zellij-utils/src/plugin_api/event.proto29
-rw-r--r--zellij-utils/src/plugin_api/event.rs176
-rw-r--r--zellij-utils/src/plugin_api/mod.rs1
-rw-r--r--zellij-utils/src/plugin_api/pane_frame_style.proto9
-rw-r--r--zellij-utils/src/plugin_api/pane_frame_style.rs49
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto14
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs110
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap1
292 files changed, 5558 insertions, 3152 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d5d8372..d0bfd03b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* chore: new integration testing infra (https://github.com/zellij-org/zellij/pull/5269)
* feat: FocusLastPane bindable action (https://github.com/zellij-org/zellij/pull/4241)
* fix: live reload on theme dir changes (https://github.com/zellij-org/zellij/pull/5135)
+* feat: new title-frames UI (https://github.com/zellij-org/zellij/pull/5318)
## [0.44.3] - 2026-05-13
* fix(windows): bump windows-sys to 0.59 to align manifest with code, fixing source builds via `cargo install`/`cargo binstall` (https://github.com/zellij-org/zellij/pull/5139)
diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs
index 4885054c..ec656443 100644
--- a/default-plugins/fixture-plugin-for-tests/src/main.rs
+++ b/default-plugins/fixture-plugin-for-tests/src/main.rs
@@ -173,6 +173,8 @@ impl ZellijPlugin for State {
BareKey::Char('6') if key.has_no_modifiers() => close_focused_tab(),
BareKey::Char('7') if key.has_no_modifiers() => undo_rename_tab(),
BareKey::Char('8') if key.has_no_modifiers() => quit_zellij(),
+ BareKey::Char('9') if key.has_no_modifiers() => new_pane(),
+ BareKey::Char('0') if key.has_no_modifiers() => toggle_floating_panes(None),
BareKey::Char('a') if key.has_only_modifiers(&[KeyModifier::Ctrl]) => {
previous_swap_layout()
},
@@ -626,6 +628,9 @@ impl ZellijPlugin for State {
// Test clear_pane_highlights
clear_pane_highlights(PaneId::Terminal(1));
},
+ BareKey::Char('i') if key.has_only_modifiers(&[KeyModifier::Super]) => {
+ toggle_floating_panes(Some(2));
+ },
BareKey::Char('a')
if key.has_only_modifiers(&[KeyModifier::Ctrl, KeyModifier::Shift]) =>
{
diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs
index 5412e6b6..6cffc5c7 100644
--- a/default-plugins/status-bar/src/main.rs
+++ b/default-plugins/status-bar/src/main.rs
@@ -42,6 +42,12 @@ struct State {
classic_ui: bool,
base_mode_is_locked: bool,
cached_keybinds: KeybindsVec,
+ hint_text: Option<BTreeMap<usize, StyledText>>,
+ outstanding_hint_timeouts: usize,
+ new_pane_ribbon_range: Option<(usize, usize)>,
+ floating_ribbon_range: Option<(usize, usize)>,
+ new_pane_ribbon_hovered: bool,
+ floating_ribbon_hovered: bool,
}
register_plugin!(State);
@@ -192,6 +198,13 @@ fn color_elements(palette: Styling, different_color_alternates: bool) -> Colored
}
}
+fn col_in_range(range: Option<(usize, usize)>, col: usize) -> bool {
+ match range {
+ Some((start, end)) => col >= start && col < end,
+ None => false,
+ }
+}
+
impl ZellijPlugin for State {
fn load(&mut self, configuration: BTreeMap<String, String>) {
// TODO: Should be able to choose whether to use the cache through config.
@@ -209,6 +222,9 @@ impl ZellijPlugin for State {
EventType::InputReceived,
EventType::SystemClipboardFailure,
EventType::InitialKeybinds,
+ EventType::HintText,
+ EventType::Timer,
+ EventType::Mouse,
]);
}
@@ -260,11 +276,55 @@ impl ZellijPlugin for State {
Event::InputReceived => {
if self.text_copy_destination.is_some()
|| self.display_system_clipboard_failure == true
+ || self.hint_text.is_some()
{
should_render = true;
}
self.text_copy_destination = None;
self.display_system_clipboard_failure = false;
+ self.hint_text = None;
+ },
+ Event::HintText(hint_variants) => {
+ if hint_variants.is_empty() {
+ if self.hint_text.is_some() {
+ self.hint_text = None;
+ should_render = true;
+ }
+ } else {
+ self.hint_text = Some(hint_variants);
+ self.outstanding_hint_timeouts += 1;
+ set_timeout(5.0);
+ should_render = true;
+ }
+ },
+ Event::Timer(_) => {
+ self.outstanding_hint_timeouts = self.outstanding_hint_timeouts.saturating_sub(1);
+ if self.outstanding_hint_timeouts == 0 && self.hint_text.is_some() {
+ self.hint_text = None;
+ should_render = true;
+ }
+ },
+ Event::Mouse(mouse_event) => match mouse_event {
+ Mouse::LeftClick(_, col) => {
+ if col_in_range(self.new_pane_ribbon_range, col) {
+ new_pane();
+ } else if col_in_range(self.floating_ribbon_range, col) {
+ toggle_floating_panes(None);
+ }
+ },
+ Mouse::Hover(_, col) => {
+ let new_pane_hovered = col_in_range(self.new_pane_ribbon_range, col);
+ let floating_hovered =
+ !new_pane_hovered && col_in_range(self.floating_ribbon_range, col);
+ if self.new_pane_ribbon_hovered != new_pane_hovered
+ || self.floating_ribbon_hovered != floating_hovered
+ {
+ self.new_pane_ribbon_hovered = new_pane_hovered;
+ self.floating_ribbon_hovered = floating_hovered;
+ should_render = true;
+ }
+ },
+ _ => {},
},
_ => {},
};
@@ -287,21 +347,31 @@ impl ZellijPlugin for State {
PaletteColor::EightBit(color) => format!("\u{1b}[48;5;{}m\u{1b}[0K", color),
};
let active_tab = self.tabs.iter().find(|t| t.active);
- print!(
- "{}{}",
- one_line_ui(
- &self.mode_info,
- active_tab,
- cols,
- separator,
- self.base_mode_is_locked,
- self.text_copy_destination,
- self.display_system_clipboard_failure,
- ),
- fill_bg,
+ let full_pane_frames = self.mode_info.pane_frame_style == Some(PaneFrameStyle::Full);
+ let hint_text = if full_pane_frames {
+ None
+ } else {
+ self.hint_text.as_ref()
+ };
+ let (line, new_pane_ribbon_range, floating_ribbon_range) = one_line_ui(
+ &self.mode_info,
+ active_tab,
+ cols,
+ separator,
+ self.base_mode_is_locked,
+ self.text_copy_destination,
+ self.display_system_clipboard_failure,
+ hint_text,
+ self.new_pane_ribbon_hovered,
+ self.floating_ribbon_hovered,
);
+ self.new_pane_ribbon_range = new_pane_ribbon_range;
+ self.floating_ribbon_range = floating_ribbon_range;
+ print!("{}{}", line, fill_bg);
return;
}
+ self.new_pane_ribbon_range = None;
+ self.floating_ribbon_range = None;
//TODO: Switch to UI components here
let active_tab = self.tabs.iter().find(|t| t.active);
diff --git a/default-plugins/status-bar/src/one_line_ui.rs b/default-plugins/status-bar/src/one_line_ui.rs
index d997fb36..97721167 100644
--- a/default-plugins/status-bar/src/one_line_ui.rs
+++ b/default-plugins/status-bar/src/one_line_ui.rs
@@ -3,10 +3,10 @@ use ansi_term::{
Color::{Fixed, RGB},
Style,
};
-use std::collections::HashMap;
+use std::collections::{BTreeMap, HashMap};
use zellij_tile::prelude::actions::Action;
use zellij_tile::prelude::*;
-use zellij_tile_utils::palette_match;
+use zellij_tile_utils::{palette_match, style};
use crate::first_line::{to_char, KeyAction, KeyMode, KeyShortcut};
use crate::second_line::{system_clipboard_error, text_copied_hint};
@@ -22,30 +22,69 @@ pub fn one_line_ui(
base_mode_is_locked: bool,
text_copied_to_clipboard_destination: Option<CopyDestination>,
clipboard_failure: bool,
-) -> LinePart {
+ hint: Option<&BTreeMap<usize, StyledText>>,
+ new_pane_hovered: bool,
+ floating_hovered: bool,
+) -> (LinePart, Option<(usize, usize)>, Option<(usize, usize)>) {
if let Some(text_copied_to_clipboard_destination) = text_copied_to_clipboard_destination {
- return text_copied_hint(text_copied_to_clipboard_destination);
+ return (
+ text_copied_hint(text_copied_to_clipboard_destination),
+ None,
+ None,
+ );
}
if clipboard_failure {
- return system_clipboard_error(&help.style.colors);
+ return (system_clipboard_error(&help.style.colors), None, None);
}
let mut line_part_to_render = LinePart::default();
- let mut append = |line_part: &LinePart, max_len: &mut usize| {
- line_part_to_render.append(line_part);
- *max_len = max_len.saturating_sub(line_part.len);
- };
+ let mut new_pane_range = None;
+ let mut floating_range = None;
+
+ let left_part = hint
+ .and_then(|hint| hint_line_part(hint, max_len))
+ .or_else(|| render_mode_key_indicators(help, max_len, separator, base_mode_is_locked));
+ if let Some(left) = left_part {
+ line_part_to_render.append(&left);
+ max_len = max_len.saturating_sub(left.len);
+ match help.mode {
+ InputMode::Normal | InputMode::Locked => {
+ let secondary_offset = line_part_to_render.len;
+ if let Some((secondary_info, new_pane, floating)) = render_secondary_info(
+ help,
+ tab_info,
+ max_len,
+ new_pane_hovered,
+ floating_hovered,
+ ) {
+ new_pane_range = new_pane
+ .map(|(start, end)| (secondary_offset + start, secondary_offset + end));
+ floating_range = floating
+ .map(|(start, end)| (secondary_offset + start, secondary_offset + end));
+ line_part_to_render.append(&secondary_info);
+ }
+ },
+ _ => {
+ if let Some(key_group_separator) = add_keygroup_separator(help, max_len) {
+ line_part_to_render.append(&key_group_separator);
+ max_len = max_len.saturating_sub(key_group_separator.len);
+ if let Some(keybinds) = keybinds(help, max_len) {
+ line_part_to_render.append(&keybinds);
+ }
+ }
+ },
+ }
+ }
+ (line_part_to_render, new_pane_range, floating_range)
+}
- render_mode_key_indicators(help, max_len, separator, base_mode_is_locked)
- .map(|mode_key_indicators| append(&mode_key_indicators, &mut max_len))
- .and_then(|_| match help.mode {
- InputMode::Normal | InputMode::Locked => render_secondary_info(help, tab_info, max_len)
- .map(|secondary_info| append(&secondary_info, &mut max_len)),
- _ => add_keygroup_separator(help, max_len)
- .map(|key_group_separator| append(&key_group_separator, &mut max_len))
- .and_then(|_| keybinds(help, max_len))
- .map(|keybinds| append(&keybinds, &mut max_len)),
- });
- line_part_to_render
+fn hint_line_part(hint: &BTreeMap<usize, StyledText>, max_len: usize) -> Option<LinePart> {
+ let fitting_variant = hint
+ .range(..=max_len)
+ .next_back()
+ .map(|(_width, styled_text)| styled_text)?;
+ let len = fitting_variant.text.width();
+ let part = serialize_text(&Text::from(fitting_variant.clone()));
+ Some(LinePart { part, len })
}
fn to_base_mode(base_mode: InputMode) -> Action {
@@ -730,11 +769,14 @@ fn render_secondary_info(
help: &ModeInfo,
tab_info: Option<&TabInfo>,
max_len: usize,
-) -> Option<LinePart> {
+ new_pane_hovered: bool,
+ floating_hovered: bool,
+) -> Option<(LinePart, Option<(usize, usize)>, Option<(usize, usize)>)> {
let mut secondary_info = LinePart::default();
let supports_arrow_fonts = !help.capabilities.arrow_fonts;
let colored_elements = color_elements(help.style.colors, !supports_arrow_fonts);
- let secondary_keybinds = secondary_keybinds(&help, tab_info, max_len);
+ let (secondary_keybinds, new_pane_range, floating_range) =
+ secondary_keybinds(&help, tab_info, max_len, new_pane_hovered, floating_hovered);
secondary_info.append(&secondary_keybinds);
let remaining_space = max_len.saturating_sub(secondary_info.len).saturating_sub(1); // 1 for the end padding of the line
let mut padding = String::new();
@@ -746,7 +788,10 @@ fn render_secondary_info(
secondary_info.part = format!("{}{}", padding, secondary_info.part);
secondary_info.len += padding_len;
if secondary_info.len <= max_len {
- Some(secondary_info)
+ let shift = |range: Option<(usize, usize)>| {
+ range.map(|(start, end)| (start + padding_len, end + padding_len))
+ };
+ Some((secondary_info, shift(new_pane_range), shift(floating_range)))
} else {
None
}
@@ -764,8 +809,16 @@ fn should_show_focus_and_resize_shortcuts(tab_info: Option<&TabInfo>) -> bool {
}
}
-fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usize) -> LinePart {
+fn secondary_keybinds(
+ help: &ModeInfo,
+ tab_info: Option<&TabInfo>,
+ max_len: usize,
+ new_pane_hovered: bool,
+ floating_hovered: bool,
+) -> (LinePart, Option<(usize, usize)>, Option<(usize, usize)>) {
let mut secondary_info = LinePart::default();
+ let mut new_pane_range;
+ let mut floating_range;
let binds = &help.get_mode_keybinds();
let should_show_focus_and_resize_shortcuts = should_show_focus_and_resize_shortcuts(tab_info);
// New Pane
@@ -908,13 +961,24 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
let no_common_modifier = common_modifiers.is_empty();
if no_common_modifier {
- secondary_info.append(&add_shortcut(
- help,
- "New Pane",
- &new_pane_key_to_display,
- false,
- Some(0),
- ));
+ let new_pane_start = secondary_info.len;
+ if new_pane_hovered {
+ secondary_info.append(&add_shortcut_hovered(
+ help,
+ "New Pane",
+ &new_pane_key_to_display,
+ Some(0),
+ ));
+ } else {
+ secondary_info.append(&add_shortcut(
+ help,
+ "New Pane",
+ &new_pane_key_to_display,
+ false,
+ Some(0),
+ ));
+ }
+ new_pane_range = ribbon_range(new_pane_start, secondary_info.len);
if should_show_focus_and_resize_shortcuts {
secondary_info.append(&add_shortcut(
help,
@@ -931,13 +995,24 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
Some(0),
));
}
- secondary_info.append(&add_shortcut(
- help,
- "Floating",
- &toggle_floating_key_to_display,
- are_floating_panes_visible,
- Some(0),
- ));
+ let floating_start = secondary_info.len;
+ if floating_hovered {
+ secondary_info.append(&add_shortcut_hovered(
+ help,
+ "Floating",
+ &toggle_floating_key_to_display,
+ Some(0),
+ ));
+ } else {
+ secondary_info.append(&add_shortcut(
+ help,
+ "Floating",
+ &toggle_floating_key_to_display,
+ are_floating_panes_visible,
+ Some(0),
+ ));
+ }
+ floating_range = ribbon_range(floating_start, secondary_info.len);
} else {
let modifier_str = text_as_line_part_with_emphasis(
format!(
@@ -967,12 +1042,22 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
.iter()
.map(|k| k.strip_common_modifiers(&common_modifiers))
.collect();
- secondary_info.append(&add_shortcut_with_inline_key(
- help,
- "New Pane",
- new_pane_key_to_display,
- false,
- ));
+ let new_pane_start = secondary_info.len;
+ if new_pane_hovered {
+ secondary_info.append(&add_shortcut_with_inline_key_hovered(
+ help,
+ "New Pane",
+ new_pane_key_to_display,
+ ));
+ } else {
+ secondary_info.append(&add_shortcut_with_inline_key(
+ help,
+ "New Pane",
+ new_pane_key_to_display,
+ false,
+ ));
+ }
+ new_pane_range = ribbon_range(new_pane_start, secondary_info.len);
if should_show_focus_and_resize_shortcuts {
secondary_info.append(&add_shortcut_with_inline_key(
help,
@@ -987,19 +1072,38 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
false,
));
}
- secondary_info.append(&add_shortcut_with_inline_key(
- help,
- "Floating",
- toggle_floating_key_to_display,
- are_floating_panes_visible,
- ));
+ let floating_start = secondary_info.len;
+ if floating_hovered {
+ secondary_info.append(&add_shortcut_with_inline_key_hovered(
+ help,
+ "Floating",
+ toggle_floating_key_to_display,
+ ));
+ } else {
+ secondary_info.append(&add_shortcut_with_inline_key(
+ help,
+ "Floating",
+ toggle_floating_key_to_display,
+ are_floating_panes_visible,
+ ));
+ }
+ floating_range = ribbon_range(floating_start, secondary_info.len);
}
if secondary_info.len <= max_len {
- secondary_info
- } else {
- let mut short_line = LinePart::default();
- if no_common_modifier {
+ return (secondary_info, new_pane_range, floating_range);
+ }
+ let mut short_line = LinePart::default();
+ if no_common_modifier {
+ let new_pane_start = short_line.len;
+ if new_pane_hovered {
+ short_line.append(&add_shortcut_hovered(
+ help,
+ "New",
+ &new_pane_key_to_display,
+ Some(0),
+ ));
+ } else {
short_line.append(&add_shortcut(
help,
"New",
@@ -1007,22 +1111,33 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
false,
Some(0),
));
- if should_show_focus_and_resize_shortcuts {
- short_line.append(&add_shortcut(
- help,
- "Focus",
- &move_focus_shortcuts,
- false,
- Some(0),
- ));
- short_line.append(&add_shortcut(
- help,
- "Resize",
- &resize_shortcuts,
- false,
- Some(0),
- ));
- }
+ }
+ new_pane_range = ribbon_range(new_pane_start, short_line.len);
+ if should_show_focus_and_resize_shortcuts {
+ short_line.append(&add_shortcut(
+ help,
+ "Focus",
+ &move_focus_shortcuts,
+ false,
+ Some(0),
+ ));
+ short_line.append(&add_shortcut(
+ help,
+ "Resize",
+ &resize_shortcuts,
+ false,
+ Some(0),
+ ));
+ }
+ let floating_start = short_line.len;
+ if floating_hovered {
+ short_line.append(&add_shortcut_hovered(
+ help,
+ "Floating",
+ &toggle_floating_key_to_display,
+ Some(0),
+ ));
+ } else {
short_line.append(&add_shortcut(
help,
"Floating",
@@ -1030,56 +1145,75 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
are_floating_panes_visible,
Some(0),
));
- } else {
- let modifier_str = text_as_line_part_with_emphasis(
- format!(
- "{} + ",
- common_modifiers
- .iter()
- .map(|m| m.to_string())
- .collect::<Vec<_>>()
- .join("-")
- ),
- 0,
- );
- short_line.append(&modifier_str);
- let new_pane_key_to_display: Vec<KeyWithModifier> = new_pane_key_to_display
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let move_focus_shortcuts: Vec<KeyWithModifier> = move_focus_shortcuts
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let resize_shortcuts: Vec<KeyWithModifier> = resize_shortcuts
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let toggle_floating_key_to_display: Vec<KeyWithModifier> =
- toggle_floating_key_to_display
+ }
+ floating_range = ribbon_range(floating_start, short_line.len);
+ } else {
+ let modifier_str = text_as_line_part_with_emphasis(
+ format!(
+ "{} + ",
+ common_modifiers
.iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
+ .map(|m| m.to_string())
+ .collect::<Vec<_>>()
+ .join("-")
+ ),
+ 0,
+ );
+ short_line.append(&modifier_str);
+ let new_pane_key_to_display: Vec<KeyWithModifier> = new_pane_key_to_display
+ .iter()
+ .map(|k| k.strip_common_modifiers(&common_modifiers))
+ .collect();
+ let move_focus_shortcuts: Vec<KeyWithModifier> = move_focus_shortcuts
+ .iter()
+ .map(|k| k.strip_common_modifiers(&common_modifiers))
+ .collect();
+ let resize_shortcuts: Vec<KeyWithModifier> = resize_shortcuts
+ .iter()
+ .map(|k| k.strip_common_modifiers(&common_modifiers))
+ .collect();
+ let toggle_floating_key_to_display: Vec<KeyWithModifier> = toggle_floating_key_to_display
+ .iter()
+ .map(|k| k.strip_common_modifiers(&common_modifiers))
+ .collect();
+ let new_pane_start = short_line.len;
+ if new_pane_hovered {
+ short_line.append(&add_shortcut_with_inline_key_hovered(
+ help,
+ "New",
+ new_pane_key_to_display,
+ ));
+ } else {
short_line.append(&add_shortcut_with_inline_key(
help,
"New",
new_pane_key_to_display,
false,
));
- if should_show_focus_and_resize_shortcuts {
- short_line.append(&add_shortcut_with_inline_key(
- help,
- "Focus",
- move_focus_shortcuts,
- false,
- ));
- short_line.append(&add_shortcut_with_inline_key(
- help,
- "Resize",
- resize_shortcuts,
- false,
- ));
- }
+ }
+ new_pane_range = ribbon_range(new_pane_start, short_line.len);
+ if should_show_focus_and_resize_shortcuts {
+ short_line.append(&add_shortcut_with_inline_key(
+ help,
+ "Focus",
+ move_focus_shortcuts,
+ false,
+ ));
+ short_line.append(&add_shortcut_with_inline_key(
+ help,
+ "Resize",
+ resize_shortcuts,
+ false,
+ ));
+ }
+ let floating_start = short_line.len;
+ if floating_hovered {
+ short_line.append(&add_shortcut_with_inline_key_hovered(
+ help,
+ "Floating",
+ toggle_floating_key_to_display,
+ ));
+ } else {
short_line.append(&add_shortcut_with_inline_key(
help,
"Floating",
@@ -1087,22 +1221,27 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
are_floating_panes_visible,
));
}
- if short_line.len <= max_len {
- short_line
- } else if max_len >= 3 {
- let part = serialize_text(
- &Text::new(format!("{:>width$}", "...", width = max_len))
- .color_range(0, ..)
- .opaque(),
- );
- let len = max_len;
- LinePart { part, len }
- } else {
+ floating_range = ribbon_range(floating_start, short_line.len);
+ }
+ if short_line.len <= max_len {
+ (short_line, new_pane_range, floating_range)
+ } else if max_len >= 3 {
+ let part = serialize_text(
+ &Text::new(format!("{:>width$}", "...", width = max_len))
+ .color_range(0, ..)
+ .opaque(),
+ );
+ let len = max_len;
+ (LinePart { part, len }, None, None)
+ } else {
+ (
LinePart {
part: "".to_owned(),
len: 0,
- }
- }
+ },
+ None,
+ None,
+ )
}
}
@@ -1126,6 +1265,107 @@ fn keybinds(help: &ModeInfo, max_width: usize) -> Option<LinePart> {
Some(best_effort_shortcut_list(help, max_width))
}
+fn ribbon_range(start: usize, end: usize) -> Option<(usize, usize)> {
+ if end > start {
+ Some((start, end))
+ } else {
+ None
+ }
+}
+
+fn hovered_ribbon_wrap(body: String, palette: Styling, supports_arrow_fonts: bool) -> String {
+ let ribbon_bg = palette.ribbon_unselected.emphasis_1;
+ let outer_bg = palette.text_unselected.background;
+ let arrow = if supports_arrow_fonts {
+ crate::ARROW_SEPARATOR
+ } else {
+ ""
+ };
+ let left = style!(outer_bg, ribbon_bg).paint(arrow).to_string();
+ let right = style!(ribbon_bg, outer_bg).paint(arrow).to_string();
+ format!("{}{}{}", left, body, right)
+}
+
+fn add_shortcut_hovered(
+ help: &ModeInfo,
+ text: &str,
+ keys: &Vec<KeyWithModifier>,
+ key_color_index: Option<usize>,
+) -> LinePart {
+ let mut ret = LinePart::default();
+ if keys.is_empty() {
+ return ret;
+ }
+ ret.append(&style_key_with_modifier(&keys, key_color_index));
+ let palette = help.style.colors;
+ let supports_arrow_fonts = !help.capabilities.arrow_fonts;
+ let ribbon_bg = palette.ribbon_unselected.emphasis_1;
+ let body = style!(palette.ribbon_unselected.base, ribbon_bg)
+ .bold()
+ .paint(format!(" {} ", text))
+ .to_string();
+ let ribbon = hovered_ribbon_wrap(body, palette, supports_arrow_fonts);
+ ret.part = format!("{}{}", ret.part, ribbon);
+ ret.len += if supports_arrow_fonts {
+ text.width() + 4
+ } else {
+ text.width() + 2
+ };
+ ret
+}
+
+fn add_shortcut_with_inline_key_hovered(
+ help: &ModeInfo,
+ text: &str,
+ key: Vec<KeyWithModifier>,
+) -> LinePart {
+ let mut ret = LinePart::default();
+ if key.is_empty() {
+ return ret;
+ }
+ let key_separator = match key
+ .iter()
+ .map(|k| k.to_string())
+ .collect::<Vec<_>>()
+ .join("")
+ .as_str()
+ {
+ "HJKL" => "",
+ "hjkl" => "",
+ "←↓↑→" => "",
+ "←→" => "",
+ "↓↑" => "",
+ "[]" => "",
+ "+-" => "",
+ _ => "|",
+ };
+ let key_string = format!(
+ "{}",
+ key.iter()
+ .map(|k| k.to_string())
+ .collect::<Vec<_>>()
+ .join(key_separator)
+ );
+ let palette = help.style.colors;
+ let supports_arrow_fonts = !help.capabilities.arrow_fonts;
+ let ribbon_bg = palette.ribbon_unselected.emphasis_1;
+ let base = style!(palette.ribbon_unselected.base, ribbon_bg).bold();
+ let emph = style!(palette.ribbon_unselected.emphasis_0, ribbon_bg).bold();
+ let body = format!(
+ "{}{}{}",
+ base.paint(" <").to_string(),
+ emph.paint(key_string.clone()).to_string(),
+ base.paint(format!("> {} ", text)).to_string(),
+ );
+ ret.part = hovered_ribbon_wrap(body, palette, supports_arrow_fonts);
+ ret.len += if supports_arrow_fonts {
+ text.width() + key_string.width() + 7
+ } else {
+ text.width() + key_string.width() + 5
+ };
+ ret
+}
+
fn add_shortcut(
help: &ModeInfo,
text: &str,
diff --git a/default-plugins/tab-bar/src/line.rs b/default-plugins/tab-bar/src/line.rs
index aa76ce27..99b85f05 100644
--- a/default-plugins/tab-bar/src/line.rs
+++ b/default-plugins/tab-bar/src/line.rs
@@ -224,7 +224,10 @@ pub fn tab_line(
mode_info: &ModeInfo,
hide_swap_layout_indicator: bool,
background: &PaletteColor,
-) -> Vec<LinePart> {
+ active_pane_scroll: Option<(usize, usize)>,
+ is_alternate_tab: bool,
+ new_tab_button_is_hovered: bool,
+) -> (Vec<LinePart>, Option<(usize, usize)>) {
let mut tabs_after_active = all_tabs.split_off(active_tab_index);
let mut tabs_before_active = all_tabs;
let active_tab = if !tabs_after_active.is_empty() {
@@ -249,6 +252,9 @@ pub fn tab_line(
)
})
};
+ if swap_layout_indicator.is_none() {
+ swap_layout_indicator = active_pane_scroll.map(|scroll| scroll_status(scroll, palette));
+ }
// Drop indicator if it would cause wrapping (active tab always rendered unconditionally)
let prefix_len = get_current_title_len(&prefix);
@@ -279,6 +285,33 @@ pub fn tab_line(
tab_index: None,
}]);
+ let supports_arrow_fonts = !capabilities.arrow_fonts;
+ let new_tab_button_background = if supports_arrow_fonts {
+ if new_tab_button_is_hovered {
+ palette.ribbon_unselected.emphasis_1
+ } else {
+ palette.ribbon_unselected.background
+ }
+ } else if is_alternate_tab {
+ palette.ribbon_unselected.emphasis_1
+ } else {
+ palette.ribbon_unselected.background
+ };
+ let new_tab_button = new_tab_button_line_part(palette, capabilities, new_tab_button_background);
+ let used = prefix.iter().map(|p| p.len).sum::<usize>();
+ let current_indicator_len = swap_layout_indicator.as_ref().map(|s| s.len).unwrap_or(0);
+ let room = cols
+ .saturating_sub(used)
+ .saturating_sub(current_indicator_len);
+ let new_tab_button_range = if room >= new_tab_button.len {
+ let button_start = used;
+ let button_end = button_start + new_tab_button.len;
+ prefix.push(new_tab_button);
+ Some((button_start, button_end))
+ } else {
+ None
+ };
+
if let Some(mut swap_layout_indicator) = swap_layout_indicator.take() {
let remaining_space = cols
.saturating_sub(prefix.iter().fold(0, |len, part| len + part.len))
@@ -301,7 +334,7 @@ pub fn tab_line(
prefix.push(swap_layout_indicator);
}
- prefix
+ (prefix, new_tab_button_range)
}
fn swap_layout_status(
@@ -329,6 +362,43 @@ fn swap_layout_status(
}
}
+fn scroll_status(scroll: (usize, usize), palette: Styling) -> LinePart {
+ let (position, length) = scroll;
+ let text = format!("[ SCROLL {}/{} ]", position, length);
+ let text_color = palette.text_unselected.base;
+ let bg_color = palette.text_unselected.background;
+ let styled_text = style!(text_color, bg_color).bold().paint(&text);
+ LinePart {
+ part: styled_text.to_string(),
+ len: text.width(),
+ tab_index: None,
+ }
+}
+
+fn new_tab_button_line_part(
+ palette: Styling,
+ capabilities: PluginCapabilities,
+ background_color: PaletteColor,
+) -> LinePart {
+ let separator = tab_separator(capabilities);
+ let separator_width = separator.width();
+ let foreground_color = palette.ribbon_unselected.base;
+ let separator_fill_color = palette.text_unselected.background;
+ let left_separator = style!(separator_fill_color, background_color).paint(separator);
+ let right_separator = style!(background_color, separator_fill_color).paint(separator);
+ let text = "+";
+ let styled_text = style!(foreground_color, background_color)
+ .bold()
+ .paint(format!(" {} ", text));
+ let part = ANSIStrings(&[left_separator, styled_text, right_separator]).to_string();
+ let len = text.width() + (separator_width * 2) + 2;
+ LinePart {
+ part,
+ len,
+ tab_index: None,
+ }
+}
+
pub fn ribbon_as_line_part(text: &str, is_selected: bool, supports_arrow_fonts: bool) -> LinePart {
let ribbon_text = if is_selected {
Text::new(text).selected()
diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs
index 6a3db351..6fa92c75 100644
--- a/default-plugins/tab-bar/src/main.rs
+++ b/default-plugins/tab-bar/src/main.rs
@@ -33,6 +33,10 @@ struct State {
tab_line: Vec<LinePart>,
hide_swap_layout_indication: bool,
cached_keybinds: KeybindsVec,
+ active_pane_scroll: Option<(usize, usize)>,
+ new_tab_button_range: Option<(usize, usize)>,
+ hovered_tab_idx: Option<usize>,
+ hovered_new_tab_button: bool,
}
static ARROW_SEPARATOR: &str = "";
@@ -51,6 +55,7 @@ impl ZellijPlugin for State {
EventType::ModeUpdate,
EventType::Mouse,
EventType::InitialKeybinds,
+ EventType::ActivePaneScroll,
]);
}
@@ -89,13 +94,48 @@ impl ZellijPlugin for State {
eprintln!("Could not find active tab.");
}
},
+ Event::ActivePaneScroll(scroll) => {
+ if self.active_pane_scroll != scroll {
+ should_render = true;
+ }
+ self.active_pane_scroll = scroll;
+ },
Event::Mouse(me) => match me {
Mouse::LeftClick(_, col) => {
+ if let Some((start, end)) = self.new_tab_button_range {
+ if col >= start && col < end {
+ new_tab::<&str>(None, None);
+ return should_render;
+ }
+ }
let tab_to_focus = get_tab_to_focus(&self.tab_line, self.active_tab_idx, col);
if let Some(idx) = tab_to_focus {
switch_tab_to(idx.try_into().unwrap());
}
},
+ Mouse::Hover(_, col) => {
+ let simplified_ui = self.mode_info.capabilities.arrow_fonts;
+ let mut new_hovered_new_tab_button = false;
+ let mut new_hovered_tab_idx = None;
+ if !simplified_ui {
+ if let Some((start, end)) = self.new_tab_button_range {
+ if col >= start && col < end {
+ new_hovered_new_tab_button = true;
+ }
+ }
+ if !new_hovered_new_tab_button {
+ new_hovered_tab_idx =
+ get_tab_to_focus(&self.tab_line, self.active_tab_idx, col);
+ }
+ }
+ if self.hovered_new_tab_button != new_hovered_new_tab_button
+ || self.hovered_tab_idx != new_hovered_tab_idx
+ {
+ self.hovered_new_tab_button = new_hovered_new_tab_button;
+ self.hovered_tab_idx = new_hovered_tab_idx;
+ should_render = true;
+ }
+ },
Mouse::ScrollUp(_) => {
switch_tab_to(min(self.active_tab_idx + 1, self.tabs.len()) as u32);
},
@@ -133,10 +173,12 @@ impl ZellijPlugin for State {
} else if t.active {
active_tab_index = t.position;
}
+ let is_hovered = self.hovered_tab_idx == Some(t.position + 1);
let tab = tab_style(
tabname,
t,
is_alternate_tab,
+ is_hovered,
self.mode_info.style.colors,
self.mode_info.capabilities,
);
@@ -146,7 +188,7 @@ impl ZellijPlugin for State {
let background = self.mode_info.style.colors.text_unselected.background;
- self.tab_line = tab_line(
+ let (line, new_tab_button_range) = tab_line(
self.mode_info.session_name.as_deref(),
all_tabs,
active_tab_index,
@@ -158,7 +200,12 @@ impl ZellijPlugin for State {
&self.mode_info,
self.hide_swap_layout_indication,
&background,
+ self.active_pane_scroll,
+ is_alternate_tab,
+ self.hovered_new_tab_button,
);
+ self.tab_line = line;
+ self.new_tab_button_range = new_tab_button_range;
let output = self
.tab_line
diff --git a/default-plugins/tab-bar/src/tab.rs b/default-plugins/tab-bar/src/tab.rs
index d211d142..3db1bbb6 100644
--- a/default-plugins/tab-bar/src/tab.rs
+++ b/default-plugins/tab-bar/src/tab.rs
@@ -24,6 +24,7 @@ pub fn render_tab(
text: String,
tab: &TabInfo,
is_alternate_tab: bool,
+ is_hovered: bool,
palette: Styling,
separator: &str,
) -> LinePart {
@@ -37,6 +38,8 @@ pub fn render_tab(
};
let background_color = if tab.active {
palette.ribbon_selected.background
+ } else if is_hovered {
+ palette.ribbon_unselected.emphasis_1
} else if is_alternate_tab {
alternate_tab_color
} else {
@@ -98,6 +101,7 @@ pub fn tab_style(
mut tabname: String,
tab: &TabInfo,
mut is_alternate_tab: bool,
+ is_hovered: bool,
palette: Styling,
capabilities: PluginCapabilities,
) -> LinePart {
@@ -116,7 +120,14 @@ pub fn tab_style(
is_alternate_tab = false;
}
- render_tab(tabname, tab, is_alternate_tab, palette, separator)
+ render_tab(
+ tabname,
+ tab,
+ is_alternate_tab,
+ is_hovered,
+ palette,
+ separator,
+ )
}
pub(crate) fn get_tab_to_focus(
diff --git a/src/main.rs b/src/main.rs
index c6ebebea..a5faf7d3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -76,6 +76,7 @@ fn main() {
floating,
in_place,
close_replaced_pane,
+ pane_id: None,
name,
close_on_exit,
start_suspended,
@@ -127,6 +128,7 @@ fn main() {
floating,
in_place,
close_replaced_pane,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs
index c20eb2c8..b83a7c6a 100644
--- a/src/tests/e2e/cases.rs
+++ b/src/tests/e2e/cases.rs
@@ -125,7 +125,7 @@ pub fn starts_with_one_terminal() {
name: "Wait for app to load",
instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
- if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2)
+ if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 1)
{
step_is_complete = true;
}
@@ -160,7 +160,7 @@ pub fn typing_exit_closes_pane() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
if remote_terminal.status_bar_appears()
- && remote_terminal.cursor_position_is(3, 2)
+ && remote_terminal.cursor_position_is(2, 1)
{
remote_terminal.send_key(&PANE_MODE);
std::thread::sleep(std::time::Duration::from_millis(100));
@@ -174,7 +174,7 @@ pub fn typing_exit_closes_pane() {
name: "Type exit",
instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
- if remote_terminal.cursor_position_is(63, 2)
+ if remote_terminal.cursor_position_is(62, 2)
&& remote_terminal.status_bar_appears()
{
remote_terminal.send_key("e".as_bytes());
@@ -196,7 +196,7 @@ pub fn typing_exit_closes_pane() {
name: "Wait for pane to close",
instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
- if remote_terminal.cursor_position_is(3, 2) && remote_terminal.status_bar_appears()
+ if remote_terminal.cursor_position_is(2, 1) && remote_terminal.status_bar_appears()
{
// cursor is in the original pane
step_is_complete = true;
@@ -232,7 +232,7 @@ pub fn resize_terminal_window() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
if remote_terminal.status_bar_appears()
- && remote_terminal.cursor_position_is(3, 2)
+ && remote_terminal.cursor_position_is(2, 1)
{
remote_terminal.send_key(&PANE_MODE);
std::thread::sleep(std::time::Duration::from_millis(100));
@@ -246,7 +246,7 @@ pub fn resize_terminal_window() {
name: "Change terminal window size",
instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
- if remote_terminal.cursor_position_is(63, 2)
+ if remote_terminal.cursor_position_is(62, 2)
&& remote_terminal.status_bar_appears()
{
// new pane has been opened and focused
@@ -261,7 +261,7 @@ pub fn resize_terminal_window() {
name: "wait for terminal to be resized and app to be re-rendered",
instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
- if remote_terminal.cursor_position_is(53, 2) && remote_terminal.ctrl_plus_appears()
+ if remote_terminal.cursor_position_is(52, 2) && remote_terminal.ctrl_plus_appears()
{
// size has been changed
step_is_complete = true;
@@ -358,7 +358,7 @@ pub fn send_blocking_command_through_the_cli() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false;
if remote_terminal.status_bar_appears()
- && remote_terminal.cursor_position_is(3, 2)
+ && remote_terminal.cursor_position_is(2, 1)
{
std::thread::sleep(std::time::Duration::from_millis(100));
remote_terminal
@@ -415,7 +415,7 @@ pub fn send_blocking_command_through_the_cli() {
// wait until echo $? is visible, the exit status rendered, and the cursor is back
// at a blank prompt, which means the shell command actually executed
if remote_terminal.snapshot_contains("echo $?")
- && remote_terminal.snapshot_contains("│42")
+ && remote_terminal.snapshot_contains("42")
&& remote_terminal.snapshot_contains("$ \u{2588}")
&& remote_terminal.status_bar_appears()
{
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap
index 2cc662bb..cee30f74 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap
@@ -1,29 +1,28 @@
---
source: src/tests/e2e/cases.rs
-assertion_line: 1212
expression: last_snapshot
---
- Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ┌ Pane #4 ────────────────────────────────────── PIN [ ] ┐ │
-│ │$ │ │
-│ │ ┌ top ────────────────────────────────────────── PIN [ ] ┐ │
-│ │ │ │ │
-│ │ │ │ ┐ │
-│ │ │ │ │────────────────────────────┘
-│ │ │ Waiting to run: top │ │────────────────────────────┐
-│ │ │ │ │ │
-│ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │ │
-│ └─│ │ │ │
-│ │ │ │ │
-│ └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ──────┘ │ │
-│ │ │ │
-│ └────────────────────────────────────────────────────────┘ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4  + 
+ Pane #1 │ Pane #2
+$ │$
+ │
+ │
+ │
+ ┌ Pane #4 ────────────────────────────────────── PIN [ ] ┐
+ │$ │
+ │ ┌ top ────────────────────────────────────────── PIN [ ] ┐
+ │ │ │
+ │ │ │ ┐
+ │ │ │ │─────────────────────────────
+ │ │ Waiting to run: top │ │ #3
+ │ │ │ │
+ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │
+ └─│ │ │
+ │ │ │
+ └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ──────┘ │
+ │ │
+ └────────────────────────────────────────────────────────┘
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
- (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide.
+ (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap
index 86285b60..f7e731a0 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap
@@ -2,27 +2,27 @@
source: src/tests/e2e/cases.rs
expression: last_snapshot
---
- Zellij (e2e-test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘
+ Zellij (e2e-test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + g  p  t  n  h  s  o  q  ...
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap
index 38453712..c1a0ac4c 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap
@@ -2,27 +2,27 @@
source: src/tests/e2e/cases.rs
expression: last_snapshot
---
- Zellij (e2e-test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ /usr/src/zellij/zellij run --blocking --floating --close-on-exit -- bash -c 'sleep 2 && exit 42' │
-│$ │
-│$ echo $? │
-│42 │
-│$ │
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New Pane  <f> Floating 
+ Zellij (e2e-test)  Tab #1  + 
+$ /usr/src/zellij/zellij run --blocking --floating --close-on-exit -- bash -c 'sleep 2 && exit 42'
+$
+$ echo $?
+42
+$
+$ █
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New Pane  <f> Floating 
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
index 9a9b2265..cb5cc64c 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap
@@ -2,27 +2,27 @@
source: src/tests/e2e/cases.rs
expression: last_snapshot
---
- Zellij (e2e-test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (e2e-test)  Tab #1  + 
+$ █
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap
index 9a9b2265..cb5cc64c 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap
@@ -2,27 +2,27 @@
source: src/tests/e2e/cases.rs
expression: last_snapshot
---
- Zellij (e2e-test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (e2e-test)  Tab #1  + 
+$ █
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/xtask/src/build.rs b/xtask/src/build.rs
index 53ab8ade..b736897f 100644
--- a/xtask/src/build.rs
+++ b/xtask/src/build.rs
@@ -27,7 +27,7 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
// See [this PR][1] for details.
//
// [1]: https://github.com/zellij-org/zellij/pull/2711#issuecomment-1695015818
- run_proto_codegen(sh);
+ run_proto_codegen(sh, false);
// Build all plugins in a single invocation so Cargo can unify transitive dependency
// features across all of them and compile shared crates (e.g. zellij-utils) only once.
@@ -114,7 +114,16 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
Ok(())
}
-fn run_proto_codegen(sh: &Shell) {
+pub fn proto(sh: &Shell) -> anyhow::Result<()> {
+ let msg = ">> Generating protobuffer code";
+ crate::status(msg);
+ println!("{}", msg);
+
+ run_proto_codegen(sh, true);
+ Ok(())
+}
+
+fn run_proto_codegen(sh: &Shell, force: bool) {
let zellij_utils_basedir = crate::project_root().join("zellij-utils");
let _pd = sh.push_dir(&zellij_utils_basedir);
@@ -142,7 +151,7 @@ fn run_proto_codegen(sh: &Shell) {
.metadata()
.and_then(|m| m.modified());
let mut proto_files = vec![];
- let mut needs_regeneration = false;
+ let mut needs_regeneration = force;
for entry in std::fs::read_dir(&src_dir).unwrap() {
let entry_path = entry.unwrap().path();
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs
index 82302e45..bd963770 100644
--- a/xtask/src/flags.rs
+++ b/xtask/src/flags.rs
@@ -42,6 +42,8 @@ xflags::xflags! {
/// Build the manpage
cmd manpage {}
+ cmd proto {}
+
/// Publish zellij and all the sub-crates
cmd publish {
/// Perform a dry-run (don't push/publish anything)
@@ -142,6 +144,7 @@ pub enum XtaskCmd {
Deprecated(Deprecated),
Ci(Ci),
Manpage(Manpage),
+ Proto(Proto),
Publish(Publish),
Dist(Dist),
Clippy(Clippy),
@@ -195,6 +198,9 @@ pub struct BuildRelease {
pub struct Manpage;
#[derive(Debug)]
+pub struct Proto;
+
+#[derive(Debug)]
pub struct Publish {
pub dry_run: bool,
pub no_push: bool,
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 0e99d0b3..cb378b44 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -134,6 +134,7 @@ fn main() -> anyhow::Result<()> {
flags::XtaskCmd::Test(flags) => test::test(shell, flags),
flags::XtaskCmd::IntegrationTest(flags) => integration_test::integration_test(shell, flags),
flags::XtaskCmd::Manpage(_flags) => build::manpage(shell),
+ flags::XtaskCmd::Proto(_flags) => build::proto(shell),
// Pipelines
// These are composite commands, made up of multiple "stages" defined above.
flags::XtaskCmd::Make(flags) => pipelines::make(shell, flags),
diff --git a/zellij-integration-tests/src/harness.rs b/zellij-integration-tests/src/harness.rs
index eb860f8f..cda8a253 100644
--- a/zellij-integration-tests/src/harness.rs
+++ b/zellij-integration-tests/src/harness.rs
@@ -18,7 +18,7 @@ pub fn claim_first_terminal_and_wait_for_prompt(zellij: &TestSession) -> FakePty
|grid_snapshot| {
grid_snapshot.tab_bar_appears()
&& grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
},
);
terminal
@@ -30,7 +30,7 @@ pub fn split_right_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle {
let terminal = zellij.expect_pty_spawn();
terminal.output(PROMPT);
zellij.wait_until("right terminal prompt rendered", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
terminal
}
@@ -41,7 +41,7 @@ pub fn split_down_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle {
let terminal = zellij.expect_pty_spawn();
terminal.output(PROMPT);
zellij.wait_until("lower terminal prompt rendered", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(13))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(13))
});
terminal
}
diff --git a/zellij-integration-tests/src/runner.rs b/zellij-integration-tests/src/runner.rs
index c430f94b..76544ecd 100644
--- a/zellij-integration-tests/src/runner.rs
+++ b/zellij-integration-tests/src/runner.rs
@@ -127,6 +127,7 @@ fn new_pane_cli_action(
floating,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit,
start_suspended,
diff --git a/zellij-integration-tests/src/test_env.rs b/zellij-integration-tests/src/test_env.rs
index a70c4e75..f5a9aa74 100644
--- a/zellij-integration-tests/src/test_env.rs
+++ b/zellij-integration-tests/src/test_env.rs
@@ -156,6 +156,7 @@ disable_session_metadata true
visual_bell false
mouse_mode false
advanced_mouse_actions false
+pane_frame_style "titles"
theme "default"
"#;
diff --git a/zellij-integration-tests/tests/app.rs b/zellij-integration-tests/tests/app.rs
index 74ed11e4..45e57512 100644
--- a/zellij-integration-tests/tests/app.rs
+++ b/zellij-integration-tests/tests/app.rs
@@ -54,7 +54,7 @@ fn resize_terminal_window() {
zellij.wait_until("app re-rendered at the new window size", |grid_snapshot| {
grid_snapshot.contains("Ctrl +")
&& grid_snapshot.tab_bar_appears()
- && grid_snapshot.cursor_is_at(col(53).row(2))
+ && grid_snapshot.cursor_is_at(col(52).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -70,7 +70,7 @@ fn status_bar_loads_custom_keybindings() {
let grid_snapshot = zellij.wait_until(
"status bar reflects the custom keybindings",
- |grid_snapshot| grid_snapshot.cursor_is_at(col(3).row(2)) && grid_snapshot.contains("LOCK"),
+ |grid_snapshot| grid_snapshot.cursor_is_at(col(2).row(1)) && grid_snapshot.contains("LOCK"),
);
assert_snapshot!(normalized(&grid_snapshot));
}
@@ -91,6 +91,7 @@ fn use_custom_layout_with_relative_path() {
let grid_snapshot = zellij.wait_until("upside-down layout loaded from disk", |grid_snapshot| {
grid_snapshot.tab_bar_appears()
+ && grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Zellij (test")
&& grid_snapshot.cursor.is_some()
});
diff --git a/zellij-integration-tests/tests/basic.rs b/zellij-integration-tests/tests/basic.rs
index e72cd1c6..1ed5b46a 100644
--- a/zellij-integration-tests/tests/basic.rs
+++ b/zellij-integration-tests/tests/basic.rs
@@ -23,7 +23,7 @@ fn starts_with_one_terminal() {
let grid_snapshot = zellij.wait_until("steady loaded state", |grid_snapshot| {
grid_snapshot.tab_bar_appears()
&& grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -35,7 +35,7 @@ fn split_terminals_vertically() {
claim_first_terminal_and_wait_for_prompt(&zellij);
split_right_and_wait_for_prompt(&zellij);
let grid_snapshot = zellij.wait_until("split rendered in normal mode", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -58,7 +58,7 @@ fn resize_pane() {
let cursor_shift_left = (resized_cols.saturating_sub(initial_cols)) as usize;
let grid_snapshot = zellij.wait_until("resized layout in normal mode", |grid_snapshot| {
grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(63 - cursor_shift_left).row(2))
+ && grid_snapshot.cursor_is_at(col(62 - cursor_shift_left).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -79,7 +79,7 @@ fn command_pane_closes_on_exit() {
zellij.wait_until(
"right terminal closed, focus back on first",
|grid_snapshot| {
- !grid_snapshot.contains("about to exit") && grid_snapshot.cursor_is_at(col(3).row(2))
+ !grid_snapshot.contains("about to exit") && grid_snapshot.cursor_is_at(col(2).row(1))
},
);
zellij.quit();
diff --git a/zellij-integration-tests/tests/cli.rs b/zellij-integration-tests/tests/cli.rs
index 75c3ce4a..3460994e 100644
--- a/zellij-integration-tests/tests/cli.rs
+++ b/zellij-integration-tests/tests/cli.rs
@@ -75,7 +75,7 @@ fn send_blocking_command_through_the_cli() {
assert_eq!(blocking_command.wait_for_exit(), 42);
let grid_snapshot = zellij.wait_until("floating pane closed on exit", |grid_snapshot| {
- !grid_snapshot.contains("PIN") && grid_snapshot.cursor_is_at(col(3).row(2))
+ !grid_snapshot.contains("PIN") && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -100,7 +100,7 @@ fn watcher_client_functionality() {
let right_terminal = zellij.expect_pty_spawn();
right_terminal.output(PROMPT);
watcher.wait_until("watcher sees the split", |grid_snapshot| {
- grid_snapshot.contains("┐┌")
+ grid_snapshot.contains("│")
});
let ignored_new_tab_from_watcher = [keys::ctrl('t'), keys::key('n')].concat();
@@ -112,7 +112,7 @@ fn watcher_client_functionality() {
"watcher keeps receiving output while no main client is attached",
|grid_snapshot| {
grid_snapshot.contains("WATCHER_DONE")
- && grid_snapshot.contains("┐┌")
+ && grid_snapshot.contains("│")
&& !grid_snapshot.contains("Tab #2")
},
);
@@ -123,7 +123,7 @@ fn watcher_client_functionality() {
|grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("WATCHER_DONE")
- && grid_snapshot.contains("┐┌")
+ && grid_snapshot.contains("│")
},
);
assert_snapshot!(normalized(&main_snapshot));
@@ -132,7 +132,7 @@ fn watcher_client_functionality() {
watcher.wait_until("watcher mirrors the re-attached session", |grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("WATCHER_DONE")
- && grid_snapshot.contains("┐┌")
+ && grid_snapshot.contains("│")
&& !grid_snapshot.contains("Tab #2")
});
assert_snapshot!(normalized(&watcher_snapshot));
diff --git a/zellij-integration-tests/tests/clients.rs b/zellij-integration-tests/tests/clients.rs
index 669e5aa3..06996b5b 100644
--- a/zellij-integration-tests/tests/clients.rs
+++ b/zellij-integration-tests/tests/clients.rs
@@ -21,7 +21,7 @@ fn mirrored_sessions() {
second_client.wait_until("second client loaded on the first tab", |grid_snapshot| {
grid_snapshot.tab_bar_appears()
&& grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
second_client.send_stdin(&keys::ctrl('p'));
@@ -34,7 +34,7 @@ fn mirrored_sessions() {
&& session_name_rendered(grid_snapshot)
&& grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Pane #2")
- && grid_snapshot.cursor_is_at(col(63).row(2))
+ && grid_snapshot.cursor_is_at(col(62).row(2))
};
let main_grid = zellij.wait_until(
"main client follows the second client's focus into the split it never asked for",
@@ -56,8 +56,16 @@ fn mirrored_sessions() {
#[test]
fn multiple_users_in_same_pane_and_tab() {
- let mut zellij = start_zellij();
- claim_first_terminal_and_wait_for_prompt(&zellij);
+ let mut zellij = TestRunner::new(TERMINAL_SIZE)
+ .with_config("pane_frame_style \"full\"")
+ .start();
+ let terminal = zellij.expect_pty_spawn();
+ terminal.output(PROMPT);
+ zellij.wait_until("first terminal prompt rendered", |grid_snapshot| {
+ grid_snapshot.tab_bar_appears()
+ && grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("$ ")
+ });
let second_client = zellij.attach_client(TERMINAL_SIZE);
let second_grid =
@@ -91,7 +99,7 @@ fn multiple_users_in_different_panes_and_same_tab() {
let second_client = zellij.attach_client(TERMINAL_SIZE);
second_client.wait_until("second client loaded on the first tab", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1))
});
second_client.send_stdin(&keys::ctrl('p'));
@@ -105,7 +113,7 @@ fn multiple_users_in_different_panes_and_same_tab() {
grid_snapshot.tab_bar_appears()
&& session_name_rendered(grid_snapshot)
&& grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(63).row(2))
+ && grid_snapshot.cursor_is_at(col(62).row(2))
},
);
let main_grid = zellij.wait_until(
@@ -115,7 +123,7 @@ fn multiple_users_in_different_panes_and_same_tab() {
&& session_name_rendered(grid_snapshot)
&& grid_snapshot.contains("Pane #2")
&& grid_snapshot.status_bar_appears()
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(2))
},
);
assert_snapshot!(normalized(&main_grid));
@@ -131,7 +139,7 @@ fn multiple_users_in_different_tabs() {
let second_client = zellij.attach_client(TERMINAL_SIZE);
second_client.wait_until("second client loaded on the first tab", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1))
});
second_client.send_stdin(&keys::ctrl('t'));
@@ -145,7 +153,7 @@ fn multiple_users_in_different_tabs() {
&& session_name_rendered(grid_snapshot)
&& grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Tab #2")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
let main_grid = zellij.wait_until(
"main client sees the new tab while staying on the first tab",
@@ -154,7 +162,7 @@ fn multiple_users_in_different_tabs() {
&& session_name_rendered(grid_snapshot)
&& grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Tab #2")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
},
);
assert_snapshot!(normalized(&main_grid));
@@ -173,7 +181,7 @@ fn detach_and_attach_session() {
let right_terminal = zellij.expect_pty_spawn();
right_terminal.output(PROMPT);
zellij.wait_until("right terminal prompt rendered", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
right_terminal.output(b"I am some text");
diff --git a/zellij-integration-tests/tests/misc.rs b/zellij-integration-tests/tests/misc.rs
index 83a02878..3bd14624 100644
--- a/zellij-integration-tests/tests/misc.rs
+++ b/zellij-integration-tests/tests/misc.rs
@@ -48,7 +48,7 @@ fn focus_next_pane_via_tmux_mode() {
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus cycled to the other pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
diff --git a/zellij-integration-tests/tests/modes.rs b/zellij-integration-tests/tests/modes.rs
index 0fc093be..c2f61d67 100644
--- a/zellij-integration-tests/tests/modes.rs
+++ b/zellij-integration-tests/tests/modes.rs
@@ -138,7 +138,7 @@ fn return_to_normal_mode() {
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("returned to normal mode", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -187,7 +187,7 @@ fn tmux_mode() {
right_terminal.output(PROMPT);
let grid_snapshot = zellij.wait_until("right terminal opened via tmux mode", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -226,14 +226,14 @@ fn scrolling_inside_a_pane() {
let right_terminal = zellij.expect_pty_spawn();
right_terminal.output(PROMPT);
zellij.wait_until("right terminal prompt rendered", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
- for line in 1..=21 {
+ for line in 1..=22 {
right_terminal.output(format!("line{}\r\n", line).as_bytes());
}
zellij.wait_until("right terminal filled past its viewport", |grid_snapshot| {
- grid_snapshot.contains("line21")
+ grid_snapshot.contains("line22")
});
zellij.send_stdin(&keys::ctrl('s'));
@@ -242,7 +242,7 @@ fn scrolling_inside_a_pane() {
let grid_snapshot =
zellij.wait_until("scrolled up one line inside the pane", |grid_snapshot| {
- grid_snapshot.contains("SCROLL: 2/2") && grid_snapshot.contains("PgDn|PgUp")
+ grid_snapshot.contains("SCROLL: 2/2") && grid_snapshot.contains("PgDn|PgUp")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
diff --git a/zellij-integration-tests/tests/mouse.rs b/zellij-integration-tests/tests/mouse.rs
index e4aa038c..4d134723 100644
--- a/zellij-integration-tests/tests/mouse.rs
+++ b/zellij-integration-tests/tests/mouse.rs
@@ -24,7 +24,7 @@ fn focus_pane_with_mouse() {
zellij.send_stdin(&sgr_mouse_report(2, 5, 0));
let grid_snapshot = zellij.wait_until("focus moved back to the left pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -78,7 +78,7 @@ fn pin_floating_panes() {
|grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("PIN [+]")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
},
);
diff --git a/zellij-integration-tests/tests/panes.rs b/zellij-integration-tests/tests/panes.rs
index 9defe5f2..61c3cd5a 100644
--- a/zellij-integration-tests/tests/panes.rs
+++ b/zellij-integration-tests/tests/panes.rs
@@ -13,7 +13,7 @@ fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() {
let terminal = zellij.expect_pty_spawn();
terminal.output(PROMPT);
zellij.wait_until("first terminal prompt rendered", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(1))
});
let (width_before_split, _) = terminal.wait_for_size("first terminal sized", |_, _| true);
@@ -50,7 +50,7 @@ fn key_after_mode_switch_is_interpreted_in_new_mode_not_leaked_to_pane() {
let second_terminal = zellij.expect_pty_spawn();
second_terminal.output(PROMPT);
zellij.wait_until("split-right interpreted in pane mode", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.cursor_is_at(col(62).row(2))
});
assert!(!first_terminal.stdin_bytes().contains(&keys::key('r')[0]));
@@ -67,7 +67,7 @@ fn toggle_pane_fullscreen() {
zellij.send_stdin(&keys::key('f'));
let grid_snapshot = zellij.wait_until("focused pane is fullscreen", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(2))
&& grid_snapshot.contains("LOCK")
&& grid_snapshot.contains("(FULLSCREEN)")
});
@@ -86,7 +86,7 @@ fn close_pane() {
let grid_snapshot =
zellij.wait_until("right pane closed, focus back on first", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -116,7 +116,7 @@ fn pane_closes_when_its_process_exits() {
let grid_snapshot =
zellij.wait_until("right pane closed, focus back on first", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -145,6 +145,7 @@ fn toggle_floating_panes() {
fn undo_rename_pane() {
let mut zellij = start_zellij();
claim_first_terminal_and_wait_for_prompt(&zellij);
+ split_right_and_wait_for_prompt(&zellij);
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('c'));
@@ -153,7 +154,9 @@ fn undo_rename_pane() {
zellij.send_stdin(&keys::ESC);
let grid_snapshot = zellij.wait_until("pane name reverted to default", |grid_snapshot| {
- grid_snapshot.contains("Pane #1") && grid_snapshot.contains("LOCK")
+ grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains("aa")
+ && grid_snapshot.contains("LOCK")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -200,7 +203,7 @@ fn move_focus_up_in_pane_mode() {
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus moved to the upper pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -215,14 +218,14 @@ fn move_focus_down_in_pane_mode() {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('k'));
zellij.wait_until("focus moved to the upper pane", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(2))
});
zellij.send_stdin(&keys::key('j'));
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus moved back to the lower pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(13))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(13))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -368,7 +371,7 @@ fn move_focus_or_tab_moves_focus_between_panes() {
zellij.send_stdin(&keys::alt('h'));
let grid_snapshot = zellij.wait_until("focus moved to the left pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -408,7 +411,7 @@ fn new_pane_in_pane_mode() {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('n'));
- let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(63).row(2));
+ let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(62).row(2));
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
@@ -419,7 +422,7 @@ fn new_pane_in_normal_mode() {
claim_first_terminal_and_wait_for_prompt(&zellij);
zellij.send_stdin(&keys::alt('n'));
- let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(63).row(2));
+ let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(62).row(2));
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
@@ -431,7 +434,7 @@ fn split_pane_downward() {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('d'));
- let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(3).row(13));
+ let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(13));
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
@@ -443,7 +446,7 @@ fn new_stacked_pane() {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('s'));
- let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(3).row(3));
+ let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(3));
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
@@ -459,7 +462,7 @@ fn move_focus_left_in_pane_mode() {
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus moved to the left pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -474,14 +477,14 @@ fn move_focus_right_in_pane_mode() {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('h'));
zellij.wait_until("focus moved to the left pane", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(2))
});
zellij.send_stdin(&keys::key('l'));
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus moved back to the right pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -498,27 +501,147 @@ fn switch_focus_in_pane_mode() {
zellij.send_stdin(&keys::ENTER);
let grid_snapshot = zellij.wait_until("focus switched to the other pane", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
+fn cycle_pane_frames(zellij: &TestSession) {
+ zellij.send_stdin(&keys::ctrl('p'));
+ zellij.send_stdin(&keys::key('z'));
+}
+
#[test]
fn toggle_pane_frames() {
let mut zellij = start_zellij();
claim_first_terminal_and_wait_for_prompt(&zellij);
split_right_and_wait_for_prompt(&zellij);
- zellij.send_stdin(&keys::ctrl('p'));
- zellij.send_stdin(&keys::key('z'));
+ zellij.wait_until("tiled panes start in titles mode", |grid_snapshot| {
+ grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains("┌")
+ });
- let grid_snapshot = zellij.wait_until("pane frames removed from both panes", |grid_snapshot| {
+ cycle_pane_frames(&zellij);
+ zellij.wait_until("titles cycle to frameless", |grid_snapshot| {
grid_snapshot.status_bar_appears()
&& !grid_snapshot.contains("Pane #1")
&& !grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains("┌")
&& grid_snapshot.cursor_is_at(col(62).row(1))
});
+
+ cycle_pane_frames(&zellij);
+ zellij.wait_until("frameless cycles to full frames", |grid_snapshot| {
+ grid_snapshot.contains("┌")
+ && grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ });
+
+ cycle_pane_frames(&zellij);
+ let grid_snapshot = zellij.wait_until("full frames cycle back to titles", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains("┌")
+ });
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+#[test]
+fn toggle_frames_with_single_pane() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ zellij.wait_until(
+ "lone pane in titles mode omits its title",
+ |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && !grid_snapshot.contains("Pane #1")
+ && !grid_snapshot.contains("┌")
+ },
+ );
+
+ cycle_pane_frames(&zellij);
+ zellij.wait_until("lone frameless pane stays untitled", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && !grid_snapshot.contains("Pane #1")
+ && !grid_snapshot.contains("┌")
+ });
+
+ cycle_pane_frames(&zellij);
+ let grid_snapshot =
+ zellij.wait_until("lone pane gains a full frame and title", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("┌")
+ && grid_snapshot.contains("Pane #1")
+ });
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+#[test]
+fn toggle_frames_with_floating_pane() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ zellij.send_stdin(&keys::ctrl('p'));
+ zellij.send_stdin(&keys::key('w'));
+ let floating_terminal = zellij.expect_pty_spawn();
+ floating_terminal.output(PROMPT);
+ zellij.wait_until("floating pane appeared with a frame", |grid_snapshot| {
+ grid_snapshot.contains("STAGGERED") && grid_snapshot.contains("┌")
+ });
+
+ cycle_pane_frames(&zellij);
+ zellij.wait_until(
+ "floating pane keeps its frame in frameless mode",
+ |grid_snapshot| grid_snapshot.status_bar_appears() && grid_snapshot.contains("┌"),
+ );
+
+ cycle_pane_frames(&zellij);
+ let grid_snapshot = zellij.wait_until(
+ "floating pane keeps its frame in full mode",
+ |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("┌")
+ && grid_snapshot.contains("Pane #1")
+ },
+ );
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+#[test]
+fn toggle_frames_with_stacked_panes() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ zellij.send_stdin(&keys::ctrl('p'));
+ zellij.send_stdin(&keys::key('s'));
+ spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(3));
+
+ zellij.wait_until("stacked panes show their titles", |grid_snapshot| {
+ grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains("┌")
+ });
+
+ cycle_pane_frames(&zellij);
+ zellij.wait_until("stacked panes cycle to frameless", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && !grid_snapshot.contains("┌")
+ });
+
+ cycle_pane_frames(&zellij);
+ let grid_snapshot = zellij.wait_until("stacked panes cycle to full frames", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("┌")
+ && grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ });
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
}
diff --git a/zellij-integration-tests/tests/resize.rs b/zellij-integration-tests/tests/resize.rs
index bf1263c3..ba9fae4b 100644
--- a/zellij-integration-tests/tests/resize.rs
+++ b/zellij-integration-tests/tests/resize.rs
@@ -11,7 +11,7 @@ fn focus_left_pane(zellij: &TestSession) {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('h'));
zellij.wait_until("focus moved to the left pane", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(2))
});
}
@@ -19,7 +19,7 @@ fn focus_upper_pane(zellij: &TestSession) {
zellij.send_stdin(&keys::ctrl('p'));
zellij.send_stdin(&keys::key('k'));
zellij.wait_until("focus moved to the upper pane", |grid_snapshot| {
- grid_snapshot.cursor_is_at(col(3).row(2))
+ grid_snapshot.cursor_is_at(col(2).row(2))
});
}
diff --git a/zellij-integration-tests/tests/resurrection.rs b/zellij-integration-tests/tests/resurrection.rs
index 7f6a10b0..63ed1626 100644
--- a/zellij-integration-tests/tests/resurrection.rs
+++ b/zellij-integration-tests/tests/resurrection.rs
@@ -50,7 +50,7 @@ fn quit_and_resurrect_session() {
let new_pane = zellij.expect_pty_spawn();
new_pane.output(PROMPT);
zellij.wait_until("new pane opened before serialization", |grid_snapshot| {
- grid_snapshot.contains("┐┌")
+ grid_snapshot.contains("│")
});
zellij.save_session();
@@ -64,7 +64,7 @@ fn quit_and_resurrect_session() {
grid_snapshot.contains("Zellij (test")
&& grid_snapshot.contains("alpha")
&& grid_snapshot.contains("beta")
- && grid_snapshot.contains("┐┌")
+ && grid_snapshot.contains("│")
&& grid_snapshot.status_bar_appears()
},
);
diff --git a/zellij-integration-tests/tests/scroll.rs b/zellij-integration-tests/tests/scroll.rs
index 35316957..1a88b84a 100644
--- a/zellij-integration-tests/tests/scroll.rs
+++ b/zellij-integration-tests/tests/scroll.rs
@@ -28,7 +28,9 @@ fn page_scroll_up() {
zellij.send_stdin(&keys::ctrl('b'));
let grid_snapshot = zellij.wait_until("scrolled up by a page", |grid_snapshot| {
- grid_snapshot.contains("PgDn|PgUp") && !grid_snapshot.contains(LAST_LINE)
+ grid_snapshot.contains("PgDn|PgUp")
+ && !grid_snapshot.contains(LAST_LINE)
+ && grid_snapshot.contains("SCROLL 19/")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -47,9 +49,11 @@ fn page_scroll_down() {
zellij.send_stdin(&keys::ctrl('f'));
- let grid_snapshot = zellij
- .wait_until("scrolled back down toward the bottom", |grid_snapshot| {
- grid_snapshot.contains("line39") && grid_snapshot.contains("PgDn|PgUp")
+ let grid_snapshot =
+ zellij.wait_until("scrolled back down toward the bottom", |grid_snapshot| {
+ grid_snapshot.contains("line39")
+ && grid_snapshot.contains("PgDn|PgUp")
+ && grid_snapshot.contains("SCROLL 0/")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -64,7 +68,9 @@ fn half_page_scroll_up() {
zellij.send_stdin(&keys::key('u'));
let grid_snapshot = zellij.wait_until("scrolled up by half a page", |grid_snapshot| {
- grid_snapshot.contains("PgDn|PgUp") && !grid_snapshot.contains(LAST_LINE)
+ grid_snapshot.contains("PgDn|PgUp")
+ && !grid_snapshot.contains(LAST_LINE)
+ && grid_snapshot.contains("SCROLL 10/")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -83,9 +89,11 @@ fn half_page_scroll_down() {
zellij.send_stdin(&keys::key('d'));
- let grid_snapshot = zellij
- .wait_until("scrolled back down toward the bottom", |grid_snapshot| {
- grid_snapshot.contains("line39") && grid_snapshot.contains("PgDn|PgUp")
+ let grid_snapshot =
+ zellij.wait_until("scrolled back down toward the bottom", |grid_snapshot| {
+ grid_snapshot.contains("line39")
+ && grid_snapshot.contains("PgDn|PgUp")
+ && grid_snapshot.contains("SCROLL 0/")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -100,13 +108,13 @@ fn scroll_down_one_line() {
zellij.send_stdin(&keys::key('k'));
zellij.send_stdin(&keys::key('k'));
zellij.wait_until("scrolled up two lines", |grid_snapshot| {
- grid_snapshot.contains("SCROLL: 2/")
+ grid_snapshot.contains("SCROLL 2/")
});
zellij.send_stdin(&keys::key('j'));
let grid_snapshot = zellij.wait_until("scrolled back down one line", |grid_snapshot| {
- grid_snapshot.contains("SCROLL: 1/") && grid_snapshot.contains("PgDn|PgUp")
+ grid_snapshot.contains("SCROLL 1/") && grid_snapshot.contains("PgDn|PgUp")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -125,9 +133,11 @@ fn scroll_to_bottom() {
zellij.send_stdin(&keys::ctrl('c'));
- let grid_snapshot = zellij
- .wait_until("returned to the bottom in normal mode", |grid_snapshot| {
- grid_snapshot.status_bar_appears() && grid_snapshot.contains(LAST_LINE)
+ let grid_snapshot =
+ zellij.wait_until("returned to the bottom in normal mode", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains(LAST_LINE)
+ && grid_snapshot.contains("SCROLL 0/")
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
diff --git a/zellij-integration-tests/tests/search.rs b/zellij-integration-tests/tests/search.rs
index c15fe76e..6c750b0b 100644
--- a/zellij-integration-tests/tests/search.rs
+++ b/zellij-integration-tests/tests/search.rs
@@ -3,9 +3,24 @@
use insta::assert_snapshot;
use zellij_integration_tests::{
claim_first_terminal_and_wait_for_prompt, keys, normalized, start_zellij, FakePtyHandle,
- TestSession,
+ TestRunner, TestSession, TERMINAL_SIZE,
};
+fn start_zellij_with_full_frames() -> TestSession {
+ TestRunner::new(TERMINAL_SIZE)
+ .with_config("pane_frame_style \"full\"")
+ .start()
+}
+
+fn enter_search_on_visible_match_with_full_frames(zellij: &TestSession) {
+ let terminal = zellij.expect_pty_spawn();
+ terminal.output(b"NEEDLE on screen\r\n");
+ zellij.wait_until("match visible on screen", |grid_snapshot| {
+ grid_snapshot.contains("NEEDLE on screen")
+ });
+ enter_search_for_needle(zellij);
+}
+
fn fill_pane_with_two_matches(zellij: &TestSession) -> FakePtyHandle {
let terminal = claim_first_terminal_and_wait_for_prompt(zellij);
for line in 1..=40 {
@@ -38,15 +53,6 @@ fn enter_search_for_needle(zellij: &TestSession) {
});
}
-fn enter_search_on_visible_match(zellij: &TestSession) {
- let terminal = claim_first_terminal_and_wait_for_prompt(zellij);
- terminal.output(b"NEEDLE on screen\r\n");
- zellij.wait_until("match visible on screen", |grid_snapshot| {
- grid_snapshot.contains("NEEDLE on screen")
- });
- enter_search_for_needle(zellij);
-}
-
#[test]
fn search_input_jumps_to_a_match() {
let mut zellij = start_zellij();
@@ -120,8 +126,8 @@ fn search_down_to_next_match() {
#[test]
fn search_toggle_case_sensitivity() {
- let mut zellij = start_zellij();
- enter_search_on_visible_match(&zellij);
+ let mut zellij = start_zellij_with_full_frames();
+ enter_search_on_visible_match_with_full_frames(&zellij);
zellij.send_stdin(&keys::key('c'));
@@ -134,8 +140,8 @@ fn search_toggle_case_sensitivity() {
#[test]
fn search_toggle_wrap() {
- let mut zellij = start_zellij();
- enter_search_on_visible_match(&zellij);
+ let mut zellij = start_zellij_with_full_frames();
+ enter_search_on_visible_match_with_full_frames(&zellij);
zellij.send_stdin(&keys::key('w'));
@@ -148,8 +154,8 @@ fn search_toggle_wrap() {
#[test]
fn search_toggle_whole_word() {
- let mut zellij = start_zellij();
- enter_search_on_visible_match(&zellij);
+ let mut zellij = start_zellij_with_full_frames();
+ enter_search_on_visible_match_with_full_frames(&zellij);
zellij.send_stdin(&keys::key('o'));
diff --git a/zellij-integration-tests/tests/set_pane_frame_style.rs b/zellij-integration-tests/tests/set_pane_frame_style.rs
new file mode 100644
index 00000000..5b18f965
--- /dev/null
+++ b/zellij-integration-tests/tests/set_pane_frame_style.rs
@@ -0,0 +1,120 @@
+#![cfg(unix)]
+
+use zellij_integration_tests::{
+ claim_first_terminal_and_wait_for_prompt, split_right_and_wait_for_prompt, start_zellij, Size,
+ TestRunner,
+};
+use zellij_utils::cli::CliAction;
+use zellij_utils::input::options::PaneFrameStyle;
+
+const FULL_FRAME_CORNER: &str = "┌";
+
+fn ctrl_y() -> [u8; 1] {
+ [0x19]
+}
+
+#[test]
+fn set_pane_frame_style_through_the_cli() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ zellij.wait_until("lone titles pane has no frame", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ });
+
+ let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle {
+ style: PaneFrameStyle::Full,
+ });
+ assert_eq!(exit_code, 0, "set-pane-frame-style exited cleanly");
+
+ zellij.wait_until(
+ "full frames drawn after switching to full",
+ |grid_snapshot| {
+ grid_snapshot.contains(FULL_FRAME_CORNER) && grid_snapshot.contains("Pane #1")
+ },
+ );
+
+ let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle {
+ style: PaneFrameStyle::Titles,
+ });
+ assert_eq!(exit_code, 0, "set-pane-frame-style exited cleanly");
+
+ zellij.wait_until(
+ "frame removed after switching back to titles",
+ |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ && !grid_snapshot.contains("Pane #1")
+ },
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn set_pane_frame_style_none_through_the_cli() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+ split_right_and_wait_for_prompt(&zellij);
+
+ zellij.wait_until(
+ "two titled panes start without full frames",
+ |grid_snapshot| {
+ grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ },
+ );
+
+ let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle {
+ style: PaneFrameStyle::None,
+ });
+ assert_eq!(exit_code, 0, "set-pane-frame-style none exited cleanly");
+
+ zellij.wait_until(
+ "titles and frames both removed in none mode",
+ |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && !grid_snapshot.contains("Pane #1")
+ && !grid_snapshot.contains("Pane #2")
+ && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ },
+ );
+
+ let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle {
+ style: PaneFrameStyle::Titles,
+ });
+ assert_eq!(exit_code, 0, "set-pane-frame-style titles exited cleanly");
+
+ zellij.wait_until("pane titles return in titles mode", |grid_snapshot| {
+ grid_snapshot.contains("Pane #1") && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ });
+
+ zellij.quit();
+}
+
+#[test]
+fn set_pane_frame_style_through_a_keybinding() {
+ let mut zellij = TestRunner::new(Size {
+ cols: 120,
+ rows: 24,
+ })
+ .with_config("keybinds {\n normal {\n bind \"Ctrl y\" { SetPaneFrameStyle \"full\"; }\n }\n}")
+ .start();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ zellij.wait_until("lone titles pane has no frame", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && !grid_snapshot.contains(FULL_FRAME_CORNER)
+ });
+
+ zellij.send_stdin(&ctrl_y());
+
+ zellij.wait_until(
+ "keybinding switched the pane to full frames",
+ |grid_snapshot| {
+ grid_snapshot.contains(FULL_FRAME_CORNER) && grid_snapshot.contains("Pane #1")
+ },
+ );
+
+ zellij.quit();
+}
diff --git a/zellij-integration-tests/tests/single_pane_tab_title.rs b/zellij-integration-tests/tests/single_pane_tab_title.rs
new file mode 100644
index 00000000..1fd1a553
--- /dev/null
+++ b/zellij-integration-tests/tests/single_pane_tab_title.rs
@@ -0,0 +1,128 @@
+#![cfg(unix)]
+
+use zellij_integration_tests::{
+ claim_first_terminal_and_wait_for_prompt, split_right_and_wait_for_prompt, start_zellij,
+ FakePtyHandle, TestSession,
+};
+use zellij_utils::cli::CliAction;
+
+fn replace_pane_in_place_with_held_command(
+ zellij: &TestSession,
+ pane_id: &str,
+ command: &str,
+) -> FakePtyHandle {
+ zellij.run_cli_action(CliAction::NewPane {
+ direction: None,
+ command: vec![command.to_string()],
+ plugin: None,
+ cwd: None,
+ floating: false,
+ in_place: true,
+ close_replaced_pane: true,
+ pane_id: Some(pane_id.to_string()),
+ name: None,
+ close_on_exit: false,
+ start_suspended: false,
+ configuration: None,
+ skip_plugin_cache: false,
+ x: None,
+ y: None,
+ width: None,
+ height: None,
+ pinned: None,
+ stacked: false,
+ blocking: false,
+ block_until_exit_success: false,
+ block_until_exit_failure: false,
+ block_until_exit: false,
+ unblock_condition: None,
+ near_current_pane: false,
+ borderless: None,
+ tab_id: None,
+ });
+ zellij.expect_pty_spawn()
+}
+
+#[test]
+fn lone_pane_title_becomes_the_tab_name() {
+ let mut zellij = start_zellij();
+ let terminal = claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ terminal.output(b"\x1b]0;my-title\x07");
+ let grid_snapshot = zellij.wait_until("tab borrows the pane title", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && grid_snapshot.contains("my-title")
+ });
+ assert!(
+ !grid_snapshot.contains("Tab #1"),
+ "the borrowed pane title replaces the default tab name:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn lone_default_pane_keeps_the_default_tab_name() {
+ let mut zellij = start_zellij();
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ let grid_snapshot = zellij.wait_until("default tab name is shown", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #1")
+ });
+ assert!(
+ !grid_snapshot.contains("Pane #1"),
+ "the default pane name never leaks into the tab name:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn tab_name_reverts_when_a_second_pane_is_opened() {
+ let mut zellij = start_zellij();
+ let terminal = claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ terminal.output(b"\x1b]0;my-title\x07");
+ zellij.wait_until("tab borrows the pane title", |grid_snapshot| {
+ grid_snapshot.contains("my-title") && !grid_snapshot.contains("Tab #1")
+ });
+
+ split_right_and_wait_for_prompt(&zellij);
+ let grid_snapshot = zellij.wait_until(
+ "tab name reverts once a second pane exists",
+ |grid_snapshot| {
+ grid_snapshot
+ .lines()
+ .first()
+ .is_some_and(|tab_bar| tab_bar.contains("Tab #1"))
+ },
+ );
+ assert!(
+ grid_snapshot.contains("my-title"),
+ "the original pane keeps its title in its frame:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn lone_held_pane_tab_name_shows_exit_status() {
+ let mut zellij = start_zellij();
+ let shell_terminal = claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ let command_pane_id = format!("terminal_{}", shell_terminal.terminal_id());
+ let command_terminal =
+ replace_pane_in_place_with_held_command(&zellij, &command_pane_id, "held-command");
+ zellij.wait_until("command pane took over the lone tab", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && grid_snapshot.tab_bar_appears()
+ });
+
+ command_terminal.exit(Some(0));
+ zellij.wait_until("tab name carries the exit status", |grid_snapshot| {
+ grid_snapshot.contains("EXIT CODE: 0")
+ });
+
+ zellij.quit();
+}
diff --git a/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap b/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap
index 80505f55..f28120d7 100644
--- a/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap
+++ b/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap
@@ -2,27 +2,8 @@
source: zellij-integration-tests/tests/app.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ EDITING SCROLLBACK ──────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ SCROLLBACK_MARKER_ONE │
-│SCROLLBACK_MARKER_TWO │
-│█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  EDITING SCROLLBACK  + 
+$ SCROLLBACK_MARKER_ONE
+SCROLLBACK_MARKER_TWO
+█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap b/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap
index 2a285443..b9e64ea2 100644
--- a/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap
+++ b/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/app.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + g  p  t  n  h  s  o  q  ...
diff --git a/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap b/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap
index 0670f288..9c8fa8c7 100644
--- a/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap
+++ b/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/app.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- F1  LOCK  F2  PANE  F3  TAB  F4  RESIZE  F5  MOVE  F6  SEARCH  Alt F7  SESSION  Ctrl F8  QUIT 
+ Zellij (test)  Tab #1  + 
+$ █
+ F1  LOCK  F2  PANE  F3  TAB  F4  RESIZE  F5  MOVE  F6  SEARCH  Alt F7  SESSION  Ctrl F8  QUIT 
diff --git a/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap b/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap
index 03d134ea..120ef352 100644
--- a/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap
+++ b/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap
@@ -2,26 +2,6 @@
source: zellij-integration-tests/tests/app.rs
expression: normalized(&grid_snapshot)
---
-
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Zellij (test)  Tab #1 
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+$ █
+ Zellij (test)  Tab #1  + 
diff --git a/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap b/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap
index ba160d8c..50538a08 100644
--- a/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap
@@ -1,28 +1,28 @@
---
source: zellij-integration-tests/tests/basic.rs
-expression: normalized(&snapshot)
+expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap b/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap
index 7f5f5a69..b50409e2 100644
--- a/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap
+++ b/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap
@@ -1,28 +1,28 @@
---
source: zellij-integration-tests/tests/basic.rs
-expression: normalized(&snapshot)
+expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap b/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap
index 7fff8f8f..f4846229 100644
--- a/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap
+++ b/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap
@@ -1,28 +1,7 @@
---
source: zellij-integration-tests/tests/basic.rs
-expression: normalized(&snapshot)
+expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap b/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap
index 386bd7e5..eaa7659e 100644
--- a/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap
+++ b/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap
@@ -2,27 +2,5 @@
source: zellij-integration-tests/tests/cli.rs
expression: normalized(&grid_snapshot)
---
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Zellij (test) NORMAL  Tab #1 
+$ █
+ Zellij (test) NORMAL  Tab #1 
diff --git a/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap b/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap
index 6b2d58e7..8901dad4 100644
--- a/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap
+++ b/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/cli.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap b/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap
index 42573137..97f46d06 100644
--- a/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap
+++ b/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/cli.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ suspended-command ───────────────────────────────────────┐
-│$ ││foo │
-│ ││foo │
-│ ││█ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ suspended-command
+$ │foo
+ │foo
+ │█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap
index 707da328..c713a934 100644
--- a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap
+++ b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/cli.rs
expression: normalized(&watcher_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│WATCHER_OUTPUT_1 ││ │
-│WATCHER_OUTPUT_2 ││ │
-│WATCHER_OUTPUT_3 ││ │
-│WATCHER_DONE ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+WATCHER_OUTPUT_1 │
+WATCHER_OUTPUT_2 │
+WATCHER_OUTPUT_3 │
+WATCHER_DONE │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap
index 633d8f3b..dc904dd6 100644
--- a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap
+++ b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/cli.rs
expression: normalized(&main_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│WATCHER_OUTPUT_1 ││ │
-│WATCHER_OUTPUT_2 ││ │
-│WATCHER_OUTPUT_3 ││ │
-│WATCHER_DONE ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+WATCHER_OUTPUT_1 │
+WATCHER_OUTPUT_2 │
+WATCHER_OUTPUT_3 │
+WATCHER_DONE │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap b/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap
index 14b6ad52..966b41df 100644
--- a/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ I am some text█ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ I am some text█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap b/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap
index 0e6e31cb..4b190af2 100644
--- a/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&main_grid)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap
index 59e690c5..2da66244 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&second_grid)
---
- Zellij (test)  Tab #1 [ ]
-┌ Pane #1 ───────────┤ FOCUSED USER: ├───────────────────┐┌ Pane #2 ──────────────┤ MY FOCUS ├───────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1 [ ] + 
+ [ FOCUSED USER: ] Pane #1 │ [ MY FOCUS ] Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap
index 6ad8e0cd..9a2de537 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&main_grid)
---
- Zellij (test)  Tab #1 [ ]
-┌ Pane #1 ──────────────┤ MY FOCUS ├───────────────────────┐┌ Pane #2 ───────────┤ FOCUSED USER: ├───────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1 [ ] + 
+ [ MY FOCUS ] Pane #1 │ [ FOCUSED USER: ] Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap
index 0806898d..9d514fe8 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&second_grid)
---
- Zellij (test)  Tab #1 [ ] Tab #2 
-┌ Pane #1 ────────────────────────────────────────────┤ MY FOCUS ├─────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1 [ ] Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap
index fe0a78a9..26f7c371 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&main_grid)
---
- Zellij (test)  Tab #1  Tab #2 [ ]
-┌ Pane #1 ────────────────────────────────────────────┤ MY FOCUS ├─────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2 [ ] + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap
index ea21dde0..803a2105 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap
@@ -2,7 +2,7 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&second_grid)
---
- Zellij (test)  Tab #1 [ ]
+ Zellij (test)  Tab #1 [ ] + 
┌ Pane #1 ─────────────────────────────────────────┤ MY FOCUS AND: ├─────────────────────────────────────────────────┐
│$ █ │
│ │
diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap
index 5e27178e..13d85f0b 100644
--- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap
@@ -2,7 +2,7 @@
source: zellij-integration-tests/tests/clients.rs
expression: normalized(&main_grid)
---
- Zellij (test)  Tab #1 [ ]
+ Zellij (test)  Tab #1 [ ] + 
┌ Pane #1 ─────────────────────────────────────────┤ MY FOCUS AND: ├─────────────────────────────────────────────────┐
│$ █ │
│ │
diff --git a/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap b/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap
index a114ffc5..8a7dc160 100644
--- a/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap b/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap
index 8e954ab9..9ec7cc4b 100644
--- a/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap b/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap
index 8e954ab9..9ec7cc4b 100644
--- a/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap b/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap
index 9932251c..c704e688 100644
--- a/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ┌ Multiple Pane Select ────────────────────────┐ ││ │
-│ │<ESC> - cancel, <TAB> - move │ ││ │
-│ │ │ ││ │
-│ │GROUP ACTIONS (1 SELECTED PANE) │ ││ │
-│ │<b> - break out, <s> - stack, <c> - close │ ││ │
-│ │<l> - break left, <r> - break right │ ││ │
-│ │<e> - embed, <f> - float │ ││ │
-│ │ │ ││ │
-│ │Alt +  <p> Toggle  <Shift p> Follow Focus │ ││ │
-│ └──────────────────────────────────────────────┘ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ ┌ Multiple Pane Select ────────────────────────┐ │
+ │<ESC> - cancel, <TAB> - move │ │
+ │ │ │
+ │GROUP ACTIONS (1 SELECTED PANE) │ │
+ │<b> - break out, <s> - stack, <c> - close │ │
+ │<l> - break left, <r> - break right │ │
+ │<e> - embed, <f> - float │ │
+ │ │ │
+ │Alt +  <p> Toggle  <Shift p> Follow Focus │ │
+ └──────────────────────────────────────────────┘ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap b/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap
index 9932251c..c704e688 100644
--- a/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ┌ Multiple Pane Select ────────────────────────┐ ││ │
-│ │<ESC> - cancel, <TAB> - move │ ││ │
-│ │ │ ││ │
-│ │GROUP ACTIONS (1 SELECTED PANE) │ ││ │
-│ │<b> - break out, <s> - stack, <c> - close │ ││ │
-│ │<l> - break left, <r> - break right │ ││ │
-│ │<e> - embed, <f> - float │ ││ │
-│ │ │ ││ │
-│ │Alt +  <p> Toggle  <Shift p> Follow Focus │ ││ │
-│ └──────────────────────────────────────────────┘ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ ┌ Multiple Pane Select ────────────────────────┐ │
+ │<ESC> - cancel, <TAB> - move │ │
+ │ │ │
+ │GROUP ACTIONS (1 SELECTED PANE) │ │
+ │<b> - break out, <s> - stack, <c> - close │ │
+ │<l> - break left, <r> - break right │ │
+ │<e> - embed, <f> - float │ │
+ │ │ │
+ │Alt +  <p> Toggle  <Shift p> Follow Focus │ │
+ └──────────────────────────────────────────────┘ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap b/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap
index 29857afc..f2a692e7 100644
--- a/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/misc.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap b/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap
index 421627c3..b2ae0119 100644
--- a/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ nabc█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ nabc█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap b/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap
index e2170783..1fb9dee7 100644
--- a/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Enter search... ─────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- ENTERING SEARCH TERM   ENTER  When done 
+ Zellij (test)  Tab #1  + 
+$ █
+ ENTERING SEARCH TERM   ENTER  When done 
diff --git a/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap b/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap
index 8dde2b5b..744d0373 100644
--- a/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ nabc█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <g> LOCK 
+ Zellij (test)  Tab #1  + 
+$ nabc█
+ Ctrl + <g> LOCK 
diff --git a/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap b/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap
index b8e8dc2c..b0605346 100644
--- a/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap b/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap
index 0af68b35..96506ac6 100644
--- a/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 2/2 ┐
-│$ ││$ line1 │
-│ ││line2 │
-│ ││line3 │
-│ ││line4 │
-│ ││line5 │
-│ ││line6 │
-│ ││line7 │
-│ ││line8 │
-│ ││line9 │
-│ ││line10 │
-│ ││line11 │
-│ ││line12 │
-│ ││line13 │
-│ ││line14 │
-│ ││line15 │
-│ ││line16 │
-│ ││line17 │
-│ ││line18 │
-│ ││line19 │
-│ ││█ine20 │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2 [ SCROLL: 2/2 ]
+$ │$ line1
+ │line2
+ │line3
+ │line4
+ │line5
+ │line6
+ │line7
+ │line8
+ │line9
+ │line10
+ │line11
+ │line12
+ │line13
+ │line14
+ │line15
+ │line16
+ │line17
+ │line18
+ │line19
+ │line20
+ │█ine21
Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap
index 2c38ca5b..7c5a8166 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <h> MOVE   ←↓↑→  Switch Location  ENTER  When done 
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <h> MOVE   ←↓↑→  Switch Location  ENTER  When done 
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap
index 77a3a87a..cf9153c1 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <p> PANE   n  New  ←↓↑→  Move  x  Close  c  Rename  f  Fullscreen  Alt f  Floating  ...
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <p> PANE   n  New  ←↓↑→  Move  x  Close  c  Rename  f  Fullscreen  Alt f  Floating  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap
index 934b93fa..cabc4035 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <n> RESIZE   +|-  Increase/Decrease  ←↓↑→  Increase  HJKL  Decrease  ENTER  Select 
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <n> RESIZE   +|-  Increase/Decrease  ←↓↑→  Increase  HJKL  Decrease  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap
index bb92c9f8..fd74b0c0 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap
index 9e647b1a..8bef38dd 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ Zellij (test)  Tab #1  + 
+$ █
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap
index df752793..55785d6e 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <o> SESSION   d  Detach  w  Manager  s  Share  c  Config  l  Layouts  p  Plugins  ...
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <o> SESSION   d  Detach  w  Manager  s  Share  c  Config  l  Layouts  p  Plugins  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap
index 0bd07696..efb2bc6a 100644
--- a/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <t> TAB   n  New  ←→  Move  x  Close  r  Rename  s  Sync  b  Break out  []  Break  ...
+ Zellij (test)  Tab #1  + 
+$ █
+ Ctrl + <t> TAB   n  New  ←→  Move  x  Close  r  Rename  s  Sync  b  Break out  []  Break  ...
diff --git a/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap b/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap
index 42363818..88429ed3 100644
--- a/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/modes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap b/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap
index f007cf9d..4b400874 100644
--- a/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap
+++ b/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/mouse.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap b/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap
index 6bdb9ca6..7ec4a10d 100644
--- a/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap
+++ b/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap
@@ -2,27 +2,22 @@
source: zellij-integration-tests/tests/mouse.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ line1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa│
-│a │
-│line2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line5aaaaaaaaaaaaaaaaaaaaaaaa┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐aaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line6aaaaaaaaaaaaaaaaaaaaaaaa│$ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line7aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line8aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line9aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │
-│line10aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│
-│line11aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│
-│line12aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│
-│line13aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│
-│█ │ │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ line1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line5aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line7aaaaaaaaaaaaaaaaaaaaaaaaa┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐aaaaaaaaaaaaaaaaaaaaaaaaaaa
+line8aaaaaaaaaaaaaaaaaaaaaaaaa│$ │aaaaaaaaaaaaaaaaaaaaaaaaaaa
+line9aaaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaa
+line10aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line11aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line12aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+line13aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+█ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap b/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap
index 629cc513..0a1495df 100644
--- a/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap
+++ b/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/mouse.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 2/2 ┐
-│$ ││$ line1 │
-│ ││line2 │
-│ ││line3 │
-│ ││line4 │
-│ ││line5 │
-│ ││line6 │
-│ ││line7 │
-│ ││line8 │
-│ ││line9 │
-│ ││line10 │
-│ ││line11 │
-│ ││line12 │
-│ ││line13 │
-│ ││line14 │
-│ ││line15 │
-│ ││line16 │
-│ ││line17 │
-│ ││line18 │
-│ ││line19 │
-│ ││█ine20 │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2 [ SCROLL: 1/1 ]
+$ │$ line1
+ │line2
+ │line3
+ │line4
+ │line5
+ │line6
+ │line7
+ │line8
+ │line9
+ │line10
+ │line11
+ │line12
+ │line13
+ │line14
+ │line15
+ │line16
+ │line17
+ │line18
+ │line19
+ │line20
+ │█ine21
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap b/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap
index 0800ee6c..0e53b7b2 100644
--- a/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap
@@ -3,22 +3,5 @@ source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
-┌──────┐
-│$ done│
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────┘
+$ done█
Ctrl +
diff --git a/zellij-integration-tests/tests/snapshots/panes__close_pane.snap b/zellij-integration-tests/tests/snapshots/panes__close_pane.snap
index b9d0bb9c..717e5a5e 100644
--- a/zellij-integration-tests/tests/snapshots/panes__close_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__close_pane.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap
index bf220375..12bf79f3 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap
index fbbe4940..dc72368a 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap
index fbbe4940..dc72368a 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap
index f0254ce4..a4690066 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ oneone█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ oneone█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap
index f68a25e2..143b1902 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap
index 1bf6e70d..9919d65f 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$ █
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap
index a5ec291c..b8007c7b 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐
-│$ BBB█ ││$ AAA │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #2 │ Pane #1
+$ BBB█ │$ AAA
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap
index 3efaa27f..f14d9dea 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ BBB█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ AAA │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #2
+$ BBB█
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #1
+$ AAA
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap
index a5ec291c..b8007c7b 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐
-│$ BBB█ ││$ AAA │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #2 │ Pane #1
+$ BBB█ │$ AAA
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap
index a5ec291c..b8007c7b 100644
--- a/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐
-│$ BBB█ ││$ AAA │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #2 │ Pane #1
+$ BBB█ │$ AAA
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap
index f68a25e2..143b1902 100644
--- a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap
index f68a25e2..143b1902 100644
--- a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap b/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap
index 64abb7f3..b47edec4 100644
--- a/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap
@@ -2,27 +2,8 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+──────────────────────────────────────────────────────── Pane #1 ───────────────────────────────────────────────────────
+──────────────────────────────────────────────────────── Pane #2 ───────────────────────────────────────────────────────
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap b/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap
index b9d0bb9c..717e5a5e 100644
--- a/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap b/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap
index bf220375..12bf79f3 100644
--- a/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap b/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap
index e58b8c3e..be4beb78 100644
--- a/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap
@@ -2,7 +2,7 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
+ Zellij (test)  Tab #1  + 
$ │$ █
│
│
diff --git a/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap
index fbbe4940..dc72368a 100644
--- a/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap
index 3a4e1240..00b7b4b4 100644
--- a/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap
@@ -2,27 +2,17 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │
-│ │$ █ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$
+ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐
+ │$ █ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap
new file mode 100644
index 00000000..be296cab
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap
@@ -0,0 +1,28 @@
+---
+source: zellij-integration-tests/tests/panes.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ │
+│ │
+│ │
+│ │
+│ │
+│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │
+│ │$ █ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ └──────────────────────────────────────────────────────────┘ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap
new file mode 100644
index 00000000..b89372c8
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap
@@ -0,0 +1,28 @@
+---
+source: zellij-integration-tests/tests/panes.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ █ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap
new file mode 100644
index 00000000..4f752a1b
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap
@@ -0,0 +1,28 @@
+---
+source: zellij-integration-tests/tests/panes.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ █ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap
index 3a4e1240..00b7b4b4 100644
--- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap
@@ -2,27 +2,17 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │
-│ │$ █ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$
+ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐
+ │$ █ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap
index e58b8c3e..143b1902 100644
--- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap
@@ -2,7 +2,8 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
$ │$ █
│
│
@@ -24,5 +25,4 @@ $ │$ █
│
│
│
- │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap
index fcb1eba9..ad010e60 100644
--- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap
@@ -2,27 +2,7 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 (FULLSCREEN) 
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1 (FULLSCREEN)  + 
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap
index 858b2446..de6f7edb 100644
--- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap
@@ -2,27 +2,17 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ ┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐ │
-│ │$ █ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$
+ ┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐
+ │$ █ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap b/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap
index b9d0bb9c..143b1902 100644
--- a/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap
+++ b/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/panes.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap b/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap
index 7341d7a6..034a2c02 100644
--- a/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap
+++ b/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap
@@ -2,27 +2,17 @@
source: zellij-integration-tests/tests/plugins.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ ┌ (.) - permission-requester ───────────────────── PIN [ ] ┐ │
-│ │This plugin asks permission to: ReadApplicationState, Chan│ │
-│ │geApplicationState, OpenFiles, RunCommands, OpenTerminalsO│ │
-│ │rPlugins, WriteToStdin, WebAccess, ReadCliPipes, MessageAn│ │
-│ │dLaunchOtherPlugins, Reconfigure, RunActionsAsUser, WriteT│ │
-│ │oClipboard, ReadSessionEnvironmentVariables. Allow? (y/n) │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-
+ Zellij (test)  Tab #1  + 
+$
+ ┌ (.) - permission-requester ───────────────────── PIN [ ] ┐
+ │This plugin asks permission to: ReadApplicationState, Chan│
+ │geApplicationState, OpenFiles, RunCommands, OpenTerminalsO│
+ │rPlugins, WriteToStdin, WebAccess, ReadCliPipes, MessageAn│
+ │dLaunchOtherPlugins, Reconfigure, RunActionsAsUser, WriteT│
+ │oClipboard, ReadSessionEnvironmentVariables. Allow? (y/n) │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────────────────────────┘
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap
index 6bb097ff..53311e6d 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$ █
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap
index 6d94b5be..89aa0ab6 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────┐┌ Pane #2 ─────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────────────────────────────────────────┘└──────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap
index 6d94b5be..89aa0ab6 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────┐┌ Pane #2 ─────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────────────────────────────────────────┘└──────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap
index 31a95ba2..086c9ed1 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap
index 8071443e..811b464d 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap
index f60a7abc..9469e37a 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap
index b04b511a..53311e6d 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$ █
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap
index 1da118af..2a1f23f0 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────┐┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────┘└──────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap
index 1da118af..2a1f23f0 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────┐┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────┘└──────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap
index fca16a54..416be42d 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────┐
-│$ █ ││$ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ █ │$
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap
index 5ff0c7aa..9469e37a 100644
--- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap
+++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap
@@ -2,27 +2,10 @@
source: zellij-integration-tests/tests/resize.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1
+$
+────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+ Pane #2
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap
index 414fdd10..70894a4e 100644
--- a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap
+++ b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/resurrection.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  alpha  beta 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│ ││█ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  alpha  beta  + 
+ Pane #1 │ Pane #2
+ │█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap
index 9cdf365b..4c6f5ee3 100644
--- a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap
+++ b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap
@@ -2,27 +2,7 @@
source: zellij-integration-tests/tests/resurrection.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│ │
-│VIEWPORT_CONTENT_TO_RESTORE │
-│ │
-│█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+VIEWPORT_CONTENT_TO_RESTORE
+█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap
index 2ce2743f..e51bd7c6 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 0/21 ┐
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│line31 │
-│line32 │
-│line33 │
-│line34 │
-│line35 │
-│line36 │
-│line37 │
-│line38 │
-│line39 │
-│line40 │
-│█ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  +  [ SCROLL 0/19 ]
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+line31
+line32
+line33
+line34
+line35
+line36
+line37
+line38
+line39
+line40
+█
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap
index 4adb7c17..1b2b0967 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 10/21 ┐
-│line12 │
-│line13 │
-│line14 │
-│line15 │
-│line16 │
-│line17 │
-│line18 │
-│line19 │
-│line20 │
-│line21 │
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│█ine31 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  +  [ SCROLL 10/19 ]
+line10
+line11
+line12
+line13
+line14
+line15
+line16
+line17
+line18
+line19
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+█ine31
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap
index 6b3cec51..e51bd7c6 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 1/21 ┐
-│line21 │
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│line31 │
-│line32 │
-│line33 │
-│line34 │
-│line35 │
-│line36 │
-│line37 │
-│line38 │
-│line39 │
-│█ine40 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  +  [ SCROLL 0/19 ]
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+line31
+line32
+line33
+line34
+line35
+line36
+line37
+line38
+line39
+line40
+█
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap
index d742f0d3..54718511 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 21/21 ┐
-│$ line01 │
-│line02 │
-│line03 │
-│line04 │
-│line05 │
-│line06 │
-│line07 │
-│line08 │
-│line09 │
-│line10 │
-│line11 │
-│line12 │
-│line13 │
-│line14 │
-│line15 │
-│line16 │
-│line17 │
-│line18 │
-│line19 │
-│█ine20 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  +  [ SCROLL 19/19 ]
+$ line01
+line02
+line03
+line04
+line05
+line06
+line07
+line08
+line09
+line10
+line11
+line12
+line13
+line14
+line15
+line16
+line17
+line18
+line19
+line20
+line21
+█ine22
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap b/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap
index 6b3cec51..873db2ac 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 1/21 ┐
-│line21 │
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│line31 │
-│line32 │
-│line33 │
-│line34 │
-│line35 │
-│line36 │
-│line37 │
-│line38 │
-│line39 │
-│█ine40 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
+ Zellij (test)  Tab #1  +  [ SCROLL 1/19 ]
+line19
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+line31
+line32
+line33
+line34
+line35
+line36
+line37
+line38
+line39
+█ine40
+ Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
diff --git a/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap b/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap
index 4e486cc2..50481925 100644
--- a/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap
+++ b/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/scroll.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 0/21 ┐
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│line31 │
-│line32 │
-│line33 │
-│line34 │
-│line35 │
-│line36 │
-│line37 │
-│line38 │
-│line39 │
-│line40 │
-│█ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  +  [ SCROLL 0/19 ]
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+line31
+line32
+line33
+line34
+line35
+line36
+line37
+line38
+line39
+line40
+█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap b/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap
index 7f89ceaa..af4123ad 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ SEARCHING: NEEDLE ──────────────────────────────────────────────────────────────────────────────────── SCROLL: 6/21 ┐
-│line16 │
-│line17 │
-│line18 │
-│line19 │
-│line20 │
-│line21 │
-│line22 │
-│line23 │
-│line24 │
-│line25 │
-│line26 │
-│line27 │
-│line28 │
-│line29 │
-│line30 │
-│line31 │
-│line32 │
-│line33 │
-│line34 │
-│█ine35 NEEDLE lower │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ Zellij (test)  Tab #1  +  [ SCROLL 15/19 ]
+line14
+line15
+line16
+line17
+line18
+line19
+line20
+line21
+line22
+line23
+line24
+line25
+line26
+line27
+line28
+line29
+line30
+line31
+line32
+line33
+line34
+█ine35 NEEDLE lower
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap b/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap
index d3c4a72d..bdceee74 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ SEARCHING: NEEDLE ─────────────────────────────────────────────────────────────────────────────────── SCROLL: 17/21 ┐
-│line05 NEEDLE │
-│line06 │
-│line07 │
-│line08 │
-│line09 │
-│line10 │
-│line11 │
-│line12 │
-│line13 │
-│line14 │
-│line15 │
-│line16 │
-│line17 │
-│line18 │
-│line19 │
-│line20 │
-│line21 │
-│line22 │
-│line23 │
-│█ine24 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- ENTERING SEARCH TERM   ENTER  When done 
+ Zellij (test)  Tab #1  +  [ SCROLL 0/19 ]
+line05 NEEDLE
+line06
+line07
+line08
+line09
+line10
+line11
+line12
+line13
+line14
+line15
+line16
+line17
+line18
+line19
+line20
+line21
+line22
+line23
+line24
+line25
+█ine26
+ ENTERING SEARCH TERM   ENTER  When done 
diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap
index 8fab3747..b1642d5b 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap
@@ -2,9 +2,9 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
+ Zellij (test)  Tab #1  + 
┌ SEARCHING: NEEDLE [c] ───────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ NEEDLE on screen │
+│NEEDLE on screen │
│█ │
│ │
│ │
@@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot)
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap
index a611c034..9011cc91 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap
@@ -2,9 +2,9 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
+ Zellij (test)  Tab #1  + 
┌ SEARCHING: NEEDLE [o] ───────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ NEEDLE on screen │
+│NEEDLE on screen │
│█ │
│ │
│ │
@@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot)
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap
index 42903ace..5d52b7ed 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap
@@ -2,9 +2,9 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
+ Zellij (test)  Tab #1  + 
┌ SEARCHING: NEEDLE [w] ───────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ NEEDLE on screen │
+│NEEDLE on screen │
│█ │
│ │
│ │
@@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot)
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap b/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap
index c113cdad..b723f787 100644
--- a/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap
+++ b/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/search.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ SEARCHING: NEEDLE ─────────────────────────────────────────────────────────────────────────────────── SCROLL: 17/21 ┐
-│line05 NEEDLE upper │
-│line06 │
-│line07 │
-│line08 │
-│line09 │
-│line10 │
-│line11 │
-│line12 │
-│line13 │
-│line14 │
-│line15 │
-│line16 │
-│line17 │
-│line18 │
-│line19 │
-│line20 │
-│line21 │
-│line22 │
-│line23 │
-│█ine24 │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
+ Zellij (test)  Tab #1  +  [ SCROLL 0/19 ]
+line05 NEEDLE upper
+line06
+line07
+line08
+line09
+line10
+line11
+line12
+line13
+line14
+line15
+line16
+line17
+line18
+line19
+line20
+line21
+line22
+line23
+line24
+line25
+█ine26
+ SEARCHING   ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  n  Down  p  Up  c  Case  w  Wrap  o  Whole 
diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap
index 83ddbab4..91c4eebe 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap
index f64e72ee..2b03a0f3 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐
-│$ alpha ││$ beta█ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #1
+$ alpha │$ beta█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap
index db5fb026..7235b444 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ gamma ││$ beta█ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+ Pane #1 │ Pane #2
+$ gamma │$ beta█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap
index f1544d42..5ffc3a99 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap
index 9441a9b1..403e5945 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ twotwo█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ twotwo█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap
index e60935a0..47ff0263 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ oneone█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ oneone█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap
index e60935a0..47ff0263 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ oneone█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ oneone█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap
index 5afe4d28..d6207d33 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #3  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #3  Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap
index d045b135..95e5f3f3 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2  Tab #3 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  Tab #3  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap
index 5afe4d28..d6207d33 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #3  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #3  Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap
index 2b4f6227..f2a22412 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #3  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #3  Tab #1  Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap
index da0f2839..91c4eebe 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap
@@ -1,28 +1,7 @@
---
source: zellij-integration-tests/tests/tabs.rs
-expression: normalized(&zellij.snapshot())
+expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap
index f34fad73..bd955b1a 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap
@@ -2,27 +2,27 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 (SYNC) 
-┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
-│$ ││$ █ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-│ ││ │
-└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1 (SYNC)  + 
+ Pane #1 │ Pane #2
+$ │$ █
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap b/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap
index e60935a0..47ff0263 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1  Tab #2 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ oneone█ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  Tab #2  + 
+$ oneone█
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap
index f1544d42..5ffc3a99 100644
--- a/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap
+++ b/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap
@@ -2,27 +2,6 @@
source: zellij-integration-tests/tests/tabs.rs
expression: normalized(&grid_snapshot)
---
- Zellij (test)  Tab #1 
-┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│$ █ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-│ │
-└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Zellij (test)  Tab #1  + 
+$ █
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  ...
diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap
new file mode 100644
index 00000000..ef47b9b9
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap
@@ -0,0 +1,18 @@
+---
+source: zellij-integration-tests/tests/title_frame_mouse.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+$
+ ┌ Pane #2 ─────────────────────────────────────────────────────────────────────────── PIN [ ] ┐
+ │$ █ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ │ │
+ └─────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New Pane  <f> Floating 
diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap
new file mode 100644
index 00000000..7a7db894
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap
@@ -0,0 +1,28 @@
+---
+source: zellij-integration-tests/tests/title_frame_mouse.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │opened from the status bar█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New Pane  <←↓↑→> Change Focus  <+-> Resize  <f> Floating 
diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap
new file mode 100644
index 00000000..e3fbdb82
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap
@@ -0,0 +1,28 @@
+---
+source: zellij-integration-tests/tests/title_frame_mouse.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  + 
+ Pane #1 │ Pane #2
+$ │first pane from the status bar
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ ├───────────────────────────────────────────────────────────────────────────────────────────────
+ │ Pane #3
+ │second pane from the status bar█
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ │
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New Pane  <←↓↑→> Change Focus  <+-> Resize  <f> Floating 
diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap
new file mode 100644
index 00000000..f05439e3
--- /dev/null
+++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap
@@ -0,0 +1,7 @@
+---
+source: zellij-integration-tests/tests/title_frame_mouse.rs
+expression: normalized(&grid_snapshot)
+---
+ Zellij (test)  Tab #1  Tab #2  + 
+$ █
+
diff --git a/zellij-integration-tests/tests/tabs.rs b/zellij-integration-tests/tests/tabs.rs
index 7ba3194a..cd37e251 100644
--- a/zellij-integration-tests/tests/tabs.rs
+++ b/zellij-integration-tests/tests/tabs.rs
@@ -26,7 +26,7 @@ fn open_new_tab_and_wait_for_prompt(zellij: &TestSession, expected_tab: &str) ->
zellij.wait_until("new tab opened with prompt", move |grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains(&expected_tab)
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
terminal
}
@@ -201,9 +201,8 @@ fn break_pane_into_new_tab() {
let grid_snapshot = zellij.wait_until("focused pane broken into a new tab", |grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Tab #2")
- && grid_snapshot.contains("Pane #2")
&& !grid_snapshot.contains("Pane #1")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -273,7 +272,7 @@ fn open_new_tab() {
let grid_snapshot = zellij.wait_until("second tab steady in normal mode", |grid_snapshot| {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Tab #2")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
});
assert_snapshot!(normalized(&grid_snapshot));
zellij.quit();
@@ -294,7 +293,7 @@ fn close_tab() {
grid_snapshot.status_bar_appears()
&& grid_snapshot.contains("Tab #1")
&& !grid_snapshot.contains("Tab #2")
- && grid_snapshot.cursor_is_at(col(3).row(2))
+ && grid_snapshot.cursor_is_at(col(2).row(1))
},
);
assert_snapshot!(normalized(&grid_snapshot));
diff --git a/zellij-integration-tests/tests/title_frame_hints.rs b/zellij-integration-tests/tests/title_frame_hints.rs
new file mode 100644
index 00000000..5f841486
--- /dev/null
+++ b/zellij-integration-tests/tests/title_frame_hints.rs
@@ -0,0 +1,233 @@
+#![cfg(unix)]
+
+use zellij_integration_tests::{
+ claim_first_terminal_and_wait_for_prompt, keys, split_right_and_wait_for_prompt, FakePtyHandle,
+ Size, TestRunner, TestSession, PROMPT,
+};
+
+const FOCUSED_PANE_COLUMN: usize = 90;
+const ALTERNATE_FOCUSED_PANE_COLUMN: usize = 100;
+const OTHER_PANE_COLUMN: usize = 10;
+const HOVER_LINE: usize = 12;
+
+fn start_zellij_with_mouse() -> TestSession {
+ TestRunner::new(Size {
+ cols: 120,
+ rows: 24,
+ })
+ .with_config("mouse_mode true\nadvanced_mouse_actions true\nmouse_hover_effects true")
+ .start()
+}
+
+fn start_full_frame_zellij_with_mouse(cols: usize) -> TestSession {
+ TestRunner::new(Size { cols, rows: 24 })
+ .with_config(
+ "pane_frame_style \"full\"\nmouse_mode true\nadvanced_mouse_actions true\nmouse_hover_effects true",
+ )
+ .start()
+}
+
+fn sgr_motion(column: usize, line: usize) -> Vec<u8> {
+ format!("\u{1b}[<35;{};{}M", column, line).into_bytes()
+}
+
+fn two_pane_session_with_handles() -> (TestSession, FakePtyHandle, FakePtyHandle) {
+ let zellij = start_zellij_with_mouse();
+ let left_terminal = claim_first_terminal_and_wait_for_prompt(&zellij);
+ let right_terminal = split_right_and_wait_for_prompt(&zellij);
+ zellij.wait_until("two panes settled in locked base mode", |grid_snapshot| {
+ grid_snapshot.status_bar_appears() && grid_snapshot.tab_bar_appears()
+ });
+ (zellij, left_terminal, right_terminal)
+}
+
+fn two_pane_session() -> TestSession {
+ two_pane_session_with_handles().0
+}
+
+fn full_frame_two_pane_session(cols: usize) -> TestSession {
+ let zellij = start_full_frame_zellij_with_mouse(cols);
+ let left_terminal = zellij.expect_pty_spawn();
+ left_terminal.output(PROMPT);
+ zellij.wait_until("first full-frame pane rendered", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("┌")
+ && grid_snapshot.contains("$ ")
+ });
+ zellij.send_stdin(&keys::ctrl('p'));
+ zellij.send_stdin(&keys::key('r'));
+ let right_terminal = zellij.expect_pty_spawn();
+ right_terminal.output(PROMPT);
+ zellij.wait_until("two full-frame panes rendered", |grid_snapshot| {
+ grid_snapshot.contains("Pane #1")
+ && grid_snapshot.contains("Pane #2")
+ && grid_snapshot.status_bar_appears()
+ });
+ zellij
+}
+
+#[test]
+fn hovering_a_pane_shows_a_hint_on_the_status_bar() {
+ let mut zellij = two_pane_session();
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until(
+ "resize hint shown when hovering the focused pane",
+ |grid_snapshot| grid_snapshot.contains("resize"),
+ );
+
+ zellij.send_stdin(&sgr_motion(OTHER_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until(
+ "group hint shown when hovering the other pane",
+ |grid_snapshot| grid_snapshot.contains("group"),
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn any_input_dismisses_the_hint() {
+ let mut zellij = two_pane_session();
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until("resize hint shown", |grid_snapshot| {
+ grid_snapshot.contains("resize")
+ });
+
+ zellij.send_stdin(b"x");
+ zellij.wait_until("hint cleared by input", |grid_snapshot| {
+ !grid_snapshot.contains("resize") && !grid_snapshot.contains("group")
+ });
+
+ zellij.quit();
+}
+
+#[test]
+fn hint_only_re_fires_when_entering_a_different_pane() {
+ let mut zellij = two_pane_session();
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until("resize hint shown on first entry", |grid_snapshot| {
+ grid_snapshot.contains("resize")
+ });
+
+ zellij.send_stdin(b"x");
+ zellij.wait_until("hint dismissed by input", |grid_snapshot| {
+ !grid_snapshot.contains("resize") && !grid_snapshot.contains("group")
+ });
+
+ zellij.send_stdin(&sgr_motion(ALTERNATE_FOCUSED_PANE_COLUMN, HOVER_LINE));
+ let after_within_pane_motion = zellij.wait_until(
+ "a render settles after within-pane motion",
+ |grid_snapshot| grid_snapshot.status_bar_appears(),
+ );
+ assert!(
+ !after_within_pane_motion.contains("resize"),
+ "within-pane motion must not re-show the resize hint:\n{}",
+ after_within_pane_motion.text
+ );
+
+ zellij.send_stdin(&sgr_motion(OTHER_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until(
+ "group hint shown when crossing into the other pane",
+ |grid_snapshot| grid_snapshot.contains("group"),
+ );
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until(
+ "resize hint shown again when crossing back",
+ |grid_snapshot| grid_snapshot.contains("resize"),
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn full_frame_help_renders_on_the_pane_not_the_status_bar() {
+ let mut zellij = full_frame_two_pane_session(120);
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ let grid_snapshot = zellij.wait_until("resize help drawn on the pane frame", |grid_snapshot| {
+ grid_snapshot.contains("to resize")
+ });
+ let status_bar = grid_snapshot.lines().last().cloned().unwrap();
+ assert!(
+ !status_bar.contains("resize"),
+ "in full-frame mode the resize help belongs on the pane frame, not the status bar:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn resize_hint_shortens_when_the_status_bar_narrows() {
+ let mut zellij = two_pane_session();
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until(
+ "full-width status bar shows the long resize hint",
+ |grid_snapshot| grid_snapshot.contains("to resize"),
+ );
+
+ zellij.resize(Size { cols: 46, rows: 24 });
+ zellij.wait_until(
+ "narrowed status bar shortens the resize hint",
+ |grid_snapshot| {
+ grid_snapshot.contains("drag borders") && !grid_snapshot.contains("to resize")
+ },
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn resize_hint_absent_with_a_single_pane() {
+ let (mut zellij, left_terminal, _right_terminal) = two_pane_session_with_handles();
+ left_terminal.output(b"LEFT_PANE_MARKER");
+ zellij.wait_until("the other pane is populated", |grid_snapshot| {
+ grid_snapshot.contains("LEFT_PANE_MARKER")
+ });
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.wait_until("resize hint shown with two panes", |grid_snapshot| {
+ grid_snapshot.contains("resize")
+ });
+
+ left_terminal.exit(Some(0));
+ zellij.wait_until(
+ "resize hint cleared once a single pane remains",
+ |grid_snapshot| {
+ !grid_snapshot.contains("LEFT_PANE_MARKER")
+ && grid_snapshot.status_bar_appears()
+ && !grid_snapshot.contains("resize")
+ },
+ );
+
+ zellij.quit();
+}
+
+#[test]
+fn resize_hint_absent_in_fullscreen() {
+ let (mut zellij, _left_terminal, _right_terminal) = two_pane_session_with_handles();
+
+ zellij.send_stdin(&keys::ctrl('p'));
+ zellij.send_stdin(&keys::key('f'));
+ zellij.wait_until("focused pane entered fullscreen", |grid_snapshot| {
+ grid_snapshot.contains("(FULLSCREEN)") && grid_snapshot.contains("LOCK")
+ });
+
+ zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE));
+ zellij.send_stdin(&sgr_motion(ALTERNATE_FOCUSED_PANE_COLUMN, HOVER_LINE));
+ let grid_snapshot = zellij
+ .wait_until("fullscreen stays settled after hovering", |grid_snapshot| {
+ grid_snapshot.contains("(FULLSCREEN)") && grid_snapshot.contains("LOCK")
+ });
+ assert!(
+ !grid_snapshot.contains("resize"),
+ "fullscreen must suppress the resize hint:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.quit();
+}
diff --git a/zellij-integration-tests/tests/title_frame_mouse.rs b/zellij-integration-tests/tests/title_frame_mouse.rs
new file mode 100644
index 00000000..68467068
--- /dev/null
+++ b/zellij-integration-tests/tests/title_frame_mouse.rs
@@ -0,0 +1,158 @@
+#![cfg(unix)]
+
+use insta::assert_snapshot;
+use zellij_integration_tests::{normalized, FakePtyHandle, Size, TestRunner, TestSession};
+
+const PROMPT: &[u8] = b"$ ";
+const STATUS_BAR_TEST_COLS: usize = 190;
+
+fn start_zellij(cols: usize) -> TestSession {
+ TestRunner::new(Size { cols, rows: 24 })
+ .with_config("mouse_mode true\npane_frame_style \"titles\"")
+ .start()
+}
+
+fn sgr_left_click(column: usize, line: usize) -> Vec<u8> {
+ format!(
+ "\u{1b}[<0;{};{}M\u{1b}[<0;{};{}m",
+ column, line, column, line
+ )
+ .into_bytes()
+}
+
+fn display_column_of(line: &str, needle: &str) -> Option<usize> {
+ line.find(needle)
+ .map(|byte_offset| line[..byte_offset].chars().count())
+}
+
+fn claim_first_terminal_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle {
+ let terminal = zellij.expect_pty_spawn();
+ terminal.output(PROMPT);
+ zellij.wait_until("first terminal prompt rendered", |grid_snapshot| {
+ grid_snapshot.tab_bar_appears()
+ && grid_snapshot.status_bar_appears()
+ && grid_snapshot.contains("$ ")
+ });
+ terminal
+}
+
+fn click_new_pane_button_in_status_bar(zellij: &TestSession, pane_output: &[u8]) -> FakePtyHandle {
+ let grid_snapshot =
+ zellij.wait_until("status bar shows the new pane button", |grid_snapshot| {
+ grid_snapshot
+ .lines()
+ .last()
+ .is_some_and(|status_bar| status_bar.contains("New Pane"))
+ });
+ let status_bar = grid_snapshot.lines().last().cloned().unwrap();
+ let new_pane_column = display_column_of(&status_bar, "New Pane")
+ .expect("new pane button is on the status bar")
+ + 1;
+ let status_bar_line = grid_snapshot.lines().len();
+
+ zellij.send_stdin(&sgr_left_click(new_pane_column, status_bar_line));
+ let new_terminal = zellij.expect_pty_spawn();
+ new_terminal.output(pane_output);
+ new_terminal
+}
+
+#[test]
+fn mouse_click_new_pane_in_status_bar_opens_a_new_pane() {
+ let mut zellij = start_zellij(STATUS_BAR_TEST_COLS);
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ click_new_pane_button_in_status_bar(&zellij, b"opened from the status bar");
+
+ let grid_snapshot = zellij.wait_until("the clicked new pane rendered", |grid_snapshot| {
+ grid_snapshot.contains("opened from the status bar")
+ && grid_snapshot.contains("Change Focus")
+ });
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+#[test]
+fn mouse_click_new_pane_in_status_bar_twice_opens_two_panes() {
+ let mut zellij = start_zellij(STATUS_BAR_TEST_COLS);
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ click_new_pane_button_in_status_bar(&zellij, b"first pane from the status bar");
+ zellij.wait_until(
+ "the first clicked pane rendered and the status bar gained the multi-pane controls",
+ |grid_snapshot| {
+ grid_snapshot.contains("first pane from the status bar")
+ && grid_snapshot.contains("Change Focus")
+ },
+ );
+
+ click_new_pane_button_in_status_bar(&zellij, b"second pane from the status bar");
+
+ let grid_snapshot = zellij.wait_until(
+ "the second clicked pane rendered alongside the first",
+ |grid_snapshot| {
+ grid_snapshot.contains("first pane from the status bar")
+ && grid_snapshot.contains("second pane from the status bar")
+ },
+ );
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+fn click_floating_ribbon_in_status_bar(zellij: &TestSession) {
+ let grid_snapshot =
+ zellij.wait_until("status bar shows the floating ribbon", |grid_snapshot| {
+ grid_snapshot
+ .lines()
+ .last()
+ .is_some_and(|status_bar| status_bar.contains("Floating"))
+ });
+ let status_bar = grid_snapshot.lines().last().cloned().unwrap();
+ let floating_ribbon_column = display_column_of(&status_bar, "Floating")
+ .expect("floating ribbon is on the status bar")
+ + 1;
+ let status_bar_line = grid_snapshot.lines().len();
+
+ zellij.send_stdin(&sgr_left_click(floating_ribbon_column, status_bar_line));
+}
+
+#[test]
+fn mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane() {
+ let mut zellij = start_zellij(STATUS_BAR_TEST_COLS);
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ click_floating_ribbon_in_status_bar(&zellij);
+ let floating_terminal = zellij.expect_pty_spawn();
+ floating_terminal.output(PROMPT);
+
+ let grid_snapshot = zellij.wait_until("a floating pane appeared", |grid_snapshot| {
+ grid_snapshot.contains("STAGGERED") && grid_snapshot.contains("┌")
+ });
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
+
+#[test]
+fn mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab() {
+ let mut zellij = start_zellij(120);
+ claim_first_terminal_and_wait_for_prompt(&zellij);
+
+ let grid_snapshot = zellij.wait_until("tab bar shows the new tab button", |grid_snapshot| {
+ grid_snapshot
+ .lines()
+ .first()
+ .is_some_and(|tab_bar| tab_bar.contains('+'))
+ });
+ let tab_bar = grid_snapshot.lines().first().cloned().unwrap();
+ let new_tab_button_column =
+ display_column_of(&tab_bar, "+").expect("new tab button is on the tab bar") + 1;
+
+ zellij.send_stdin(&sgr_left_click(new_tab_button_column, 1));
+ let new_tab_terminal = zellij.expect_pty_spawn();
+ new_tab_terminal.output(PROMPT);
+
+ let grid_snapshot = zellij.wait_until("a second tab opened", |grid_snapshot| {
+ grid_snapshot.contains("Tab #1") && grid_snapshot.contains("Tab #2")
+ });
+ assert_snapshot!(normalized(&grid_snapshot));
+ zellij.quit();
+}
diff --git a/zellij-integration-tests/tests/title_frame_scroll.rs b/zellij-integration-tests/tests/title_frame_scroll.rs
new file mode 100644
index 00000000..a99e98dd
--- /dev/null
+++ b/zellij-integration-tests/tests/title_frame_scroll.rs
@@ -0,0 +1,58 @@
+#![cfg(unix)]
+
+use zellij_integration_tests::{
+ claim_first_terminal_and_wait_for_prompt, keys, split_right_and_wait_for_prompt, start_zellij,
+ FakePtyHandle, GridSnapshot, TestSession,
+};
+
+const LAST_LINE: &str = "line40";
+
+fn tab_line_shows_scroll(grid_snapshot: &GridSnapshot) -> bool {
+ grid_snapshot
+ .lines()
+ .first()
+ .is_some_and(|tab_bar| tab_bar.contains("SCROLL"))
+}
+
+fn fill_pane_past_viewport(zellij: &TestSession) -> FakePtyHandle {
+ let terminal = claim_first_terminal_and_wait_for_prompt(zellij);
+ for line in 1..=40 {
+ terminal.output(format!("line{:02}\r\n", line).as_bytes());
+ }
+ zellij.wait_until("pane filled past its viewport", |grid_snapshot| {
+ grid_snapshot.contains(LAST_LINE)
+ });
+ terminal
+}
+
+#[test]
+fn single_pane_scroll_shows_on_the_tab_line() {
+ let mut zellij = start_zellij();
+ fill_pane_past_viewport(&zellij);
+
+ zellij.send_stdin(&keys::ctrl('s'));
+ zellij.send_stdin(&keys::ctrl('b'));
+
+ let grid_snapshot = zellij.wait_until(
+ "scroll indicator appears on the tab line",
+ |grid_snapshot| tab_line_shows_scroll(grid_snapshot) && !grid_snapshot.contains(LAST_LINE),
+ );
+ assert!(
+ !grid_snapshot.contains("SCROLL:"),
+ "the single-pane tab-line indicator uses the colon-free format:\n{}",
+ grid_snapshot.text
+ );
+
+ zellij.send_stdin(&keys::ESC);
+ zellij.wait_until("back in the base mode after scrolling", |grid_snapshot| {
+ grid_snapshot.status_bar_appears()
+ });
+ split_right_and_wait_for_prompt(&zellij);
+
+ zellij.wait_until(
+ "tab-line scroll indicator clears once a second pane exists",
+ |grid_snapshot| !tab_line_shows_scroll(grid_snapshot),
+ );
+
+ zellij.quit();
+}
diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs
index f9fcb649..62f8d651 100644
--- a/zellij-server/src/lib.rs
+++ b/zellij-server/src/lib.rs
@@ -40,6 +40,7 @@ use zellij_utils::envs;
use zellij_utils::pane_size::Size;
use zellij_utils::input::cli_assets::CliAssets;
+use zellij_utils::input::options::PaneFrameStyle;
use wasmi::Engine;
@@ -402,6 +403,7 @@ impl SessionMetaData {
new_config.options.theme_light.as_deref().unwrap_or("?")
);
}
+ let pane_frame_style = PaneFrameStyle::from_options(&new_config.options);
self.senders
.send_to_screen(ScreenInstruction::Reconfigure {
client_id,
@@ -417,7 +419,7 @@ impl SessionMetaData {
host_theme_light,
simplified_ui: new_config.options.simplified_ui.unwrap_or(false),
default_shell: new_config.options.default_shell,
- pane_frames: new_config.options.pane_frames.unwrap_or(true),
+ pane_frame_style,
copy_command: new_config.options.copy_command,
copy_to_clipboard: new_config.options.copy_clipboard,
copy_on_select: new_config.options.copy_on_select.unwrap_or(true),
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs
index 4093e488..5dbc7fb2 100644
--- a/zellij-server/src/panes/floating_panes/mod.rs
+++ b/zellij-server/src/panes/floating_panes/mod.rs
@@ -491,6 +491,7 @@ impl FloatingPanes {
mouse_hover_pane_id,
current_pane_group.clone(),
show_help_text,
+ false,
);
for client_id in &connected_clients {
let client_mode = self
diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs
index 477185a4..84c2e970 100644
--- a/zellij-server/src/panes/terminal_pane.rs
+++ b/zellij-server/src/panes/terminal_pane.rs
@@ -377,10 +377,12 @@ impl Pane for TerminalPane {
fn render_frame(
&mut self,
client_id: ClientId,
- frame_params: FrameParams,
+ mut frame_params: FrameParams,
input_mode: InputMode,
) -> Result<Option<(Vec<CharacterChunk>, Option<String>)>> {
let err_context = || format!("failed to render frame for client {client_id}");
+ frame_params.omit_title = frame_params.omit_title
+ && !(input_mode == InputMode::RenamePane && frame_params.is_main_client);
// TODO: remove the cursor stuff from here
let normal_title = if self.pane_name.is_empty()
&& input_mode == InputMode::RenamePane
@@ -902,6 +904,12 @@ impl Pane for TerminalPane {
Some(self.pane_name.clone())
}
}
+ fn has_explicit_title(&self) -> bool {
+ !self.pane_name.is_empty() || self.grid.title.is_some()
+ }
+ fn scroll_position(&self) -> (usize, usize) {
+ self.grid.scrollback_position_and_length()
+ }
fn exit_status(&self) -> Option<i32> {
self.is_held
.as_ref()
diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs
index 04ca0a8b..e3f66c37 100644
--- a/zellij-server/src/panes/tiled_panes/mod.rs
+++ b/zellij-server/src/panes/tiled_panes/mod.rs
@@ -23,6 +23,7 @@ use zellij_utils::{
input::{
command::RunCommand,
layout::{Run, RunPluginOrAlias, SplitDirection},
+ options::PaneFrameStyle,
},
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
};
@@ -66,7 +67,7 @@ pub struct TiledPanes {
style: Style,
session_is_mirrored: bool,
active_panes: ActivePanes,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
panes_to_hide: HashSet<PaneId>,
fullscreen_is_active: Option<PaneId>,
senders: ThreadSenders,
@@ -87,7 +88,7 @@ impl TiledPanes {
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
stacked_resize: Rc<RefCell<bool>>,
session_is_mirrored: bool,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
default_mode_info: ModeInfo,
style: Style,
os_api: Box<dyn ServerOsApi>,
@@ -106,7 +107,7 @@ impl TiledPanes {
style,
session_is_mirrored,
active_panes: ActivePanes::new(&os_api),
- draw_pane_frames,
+ pane_frame_style,
panes_to_hide: HashSet::new(),
fullscreen_is_active: None,
senders,
@@ -117,7 +118,7 @@ impl TiledPanes {
}
}
pub fn add_pane_with_existing_geom(&mut self, pane_id: PaneId, mut pane: Box<dyn Pane>) {
- if self.draw_pane_frames {
+ if self.pane_frame_style.draws_full_frames() {
pane.set_content_offset(Offset::frame(1));
}
self.panes.insert(pane_id, pane);
@@ -148,7 +149,7 @@ impl TiledPanes {
mut with_pane: Box<dyn Pane>,
) -> Option<Box<dyn Pane>> {
let with_pane_id = with_pane.pid();
- if self.draw_pane_frames && !with_pane.borderless() {
+ if self.pane_frame_style.draws_full_frames() && !with_pane.borderless() {
with_pane.set_content_offset(Offset::frame(1));
}
let removed_pane = self.panes.remove(&pane_id).map(|removed_pane| {
@@ -547,14 +548,22 @@ impl TiledPanes {
.with_context(|| format!("{:?} relayout of tab failed", direction))
.non_fatal();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
pub fn reapply_pane_frames(&mut self) {
// same as set_pane_frames except it reapplies the current situation
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
- pub fn set_pane_frames(&mut self, draw_pane_frames: bool) {
- self.draw_pane_frames = draw_pane_frames;
+ pub fn set_pane_frames(&mut self, pane_frame_style: PaneFrameStyle) {
+ self.pane_frame_style = pane_frame_style;
+ let draws_full_frames = pane_frame_style.draws_full_frames();
+ let draws_titles = pane_frame_style.draws_titles();
+ let single_selectable_tiled_pane = self
+ .panes
+ .values()
+ .filter(|p| p.selectable() && !p.borderless())
+ .count()
+ == 1;
let viewport = *self.viewport.borrow();
let position_and_sizes_of_stacks = {
StackedPanes::new_from_btreemap(&mut self.panes, &self.panes_to_hide)
@@ -563,41 +572,35 @@ impl TiledPanes {
};
for pane in self.panes.values_mut() {
if !pane.borderless() {
- pane.set_frame(draw_pane_frames);
+ pane.set_frame(draws_full_frames);
}
#[allow(clippy::if_same_then_else)]
- if draw_pane_frames && !pane.borderless() {
- // there's definitely a frame around this pane, offset its contents
+ if draws_full_frames && !pane.borderless() {
pane.set_content_offset(Offset::frame(1));
- } else if draw_pane_frames && pane.borderless() {
- // there's no frame around this pane, and the tab isn't handling the boundaries
- // between panes (they each draw their own frames as they please)
- // this one doesn't - do not offset its content
+ } else if draws_full_frames && pane.borderless() {
pane.set_content_offset(Offset::default());
} else if !is_inside_viewport(&viewport, pane) {
- // this pane is outside the viewport and has no border - it should not have an offset
pane.set_content_offset(Offset::default());
} else {
- // no draw_pane_frames and this pane should have a separation to other panes
- // according to its position in the viewport (eg. no separation if it's at the
- // viewport bottom) - offset its content accordingly
let mut position_and_size = pane.current_geom();
let is_stacked = position_and_size.is_stacked();
let is_flexible = !position_and_size.rows.is_fixed();
+ let pane_is_borderless = pane.borderless();
if let Some(position_and_size_of_stack) = position_and_size
.stacked
.and_then(|s_id| position_and_sizes_of_stacks.get(&s_id))
{
- // we want to check the offset against the position_and_size of the whole
- // stack rather than the pane, because the stack needs to have a consistent
- // offset with itself
position_and_size = *position_and_size_of_stack;
};
let (pane_columns_offset, pane_rows_offset) =
pane_content_offset(&position_and_size, &viewport);
- if is_stacked && is_flexible {
- // 1 to save room for the pane title
+ let reserve_title_row = if draws_titles {
+ !pane_is_borderless && is_flexible && !single_selectable_tiled_pane
+ } else {
+ is_stacked && is_flexible
+ };
+ if reserve_title_row {
pane.set_content_offset(Offset::shift_right_top_and_bottom(
pane_columns_offset,
1,
@@ -1062,6 +1065,12 @@ impl TiledPanes {
.with_context(err_context)?
};
let selectable_pane_count = self.panes.iter().filter(|(_, p)| p.selectable()).count();
+ let content_pane_count = self
+ .panes
+ .iter()
+ .filter(|(_, p)| p.selectable() && !p.borderless())
+ .count();
+ let omit_pane_title = self.pane_frame_style.draws_titles() && content_pane_count == 1;
for (kind, pane) in self.panes.iter_mut() {
match kind {
PaneId::Terminal(_) => {
@@ -1105,7 +1114,7 @@ impl TiledPanes {
stacked_pane_ids_on_top_of_stacks.contains(&pane.pid());
let pane_is_on_bottom_of_stack =
stacked_pane_ids_on_bottom_of_stacks.contains(&pane.pid());
- let should_draw_pane_frames = self.draw_pane_frames;
+ let should_draw_pane_frames = self.pane_frame_style.draws_full_frames();
let pane_is_stacked = pane.current_geom().is_stacked();
let pane_is_one_liner_in_stack =
pane_is_stacked && pane.current_geom().rows.is_fixed();
@@ -1128,6 +1137,7 @@ impl TiledPanes {
&mouse_hover_pane_id,
current_pane_group.clone(),
show_help_text,
+ omit_pane_title,
);
for client_id in &connected_clients {
let client_mode = self
@@ -1146,7 +1156,7 @@ impl TiledPanes {
}
}
let is_floating = false;
- if self.draw_pane_frames {
+ if self.pane_frame_style.draws_full_frames() {
pane_contents_and_ui
.render_pane_frame(
*client_id,
@@ -1156,9 +1166,7 @@ impl TiledPanes {
pane_is_selectable,
)
.with_context(err_context)?;
- } else if pane_is_stacked {
- // if we have no pane frames but the pane is stacked, we need to render its
- // frame which will amount to only rendering the title line
+ } else if self.pane_frame_style.draws_titles() || pane_is_stacked {
pane_contents_and_ui
.render_pane_frame(
*client_id,
@@ -1168,7 +1176,6 @@ impl TiledPanes {
pane_is_selectable,
)
.with_context(err_context)?;
- // we also need to render its boundaries as normal
let boundaries = client_id_to_boundaries
.entry(*client_id)
.or_insert_with(|| Boundaries::new(*self.viewport.borrow()));
@@ -1255,7 +1262,7 @@ impl TiledPanes {
} else {
pane.set_content_offset(Offset::frame(1));
}
- } else if self.draw_pane_frames {
+ } else if self.pane_frame_style.draws_full_frames() {
pane.set_content_offset(Offset::frame(1));
}
},
@@ -1353,7 +1360,7 @@ impl TiledPanes {
display_area.rows = rows;
display_area.cols = cols;
}
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
pub fn resize_active_pane(
@@ -2178,7 +2185,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.focus_pane_for_all_clients(active_pane_id);
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
}
pub fn move_active_pane(&mut self, search_backwards: bool, client_id: ClientId) {
@@ -2244,7 +2251,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.reapply_pane_focus();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
pub fn move_active_pane_down(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
@@ -2296,7 +2303,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.reapply_pane_focus();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
}
pub fn move_active_pane_left(&mut self, client_id: ClientId) {
@@ -2347,7 +2354,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.reapply_pane_focus();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
}
pub fn move_active_pane_right(&mut self, client_id: ClientId) {
@@ -2398,7 +2405,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.reapply_pane_focus();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
}
pub fn move_active_pane_up(&mut self, client_id: ClientId) {
@@ -2451,7 +2458,7 @@ impl TiledPanes {
.unwrap();
current_position.set_should_render(true);
self.reapply_pane_focus();
- self.set_pane_frames(self.draw_pane_frames);
+ self.set_pane_frames(self.pane_frame_style);
}
}
pub fn move_clients_out_of_pane(&mut self, pane_id: PaneId) {
@@ -2522,7 +2529,7 @@ impl TiledPanes {
// successfully filled space over pane
let closed_pane = self.panes.remove(&pane_id);
self.move_clients_out_of_pane(pane_id);
- self.set_pane_frames(self.draw_pane_frames); // recalculate pane frames and update size
+ self.set_pane_frames(self.pane_frame_style);
closed_pane
} else {
let closed_pane = self.panes.remove(&pane_id);
diff --git a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs
index 0c989a9e..985e2c42 100644
--- a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs
+++ b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs
@@ -2330,13 +2330,15 @@ pub fn split(direction: SplitDirection, rect: &PaneGeom) -> Option<(PaneGeom, Pa
SplitDirection::Horizontal => rect.rows,
};
if let Some(p) = space.as_percent() {
+ let mut halved = Dimension::percent(p / 2.0);
+ halved.set_inner((space.as_usize() / 2).max(1));
let first_rect = match direction {
SplitDirection::Vertical => PaneGeom {
- cols: Dimension::percent(p / 2.0),
+ cols: halved,
..*rect
},
SplitDirection::Horizontal => PaneGeom {
- rows: Dimension::percent(p / 2.0),
+ rows: halved,
..*rect
},
};
diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs
index 5cc5835b..e92d7204 100644
--- a/zellij-server/src/plugins/mod.rs
+++ b/zellij-server/src/plugins/mod.rs
@@ -773,6 +773,11 @@ pub(crate) fn plugin_thread_main(
if events.contains(&EventType::InitialKeybinds) {
wasm_bridge.send_initial_keybinds_to_plugin(plugin_id, client_id);
}
+ if events.contains(&EventType::HintText) {
+ let _ = bus
+ .senders
+ .send_to_screen(ScreenInstruction::ClearHintTextCache);
+ }
},
PluginInstruction::PermissionRequestResult(
plugin_id,
diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs
index 431d550e..a5dd5f9c 100644
--- a/zellij-server/src/plugins/unit/plugin_tests.rs
+++ b/zellij-server/src/plugins/unit/plugin_tests.rs
@@ -3351,6 +3351,238 @@ pub fn toggle_pane_embed_or_eject_plugin_command() {
#[test]
#[ignore]
+pub fn new_pane_plugin_command() {
+ let temp_folder = tempdir().unwrap();
+ let plugin_host_folder = PathBuf::from(temp_folder.path());
+ let cache_path = plugin_host_folder.join("permissions_test.kdl");
+ let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) =
+ create_plugin_thread_with_pty_receiver(Some(plugin_host_folder), None, None);
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: Default::default(),
+ ..Default::default()
+ });
+ let tab_index = 1;
+ let client_id = 1;
+ let size = Size {
+ cols: 121,
+ rows: 20,
+ };
+ let received_pty_instructions = Arc::new(Mutex::new(vec![]));
+ let pty_thread = log_actions_in_thread!(
+ received_pty_instructions,
+ PtyInstruction::SpawnTerminal,
+ pty_receiver,
+ 1
+ );
+ let received_screen_instructions = Arc::new(Mutex::new(vec![]));
+ let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!(
+ received_screen_instructions,
+ ScreenInstruction::Exit,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+
+ let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
+ let _ = plugin_thread_sender.send(PluginInstruction::Load(
+ plugin_should_float,
+ false,
+ false,
+ plugin_title,
+ run_plugin,
+ Some(tab_index),
+ None,
+ client_id,
+ size,
+ None,
+ None,
+ false,
+ None,
+ None,
+ None,
+ ));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
+ None,
+ Some(client_id),
+ Event::Key(KeyWithModifier::new(BareKey::Char('9'))),
+ )]));
+ pty_thread.join().unwrap();
+ teardown();
+ let new_pane_event = received_pty_instructions
+ .lock()
+ .unwrap()
+ .iter()
+ .find_map(|i| {
+ if let PtyInstruction::SpawnTerminal(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", new_pane_event));
+}
+
+#[test]
+#[ignore]
+pub fn toggle_floating_panes_plugin_command() {
+ let temp_folder = tempdir().unwrap();
+ let plugin_host_folder = PathBuf::from(temp_folder.path());
+ let cache_path = plugin_host_folder.join("permissions_test.kdl");
+ let (plugin_thread_sender, screen_receiver, teardown) =
+ create_plugin_thread(Some(plugin_host_folder), None);
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: Default::default(),
+ ..Default::default()
+ });
+ let tab_index = 1;
+ let client_id = 1;
+ let size = Size {
+ cols: 121,
+ rows: 20,
+ };
+ let received_screen_instructions = Arc::new(Mutex::new(vec![]));
+ let screen_thread = grant_permissions_and_log_actions_in_thread!(
+ received_screen_instructions,
+ ScreenInstruction::ToggleFloatingPanes,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+
+ let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
+ let _ = plugin_thread_sender.send(PluginInstruction::Load(
+ plugin_should_float,
+ false,
+ false,
+ plugin_title,
+ run_plugin,
+ Some(tab_index),
+ None,
+ client_id,
+ size,
+ None,
+ None,
+ false,
+ None,
+ None,
+ None,
+ ));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
+ None,
+ Some(client_id),
+ Event::Key(KeyWithModifier::new(BareKey::Char('0'))),
+ )]));
+ screen_thread.join().unwrap();
+ teardown();
+ let toggle_floating_panes_event = received_screen_instructions
+ .lock()
+ .unwrap()
+ .iter()
+ .find_map(|i| {
+ if let ScreenInstruction::ToggleFloatingPanes(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", toggle_floating_panes_event));
+}
+
+#[test]
+#[ignore]
+pub fn toggle_floating_panes_with_tab_id_plugin_command() {
+ let temp_folder = tempdir().unwrap();
+ let plugin_host_folder = PathBuf::from(temp_folder.path());
+ let cache_path = plugin_host_folder.join("permissions_test.kdl");
+ let (plugin_thread_sender, screen_receiver, teardown) =
+ create_plugin_thread(Some(plugin_host_folder), None);
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: Default::default(),
+ ..Default::default()
+ });
+ let tab_index = 1;
+ let client_id = 1;
+ let size = Size {
+ cols: 121,
+ rows: 20,
+ };
+ let received_screen_instructions = Arc::new(Mutex::new(vec![]));
+ let screen_thread = grant_permissions_and_log_actions_in_thread!(
+ received_screen_instructions,
+ ScreenInstruction::ToggleFloatingPanesWithTabId,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+
+ let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
+ let _ = plugin_thread_sender.send(PluginInstruction::Load(
+ plugin_should_float,
+ false,
+ false,
+ plugin_title,
+ run_plugin,
+ Some(tab_index),
+ None,
+ client_id,
+ size,
+ None,
+ None,
+ false,
+ None,
+ None,
+ None,
+ ));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
+ None,
+ Some(client_id),
+ Event::Key(KeyWithModifier::new(BareKey::Char('i')).with_super_modifier()),
+ )]));
+ screen_thread.join().unwrap();
+ teardown();
+ let toggle_floating_panes_event = received_screen_instructions
+ .lock()
+ .unwrap()
+ .iter()
+ .find_map(|i| {
+ if let ScreenInstruction::ToggleFloatingPanesWithTabId(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", toggle_floating_panes_event));
+}
+
+#[test]
+#[ignore]
pub fn undo_rename_pane_plugin_command() {
let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its
// destructor removes the directory
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap
new file mode 100644
index 00000000..9b2efb21
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap
@@ -0,0 +1,29 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+expression: "format!(\"{:#?}\", new_pane_event)"
+---
+Some(
+ SpawnTerminal(
+ None,
+ None,
+ NoPreference {
+ borderless: None,
+ },
+ false,
+ ClientId(
+ 1,
+ ),
+ Some(
+ NotificationEnd {
+ channel: None,
+ exit_status: None,
+ unblock_condition: None,
+ affected_pane_id: None,
+ affected_tab_id: None,
+ error_message: None,
+ stdout_message: None,
+ },
+ ),
+ false,
+ ),
+)
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap
new file mode 100644
index 00000000..fac5fcd5
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap
@@ -0,0 +1,21 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+expression: "format!(\"{:#?}\", toggle_floating_panes_event)"
+---
+Some(
+ ToggleFloatingPanes(
+ 1,
+ None,
+ Some(
+ NotificationEnd {
+ channel: None,
+ exit_status: None,
+ unblock_condition: None,
+ affected_pane_id: None,
+ affected_tab_id: None,
+ error_message: None,
+ stdout_message: None,
+ },
+ ),
+ ),
+)
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap
new file mode 100644
index 00000000..6668b899
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap
@@ -0,0 +1,21 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+expression: "format!(\"{:#?}\", toggle_floating_panes_event)"
+---
+Some(
+ ToggleFloatingPanesWithTabId(
+ 2,
+ None,
+ Some(
+ NotificationEnd {
+ channel: None,
+ exit_status: None,
+ unblock_condition: None,
+ affected_pane_id: None,
+ affected_tab_id: None,
+ error_message: None,
+ stdout_message: None,
+ },
+ ),
+ ),
+)
diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs
index 13e5ff82..4121684b 100644
--- a/zellij-server/src/plugins/wasm_bridge.rs
+++ b/zellij-server/src/plugins/wasm_bridge.rs
@@ -2170,6 +2170,8 @@ fn check_event_permission(
| Event::PluginConfigurationChanged(..)
| Event::HighlightClicked { .. }
| Event::SoftKeyboardVisibilityChanged(..)
+ | Event::HintText(..)
+ | Event::ActivePaneScroll(..)
| Event::InputReceived => PermissionType::ReadApplicationState,
Event::WebServerStatus(..) => PermissionType::StartWebServer,
Event::PaneRenderReport(..) | Event::PaneRenderReportWithAnsi(..) => {
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index c9c3515e..4dd559ed 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -37,8 +37,8 @@ use zellij_utils::data::{
OpenPluginPaneFloatingResponse, OpenTerminalFloatingNearPluginResponse,
OpenTerminalFloatingResponse, OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse,
OpenTerminalNearPluginResponse, OpenTerminalPaneInPlaceOfPaneIdResponse, OpenTerminalResponse,
- OriginatingPlugin, PaneScrollbackResponse, PermissionStatus, PermissionType, PluginPermission,
- RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, TabMetadata,
+ OriginatingPlugin, PaneFrameStyle, PaneScrollbackResponse, PermissionStatus, PermissionType,
+ PluginPermission, RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, TabMetadata,
};
use zellij_utils::home::default_layout_dir;
use zellij_utils::input::permission::PermissionCache;
@@ -304,6 +304,10 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) {
PluginCommand::NewTiledPaneInTab { tab_position } => {
new_tiled_pane_in_tab(env, tab_position)
},
+ PluginCommand::ToggleFloatingPanes { tab_id } => {
+ toggle_floating_panes(env, tab_id)
+ },
+ PluginCommand::NewPane => new_pane(env),
PluginCommand::GoToNextTab => go_to_next_tab(env),
PluginCommand::GoToPreviousTab => go_to_previous_tab(env),
PluginCommand::Resize(resize_payload) => resize(env, resize_payload),
@@ -334,6 +338,9 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) {
PluginCommand::PageScrollDown => page_scroll_down(env),
PluginCommand::ToggleFocusFullscreen => toggle_focus_fullscreen(env),
PluginCommand::TogglePaneFrames => toggle_pane_frames(env),
+ PluginCommand::SetPaneFrameStyle(pane_frame_style) => {
+ set_pane_frame_style(env, pane_frame_style)
+ },
PluginCommand::TogglePaneEmbedOrEject => toggle_pane_embed_or_eject(env),
PluginCommand::UndoRenamePane => undo_rename_pane(env),
PluginCommand::CloseFocus => close_focus(env),
@@ -3146,6 +3153,12 @@ fn toggle_pane_frames(env: &PluginEnv) {
apply_action!(action, error_msg, env);
}
+fn set_pane_frame_style(env: &PluginEnv, pane_frame_style: PaneFrameStyle) {
+ let error_msg = || format!("failed to set pane frame style in plugin {}", env.name());
+ let action = Action::SetPaneFrameStyle(pane_frame_style);
+ apply_action!(action, error_msg, env);
+}
+
fn toggle_pane_embed_or_eject(env: &PluginEnv) {
let error_msg = || {
format!(
@@ -3157,6 +3170,25 @@ fn toggle_pane_embed_or_eject(env: &PluginEnv) {
apply_action!(action, error_msg, env);
}
+fn toggle_floating_panes(env: &PluginEnv, tab_id: Option<u64>) {
+ let error_msg = || format!("failed to toggle floating panes in plugin {}", env.name());
+ let action = match tab_id {
+ Some(id) => Action::ToggleFloatingPanesByTabId { id },
+ None => Action::ToggleFloatingPanes,
+ };
+ apply_action!(action, error_msg, env);
+}
+
+fn new_pane(env: &PluginEnv) {
+ let error_msg = || format!("failed to open new pane in plugin {}", env.name());
+ let action = Action::NewPane {
+ direction: None,
+ pane_name: None,
+ start_suppressed: false,
+ };
+ apply_action!(action, error_msg, env);
+}
+
fn undo_rename_pane(env: &PluginEnv) {
let error_msg = || format!("failed to undo rename pane in plugin {}", env.name());
let action = Action::UndoRenamePane;
@@ -5494,6 +5526,9 @@ fn check_command_permission(
| PluginCommand::ToggleFocusFullscreen
| PluginCommand::TogglePaneIdFullscreen(..)
| PluginCommand::TogglePaneFrames
+ | PluginCommand::SetPaneFrameStyle(..)
+ | PluginCommand::ToggleFloatingPanes { .. }
+ | PluginCommand::NewPane
| PluginCommand::TogglePaneEmbedOrEject
| PluginCommand::TogglePaneEmbedOrEjectForPaneId(..)
| PluginCommand::UndoRenamePane
diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs
index 9b9de0ec..529a93b9 100644
--- a/zellij-server/src/route.rs
+++ b/zellij-server/src/route.rs
@@ -596,6 +596,14 @@ pub(crate) fn route_action(
)))
.with_context(err_context)?;
},
+ Action::SetPaneFrameStyle(pane_frame_style) => {
+ senders
+ .send_to_screen(ScreenInstruction::SetPaneFrameStyle(
+ pane_frame_style,
+ Some(NotificationEnd::new(completion_tx)),
+ ))
+ .with_context(err_context)?;
+ },
Action::NewPane {
direction,
pane_name,
@@ -787,14 +795,15 @@ pub(crate) fn route_action(
let run_cmd = run_command
.map(|cmd| TerminalAction::RunCommand(cmd.into()))
.or_else(|| default_shell.clone());
- let pane_id = match pane_id_to_replace {
- Some(pane_id_to_replace) => pane_id_to_replace.try_into().ok(),
- None => pane_id,
- };
+ let explicit_pane_id_to_replace: Option<PaneId> = pane_id_to_replace
+ .and_then(|pane_id_to_replace| pane_id_to_replace.try_into().ok());
+ let pane_id = explicit_pane_id_to_replace.or(pane_id);
let client_tab_index_or_paneid = if let Some(tab_id) = tab_id {
ClientTabIndexOrPaneId::TabIndex(tab_id)
- } else if near_current_pane && pane_id.is_some() {
- ClientTabIndexOrPaneId::PaneId(pane_id.unwrap())
+ } else if let Some(pane_id) =
+ pane_id.filter(|_| explicit_pane_id_to_replace.is_some() || near_current_pane)
+ {
+ ClientTabIndexOrPaneId::PaneId(pane_id)
} else {
ClientTabIndexOrPaneId::ClientId(client_id)
};
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index e6bbbf82..b876b0e4 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -51,7 +51,7 @@ use zellij_utils::input::command::RunCommand;
use zellij_utils::input::config::Config;
use zellij_utils::input::keybinds::Keybinds;
use zellij_utils::input::mouse::{MouseEvent, MouseEventType};
-use zellij_utils::input::options::{Clipboard, MobileLayoutConfiguration};
+use zellij_utils::input::options::{Clipboard, MobileLayoutConfiguration, PaneFrameStyle};
use zellij_utils::ipc::{ExitReason, ServerToClientMsg};
use zellij_utils::pane_size::{PaneGeom, Size, SizeInPixels};
use zellij_utils::shared::clean_string_from_control_and_linebreak;
@@ -430,6 +430,7 @@ pub enum ScreenInstruction {
CloseFocusedPane(ClientId, Option<NotificationEnd>),
ToggleActiveTerminalFullscreen(ClientId, Option<NotificationEnd>),
TogglePaneFrames(Option<NotificationEnd>),
+ SetPaneFrameStyle(PaneFrameStyle, Option<NotificationEnd>),
SetSelectable(PaneId, bool),
ShowPluginCursor(u32, ClientId, Option<(usize, usize)>),
ClosePane(
@@ -735,7 +736,7 @@ pub enum ScreenInstruction {
host_theme_light: Option<Styling>,
simplified_ui: bool,
default_shell: Option<PathBuf>,
- pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
copy_command: Option<String>,
copy_to_clipboard: Option<Clipboard>,
copy_on_select: bool,
@@ -852,6 +853,7 @@ pub enum ScreenInstruction {
DesktopNotificationResponse(Vec<u8>, ClientId),
PluginSubscribedToAnsiPaneContents(bool), // true = at least one plugin needs ANSI content
UpdateBackgroundPluginSubscriptions(PluginId, ClientId, HashSet<EventType>),
+ ClearHintTextCache,
BroadcastModeUpdate(ModeInfo, Option<ClientId>), // ModeInfo, optional specific client_id (None = all clients)
// Pane-targeting CLI variants
ScrollUpWithPaneId(PaneId, Option<NotificationEnd>),
@@ -985,6 +987,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenContext::ToggleActiveTerminalFullscreen
},
ScreenInstruction::TogglePaneFrames(..) => ScreenContext::TogglePaneFrames,
+ ScreenInstruction::SetPaneFrameStyle(..) => ScreenContext::SetPaneFrameStyle,
ScreenInstruction::SetSelectable(..) => ScreenContext::SetSelectable,
ScreenInstruction::ShowPluginCursor(..) => ScreenContext::ShowPluginCursor,
ScreenInstruction::ClosePane(..) => ScreenContext::ClosePane,
@@ -1203,6 +1206,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::UpdateBackgroundPluginSubscriptions(..) => {
ScreenContext::UpdateBackgroundPluginSubscriptions
},
+ ScreenInstruction::ClearHintTextCache => ScreenContext::ClearHintTextCache,
ScreenInstruction::BroadcastModeUpdate(..) => ScreenContext::BroadcastModeUpdate,
// Pane-targeting CLI variants
ScreenInstruction::ScrollUpWithPaneId(..) => ScreenContext::ScrollUpWithPaneId,
@@ -1401,6 +1405,7 @@ pub(crate) struct Screen {
max_panes: Option<usize>,
/// A map between this [`Screen`]'s tabs and their ID/key.
tabs: BTreeMap<usize, Tab>,
+ last_single_pane_tab_names: HashMap<usize, Option<String>>,
/// The full size of this [`Screen`].
size: Size,
pixel_dimensions: PixelDimensions,
@@ -1419,7 +1424,7 @@ pub(crate) struct Screen {
mode_info: BTreeMap<ClientId, ModeInfo>,
default_mode_info: ModeInfo, // TODO: restructure ModeInfo to prevent this duplication
style: Style,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
auto_layout: bool,
session_serialization: bool,
serialize_pane_viewport: bool,
@@ -1527,7 +1532,7 @@ impl Screen {
client_attributes: &ClientAttributes,
max_panes: Option<usize>,
mode_info: ModeInfo,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
auto_layout: bool,
session_is_mirrored: bool,
copy_options: CopyOptions,
@@ -1575,13 +1580,14 @@ impl Screen {
client_sizes: HashMap::new(),
global_last_active_tab_id: 0,
tabs: BTreeMap::new(),
+ last_single_pane_tab_names: HashMap::new(),
terminal_emulator_colors: Rc::new(RefCell::new(Palette::default())),
terminal_emulator_color_codes: Rc::new(RefCell::new(HashMap::new())),
tab_history: BTreeMap::new(),
pane_history: BTreeMap::new(),
mode_info: BTreeMap::new(),
default_mode_info: mode_info,
- draw_pane_frames,
+ pane_frame_style,
auto_layout,
session_is_mirrored,
copy_options,
@@ -2971,7 +2977,8 @@ impl Screen {
}
}
- if bell_state_changed {
+ let single_pane_names_changed = self.update_single_pane_tab_names();
+ if bell_state_changed || single_pane_names_changed {
self.log_and_report_session_state()?;
}
} else {
@@ -3308,7 +3315,7 @@ impl Screen {
self.max_panes,
self.style,
self.default_mode_info.clone(),
- self.draw_pane_frames,
+ self.pane_frame_style,
self.auto_layout,
self.connected_clients.clone(),
self.session_is_mirrored,
@@ -3696,7 +3703,9 @@ impl Screen {
let selectable_floating_panes_count = tab.get_selectable_floating_panes_count();
let tab_info_for_plugins = TabInfo {
position: tab.position,
- name: tab.name.clone(),
+ name: tab
+ .single_pane_tab_name()
+ .unwrap_or_else(|| tab.name.clone()),
active: *active_tab_index == tab.id,
panes_to_hide: tab.panes_to_hide_count(),
is_fullscreen_active: tab.is_fullscreen_active(),
@@ -3818,6 +3827,19 @@ impl Screen {
}
}
+ fn update_single_pane_tab_names(&mut self) -> bool {
+ let current: HashMap<usize, Option<String>> = self
+ .tabs
+ .values()
+ .map(|tab| (tab.id, tab.single_pane_tab_name()))
+ .collect();
+ if current != self.last_single_pane_tab_names {
+ self.last_single_pane_tab_names = current;
+ true
+ } else {
+ false
+ }
+ }
fn log_and_report_session_state(&mut self) -> Result<()> {
let err_context = || format!("Failed to log and report session state");
@@ -4997,7 +5019,7 @@ impl Screen {
theme: Styling,
simplified_ui: bool,
default_shell: Option<PathBuf>,
- pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
copy_command: Option<String>,
copy_to_clipboard: Option<Clipboard>,
copy_on_select: bool,
@@ -5014,6 +5036,7 @@ impl Screen {
client_id: ClientId,
) -> Result<()> {
let should_support_arrow_fonts = !simplified_ui;
+ self.arrow_fonts = should_support_arrow_fonts;
// global configuration
self.default_mode_info.update_theme(theme);
@@ -5029,7 +5052,7 @@ impl Screen {
self.auto_layout = auto_layout;
self.copy_options.command = copy_command.clone();
self.copy_options.copy_on_select = copy_on_select;
- self.draw_pane_frames = pane_frames;
+ self.pane_frame_style = pane_frame_style;
self.advanced_mouse_actions = advanced_mouse_actions;
self.mouse_hover_effects = mouse_hover_effects;
self.visual_bell = visual_bell;
@@ -5052,7 +5075,7 @@ impl Screen {
tab.update_default_editor(self.default_editor.clone());
tab.update_auto_layout(auto_layout);
tab.update_copy_options(&self.copy_options);
- tab.set_pane_frames(pane_frames);
+ tab.set_pane_frames(pane_frame_style);
tab.update_arrow_fonts(should_support_arrow_fonts);
tab.update_advanced_mouse_actions(advanced_mouse_actions);
tab.update_mouse_hover_effects(mouse_hover_effects);
@@ -6125,7 +6148,7 @@ pub(crate) fn screen_thread_main(
let config_options = config.options;
let arrow_fonts = !config_options.simplified_ui.unwrap_or_default();
- let draw_pane_frames = config_options.pane_frames.unwrap_or(true);
+ let pane_frame_style = PaneFrameStyle::from_options(&config_options);
let auto_layout = config_options.auto_layout.unwrap_or(true);
let session_serialization = config_options.session_serialization.unwrap_or(true);
let serialize_pane_viewport = config_options.serialize_pane_viewport.unwrap_or(false);
@@ -6194,7 +6217,7 @@ pub(crate) fn screen_thread_main(
&config.keybinds,
config_options.default_mode,
),
- draw_pane_frames,
+ pane_frame_style,
auto_layout,
session_is_mirrored,
copy_options,
@@ -7494,9 +7517,23 @@ pub(crate) fn screen_thread_main(
_completion_tx, // the action ends here, dropping this will release anything
// waiting for it
) => {
- screen.draw_pane_frames = !screen.draw_pane_frames;
+ screen.pane_frame_style = match screen.pane_frame_style {
+ PaneFrameStyle::Full => PaneFrameStyle::Titles,
+ PaneFrameStyle::Titles => PaneFrameStyle::None,
+ PaneFrameStyle::None => PaneFrameStyle::Full,
+ };
for tab in screen.tabs.values_mut() {
- tab.set_pane_frames(screen.draw_pane_frames);
+ tab.set_pane_frames(screen.pane_frame_style);
+ tab.update_input_modes()?;
+ }
+ screen.render(None)?;
+ screen.log_and_report_session_state()?;
+ },
+ ScreenInstruction::SetPaneFrameStyle(pane_frame_style, _completion_tx) => {
+ screen.pane_frame_style = pane_frame_style;
+ for tab in screen.tabs.values_mut() {
+ tab.set_pane_frames(screen.pane_frame_style);
+ tab.update_input_modes()?;
}
screen.render(None)?;
screen.log_and_report_session_state()?;
@@ -9328,7 +9365,7 @@ pub(crate) fn screen_thread_main(
host_theme_light,
simplified_ui,
default_shell,
- pane_frames,
+ pane_frame_style,
copy_to_clipboard,
copy_command,
copy_on_select,
@@ -9352,7 +9389,7 @@ pub(crate) fn screen_thread_main(
theme,
simplified_ui,
default_shell,
- pane_frames,
+ pane_frame_style,
copy_command,
copy_to_clipboard,
copy_on_select,
@@ -10048,6 +10085,12 @@ pub(crate) fn screen_thread_main(
.insert((plugin_id, client_id), subscriptions);
}
},
+ ScreenInstruction::ClearHintTextCache => {
+ for tab in screen.tabs.values_mut() {
+ tab.clear_hint_text_cache();
+ }
+ screen.render(None)?;
+ },
ScreenInstruction::BroadcastModeUpdate(mode_info, target_client_id) => {
screen.broadcast_mode_update(mode_info, target_client_id)?;
},
diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs
index 21d8c92a..1c3a604d 100644
--- a/zellij-server/src/tab/layout_applier.rs
+++ b/zellij-server/src/tab/layout_applier.rs
@@ -19,6 +19,7 @@ use std::rc::Rc;
use zellij_utils::{
data::{Palette, Style},
input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias, TiledPaneLayout},
+ input::options::PaneFrameStyle,
pane_size::{PaneGeom, Size, SizeInPixels, Viewport},
};
@@ -35,7 +36,7 @@ pub struct LayoutApplier<'a> {
display_area: Rc<RefCell<Size>>, // includes all panes (including eg. the status bar and tab bar in the default layout)
tiled_panes: &'a mut TiledPanes,
floating_panes: &'a mut FloatingPanes,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
focus_pane_id: &'a mut Option<PaneId>,
os_api: Box<dyn ServerOsApi>,
debug: bool,
@@ -60,7 +61,7 @@ impl<'a> LayoutApplier<'a> {
display_area: &Rc<RefCell<Size>>, // includes all panes (including eg. the status bar and tab bar in the default layout)
tiled_panes: &'a mut TiledPanes,
floating_panes: &'a mut FloatingPanes,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
focus_pane_id: &'a mut Option<PaneId>,
os_api: &Box<dyn ServerOsApi>,
debug: bool,
@@ -94,7 +95,7 @@ impl<'a> LayoutApplier<'a> {
display_area,
tiled_panes,
floating_panes,
- draw_pane_frames,
+ pane_frame_style,
focus_pane_id,
os_api,
debug,
@@ -228,7 +229,7 @@ impl<'a> LayoutApplier<'a> {
self.viewport.clone(),
self.display_area.clone(),
self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
Ok(())
}
@@ -321,7 +322,7 @@ impl<'a> LayoutApplier<'a> {
self.viewport.clone(),
self.display_area.clone(),
self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
Ok(())
}
@@ -1033,7 +1034,7 @@ impl<'a> LayoutApplier<'a> {
viewport: Rc<RefCell<Viewport>>,
display_area: Rc<RefCell<Size>>,
tiled_panes: &mut TiledPanes,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
) {
{
// reset viewport before reapplying offset
@@ -1071,7 +1072,7 @@ impl<'a> LayoutApplier<'a> {
}
}
}
- tiled_panes.set_pane_frames(draw_pane_frames);
+ tiled_panes.set_pane_frames(pane_frame_style);
}
fn adjust_viewport(&mut self) -> Result<()> {
// here we offset the viewport after applying a tiled panes layout
@@ -1091,7 +1092,7 @@ impl<'a> LayoutApplier<'a> {
self.viewport.clone(),
self.display_area.clone(),
self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
Ok(())
}
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index 02e7bece..a2601966 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -17,7 +17,7 @@ use uuid::Uuid;
use zellij_utils::data::PaneContents;
use zellij_utils::data::{
Direction, KeyWithModifier, NewPanePlacement, PaneInfo, PermissionStatus, PermissionType,
- PluginPermission, RegexHighlight, ResizeStrategy, Style, WebSharing,
+ PluginPermission, RegexHighlight, ResizeStrategy, Style, StyledText, WebSharing,
};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::command::RunCommand;
@@ -30,6 +30,9 @@ use crate::background_jobs::BackgroundJob;
use crate::pane_groups::PaneGroups;
use crate::pty_writer::PtyWriteInstruction;
use crate::screen::{CopyOptions, ScreenInstruction};
+use crate::ui::hint_text::{
+ held_hint_variants, hover_hint_variants, resize_hint_variants, HintExitStatus,
+};
use crate::ui::{loading_indication::LoadingIndication, pane_boundaries_frame::FrameParams};
use layout_applier::LayoutApplier;
use swap_layouts::SwapLayouts;
@@ -64,6 +67,7 @@ use zellij_utils::{
FloatingPaneLayout, Run, RunPluginOrAlias, SwapFloatingLayout, SwapTiledLayout,
TiledPaneLayout,
},
+ options::PaneFrameStyle,
parse_keys,
},
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
@@ -158,6 +162,7 @@ pub(crate) struct Tab {
pub position: usize,
pub name: String,
pub prev_name: String,
+ default_name: String,
pub size: Size,
pub visible_to: Option<HashSet<ClientId>>,
tiled_panes: TiledPanes,
@@ -176,7 +181,7 @@ pub(crate) struct Tab {
default_mode_info: ModeInfo,
pub style: Style,
connected_clients: Rc<RefCell<HashSet<ClientId>>>,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
auto_layout: bool,
pending_vte_events: HashMap<u32, Vec<VteBytes>>,
pub selecting_with_mouse_in_pane: Option<PaneId>, // this is only pub for the tests
@@ -207,8 +212,12 @@ pub(crate) struct Tab {
web_clients_allowed: bool,
web_sharing: WebSharing,
mouse_hover_pane_id: HashMap<ClientId, PaneId>,
+ plugin_hover_pane_id: HashMap<ClientId, PaneId>,
+ mouse_last_pane_id: HashMap<ClientId, PaneId>,
mouse_help_text_visible: HashMap<ClientId, bool>,
last_mouse_activity_time: HashMap<ClientId, Instant>,
+ last_hint_text: HashMap<ClientId, BTreeMap<usize, StyledText>>,
+ last_active_pane_scroll: HashMap<ClientId, Option<(usize, usize)>>,
current_pane_group: Rc<RefCell<PaneGroups>>,
advanced_mouse_actions: bool,
mouse_hover_effects: bool,
@@ -620,6 +629,12 @@ pub trait Pane {
fn progress_animation_offset(&mut self) {} // only relevant for plugins
fn current_title(&self) -> String;
fn custom_title(&self) -> Option<String>;
+ fn has_explicit_title(&self) -> bool {
+ false
+ }
+ fn scroll_position(&self) -> (usize, usize) {
+ (0, 0)
+ }
fn is_held(&self) -> bool {
false
}
@@ -736,7 +751,7 @@ impl Tab {
max_panes: Option<usize>,
style: Style,
default_mode_info: ModeInfo,
- draw_pane_frames: bool,
+ pane_frame_style: PaneFrameStyle,
auto_layout: bool,
connected_clients_in_app: Rc<RefCell<HashMap<ClientId, bool>>>, // bool -> is_web_client
session_is_mirrored: bool,
@@ -764,9 +779,14 @@ impl Tab {
web_server_port: u16,
mobile_tab_count: usize,
) -> Self {
- let name = if name.is_empty() {
+ let default_name = if name.is_empty() {
format!("Tab #{}", (id + 1).saturating_sub(mobile_tab_count))
} else {
+ String::new()
+ };
+ let name = if name.is_empty() {
+ default_name.clone()
+ } else {
name
};
@@ -790,7 +810,7 @@ impl Tab {
character_cell_size.clone(),
stacked_resize.clone(),
session_is_mirrored,
- draw_pane_frames,
+ pane_frame_style,
default_mode_info.clone(),
style,
os_api.clone(),
@@ -824,6 +844,7 @@ impl Tab {
suppressed_panes: HashMap::new(),
name: name.clone(),
prev_name: name,
+ default_name,
size: initial_size,
visible_to: None,
max_panes,
@@ -838,7 +859,7 @@ impl Tab {
style,
mode_info,
default_mode_info,
- draw_pane_frames,
+ pane_frame_style,
auto_layout,
pending_vte_events: HashMap::new(),
connected_clients,
@@ -865,8 +886,12 @@ impl Tab {
web_clients_allowed,
web_sharing,
mouse_hover_pane_id: HashMap::new(),
+ plugin_hover_pane_id: HashMap::new(),
+ mouse_last_pane_id: HashMap::new(),
mouse_help_text_visible: HashMap::new(),
last_mouse_activity_time: HashMap::new(),
+ last_hint_text: HashMap::new(),
+ last_active_pane_scroll: HashMap::new(),
current_pane_group,
currently_marking_pane_group,
advanced_mouse_actions,
@@ -908,7 +933,7 @@ impl Tab {
&self.display_area,
&mut self.tiled_panes,
&mut self.floating_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
&mut self.focus_pane_id,
&self.os_api,
self.debug,
@@ -986,7 +1011,7 @@ impl Tab {
&self.display_area,
&mut self.tiled_panes,
&mut self.floating_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
&mut self.focus_pane_id,
&self.os_api,
self.debug,
@@ -1032,7 +1057,7 @@ impl Tab {
self.viewport.clone(),
self.display_area.clone(),
&mut self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
self.apply_buffered_instructions().non_fatal();
@@ -1079,7 +1104,7 @@ impl Tab {
&self.display_area,
&mut self.tiled_panes,
&mut self.floating_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
&mut self.focus_pane_id,
&self.os_api,
self.debug,
@@ -1119,7 +1144,7 @@ impl Tab {
&self.display_area,
&mut self.tiled_panes,
&mut self.floating_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
&mut self.focus_pane_id,
&self.os_api,
self.debug,
@@ -1227,6 +1252,7 @@ impl Tab {
} else {
mode_info.web_server_capability = Some(false);
}
+ mode_info.pane_frame_style = Some(self.pane_frame_style);
for plugin_id in &tab_plugin_ids {
plugin_updates.push((
Some(*plugin_id),
@@ -1242,6 +1268,131 @@ impl Tab {
}
Ok(())
}
+ fn resolve_hint_text(&self, client_id: ClientId) -> BTreeMap<usize, StyledText> {
+ let focused_pane_id = self.get_active_pane_id(client_id);
+ let hovered_pane_id = self.mouse_hover_pane_id.get(&client_id).copied();
+ if let Some(hovered_pane_id) = hovered_pane_id {
+ if Some(hovered_pane_id) != focused_pane_id {
+ return hover_hint_variants();
+ }
+ }
+ if let Some(focused_pane) = self.get_active_pane(client_id) {
+ if focused_pane.is_held() {
+ let exited = focused_pane.exited();
+ let is_first_run = !exited;
+ let exit_status = if exited {
+ Some(match focused_pane.exit_status() {
+ Some(exit_code) => HintExitStatus::Code(exit_code),
+ None => HintExitStatus::Exited,
+ })
+ } else {
+ None
+ };
+ return held_hint_variants(is_first_run, exit_status);
+ }
+ }
+ let resize_help_visible = self
+ .mouse_help_text_visible
+ .get(&client_id)
+ .copied()
+ .unwrap_or(false);
+ if resize_help_visible {
+ let selectable_pane_count = self.get_selectable_tiled_panes().count()
+ + self.get_selectable_floating_panes().count();
+ if selectable_pane_count > 1 && !self.is_fullscreen_active() {
+ let focused_pane_is_floating = self.floating_panes.panes_are_visible();
+ return resize_hint_variants(focused_pane_is_floating);
+ }
+ }
+ BTreeMap::new()
+ }
+ pub fn emit_hint_text_if_changed(&mut self) -> Result<()> {
+ let connected_clients: Vec<ClientId> =
+ self.connected_clients.borrow().iter().copied().collect();
+ let mut plugin_updates = vec![];
+ for client_id in connected_clients {
+ let hint_text = self.resolve_hint_text(client_id);
+ if self.last_hint_text.get(&client_id) != Some(&hint_text) {
+ self.last_hint_text.insert(client_id, hint_text.clone());
+ plugin_updates.push((None, Some(client_id), Event::HintText(hint_text)));
+ }
+ }
+ if !plugin_updates.is_empty() {
+ self.senders
+ .send_to_plugin(PluginInstruction::Update(plugin_updates))
+ .with_context(|| format!("failed to update plugins with hint text"))?;
+ }
+ Ok(())
+ }
+ pub fn clear_hint_text_cache(&mut self) {
+ self.last_hint_text.clear();
+ }
+ fn get_selectable_tiled_content_panes(
+ &self,
+ ) -> impl Iterator<Item = (&PaneId, &Box<dyn Pane>)> {
+ self.get_selectable_tiled_panes()
+ .filter(|(_, p)| !p.borderless())
+ }
+ pub fn single_pane_titles(&self) -> bool {
+ self.pane_frame_style.draws_titles()
+ && self.get_selectable_tiled_content_panes().count() == 1
+ }
+ fn tab_name_is_default(&self) -> bool {
+ !self.name.is_empty() && self.name == self.default_name
+ }
+ pub fn single_pane_tab_name(&self) -> Option<String> {
+ if !self.single_pane_titles() {
+ return None;
+ }
+ let (_, pane) = self.get_selectable_tiled_content_panes().next()?;
+ let mut base = if self.tab_name_is_default() && pane.has_explicit_title() {
+ pane.current_title()
+ } else {
+ self.name.clone()
+ };
+ if pane.is_held() && pane.exited() {
+ match pane.exit_status() {
+ Some(exit_code) => base.push_str(&format!(" [ EXIT CODE: {} ] ", exit_code)),
+ None => base.push_str(" [ EXITED ] "),
+ }
+ }
+ Some(base)
+ }
+ fn resolve_active_pane_scroll(&self, _client_id: ClientId) -> Option<(usize, usize)> {
+ if !self.single_pane_titles() {
+ return None;
+ }
+ let (_, pane) = self.get_selectable_tiled_content_panes().next()?;
+ let (position, length) = pane.scroll_position();
+ if position > 0 || length > 0 {
+ Some((position, length))
+ } else {
+ None
+ }
+ }
+ pub fn emit_active_pane_scroll_if_changed(&mut self) -> Result<()> {
+ let connected_clients: Vec<ClientId> =
+ self.connected_clients.borrow().iter().copied().collect();
+ let mut plugin_updates = vec![];
+ for client_id in connected_clients {
+ let active_pane_scroll = self.resolve_active_pane_scroll(client_id);
+ if self.last_active_pane_scroll.get(&client_id) != Some(&active_pane_scroll) {
+ self.last_active_pane_scroll
+ .insert(client_id, active_pane_scroll);
+ plugin_updates.push((
+ None,
+ Some(client_id),
+ Event::ActivePaneScroll(active_pane_scroll),
+ ));
+ }
+ }
+ if !plugin_updates.is_empty() {
+ self.senders
+ .send_to_plugin(PluginInstruction::Update(plugin_updates))
+ .with_context(|| format!("failed to update plugins with active pane scroll"))?;
+ }
+ Ok(())
+ }
pub fn add_client(&mut self, client_id: ClientId, mode_info: Option<ModeInfo>) -> Result<()> {
let other_clients_exist_in_tab = { !self.connected_clients.borrow().is_empty() };
if other_clients_exist_in_tab {
@@ -1314,6 +1465,7 @@ impl Tab {
.map(|c| c.change_to_default_mode()); // TODO: no races?
self.connected_clients.borrow_mut().remove(&client_id);
self.mouse_help_text_visible.remove(&client_id);
+ self.mouse_last_pane_id.remove(&client_id);
self.last_mouse_activity_time.remove(&client_id);
self.set_force_render();
}
@@ -3404,6 +3556,10 @@ impl Tab {
self.hide_cursor_and_clear_display_as_needed(output);
}
+ self.emit_hint_text_if_changed().with_context(err_context)?;
+ self.emit_active_pane_scroll_if_changed()
+ .with_context(err_context)?;
+
Ok(())
}
@@ -3605,7 +3761,7 @@ impl Tab {
self.viewport.clone(),
self.display_area.clone(),
&mut self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
if let Some(pane_id) = fullscreen_pane_to_restore {
if self.tiled_panes.panes_contain(&pane_id) {
@@ -4058,7 +4214,7 @@ impl Tab {
self.viewport.clone(),
self.display_area.clone(),
&mut self.tiled_panes,
- self.draw_pane_frames,
+ self.pane_frame_style,
);
}
pub fn set_mouse_selection_support(&mut self, pane_id: PaneId, selection_support: bool) {
@@ -4799,25 +4955,26 @@ impl Tab {
let is_flexible_in_stack =
p.current_geom().is_stacked() && !p.current_geom().rows.is_fixed();
let is_stacked_under = stacked_pane_ids_under_flexible_pane.contains(&p.pid());
- let geom_to_compare_against = if is_stacked_under && !self.draw_pane_frames {
- // these sort of panes are one-liner panes under a flexible pane in a stack when we
- // don't draw pane frames - because the whole stack's content is offset to allow
- // room for the boundary between panes, they are actually drawn 1 line above where
- // they are
- let mut geom = p.current_geom();
- geom.y = geom.y.saturating_sub(p.get_content_offset().bottom);
- geom
- } else if is_flexible_in_stack && !self.draw_pane_frames {
- // these sorts of panes are flexible panes inside a stack when we don't draw pane
- // frames - because the whole stack's content is offset to give room for the
- // boundary between panes, we need to take this offset into account when figuring
- // out whether the position is inside them
- let mut geom = p.current_geom();
- geom.rows.decrease_inner(p.get_content_offset().bottom);
- geom
- } else {
- p.current_geom()
- };
+ let geom_to_compare_against =
+ if is_stacked_under && !self.pane_frame_style.draws_full_frames() {
+ // these sort of panes are one-liner panes under a flexible pane in a stack when we
+ // don't draw pane frames - because the whole stack's content is offset to allow
+ // room for the boundary between panes, they are actually drawn 1 line above where
+ // they are
+ let mut geom = p.current_geom();
+ geom.y = geom.y.saturating_sub(p.get_content_offset().bottom);
+ geom
+ } else if is_flexible_in_stack && !self.pane_frame_style.draws_full_frames() {
+ // these sorts of panes are flexible panes inside a stack when we don't draw pane
+ // frames - because the whole stack's content is offset to give room for the
+ // boundary between panes, we need to take this offset into account when figuring
+ // out whether the position is inside them
+ let mut geom = p.current_geom();
+ geom.rows.decrease_inner(p.get_content_offset().bottom);
+ geom
+ } else {
+ p.current_geom()
+ };
geom_to_compare_against.contains(point)
};
@@ -4975,6 +5132,7 @@ impl Tab {
.with_context(|| format!("failed to set visibility of tab to {visible}"))?;
if !visible {
self.mouse_hover_pane_id.clear();
+ self.plugin_hover_pane_id.clear();
}
Ok(())
}
@@ -5064,9 +5222,9 @@ impl Tab {
&& column < viewport.x + viewport.cols)
}
- pub fn set_pane_frames(&mut self, should_set_pane_frames: bool) {
- self.tiled_panes.set_pane_frames(should_set_pane_frames);
- self.draw_pane_frames = should_set_pane_frames;
+ pub fn set_pane_frames(&mut self, pane_frame_style: PaneFrameStyle) {
+ self.tiled_panes.set_pane_frames(pane_frame_style);
+ self.pane_frame_style = pane_frame_style;
self.set_should_clear_display_before_rendering();
self.set_force_render();
}
@@ -5847,6 +6005,8 @@ impl Tab {
}
pub fn clear_mouse_hover_state(&mut self) {
self.mouse_hover_pane_id.clear();
+ self.plugin_hover_pane_id.clear();
+ self.mouse_last_pane_id.clear();
self.mouse_help_text_visible.clear();
}
pub fn update_web_sharing(&mut self, web_sharing: WebSharing) {
diff --git a/zellij-server/src/tab/mouse_handler.rs b/zellij-server/src/tab/mouse_handler.rs
index 0397a7f4..61718864 100644
--- a/zellij-server/src/tab/mouse_handler.rs
+++ b/zellij-server/src/tab/mouse_handler.rs
@@ -13,14 +13,23 @@ use crate::ClientId;
use super::{Pane, Tab};
fn clear_hover_for_client(tab: &mut Tab, client_id: ClientId) -> bool {
+ let mut cleared = false;
if let Some(prev_pid) = tab.mouse_hover_pane_id.remove(&client_id) {
if let Some(pane) = tab.get_pane_with_id_mut(prev_pid) {
pane.set_hover_position(None);
}
- true
- } else {
- false
+ cleared = true;
}
+ if let Some(prev_plugin_pid) = tab.plugin_hover_pane_id.remove(&client_id) {
+ if let Some(pane) = tab.get_pane_with_id(prev_plugin_pid) {
+ let _ = pane.mouse_event(
+ &MouseEvent::new_buttonless_motion(Position::new(0, u16::MAX)),
+ client_id,
+ );
+ }
+ cleared = true;
+ }
+ cleared
}
#[derive(Debug, Default, Copy, Clone)]
@@ -1059,11 +1068,46 @@ impl MouseHandler {
fn execute_update_hover(
tab: &mut Tab,
pane_id: Option<PaneId>,
- _position: Option<Position>,
+ position: Option<Position>,
client_id: ClientId,
) -> Result<MouseEffect> {
let mut should_render = false;
let previous_hover_pane_id = tab.mouse_hover_pane_id.get(&client_id).copied();
+
+ if tab.mouse_hover_effects {
+ let previous_plugin_hover_pane_id = tab.plugin_hover_pane_id.get(&client_id).copied();
+ let current_plugin_hover_pane_id = match pane_id {
+ Some(pid) if matches!(pid, PaneId::Plugin(_)) => Some(pid),
+ _ => None,
+ };
+ if let (Some(pid), Some(position)) = (current_plugin_hover_pane_id, position) {
+ if let Some(pane) = tab.get_pane_with_id(pid) {
+ let relative_position = pane.relative_position(&position);
+ let _ = pane.mouse_event(
+ &MouseEvent::new_buttonless_motion(relative_position),
+ client_id,
+ );
+ }
+ }
+ if previous_plugin_hover_pane_id != current_plugin_hover_pane_id {
+ if let Some(previous_pid) = previous_plugin_hover_pane_id {
+ if let Some(pane) = tab.get_pane_with_id(previous_pid) {
+ let _ = pane.mouse_event(
+ &MouseEvent::new_buttonless_motion(Position::new(0, u16::MAX)),
+ client_id,
+ );
+ }
+ }
+ match current_plugin_hover_pane_id {
+ Some(pid) => {
+ tab.plugin_hover_pane_id.insert(client_id, pid);
+ },
+ None => {
+ tab.plugin_hover_pane_id.remove(&client_id);
+ },
+ }
+ }
+ }
match pane_id {
Some(pid) => {
if let Some(pane) = tab.get_pane_with_id(pid) {
@@ -1073,10 +1117,12 @@ impl MouseHandler {
} else if tab.advanced_mouse_actions || !tab.mouse_hover_effects {
tab.mouse_hover_pane_id.remove(&client_id);
}
+ tab.mouse_last_pane_id.insert(client_id, pid);
should_render = true;
}
},
None => {
+ tab.mouse_last_pane_id.remove(&client_id);
let removed = tab.mouse_hover_pane_id.remove(&client_id);
if removed.is_some() {
should_render = true;
@@ -1146,19 +1192,23 @@ impl MouseHandler {
if event.event_type == MouseEventType::Motion && tab.mouse_hover_effects {
tab.last_mouse_activity_time
.insert(client_id, Instant::now());
- let was_visible = tab
- .mouse_help_text_visible
- .get(&client_id)
- .copied()
- .unwrap_or(false);
- tab.mouse_help_text_visible.insert(client_id, true);
- if !was_visible {
- should_render = true;
- }
+ let entered_pane = tab.mouse_last_pane_id.get(&client_id) != Some(&pane_id);
+ tab.mouse_last_pane_id.insert(client_id, pane_id);
+ if entered_pane {
+ let was_visible = tab
+ .mouse_help_text_visible
+ .get(&client_id)
+ .copied()
+ .unwrap_or(false);
+ tab.mouse_help_text_visible.insert(client_id, true);
+ if !was_visible {
+ should_render = true;
+ }
- tab.senders
- .send_to_background_jobs(BackgroundJob::ClearHelpText { client_id })
- .with_context(err_context)?;
+ tab.senders
+ .send_to_background_jobs(BackgroundJob::ClearHelpText { client_id })
+ .with_context(err_context)?;
+ }
}
}
let mouse_effect = if should_render {
diff --git a/zellij-server/src/tab/unit/layout_applier_tests.rs b/zellij-server/src/tab/unit/layout_applier_tests.rs
index 2d6fd949..33ad8ee4 100644
--- a/zellij-server/src/tab/unit/layout_applier_tests.rs
+++ b/zellij-server/src/tab/unit/layout_applier_tests.rs
@@ -12,6 +12,7 @@ use std::collections::{HashMap, HashSet};
use std::fmt::Write;
use std::path::PathBuf;
use std::rc::Rc;
+use zellij_utils::input::options::PaneFrameStyle;
use interprocess::local_socket::Stream as LocalSocketStream;
use zellij_utils::{
@@ -147,7 +148,7 @@ fn create_layout_applier_fixtures(
Rc<RefCell<Size>>,
TiledPanes,
FloatingPanes,
- bool,
+ PaneFrameStyle,
Option<PaneId>,
Box<dyn ServerOsApi>,
bool,
@@ -187,7 +188,7 @@ fn create_layout_applier_fixtures(
let mode_info = Rc::new(RefCell::new(HashMap::new()));
let stacked_resize = Rc::new(RefCell::new(false));
let session_is_mirrored = true;
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let default_mode_info = ModeInfo::default();
let tiled_panes = TiledPanes::new(
@@ -269,7 +270,7 @@ fn create_layout_applier_fixtures_with_receivers(
Rc<RefCell<Size>>,
TiledPanes,
FloatingPanes,
- bool,
+ PaneFrameStyle,
Option<PaneId>,
Box<dyn ServerOsApi>,
bool,
@@ -317,7 +318,7 @@ fn create_layout_applier_fixtures_with_receivers(
let mode_info = Rc::new(RefCell::new(HashMap::new()));
let stacked_resize = Rc::new(RefCell::new(false));
let session_is_mirrored = true;
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let default_mode_info = ModeInfo::default();
let tiled_panes = TiledPanes::new(
diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap
index 8ce91b92..3e3b3084 100644
--- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap
+++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap
@@ -1,11 +1,10 @@
---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
-assertion_line: 1134
expression: snapshot
---
-00 (C): ─ Pane #1 ────────────────────────────────────────────┼─ Pane #7 ───────────────────────────────────
-01 (C): ─ Pane #9 ────────────────────────────────────────────┤
-02 (C): ─ Pane #10 ───────────────────────────────────────────┤
+00 (C): ─────────────────────── Pane #1 ──────────────────────┼────────────────── Pane #7 ──────────────────
+01 (C): ─────────────────────── Pane #9 ──────────────────────┤
+02 (C): ────────────────────── Pane #10 ──────────────────────┤
03 (C): │
04 (C): │
05 (C): │
@@ -21,10 +20,10 @@ expression: snapshot
15 (C): │
16 (C): │
17 (C): │
-18 (C): ├─ Pane #8 ───────────────────────────────────
+18 (C): ├────────────────── Pane #8 ──────────────────
19 (C): ─────────────────────────────────────────────────┬────┴─────────────────────────────────────────────
-20 (C): ─ Pane #2 ───────────────────────────────────────┼─ Pane #4 ────────────────────────────────────────
-21 (C): ─ Pane #3 ───────────────────────────────────────┼─ Pane #5 ────────────────────────────────────────
+20 (C): ───────────────────── Pane #2 ───────────────────┼───────────────────── Pane #4 ────────────────────
+21 (C): ───────────────────── Pane #3 ───────────────────┼───────────────────── Pane #5 ────────────────────
22 (C): │
23 (C): │
24 (C): │
@@ -42,5 +41,4 @@ expression: snapshot
36 (C): │
37 (C): │
38 (C): │
-39 (C): ├─ Pane #6 ────────────────────────────────────────
-
+39 (C): ├───────────────────── Pane #6 ────────────────────
diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap
index ee77150c..a9bf60ab 100644
--- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap
+++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap
@@ -1,11 +1,10 @@
---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
-assertion_line: 3249
expression: snapshot
---
-00 (C): ├─ Pane #2 ──────────────────────────────────────────────────
-01 (C): ├─ Pane #3 ──────────────────────────────────────────────────
-02 (C): ├─ Pane #4 ──────────────────────────────────────────────────
+00 (C): ├────────────────────────── Pane #2 ─────────────────────────
+01 (C): ├────────────────────────── Pane #3 ─────────────────────────
+02 (C): ├────────────────────────── Pane #4 ─────────────────────────
03 (C): │
04 (C): │
05 (C): │
@@ -22,5 +21,4 @@ expression: snapshot
16 (C): │
17 (C): │
18 (C): │
-19 (C): │
-
+19 (C): │
diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs
index c9a7508c..5b623b00 100644
--- a/zellij-server/src/tab/unit/tab_integration_tests.rs
+++ b/zellij-server/src/tab/unit/tab_integration_tests.rs
@@ -2,6 +2,7 @@ use super::{Output, Tab};
use crate::panes::sixel::SixelImageStore;
use crate::screen::CopyOptions;
use crate::Arc;
+use zellij_utils::input::options::PaneFrameStyle;
use crate::{
os_input_output::ServerOsApi, pane_groups::PaneGroups, panes::PaneId,
@@ -214,7 +215,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab {
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -302,7 +303,7 @@ fn create_new_tab_without_pane_frames(size: Size, default_mode: ModeInfo) -> Tab
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = false;
+ let draw_pane_frames = PaneFrameStyle::None;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -442,7 +443,11 @@ fn create_new_tab_with_swap_layouts(
max_panes,
style,
mode_info,
- draw_pane_frames,
+ if draw_pane_frames {
+ PaneFrameStyle::Full
+ } else {
+ PaneFrameStyle::None
+ },
auto_layout,
connected_clients,
session_is_mirrored,
@@ -509,7 +514,7 @@ fn create_new_tab_with_os_api(
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -597,7 +602,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str)
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -703,7 +708,7 @@ fn create_new_tab_with_mock_pty_writer(
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -796,7 +801,7 @@ fn create_new_tab_with_sixel_support(
let max_panes = None;
let mode_info = ModeInfo::default();
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -3253,7 +3258,7 @@ fn embed_floating_pane_without_pane_frames() {
let mut tab = create_new_tab(size, ModeInfo::default());
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
- tab.set_pane_frames(false);
+ tab.set_pane_frames(PaneFrameStyle::None);
tab.toggle_floating_panes(Some(client_id), None, None)
.unwrap();
tab.new_pane(
@@ -3293,7 +3298,7 @@ fn float_embedded_pane_without_pane_frames() {
let mut tab = create_new_tab(size, ModeInfo::default());
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
- tab.set_pane_frames(false);
+ tab.set_pane_frames(PaneFrameStyle::None);
tab.new_pane(
new_pane_id,
None,
@@ -12691,7 +12696,7 @@ fn create_new_tab_with_plugin_receiver(
let max_panes = None;
let mode_info = default_mode;
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -14513,7 +14518,7 @@ fn create_new_tab_with_server_receiver(
max_panes,
Style::default(),
default_mode,
- true, // draw_pane_frames
+ PaneFrameStyle::Full,
true, // auto_layout
connected_clients,
true, // session_is_mirrored
diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs
index 4651c0a6..0d18897e 100644
--- a/zellij-server/src/tab/unit/tab_tests.rs
+++ b/zellij-server/src/tab/unit/tab_tests.rs
@@ -10,6 +10,7 @@ use zellij_utils::channels::{unbounded, Receiver, SenderWithContext};
use zellij_utils::data::{Direction, NewPanePlacement, Resize, ResizeStrategy, WebSharing};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::layout::{SplitDirection, SplitSize, TiledPaneLayout};
+use zellij_utils::input::options::PaneFrameStyle;
use zellij_utils::ipc::IpcReceiverWithContext;
use zellij_utils::pane_size::{Size, SizeInPixels};
@@ -156,7 +157,7 @@ fn create_new_tab(size: Size, stacked_resize: bool) -> Tab {
let max_panes = None;
let mode_info = ModeInfo::default();
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -243,7 +244,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab {
let max_panes = None;
let mode_info = ModeInfo::default();
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -337,7 +338,7 @@ fn create_new_tab_with_cell_size(
let max_panes = None;
let mode_info = ModeInfo::default();
let style = Style::default();
- let draw_pane_frames = true;
+ let draw_pane_frames = PaneFrameStyle::Full;
let auto_layout = true;
let client_id = 1;
let session_is_mirrored = true;
@@ -15464,7 +15465,7 @@ fn correctly_resize_frameless_panes_on_pane_close() {
let size = Size { cols, rows };
let stacked_resize = true;
let mut tab = create_new_tab(size, stacked_resize);
- tab.set_pane_frames(false);
+ tab.set_pane_frames(PaneFrameStyle::None);
// a single frameless pane should take up all available space
let pane = tab.tiled_panes.panes.get(&PaneId::Terminal(1)).unwrap();
diff --git a/zellij-server/src/ui/hint_text.rs b/zellij-server/src/ui/hint_text.rs
new file mode 100644
index 00000000..84a8406d
--- /dev/null
+++ b/zellij-server/src/ui/hint_text.rs
@@ -0,0 +1,303 @@
+use std::collections::BTreeMap;
+use unicode_width::UnicodeWidthStr;
+use zellij_utils::data::StyledText;
+
+pub enum HintLevel {
+ Plain,
+ Emphasis,
+ Emphasis2,
+ Error,
+ Success,
+}
+
+pub struct HintSegment {
+ pub text: String,
+ pub level: HintLevel,
+}
+
+impl HintSegment {
+ fn plain(text: &str) -> Self {
+ HintSegment {
+ text: text.to_string(),
+ level: HintLevel::Plain,
+ }
+ }
+ fn emphasis(text: &str) -> Self {
+ HintSegment {
+ text: text.to_string(),
+ level: HintLevel::Emphasis,
+ }
+ }
+ fn emphasis_2(text: &str) -> Self {
+ HintSegment {
+ text: text.to_string(),
+ level: HintLevel::Emphasis2,
+ }
+ }
+ fn error(text: &str) -> Self {
+ HintSegment {
+ text: text.to_string(),
+ level: HintLevel::Error,
+ }
+ }
+ fn success(text: &str) -> Self {
+ HintSegment {
+ text: text.to_string(),
+ level: HintLevel::Success,
+ }
+ }
+}
+
+#[derive(Copy, Clone)]
+pub enum HintExitStatus {
+ Code(i32),
+ Exited,
+}
+
+#[derive(Copy, Clone)]
+pub enum HintTier {
+ Full,
+ Medium,
+ Minimal,
+}
+
+const ALL_TIERS: [HintTier; 3] = [HintTier::Full, HintTier::Medium, HintTier::Minimal];
+
+fn level_index(level: &HintLevel) -> Option<usize> {
+ match level {
+ HintLevel::Plain => None,
+ HintLevel::Emphasis => Some(0),
+ HintLevel::Emphasis2 => Some(2),
+ HintLevel::Error => Some(6),
+ HintLevel::Success => Some(7),
+ }
+}
+
+pub fn segments_to_styled_text(segments: &[HintSegment]) -> StyledText {
+ let mut text = String::new();
+ let mut indices: Vec<Vec<usize>> = vec![];
+ let mut offset = 0;
+ for segment in segments {
+ let char_count = segment.text.chars().count();
+ if let Some(level) = level_index(&segment.level) {
+ if indices.len() <= level {
+ indices.resize(level + 1, vec![]);
+ }
+ for position in offset..offset + char_count {
+ indices[level].push(position);
+ }
+ }
+ text.push_str(&segment.text);
+ offset += char_count;
+ }
+ StyledText { text, indices }
+}
+
+pub fn rerun_segments(is_first_run: bool, tier: HintTier) -> Vec<HintSegment> {
+ match tier {
+ HintTier::Full => vec![
+ HintSegment::plain(if is_first_run { " <" } else { "<" }),
+ HintSegment::emphasis("ENTER"),
+ HintSegment::plain(">"),
+ HintSegment::plain(if is_first_run { " run, " } else { " re-run, " }),
+ HintSegment::plain("<"),
+ HintSegment::emphasis("ESC"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" drop to shell, "),
+ HintSegment::plain("<"),
+ HintSegment::emphasis("Ctrl-c"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" exit "),
+ ],
+ HintTier::Medium => vec![
+ HintSegment::plain("<"),
+ HintSegment::emphasis("ENTER"),
+ HintSegment::plain(">"),
+ HintSegment::plain(if is_first_run { " run " } else { " re-run " }),
+ HintSegment::plain("<"),
+ HintSegment::emphasis("ESC"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" shell "),
+ HintSegment::plain("<"),
+ HintSegment::emphasis("Ctrl-c"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" exit"),
+ ],
+ HintTier::Minimal => vec![
+ HintSegment::plain("<"),
+ HintSegment::emphasis("ENTER"),
+ HintSegment::plain(">"),
+ HintSegment::plain(if is_first_run { " run" } else { " re-run" }),
+ ],
+ }
+}
+
+pub fn exit_code_segments(exit_status: HintExitStatus) -> Vec<HintSegment> {
+ match exit_status {
+ HintExitStatus::Code(exit_code) => {
+ let exit_code_text = format!("{}", exit_code);
+ let exit_code_segment = if exit_code == 0 {
+ HintSegment::success(&exit_code_text)
+ } else {
+ HintSegment::error(&exit_code_text)
+ };
+ vec![
+ HintSegment::plain(" [ "),
+ HintSegment::plain("EXIT CODE: "),
+ exit_code_segment,
+ HintSegment::plain(" ] "),
+ ]
+ },
+ HintExitStatus::Exited => vec![
+ HintSegment::plain(" [ "),
+ HintSegment::error("EXITED"),
+ HintSegment::plain(" ] "),
+ ],
+ }
+}
+
+pub fn hover_segments(tier: HintTier) -> Vec<HintSegment> {
+ match tier {
+ HintTier::Full => vec![
+ HintSegment::plain(" "),
+ HintSegment::emphasis("Alt"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis("Click"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" - group,"),
+ HintSegment::plain(" "),
+ HintSegment::emphasis("Alt"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis("Right-Click"),
+ HintSegment::plain(">"),
+ HintSegment::plain(" - ungroup all "),
+ ],
+ HintTier::Medium => vec![
+ HintSegment::emphasis("Alt"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis("Click"),
+ HintSegment::plain("> group, "),
+ HintSegment::emphasis("Alt"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis("Right-Click"),
+ HintSegment::plain("> ungroup"),
+ ],
+ HintTier::Minimal => vec![
+ HintSegment::emphasis("Alt"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis("Click"),
+ HintSegment::plain("> group"),
+ ],
+ }
+}
+
+pub fn hover_hint_variants() -> BTreeMap<usize, StyledText> {
+ let mut variants = BTreeMap::new();
+ for tier in ALL_TIERS {
+ let styled_text = segments_to_styled_text(&hover_segments(tier));
+ variants.insert(styled_text.text.width(), styled_text);
+ }
+ variants
+}
+
+pub fn resize_segments(is_floating: bool, tier: HintTier) -> Vec<HintSegment> {
+ match tier {
+ HintTier::Full => {
+ if is_floating {
+ vec![
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain("> or "),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> to resize "),
+ ]
+ } else {
+ vec![
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain("> or <"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> to resize "),
+ ]
+ }
+ },
+ HintTier::Medium => {
+ if is_floating {
+ vec![
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain("/"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> resize "),
+ ]
+ } else {
+ vec![
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain(">/<"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> resize "),
+ ]
+ }
+ },
+ HintTier::Minimal => {
+ if is_floating {
+ vec![
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain("/"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> "),
+ ]
+ } else {
+ vec![
+ HintSegment::plain(" <"),
+ HintSegment::emphasis_2("Ctrl"),
+ HintSegment::plain(" "),
+ HintSegment::emphasis_2("MouseScroll"),
+ HintSegment::plain(">/<"),
+ HintSegment::emphasis_2("drag borders"),
+ HintSegment::plain("> "),
+ ]
+ }
+ },
+ }
+}
+
+pub fn resize_hint_variants(is_floating: bool) -> BTreeMap<usize, StyledText> {
+ let mut variants = BTreeMap::new();
+ for tier in ALL_TIERS {
+ let styled_text = segments_to_styled_text(&resize_segments(is_floating, tier));
+ variants.insert(styled_text.text.width(), styled_text);
+ }
+ variants
+}
+
+pub fn held_hint_variants(
+ is_first_run: bool,
+ exit_status: Option<HintExitStatus>,
+) -> BTreeMap<usize, StyledText> {
+ let mut variants = BTreeMap::new();
+ for tier in ALL_TIERS {
+ let mut segments = vec![];
+ if let Some(exit_status) = exit_status {
+ segments.extend(exit_code_segments(exit_status));
+ }
+ segments.extend(rerun_segments(is_first_run, tier));
+ let styled_text = segments_to_styled_text(&segments);
+ variants.insert(styled_text.text.width(), styled_text);
+ }
+ variants
+}
diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs
index 1a17e743..1d3ba1f6 100644
--- a/zellij-server/src/ui/mod.rs
+++ b/zellij-server/src/ui/mod.rs
@@ -1,5 +1,6 @@
pub mod boundaries;
pub mod components;
+pub mod hint_text;
pub mod loading_indication;
pub mod pane_boundaries_frame;
pub mod pane_contents_and_ui;
diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs
index a464e4b0..d7abdfd1 100644
--- a/zellij-server/src/ui/pane_boundaries_frame.rs
+++ b/zellij-server/src/ui/pane_boundaries_frame.rs
@@ -1,6 +1,10 @@
use crate::output::CharacterChunk;
use crate::panes::{AnsiCode, RcCharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER};
use crate::ui::boundaries::boundary_type;
+use crate::ui::hint_text::{
+ exit_code_segments, hover_segments, rerun_segments, HintExitStatus, HintLevel, HintSegment,
+ HintTier,
+};
use crate::ClientId;
use zellij_utils::data::{client_id_to_colors, PaletteColor, Style};
use zellij_utils::errors::prelude::*;
@@ -60,6 +64,7 @@ pub struct FrameParams {
pub other_cursors_exist_in_session: bool,
pub pane_is_stacked_under: bool,
pub pane_is_stacked_over: bool,
+ pub pane_is_stacked: bool,
pub should_draw_pane_frames: bool,
pub pane_is_floating: bool,
pub content_offset: Offset,
@@ -67,6 +72,7 @@ pub struct FrameParams {
pub pane_is_selectable: bool,
pub show_help_text: bool,
pub highlight_tooltip: Option<String>,
+ pub omit_title: bool,
}
#[derive(Default, PartialEq)]
@@ -84,6 +90,7 @@ pub struct PaneFrame {
is_first_run: bool,
pane_is_stacked_over: bool,
pane_is_stacked_under: bool,
+ pane_is_stacked: bool,
should_draw_pane_frames: bool,
is_pinned: bool,
is_floating: bool,
@@ -92,6 +99,7 @@ pub struct PaneFrame {
is_selectable: bool,
show_help_text: bool,
highlight_tooltip: Option<String>,
+ omit_title: bool,
}
impl PaneFrame {
@@ -115,6 +123,7 @@ impl PaneFrame {
is_first_run: false,
pane_is_stacked_over: frame_params.pane_is_stacked_over,
pane_is_stacked_under: frame_params.pane_is_stacked_under,
+ pane_is_stacked: frame_params.pane_is_stacked,
should_draw_pane_frames: frame_params.should_draw_pane_frames,
is_pinned: false,
is_floating: frame_params.pane_is_floating,
@@ -123,6 +132,7 @@ impl PaneFrame {
is_selectable: frame_params.pane_is_selectable,
show_help_text: frame_params.show_help_text,
highlight_tooltip: frame_params.highlight_tooltip,
+ omit_title: frame_params.omit_title,
}
}
pub fn is_pinned(mut self, is_pinned: bool) -> Self {
@@ -386,6 +396,17 @@ impl PaneFrame {
}
fn render_title_middle(&self, max_length: usize) -> Option<(Vec<TerminalCharacter>, usize)> {
// string and length because of color
+ let renders_exit_status_in_title = self.pane_is_stacked_under
+ || self.pane_is_stacked_over
+ || !self.should_draw_pane_frames;
+ if renders_exit_status_in_title && self.exit_status.is_some() {
+ let (first_part, first_part_len) = self.first_exited_held_title_part_full();
+ return if first_part_len <= max_length {
+ Some((first_part, first_part_len))
+ } else {
+ None
+ };
+ }
if self.is_main_client
&& self.other_focused_clients.is_empty()
&& !self.other_cursors_exist_in_session
@@ -400,15 +421,6 @@ impl PaneFrame {
self.render_my_and_others_focus(max_length)
} else if !self.other_focused_clients.is_empty() {
self.render_other_focused_users(max_length)
- } else if (self.pane_is_stacked_under || self.pane_is_stacked_over)
- && self.exit_status.is_some()
- {
- let (first_part, first_part_len) = self.first_exited_held_title_part_full();
- if first_part_len <= max_length {
- Some((first_part, first_part_len))
- } else {
- None
- }
} else {
None
}
@@ -704,12 +716,236 @@ impl PaneFrame {
.with_context(|| format!("failed to render title '{}'", self.title))
}
fn render_one_line_title(&self) -> Result<Vec<TerminalCharacter>> {
- let total_title_length = self.geom.cols.saturating_sub(2); // 2 for the left and right corners
+ if self.should_draw_pane_frames {
+ let total_title_length = self.geom.cols.saturating_sub(2);
+ return self
+ .render_title_middle(total_title_length)
+ .map(|(middle, middle_length)| self.title_line_with_middle(middle, &middle_length))
+ .or_else(|| Some(self.title_line_without_middle()))
+ .with_context(|| format!("failed to render title '{}'", self.title));
+ }
- self.render_title_middle(total_title_length)
- .map(|(middle, middle_length)| self.title_line_with_middle(middle, &middle_length))
- .or_else(|| Some(self.title_line_without_middle()))
- .with_context(|| format!("failed to render title '{}'", self.title))
+ let width = self.geom.cols;
+ let title = self.bracketed_pane_title(width);
+ let title_length = title.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let side_budget = width.saturating_sub(title_length) / 2;
+ let focus = self.bracketed_focus_indicator(side_budget);
+ let focus_length = focus.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let scroll =
+ self.bracketed_scroll_indicator(width.saturating_sub(focus_length + title_length));
+ Ok(self.compose_bracketed_title(focus, title, scroll))
+ }
+ fn bracketed_title_part(&self, content: &str) -> (Vec<TerminalCharacter>, usize) {
+ let text = format!(" [ {} ] ", content);
+ (foreground_color(&text, self.color), text.width())
+ }
+ fn bracketed_title_part_from_characters(
+ &self,
+ mut content: Vec<TerminalCharacter>,
+ content_length: usize,
+ ) -> (Vec<TerminalCharacter>, usize) {
+ let mut part = foreground_color(" [ ", self.color);
+ part.append(&mut content);
+ part.append(&mut foreground_color(" ] ", self.color));
+ (part, content_length + 6)
+ }
+ fn plain_title_part(&self, content: &str) -> (Vec<TerminalCharacter>, usize) {
+ let text = format!(" {} ", content);
+ (foreground_color(&text, self.color), text.width())
+ }
+ fn bracketed_pane_title(&self, max_length: usize) -> Option<(Vec<TerminalCharacter>, usize)> {
+ let title_padding = 2;
+ if self.title.is_empty() || max_length <= title_padding {
+ return None;
+ }
+ let exit_part = self
+ .exit_status
+ .is_some()
+ .then(|| self.first_exited_held_title_part_full());
+ let exit_length = exit_part.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let content_max_length = max_length.saturating_sub(title_padding + exit_length);
+ let content = if self.title.width() <= content_max_length {
+ self.title.clone()
+ } else {
+ let truncation_budget = content_max_length.saturating_sub(1);
+ let mut truncated = String::new();
+ for character in self.title.chars() {
+ if truncated.width() + character.width().unwrap_or(0) > truncation_budget {
+ break;
+ }
+ truncated.push(character);
+ }
+ truncated.push('…');
+ truncated
+ };
+ let (mut part, mut length) = self.plain_title_part(&content);
+ if let Some((mut exit, exit_length)) = exit_part {
+ part.append(&mut exit);
+ length += exit_length;
+ }
+ Some((part, length))
+ }
+ fn bracketed_scroll_indicator(
+ &self,
+ max_length: usize,
+ ) -> Option<(Vec<TerminalCharacter>, usize)> {
+ let has_scroll = self.scroll_position.0 > 0 || self.scroll_position.1 > 0;
+ if !(has_scroll && self.is_selectable) {
+ return None;
+ }
+ let full_indication = format!(
+ "SCROLL: {}/{}",
+ self.scroll_position.0, self.scroll_position.1
+ );
+ let (full_part, full_length) = self.bracketed_title_part(&full_indication);
+ if full_length <= max_length {
+ return Some((full_part, full_length));
+ }
+ let short_indication = format!("{}/{}", self.scroll_position.0, self.scroll_position.1);
+ let (short_part, short_length) = self.bracketed_title_part(&short_indication);
+ if short_length <= max_length {
+ return Some((short_part, short_length));
+ }
+ None
+ }
+ fn bracketed_focus_indicator(
+ &self,
+ max_length: usize,
+ ) -> Option<(Vec<TerminalCharacter>, usize)> {
+ if self.is_main_client
+ && self.other_focused_clients.is_empty()
+ && !self.other_cursors_exist_in_session
+ {
+ None
+ } else if self.is_main_client
+ && self.other_focused_clients.is_empty()
+ && self.other_cursors_exist_in_session
+ {
+ let (full_part, full_length) = self.bracketed_title_part("MY FOCUS");
+ if full_length <= max_length {
+ Some((full_part, full_length))
+ } else {
+ let (short_part, short_length) = self.bracketed_title_part("ME");
+ (short_length <= max_length).then_some((short_part, short_length))
+ }
+ } else if self.is_main_client && !self.other_focused_clients.is_empty() {
+ self.bracketed_focused_users("MY FOCUS AND:", "+", max_length)
+ } else if !self.other_focused_clients.is_empty() {
+ let full_label = if self.other_focused_clients.len() == 1 {
+ "FOCUSED USER:"
+ } else {
+ "FOCUSED USERS:"
+ };
+ self.bracketed_focused_users(full_label, "U:", max_length)
+ } else {
+ None
+ }
+ }
+ fn focused_users_part(&self, label: &str) -> (Vec<TerminalCharacter>, usize) {
+ let mut content = foreground_color(label, self.color);
+ let mut content_length = label.width();
+ for client_id in &self.other_focused_clients {
+ content.push(EMPTY_TERMINAL_CHARACTER);
+ content.append(&mut self.client_cursor(*client_id));
+ content_length += 2;
+ }
+ self.bracketed_title_part_from_characters(content, content_length)
+ }
+ fn focused_users_cursors_part(&self) -> (Vec<TerminalCharacter>, usize) {
+ let mut content = vec![];
+ let mut content_length = 0;
+ for client_id in &self.other_focused_clients {
+ if content_length > 0 {
+ content.push(EMPTY_TERMINAL_CHARACTER);
+ content_length += 1;
+ }
+ content.append(&mut self.client_cursor(*client_id));
+ content_length += 1;
+ }
+ self.bracketed_title_part_from_characters(content, content_length)
+ }
+ fn bracketed_focused_users(
+ &self,
+ full_label: &str,
+ short_label: &str,
+ max_length: usize,
+ ) -> Option<(Vec<TerminalCharacter>, usize)> {
+ let (full_part, full_length) = self.focused_users_part(full_label);
+ if full_length <= max_length {
+ return Some((full_part, full_length));
+ }
+ let (short_part, short_length) = self.focused_users_part(short_label);
+ if short_length <= max_length {
+ return Some((short_part, short_length));
+ }
+ let (cursors_part, cursors_length) = self.focused_users_cursors_part();
+ (cursors_length <= max_length).then_some((cursors_part, cursors_length))
+ }
+ fn compose_bracketed_title(
+ &self,
+ left: Option<(Vec<TerminalCharacter>, usize)>,
+ middle: Option<(Vec<TerminalCharacter>, usize)>,
+ right: Option<(Vec<TerminalCharacter>, usize)>,
+ ) -> Vec<TerminalCharacter> {
+ let width = self.geom.cols;
+ let left_length = left.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let middle_length = middle.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let right_length = right.as_ref().map(|(_, length)| *length).unwrap_or(0);
+ let centered_start = (width / 2)
+ .saturating_sub(middle_length / 2)
+ .max(left_length);
+ let middle_start = if middle.is_some() {
+ if right_length > 0 {
+ let scroll_start = width.saturating_sub(right_length);
+ let centered_end = centered_start + middle_length;
+ if centered_end > scroll_start {
+ scroll_start.saturating_sub(middle_length).max(left_length)
+ } else {
+ centered_start
+ }
+ } else {
+ centered_start
+ }
+ } else {
+ left_length
+ };
+ let middle_end = if middle.is_some() {
+ middle_start + middle_length
+ } else {
+ left_length
+ };
+ let right_start = width.saturating_sub(right_length).max(middle_end);
+ let fill_character = if self.pane_is_stacked {
+ foreground_color(boundary_type::HORIZONTAL, self.color)
+ .into_iter()
+ .next()
+ .unwrap_or(EMPTY_TERMINAL_CHARACTER)
+ } else {
+ EMPTY_TERMINAL_CHARACTER
+ };
+ let mut placements: Vec<(usize, Vec<TerminalCharacter>, usize)> = vec![];
+ if let Some((characters, length)) = left {
+ placements.push((0, characters, length));
+ }
+ if let Some((characters, length)) = middle {
+ placements.push((middle_start, characters, length));
+ }
+ if let Some((characters, length)) = right {
+ placements.push((right_start, characters, length));
+ }
+ let mut title_line = vec![];
+ let mut col = 0;
+ while col < width {
+ if let Some(index) = placements.iter().position(|(start, _, _)| *start == col) {
+ let (_, mut characters, length) = placements.remove(index);
+ title_line.append(&mut characters);
+ col += length;
+ } else {
+ title_line.push(fill_character.clone());
+ col += 1;
+ }
+ }
+ title_line
}
fn render_highlight_tooltip_undertitle(&self) -> Result<Vec<TerminalCharacter>> {
let max_undertitle_length = self.geom.cols.saturating_sub(2);
@@ -929,6 +1165,9 @@ impl PaneFrame {
pub fn render(&self) -> Result<(Vec<CharacterChunk>, Option<String>)> {
let err_context = || "failed to render pane frame";
let mut character_chunks = vec![];
+ if self.omit_title {
+ return Ok((character_chunks, None));
+ }
if self.geom.rows == 1 || !self.should_draw_pane_frames {
// we do this explicitly when not drawing pane frames because this should only happen
// if this is a stacked pane with pane frames off (and it doesn't necessarily have only
@@ -1038,133 +1277,38 @@ impl PaneFrame {
}
Ok((character_chunks, None))
}
+ fn render_hint_segments(&self, segments: &[HintSegment]) -> (Vec<TerminalCharacter>, usize) {
+ let mut characters = vec![];
+ let mut length = 0;
+ for segment in segments {
+ let color = match segment.level {
+ HintLevel::Plain => self.color,
+ HintLevel::Emphasis => Some(self.style.colors.text_unselected.emphasis_0),
+ HintLevel::Emphasis2 => Some(self.style.colors.text_unselected.emphasis_2),
+ HintLevel::Error => Some(self.style.colors.exit_code_error.base),
+ HintLevel::Success => Some(self.style.colors.exit_code_success.base),
+ };
+ characters.append(&mut foreground_color(&segment.text, color));
+ length += segment.text.width();
+ }
+ (characters, length)
+ }
fn first_exited_held_title_part_full(&self) -> (Vec<TerminalCharacter>, usize) {
- // (title part, length)
match self.exit_status {
Some(ExitStatus::Code(exit_code)) => {
- let mut first_part = vec![];
- let left_bracket = " [ ";
- let exited_text = "EXIT CODE: ";
- let exit_code_text = format!("{}", exit_code);
- let exit_code_color = if exit_code == 0 {
- self.style.colors.exit_code_success.base
- } else {
- self.style.colors.exit_code_error.base
- };
- let right_bracket = " ] ";
- first_part.append(&mut foreground_color(left_bracket, self.color));
- first_part.append(&mut foreground_color(exited_text, self.color));
- first_part.append(&mut foreground_color(
- &exit_code_text,
- Some(exit_code_color),
- ));
- first_part.append(&mut foreground_color(right_bracket, self.color));
- (
- first_part,
- left_bracket.len()
- + exited_text.len()
- + exit_code_text.len()
- + right_bracket.len(),
- )
+ self.render_hint_segments(&exit_code_segments(HintExitStatus::Code(exit_code)))
},
Some(ExitStatus::Exited) => {
- let mut first_part = vec![];
- let left_bracket = " [ ";
- let exited_text = "EXITED";
- let right_bracket = " ] ";
- first_part.append(&mut foreground_color(left_bracket, self.color));
- first_part.append(&mut foreground_color(
- exited_text,
- Some(self.style.colors.exit_code_error.base),
- ));
- first_part.append(&mut foreground_color(right_bracket, self.color));
- (
- first_part,
- left_bracket.len() + exited_text.len() + right_bracket.len(),
- )
+ self.render_hint_segments(&exit_code_segments(HintExitStatus::Exited))
},
None => (foreground_color(boundary_type::HORIZONTAL, self.color), 1),
}
}
fn second_held_title_part_full(&self) -> (Vec<TerminalCharacter>, usize) {
- // (title part, length)
- let mut second_part = vec![];
- let left_enter_bracket = if self.is_first_run { " <" } else { "<" };
- let enter_text = "ENTER";
- let right_enter_bracket = ">";
- let enter_tip = if self.is_first_run {
- " run, "
- } else {
- " re-run, "
- };
-
- let left_esc_bracket = "<";
- let esc_text = "ESC";
- let right_esc_bracket = ">";
- let esc_tip = " drop to shell, ";
-
- let left_break_bracket = "<";
- let break_text = "Ctrl-c";
- let right_break_bracket = ">";
- let break_tip = " exit ";
- second_part.append(&mut foreground_color(left_enter_bracket, self.color));
- second_part.append(&mut foreground_color(
- enter_text,
- Some(self.style.colors.text_unselected.emphasis_0),
- ));
- second_part.append(&mut foreground_color(right_enter_bracket, self.color));
- second_part.append(&mut foreground_color(enter_tip, self.color));
-
- second_part.append(&mut foreground_color(left_esc_bracket, self.color));
- second_part.append(&mut foreground_color(
- esc_text,
- Some(self.style.colors.text_unselected.emphasis_0),
- ));
- second_part.append(&mut foreground_color(right_esc_bracket, self.color));
- second_part.append(&mut foreground_color(esc_tip, self.color));
-
- second_part.append(&mut foreground_color(left_break_bracket, self.color));
- second_part.append(&mut foreground_color(
- break_text,
- Some(self.style.colors.text_unselected.emphasis_0),
- ));
- second_part.append(&mut foreground_color(right_break_bracket, self.color));
- second_part.append(&mut foreground_color(break_tip, self.color));
- (
- second_part,
- left_enter_bracket.len()
- + enter_text.len()
- + right_enter_bracket.len()
- + enter_tip.len()
- + left_esc_bracket.len()
- + esc_text.len()
- + right_esc_bracket.len()
- + esc_tip.len()
- + left_break_bracket.len()
- + break_text.len()
- + right_break_bracket.len()
- + break_tip.len(),
- )
+ self.render_hint_segments(&rerun_segments(self.is_first_run, HintTier::Full))
}
fn hover_shortcuts_part_full(&self) -> (Vec<TerminalCharacter>, usize) {
- // (title part, length)
- let mut hover_shortcuts = vec![];
- let alt_click_text = " Alt <Click>";
- let alt_click_tip = " - group,";
- let alt_right_click_text = " Alt <Right-Click>";
- let alt_right_click_tip = " - ungroup all ";
-
- hover_shortcuts.append(&mut foreground_color(alt_click_text, self.color));
- hover_shortcuts.append(&mut foreground_color(alt_click_tip, self.color));
- hover_shortcuts.append(&mut foreground_color(alt_right_click_text, self.color));
- hover_shortcuts.append(&mut foreground_color(alt_right_click_tip, self.color));
- (
- hover_shortcuts,
- alt_click_text.chars().count()
- + alt_click_tip.chars().count()
- + alt_right_click_text.chars().count()
- + alt_right_click_tip.chars().count(),
- )
+ self.render_hint_segments(&hover_segments(HintTier::Full))
}
fn empty_undertitle(&self, max_undertitle_length: usize) -> Vec<TerminalCharacter> {
let mut left_boundary =
diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs
index db7138f5..f2763a9b 100644
--- a/zellij-server/src/ui/pane_contents_and_ui.rs
+++ b/zellij-server/src/ui/pane_contents_and_ui.rs
@@ -20,6 +20,7 @@ pub struct PaneContentsAndUi<'a> {
mouse_is_hovering_over_pane_for_clients: HashSet<ClientId>,
current_pane_group: HashMap<ClientId, Vec<PaneId>>,
show_help_text: bool,
+ omit_title: bool,
}
impl<'a> PaneContentsAndUi<'a> {
@@ -36,6 +37,7 @@ impl<'a> PaneContentsAndUi<'a> {
mouse_hover_pane_id: &HashMap<ClientId, PaneId>,
current_pane_group: HashMap<ClientId, Vec<PaneId>>,
show_help_text: bool,
+ omit_title: bool,
) -> Self {
let mut focused_clients: Vec<ClientId> = active_panes
.iter()
@@ -66,6 +68,7 @@ impl<'a> PaneContentsAndUi<'a> {
mouse_is_hovering_over_pane_for_clients,
current_pane_group,
show_help_text,
+ omit_title,
}
}
pub fn render_pane_contents_to_multiple_clients(
@@ -239,6 +242,7 @@ impl<'a> PaneContentsAndUi<'a> {
} else {
None
};
+ let pane_is_stacked = self.pane.current_geom().is_stacked();
let frame_params = if session_is_mirrored {
FrameParams {
focused_client,
@@ -249,6 +253,7 @@ impl<'a> PaneContentsAndUi<'a> {
other_cursors_exist_in_session: false,
pane_is_stacked_over: self.pane_is_stacked_over,
pane_is_stacked_under: self.pane_is_stacked_under,
+ pane_is_stacked,
should_draw_pane_frames: self.should_draw_pane_frames,
pane_is_floating,
content_offset: self.pane.get_content_offset(),
@@ -258,6 +263,7 @@ impl<'a> PaneContentsAndUi<'a> {
pane_is_selectable,
show_help_text: self.show_help_text,
highlight_tooltip: highlight_tooltip.clone(),
+ omit_title: self.omit_title,
}
} else {
FrameParams {
@@ -269,6 +275,7 @@ impl<'a> PaneContentsAndUi<'a> {
other_cursors_exist_in_session: self.multiple_users_exist_in_session,
pane_is_stacked_over: self.pane_is_stacked_over,
pane_is_stacked_under: self.pane_is_stacked_under,
+ pane_is_stacked,
should_draw_pane_frames: self.should_draw_pane_frames,
pane_is_floating,
content_offset: self.pane.get_content_offset(),
@@ -278,6 +285,7 @@ impl<'a> PaneContentsAndUi<'a> {
pane_is_selectable,
show_help_text: self.show_help_text,
highlight_tooltip,
+ omit_title: self.omit_title,
}
};
diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs
index 245cac8c..ee46dad3 100644
--- a/zellij-server/src/unit/screen_tests.rs
+++ b/zellij-server/src/unit/screen_tests.rs
@@ -18,7 +18,7 @@ use zellij_utils::input::layout::{
RunPlugin, RunPluginLocation, RunPluginOrAlias, SplitDirection, TiledPaneLayout,
};
use zellij_utils::input::mouse::MouseEvent;
-use zellij_utils::input::options::Options;
+use zellij_utils::input::options::{Options, PaneFrameStyle};
use zellij_utils::ipc::IpcReceiverWithContext;
use zellij_utils::pane_size::{Size, SizeInPixels};
use zellij_utils::position::Position;
@@ -262,7 +262,7 @@ fn create_new_screen(
let max_panes = None;
let mut mode_info = ModeInfo::default();
mode_info.session_name = Some("zellij-test".into());
- let draw_pane_frames = false;
+ let draw_pane_frames = PaneFrameStyle::None;
let auto_layout = true;
let session_is_mirrored = true;
let copy_options = CopyOptions::default();
@@ -693,6 +693,8 @@ impl MockScreen {
let os_input = FakeInputOutput::default();
let config_options = Options::default();
+ let mut config = Config::default();
+ config.options.pane_frame_style = Some(PaneFrameStyle::Full);
let main_client_id = 1;
std::thread::Builder::new()
@@ -734,7 +736,7 @@ impl MockScreen {
config_options,
session_metadata,
last_opened_tab_index: None,
- config: Config::default(),
+ config,
advanced_mouse_actions: true,
}
}
@@ -3230,6 +3232,7 @@ pub fn send_cli_new_pane_action_with_default_parameters() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3284,6 +3287,7 @@ pub fn send_cli_new_pane_action_with_split_direction() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3338,6 +3342,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3403,6 +3408,7 @@ pub fn send_cli_new_pane_action_with_floating_pane_and_coordinates() {
floating: true,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -5224,6 +5230,7 @@ pub fn send_cli_new_pane_in_place_with_close_replaced_pane() {
floating: false,
in_place: true,
close_replaced_pane: true,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -5375,7 +5382,7 @@ fn create_new_screen_with_message_capture(
let max_panes = None;
let mut mode_info = ModeInfo::default();
mode_info.session_name = Some("zellij-test".into());
- let draw_pane_frames = false;
+ let draw_pane_frames = PaneFrameStyle::None;
let auto_layout = true;
let session_is_mirrored = true;
let copy_options = CopyOptions::default();
@@ -7949,6 +7956,7 @@ pub fn send_cli_new_pane_action_with_tab_id() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -8010,6 +8018,7 @@ pub fn send_cli_new_floating_pane_action_with_tab_id() {
floating: true,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -8119,6 +8128,7 @@ pub fn send_cli_new_pane_action_with_tab_id_and_direction() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -8179,6 +8189,7 @@ pub fn send_cli_new_pane_action_with_tab_id_and_stacked() {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -8445,7 +8456,7 @@ fn create_new_screen_with_forward_capture(size: Size) -> (Screen, ForwardCapture
let max_panes = None;
let mut mode_info = ModeInfo::default();
mode_info.session_name = Some("zellij-test".into());
- let draw_pane_frames = false;
+ let draw_pane_frames = PaneFrameStyle::None;
let auto_layout = true;
let session_is_mirrored = true;
let copy_options = CopyOptions::default();
@@ -9054,7 +9065,7 @@ fn create_new_screen_with_theme_capture(size: Size) -> (Screen, ThemeCapture) {
&client_attributes,
None,
mode_info,
- false,
+ PaneFrameStyle::None,
true,
true,
copy_options,
@@ -9533,7 +9544,7 @@ fn create_non_mirrored_screen(size: Size) -> Screen {
&client_attributes,
None, // max_panes
mode_info,
- false, // draw_pane_frames
+ PaneFrameStyle::None,
true, // auto_layout
false, // session_is_mirrored
CopyOptions::default(),
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap
index 6274f758..78d55494 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2849
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap
index a87d4588..03497d19 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3395
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap
index 8fc16e07..78d55494 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3502
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap
index 347d93d4..6a14b417 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2739
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap
index 2ee1fac4..1a41cccd 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2739
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap
index 347d93d4..6a14b417 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2739
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap
index 765e5426..33a1d24d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2739
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap
index bbcf4b3a..1a41cccd 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2914
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap
index 91a3ecd4..1a41cccd 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3429
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap
index bb34d594..6a14b417 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3079
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap
index 262029b4..33a1d24d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3079
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap
index 32f3248e..6a14b417 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3032
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap
index 31169db3..33a1d24d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3032
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap
index e4fbe942..7b8c7366 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2852
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap
index 3a14dc55..69ea0a2e 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2852
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap
index ff7668a0..7b8c7366 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2773
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ │
18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap
index 4ea0e091..8a6f7e59 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3725
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ P[..]2 ┐─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │ │
08 (C): │ │ │
09 (C): └────────┘─────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap
index 01d4a3ae..f6dec9be 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3725
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ └──────────────────────────────────────┘ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap
index a95a55c6..b8ec0590 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2223
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap
index 6c5fd6ab..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1805
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap
index 495842f6..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2459
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap
index 9abd2dfc..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2459
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap
index d4fce111..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2118
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap
index 1305cf7b..13eb550d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1042
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((41, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap
index 74460796..e627107f 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 939
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((1, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap
index ae6be657..13eb550d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1080
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((41, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap
index c8861240..e627107f 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 968
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((1, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap
index a0264d66..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2423
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap
index cd63569f..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2423
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap
index 1688290e..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2037
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap
index d03e1da4..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1397
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap
index d38454b4..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1354
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap
index 2cbf6cd5..13eb550d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1160
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((41, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap
index 7a6fd48a..e627107f 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1030
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((1, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap
index 83bbdbb6..13eb550d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1120
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((41, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap
index 208d683f..e627107f 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 999
expression: "format!(\"{:?}\", cursor_coordinates)"
---
Some((1, 1))
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap
index ad657ff1..e6f32591 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1194
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────┐┌ Pane #1 ─────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap
index 1c054e3a..69ea0a2e 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1061
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)"
17 (C): │ ││ │
18 (C): │ ││ │
19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap
index fbf000fe..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2346
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap
index 05259017..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2366
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap
index fdac85da..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1969
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap
index 19f6d030..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1318
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap
index a59f6869..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1275
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap
index a677592e..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2387
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap
index 1f0f1907..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2387
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap
index b0d42634..793c70c6 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2003
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap
index 0555f99f..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1565
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap
index 94eef91e..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1147
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap
index 8b57c658..b4649346 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 3687
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────┐┌ Pane #2 ─────┐┌ Pane #3 ─────┐┌ Pane #4 ─────┐┌ Pane #5 ─────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ ││ ││ ││ │
08 (C): │ ││ ││ ││ ││ │
09 (C): └──────────────┘└──────────────┘└──────────────┘└──────────────┘└──────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap
index 0eaddd57..13c2a287 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2609
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ └──────────────────────────────────────┘ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap
index 70970461..b8ec0590 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2186
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap
index 0eaddd57..13c2a287 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2609
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ └──────────────────────────────────────┘ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap
index b7d2d258..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1775
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap
index a5049d6c..7b763850 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1739
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap
index a18e57fb..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1427
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap
index ca19a162..13c2a287 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2569
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ └──────────────────────────────────────┘ │
08 (C): │ │
09 (C): └──────────────────────────────────────────────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap
index 5a16d92e..85c2d9ae 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2583
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #2 ─────────────────────────────┐┌ Pane #1 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap
index 626bca74..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1737
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap
index 5d8c103b..6fdc8cca 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap
@@ -1,9 +1,8 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1776
expression: "format!(\"{}\", snapshot)"
---
-00 (C): │
+00 (C): Pane #1 │ Pane #2
01 (C): │
02 (C): │
03 (C): │
@@ -12,5 +11,4 @@ expression: "format!(\"{}\", snapshot)"
06 (C): │
07 (C): │
08 (C): │
-09 (C): │
-
+09 (C): │
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap
index e8307ea9..a54fd73c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 1457
expression: "format!(\"{}\", snapshot)"
---
00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐
@@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)"
07 (C): │ ││ │
08 (C): │ ││ │
09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘
-
diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs
index 54431151..00be00bf 100644
--- a/zellij-tile/src/shim.rs
+++ b/zellij-tile/src/shim.rs
@@ -1300,6 +1300,13 @@ pub fn toggle_pane_frames() {
unsafe { host_run_plugin_command() };
}
+pub fn set_pane_frame_style(pane_frame_style: PaneFrameStyle) {
+ let plugin_command = PluginCommand::SetPaneFrameStyle(pane_frame_style);
+ let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
+ object_to_stdout(&protobuf_plugin_command.encode_to_vec());
+ unsafe { host_run_plugin_command() };
+}
+
/// Embed the currently focused pane (make it stop floating) or turn it to a float pane if it is not
pub fn toggle_pane_embed_or_eject() {
let plugin_command = PluginCommand::TogglePaneEmbedOrEject;
@@ -1323,6 +1330,20 @@ pub fn close_focus() {
unsafe { host_run_plugin_command() };
}
+pub fn new_pane() {
+ let plugin_command = PluginCommand::NewPane;
+ let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
+ object_to_stdout(&protobuf_plugin_command.encode_to_vec());
+ unsafe { host_run_plugin_command() };
+}
+
+pub fn toggle_floating_panes(tab_id: Option<u64>) {
+ let plugin_command = PluginCommand::ToggleFloatingPanes { tab_id };
+ let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
+ object_to_stdout(&protobuf_plugin_command.encode_to_vec());
+ unsafe { host_run_plugin_command() };
+}
+
/// Turn the `STDIN` synchronization of the current tab on or off
pub fn toggle_active_tab_sync() {
let plugin_command = PluginCommand::ToggleActiveTabSync;
diff --git a/zellij-tile/src/ui_components/text.rs b/zellij-tile/src/ui_components/text.rs
index fe813fb3..ddfbc0e8 100644
--- a/zellij-tile/src/ui_components/text.rs
+++ b/zellij-tile/src/ui_components/text.rs
@@ -1,5 +1,6 @@
use std::ops::Bound;
use std::ops::RangeBounds;
+use zellij_utils::data::StyledText;
#[derive(Debug, Default, Clone)]
pub struct Text {
@@ -9,6 +10,17 @@ pub struct Text {
indices: Vec<Vec<usize>>,
}
+impl From<StyledText> for Text {
+ fn from(styled_text: StyledText) -> Self {
+ Text {
+ text: styled_text.text,
+ selected: false,
+ opaque: false,
+ indices: styled_text.indices,
+ }
+ }
+}
+
impl Text {
pub fn new<S: AsRef<str>>(content: S) -> Self
where
diff --git a/zellij-utils/assets/plugins/about.wasm b/zellij-utils/assets/plugins/about.wasm
index 020b3970..b36db1c4 100755
--- a/zellij-utils/assets/plugins/about.wasm
+++ b/zellij-utils/assets/plugins/about.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm
index 98b6939c..58b5f638 100755
--- a/zellij-utils/assets/plugins/compact-bar.wasm
+++ b/zellij-utils/assets/plugins/compact-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/configuration.wasm b/zellij-utils/assets/plugins/configuration.wasm
index 60ba05c7..cf12f093 100755
--- a/zellij-utils/assets/plugins/configuration.wasm
+++ b/zellij-utils/assets/plugins/configuration.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
index 5dd2d0a6..0877d78a 100755
--- a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
+++ b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/layout-manager.wasm b/zellij-utils/assets/plugins/layout-manager.wasm
index 610b4bcb..d41686c5 100755
--- a/zellij-utils/assets/plugins/layout-manager.wasm
+++ b/zellij-utils/assets/plugins/layout-manager.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/link.wasm b/zellij-utils/assets/plugins/link.wasm
index c04c3791..dc5b14ec 100755
--- a/zellij-utils/assets/plugins/link.wasm
+++ b/zellij-utils/assets/plugins/link.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/mobile.wasm b/zellij-utils/assets/plugins/mobile.wasm
index d31d600e..65ae6f64 100755
--- a/zellij-utils/assets/plugins/mobile.wasm
+++ b/zellij-utils/assets/plugins/mobile.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/multiple-select.wasm b/zellij-utils/assets/plugins/multiple-select.wasm
index 925c5101..9ed820ed 100755
--- a/zellij-utils/assets/plugins/multiple-select.wasm
+++ b/zellij-utils/assets/plugins/multiple-select.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/plugin-manager.wasm b/zellij-utils/assets/plugins/plugin-manager.wasm
index da2bc87e..b761818a 100755
--- a/zellij-utils/assets/plugins/plugin-manager.wasm
+++ b/zellij-utils/assets/plugins/plugin-manager.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/session-manager.wasm b/zellij-utils/assets/plugins/session-manager.wasm
index 20719005..03c8e421 100755
--- a/zellij-utils/assets/plugins/session-manager.wasm
+++ b/zellij-utils/assets/plugins/session-manager.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/share.wasm b/zellij-utils/assets/plugins/share.wasm
index 28403157..53622d68 100755
--- a/zellij-utils/assets/plugins/share.wasm
+++ b/zellij-utils/assets/plugins/share.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/status-bar.wasm b/zellij-utils/assets/plugins/status-bar.wasm
index aaddeeb1..c70dff5d 100755
--- a/zellij-utils/assets/plugins/status-bar.wasm
+++ b/zellij-utils/assets/plugins/status-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/strider.wasm b/zellij-utils/assets/plugins/strider.wasm
index 2ea2f96e..8e0ad467 100755
--- a/zellij-utils/assets/plugins/strider.wasm
+++ b/zellij-utils/assets/plugins/strider.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm
index 7f63366e..2a1bb455 100755
--- a/zellij-utils/assets/plugins/tab-bar.wasm
+++ b/zellij-utils/assets/plugins/tab-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs
index 31325096..a703c9f0 100644
--- a/zellij-utils/assets/prost/api.action.rs
+++ b/zellij-utils/assets/prost/api.action.rs
@@ -302,7 +302,7 @@ pub struct OverrideLayoutPayload {
pub struct Action {
#[prost(enumeration="ActionName", tag="1")]
pub name: i32,
- #[prost(oneof="action::OptionalPayload", tags="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, 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")]
+ #[prost(oneof="action::OptionalPayload", tags="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, 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")]
pub optional_payload: ::core::option::Option<action::OptionalPayload>,
}
/// Nested message and enum types in `Action`.
@@ -422,10 +422,18 @@ pub mod action {
HideFloatingPanesPayload(super::HideFloatingPanesPayload),
#[prost(message, tag="60")]
AreFloatingPanesVisiblePayload(super::AreFloatingPanesVisiblePayload),
+ #[prost(message, tag="61")]
+ SetPaneFrameStylePayload(super::SetPaneFrameStylePayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct SetPaneFrameStylePayload {
+ #[prost(enumeration="super::pane_frame_style::PaneFrameStyle", tag="1")]
+ pub pane_frame_style: i32,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct CliPipePayload {
#[prost(string, optional, tag="1")]
pub name: ::core::option::Option<::prost::alloc::string::String>,
@@ -1125,6 +1133,7 @@ pub enum ActionName {
SetLightTheme = 102,
ToggleTheme = 103,
FocusLastPane = 104,
+ SetPaneFrameStyle = 105,
}
impl ActionName {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -1235,6 +1244,7 @@ impl ActionName {
ActionName::SetLightTheme => "SetLightTheme",
ActionName::ToggleTheme => "ToggleTheme",
ActionName::FocusLastPane => "FocusLastPane",
+ ActionName::SetPaneFrameStyle => "SetPaneFrameStyle",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -1342,6 +1352,7 @@ impl ActionName {
"SetLightTheme" => Some(Self::SetLightTheme),
"ToggleTheme" => Some(Self::ToggleTheme),
"FocusLastPane" => Some(Self::FocusLastPane),
+ "SetPaneFrameStyle" => Some(Self::SetPaneFrameStyle),
_ => None,
}
}
diff --git a/zellij-utils/assets/prost/api.event.rs b/zellij-utils/assets/prost/api.event.rs
index eadb9394..8f050da7 100644
--- a/zellij-utils/assets/prost/api.event.rs
+++ b/zellij-utils/assets/prost/api.event.rs
@@ -9,7 +9,7 @@ pub struct EventNameList {
pub struct Event {
#[prost(enumeration="EventType", tag="1")]
pub name: i32,
- #[prost(oneof="event::Payload", tags="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")]
+ #[prost(oneof="event::Payload", tags="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")]
pub payload: ::core::option::Option<event::Payload>,
}
/// Nested message and enum types in `Event`.
@@ -97,10 +97,42 @@ pub mod event {
HostTerminalThemeChangedPayload(super::HostTerminalThemeChangedPayload),
#[prost(message, tag="41")]
SoftKeyboardVisibilityChangedPayload(super::SoftKeyboardVisibilityChangedPayload),
+ #[prost(message, tag="42")]
+ HintTextPayload(super::HintTextPayload),
+ #[prost(message, tag="43")]
+ ActivePaneScrollPayload(super::ActivePaneScrollPayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct HintTextPayload {
+ #[prost(map="uint32, message", tag="1")]
+ pub hint_text: ::std::collections::HashMap<u32, StyledText>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct ActivePaneScrollPayload {
+ #[prost(uint32, optional, tag="1")]
+ pub position: ::core::option::Option<u32>,
+ #[prost(uint32, optional, tag="2")]
+ pub length: ::core::option::Option<u32>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct StyledText {
+ #[prost(string, tag="1")]
+ pub text: ::prost::alloc::string::String,
+ #[prost(message, repeated, tag="2")]
+ pub indices: ::prost::alloc::vec::Vec<StyledTextIndices>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct StyledTextIndices {
+ #[prost(uint32, repeated, tag="1")]
+ pub indices: ::prost::alloc::vec::Vec<u32>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct HostTerminalThemeChangedPayload {
#[prost(enumeration="HostTerminalThemeIndication", tag="1")]
pub mode: i32,
@@ -669,6 +701,8 @@ pub struct ModeUpdatePayload {
pub web_server_port: ::core::option::Option<u32>,
#[prost(bool, optional, tag="15")]
pub web_server_capability: ::core::option::Option<bool>,
+ #[prost(enumeration="PaneFrameStyle", optional, tag="16")]
+ pub pane_frame_style: ::core::option::Option<i32>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -850,6 +884,8 @@ pub enum EventType {
CommandChanged = 45,
HostTerminalThemeChanged = 46,
SoftKeyboardVisibilityChanged = 47,
+ HintText = 48,
+ ActivePaneScroll = 49,
}
impl EventType {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -905,6 +941,8 @@ impl EventType {
EventType::CommandChanged => "CommandChanged",
EventType::HostTerminalThemeChanged => "HostTerminalThemeChanged",
EventType::SoftKeyboardVisibilityChanged => "SoftKeyboardVisibilityChanged",
+ EventType::HintText => "HintText",
+ EventType::ActivePaneScroll => "ActivePaneScroll",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -957,6 +995,8 @@ impl EventType {
"CommandChanged" => Some(Self::CommandChanged),
"HostTerminalThemeChanged" => Some(Self::HostTerminalThemeChanged),
"SoftKeyboardVisibilityChanged" => Some(Self::SoftKeyboardVisibilityChanged),
+ "HintText" => Some(Self::HintText),
+ "ActivePaneScroll" => Some(Self::ActivePaneScroll),
_ => None,
}
}
@@ -1148,3 +1188,32 @@ impl WebSharing {
}
}
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
+#[repr(i32)]
+pub enum PaneFrameStyle {
+ Full = 0,
+ Titles = 1,
+ None = 2,
+}
+impl PaneFrameStyle {
+ /// String value of the enum field names used in the ProtoBuf definition.
+ ///
+ /// The values are not transformed in any way and thus are considered stable
+ /// (if the ProtoBuf definition does not change) and safe for programmatic use.
+ pub fn as_str_name(&self) -> &'static str {
+ match self {
+ PaneFrameStyle::Full => "Full",
+ PaneFrameStyle::Titles => "Titles",
+ PaneFrameStyle::None => "None",
+ }
+ }
+ /// Creates an enum from field names used in the ProtoBuf definition.
+ pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
+ match value {
+ "Full" => Some(Self::Full),
+ "Titles" => Some(Self::Titles),
+ "None" => Some(Self::None),
+ _ => None,
+ }
+ }
+}
diff --git a/zellij-utils/assets/prost/api.pane_frame_style.rs b/zellij-utils/assets/prost/api.pane_frame_style.rs
new file mode 100644
index 00000000..a39ff161
--- /dev/null
+++ b/zellij-utils/assets/prost/api.pane_frame_style.rs
@@ -0,0 +1,29 @@
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
+#[repr(i32)]
+pub enum PaneFrameStyle {
+ Full = 0,
+ Titles = 1,
+ None = 2,
+}
+impl PaneFrameStyle {
+ /// String value of the enum field names used in the ProtoBuf definition.
+ ///
+ /// The values are not transformed in any way and thus are considered stable
+ /// (if the ProtoBuf definition does not change) and safe for programmatic use.
+ pub fn as_str_name(&self) -> &'static str {
+ match self {
+ PaneFrameStyle::Full => "Full",
+ PaneFrameStyle::Titles => "Titles",
+ PaneFrameStyle::None => "None",
+ }
+ }
+ /// Creates an enum from field names used in the ProtoBuf definition.
+ pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
+ match value {
+ "Full" => Some(Self::Full),
+ "Titles" => Some(Self::Titles),
+ "None" => Some(Self::None),
+ _ => None,
+ }
+ }
+}
diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs
index 4cef814a..676361b2 100644
--- a/zellij-utils/assets/prost/api.plugin_command.rs
+++ b/zellij-utils/assets/prost/api.plugin_command.rs
@@ -3,7 +3,7 @@
pub struct PluginCommand {
#[prost(enumeration="CommandName", tag="1")]
pub name: i32,
- #[prost(oneof="plugin_command::Payload", tags="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, 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, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 167, 168, 169")]
+ #[prost(oneof="plugin_command::Payload", tags="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, 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, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 167, 168, 169, 170, 171")]
pub payload: ::core::option::Option<plugin_command::Payload>,
}
/// Nested message and enum types in `PluginCommand`.
@@ -319,10 +319,26 @@ pub mod plugin_command {
NewTabUnfocusedPayload(super::NewTabUnfocusedPayload),
#[prost(message, tag="169")]
NewTiledPaneInTabPayload(super::NewTiledPaneInTabPayload),
+ #[prost(message, tag="170")]
+ SetPaneFrameStylePayload(super::SetPaneFrameStylePayload),
+ #[prost(message, tag="171")]
+ ToggleFloatingPanesPayload(super::ToggleFloatingPanesPayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct SetPaneFrameStylePayload {
+ #[prost(enumeration="super::pane_frame_style::PaneFrameStyle", tag="1")]
+ pub pane_frame_style: i32,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct ToggleFloatingPanesPayload {
+ #[prost(uint64, optional, tag="1")]
+ pub tab_id: ::core::option::Option<u64>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct NewTabPayload {
#[prost(string, optional, tag="1")]
pub name: ::core::option::Option<::prost::alloc::string::String>,
@@ -2230,6 +2246,9 @@ pub enum CommandName {
NewTiledPaneInTab = 221,
ExitMobileMode = 222,
FocusLastPane = 223,
+ SetPaneFrameStyle = 224,
+ ToggleFloatingPanes = 225,
+ NewPane = 226,
}
impl CommandName {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -2439,6 +2458,9 @@ impl CommandName {
CommandName::NewTiledPaneInTab => "NewTiledPaneInTab",
CommandName::ExitMobileMode => "ExitMobileMode",
CommandName::FocusLastPane => "FocusLastPane",
+ CommandName::SetPaneFrameStyle => "SetPaneFrameStyle",
+ CommandName::ToggleFloatingPanes => "ToggleFloatingPanes",
+ CommandName::NewPane => "NewPane",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -2645,6 +2667,9 @@ impl CommandName {
"NewTiledPaneInTab" => Some(Self::NewTiledPaneInTab),
"ExitMobileMode" => Some(Self::ExitMobileMode),
"FocusLastPane" => Some(Self::FocusLastPane),
+ "SetPaneFrameStyle" => Some(Self::SetPaneFrameStyle),
+ "ToggleFloatingPanes" => Some(Self::ToggleFloatingPanes),
+ "NewPane" => Some(Self::NewPane),
_ => None,
}
}
diff --git a/zellij-utils/assets/prost/generated_plugin_api.rs b/zellij-utils/assets/prost/generated_plugin_api.rs
index ee70c470..fcea0e0a 100644
--- a/zellij-utils/assets/prost/generated_plugin_api.rs
+++ b/zellij-utils/assets/prost/generated_plugin_api.rs
@@ -20,6 +20,9 @@ pub mod api {
pub mod message {
include!("api.message.rs");
}
+ pub mod pane_frame_style {
+ include!("api.pane_frame_style.rs");
+ }
pub mod pipe_message {
include!("api.pipe_message.rs");
}
diff --git a/zellij-utils/assets/prost_ipc/client_server_contract.rs b/zellij-utils/assets/prost_ipc/client_server_contract.rs
index e08496e7..3dada2ac 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, 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, 135, 136, 137, 138, 139, 140, 141")]
+ #[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, 135, 136, 137, 138, 139, 140, 141, 142")]
pub action_type: ::core::option::Option<action::ActionType>,
}
/// Nested message and enum types in `Action`.
@@ -411,6 +411,8 @@ pub mod action {
ToggleMobileMode(super::ToggleMobileModeAction),
#[prost(message, tag="141")]
FocusLastPane(super::FocusLastPaneAction),
+ #[prost(message, tag="142")]
+ SetPaneFrameStyle(super::SetPaneFrameStyleAction),
}
}
// Action message definitions (all 92 variants)
@@ -500,6 +502,12 @@ pub struct TogglePaneFramesAction {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct SetPaneFrameStyleAction {
+ #[prost(string, tag="1")]
+ pub style: ::prost::alloc::string::String,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ToggleActiveSyncTabAction {
}
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -1971,6 +1979,8 @@ pub struct Options {
pub mobile_threshold_cols: ::core::option::Option<u32>,
#[prost(uint32, optional, tag="50")]
pub mobile_threshold_rows: ::core::option::Option<u32>,
+ #[prost(string, optional, tag="51")]
+ pub pane_frame_style: ::core::option::Option<::prost::alloc::string::String>,
}
/// Pane-targeting action messages
#[allow(clippy::derive_partial_eq_without_eq)]
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index a00c4d05..ee2b6da1 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -2,7 +2,10 @@ use crate::data::{Direction, InputMode, Resize, UnblockCondition};
use crate::setup::Setup;
use crate::{
consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV},
- input::{layout::PluginUserConfiguration, options::Options},
+ input::{
+ layout::PluginUserConfiguration,
+ options::{Options, PaneFrameStyle},
+ },
};
use clap::{ArgEnum, Args, Parser, Subcommand};
use serde::{Deserialize, Serialize};
@@ -884,6 +887,10 @@ pub enum CliAction {
},
/// Toggle frames around panes in the UI
TogglePaneFrames,
+ SetPaneFrameStyle {
+ #[clap(arg_enum, value_parser)]
+ style: PaneFrameStyle,
+ },
/// Toggle between sending text commands to all panes on the current tab and normal mode.
ToggleActiveSyncTab {
/// Target a specific tab by ID
@@ -934,6 +941,16 @@ pub enum CliAction {
)]
close_replaced_pane: bool,
+ /// The pane to replace when opening in place, eg. terminal_1, plugin_2 or 3 (only
+ /// effective with --in-place; defaults to the focused pane)
+ #[clap(
+ long,
+ value_parser,
+ requires("in-place"),
+ conflicts_with("near-current-pane")
+ )]
+ pane_id: Option<String>,
+
/// Name of the new pane
#[clap(short, long, value_parser)]
name: Option<String>,
diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto
index 718cc279..6a7809c8 100644
--- a/zellij-utils/src/client_server_contract/common_types.proto
+++ b/zellij-utils/src/client_server_contract/common_types.proto
@@ -279,6 +279,7 @@ message Action {
ToggleThemeAction toggle_theme = 139;
ToggleMobileModeAction toggle_mobile_mode = 140;
FocusLastPaneAction focus_last_pane = 141;
+ SetPaneFrameStyleAction set_pane_frame_style = 142;
}
}
@@ -307,6 +308,9 @@ message HalfPageScrollUpAction {}
message HalfPageScrollDownAction {}
message ToggleFocusFullscreenAction {}
message TogglePaneFramesAction {}
+message SetPaneFrameStyleAction {
+ string style = 1;
+}
message ToggleActiveSyncTabAction {}
message TogglePaneEmbedOrFloatingAction {}
message ToggleFloatingPanesAction {}
@@ -1183,6 +1187,7 @@ message Options {
optional MobileLayout mobile_layout = 48;
optional uint32 mobile_threshold_cols = 49;
optional uint32 mobile_threshold_rows = 50;
+ optional string pane_frame_style = 51;
}
enum OnForceClose {
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index c11f777f..758e2ab3 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -5,6 +5,7 @@ use crate::input::keybinds::Keybinds;
use crate::input::layout::{
Layout, PercentOrFixed, Run, RunPlugin, RunPluginLocation, RunPluginOrAlias,
};
+pub use crate::input::options::PaneFrameStyle;
use crate::pane_size::{PaneGeom, Size};
use crate::position::Position;
use crate::shared::{colors as default_colors, eightbit_to_rgb};
@@ -938,6 +939,12 @@ impl From<Metadata> for FileMetadata {
}
}
+#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+pub struct StyledText {
+ pub text: String,
+ pub indices: Vec<Vec<usize>>,
+}
+
/// These events can be subscribed to with subscribe method exported by `zellij-tile`.
/// Once subscribed to, they will trigger the `update` method of the `ZellijPlugin` trait.
#[derive(Debug, Clone, PartialEq, EnumDiscriminants, Display, Serialize, Deserialize)]
@@ -1031,6 +1038,8 @@ pub enum Event {
/// The host terminal indicated its color palette theme mode (CSI 2031 / DSR 997).
HostTerminalThemeChanged(HostTerminalThemeMode),
SoftKeyboardVisibilityChanged(bool),
+ HintText(BTreeMap<usize, StyledText>),
+ ActivePaneScroll(Option<(usize, usize)>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@@ -1741,6 +1750,7 @@ pub struct ModeInfo {
pub web_server_ip: Option<IpAddr>,
pub web_server_port: Option<u16>,
pub web_server_capability: Option<bool>,
+ pub pane_frame_style: Option<PaneFrameStyle>,
}
impl ModeInfo {
@@ -3378,6 +3388,10 @@ pub enum PluginCommand {
NewTiledPaneInTab {
tab_position: usize,
},
+ ToggleFloatingPanes {
+ tab_id: Option<u64>,
+ },
+ NewPane,
GoToNextTab,
GoToPreviousTab,
Resize(Resize),
@@ -3403,6 +3417,7 @@ pub enum PluginCommand {
PageScrollDown,
ToggleFocusFullscreen,
TogglePaneFrames,
+ SetPaneFrameStyle(PaneFrameStyle),
TogglePaneEmbedOrEject,
UndoRenamePane,
CloseFocus,
diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs
index c9e8e25f..8ffe0907 100644
--- a/zellij-utils/src/errors.rs
+++ b/zellij-utils/src/errors.rs
@@ -282,6 +282,7 @@ pub enum ScreenContext {
ToggleActiveSyncTab,
ToggleActiveTerminalFullscreen,
TogglePaneFrames,
+ SetPaneFrameStyle,
SetSelectable,
ShowPluginCursor,
SetInvisibleBorders,
@@ -466,6 +467,7 @@ pub enum ScreenContext {
MoveTabWithTabId,
PluginSubscribedToAnsiPaneContents,
UpdateBackgroundPluginSubscriptions,
+ ClearHintTextCache,
BroadcastModeUpdate,
EnterMobileMode,
ExitMobileMode,
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index 40158b8b..757e99e4 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -14,7 +14,7 @@ use crate::data::{FloatingPaneCoordinates, InputMode};
use crate::home::{find_default_config_dir, get_layout_dir};
use crate::input::config::{Config, ConfigError, KdlError};
use crate::input::mouse::MouseEvent;
-use crate::input::options::OnForceClose;
+use crate::input::options::{OnForceClose, PaneFrameStyle};
use miette::{NamedSource, Report};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
@@ -218,6 +218,7 @@ pub enum Action {
ToggleFocusFullscreen,
/// Toggle frames around panes in the UI
TogglePaneFrames,
+ SetPaneFrameStyle(PaneFrameStyle),
/// Toggle between sending text commands to all panes on the current tab and normal mode.
ToggleActiveSyncTab,
/// Open a new pane in the specified direction (relative to focus).
@@ -1007,6 +1008,7 @@ impl Action {
None => Ok(vec![Action::ToggleFocusFullscreen]),
},
CliAction::TogglePaneFrames => Ok(vec![Action::TogglePaneFrames]),
+ CliAction::SetPaneFrameStyle { style } => Ok(vec![Action::SetPaneFrameStyle(style)]),
CliAction::ToggleActiveSyncTab { tab_id } => match tab_id {
Some(id) => Ok(vec![Action::ToggleActiveSyncTabByTabId { id: id as u64 }]),
None => Ok(vec![Action::ToggleActiveSyncTab]),
@@ -1019,6 +1021,7 @@ impl Action {
floating,
in_place,
close_replaced_pane,
+ pane_id,
name,
close_on_exit,
start_suspended,
@@ -1039,6 +1042,18 @@ impl Action {
borderless,
tab_id,
} => {
+ let pane_id_to_replace = match pane_id {
+ Some(pane_id_str) => match PaneId::from_str(&pane_id_str) {
+ Ok(parsed_pane_id) => Some(parsed_pane_id),
+ Err(_e) => {
+ return Err(format!(
+ "Malformed pane id: {}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)",
+ pane_id_str
+ ))
+ },
+ },
+ None => None,
+ };
let current_dir = get_current_dir();
// cwd should only be specified in a plugin alias if it was explicitly given to us,
// otherwise the current_dir might override a cwd defined in the alias itself
@@ -1087,7 +1102,7 @@ impl Action {
))
} else if in_place {
NewPanePlacement::InPlace {
- pane_id_to_replace: None,
+ pane_id_to_replace,
close_replaced_pane,
borderless,
}
@@ -1197,7 +1212,7 @@ impl Action {
command: Some(run_command_action),
pane_name: name,
near_current_pane,
- pane_id_to_replace: None, // TODO: support this
+ pane_id_to_replace,
close_replaced_pane,
tab_id,
}])
@@ -1234,7 +1249,7 @@ impl Action {
command: None,
pane_name: name,
near_current_pane,
- pane_id_to_replace: None, // TODO: support this
+ pane_id_to_replace,
close_replaced_pane,
tab_id,
}])
@@ -3575,6 +3590,7 @@ mod tests {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3617,6 +3633,7 @@ mod tests {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3650,6 +3667,87 @@ mod tests {
}
#[test]
+ fn test_new_in_place_pane_with_pane_id_to_replace() {
+ let cli_action = CliAction::NewPane {
+ direction: None,
+ command: vec![],
+ plugin: None,
+ cwd: None,
+ floating: false,
+ in_place: true,
+ close_replaced_pane: true,
+ pane_id: Some("terminal_4".to_string()),
+ name: None,
+ close_on_exit: false,
+ start_suspended: false,
+ configuration: None,
+ skip_plugin_cache: false,
+ x: None,
+ y: None,
+ width: None,
+ height: None,
+ pinned: None,
+ stacked: false,
+ blocking: false,
+ block_until_exit_success: false,
+ block_until_exit_failure: false,
+ block_until_exit: false,
+ unblock_condition: None,
+ near_current_pane: false,
+ borderless: None,
+ 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::NewInPlacePane {
+ pane_id_to_replace, ..
+ } => {
+ assert_eq!(*pane_id_to_replace, Some(PaneId::Terminal(4)));
+ },
+ _ => panic!("Expected NewInPlacePane action"),
+ }
+ }
+
+ #[test]
+ fn test_new_in_place_pane_with_malformed_pane_id() {
+ let cli_action = CliAction::NewPane {
+ direction: None,
+ command: vec![],
+ plugin: None,
+ cwd: None,
+ floating: false,
+ in_place: true,
+ close_replaced_pane: false,
+ pane_id: Some("not_a_pane".to_string()),
+ name: None,
+ close_on_exit: false,
+ start_suspended: false,
+ configuration: None,
+ skip_plugin_cache: false,
+ x: None,
+ y: None,
+ width: None,
+ height: None,
+ pinned: None,
+ stacked: false,
+ blocking: false,
+ block_until_exit_success: false,
+ block_until_exit_failure: false,
+ block_until_exit: false,
+ unblock_condition: None,
+ near_current_pane: false,
+ borderless: None,
+ tab_id: None,
+ };
+ let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None);
+ assert!(result.is_err());
+ assert!(result.unwrap_err().contains("Malformed pane id"));
+ }
+
+ #[test]
fn test_new_pane_floating_with_tab_id() {
let cli_action = CliAction::NewPane {
direction: None,
@@ -3659,6 +3757,7 @@ mod tests {
floating: true,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3701,6 +3800,7 @@ mod tests {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3743,6 +3843,7 @@ mod tests {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3847,6 +3948,7 @@ mod tests {
floating: false,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
@@ -3889,6 +3991,7 @@ mod tests {
floating: true,
in_place: false,
close_replaced_pane: false,
+ pane_id: None,
name: None,
close_on_exit: false,
start_suspended: false,
diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs
index c103e580..0934287e 100644
--- a/zellij-utils/src/input/mod.rs
+++ b/zellij-utils/src/input/mod.rs
@@ -54,6 +54,7 @@ mod not_wasm {
web_server_ip: None,
web_server_port: None,
web_server_capability: None,
+ pane_frame_style: None,
}
}
diff --git a/zellij-utils/src/input/options.rs b/zellij-utils/src/input/options.rs
index 8f91cb47..a1cfdd67 100644
--- a/zellij-utils/src/input/options.rs
+++ b/zellij-utils/src/input/options.rs
@@ -93,6 +93,56 @@ impl FromStr for OnForceClose {
}
}
+#[derive(ArgEnum, Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[serde(rename_all = "lowercase")]
+pub enum PaneFrameStyle {
+ Full,
+ Titles,
+ None,
+}
+
+impl Default for PaneFrameStyle {
+ fn default() -> Self {
+ PaneFrameStyle::Titles
+ }
+}
+
+impl PaneFrameStyle {
+ pub fn draws_full_frames(&self) -> bool {
+ matches!(self, PaneFrameStyle::Full)
+ }
+
+ pub fn draws_titles(&self) -> bool {
+ matches!(self, PaneFrameStyle::Titles)
+ }
+
+ pub fn from_options(options: &Options) -> Self {
+ if options.pane_frames == Some(false) {
+ return PaneFrameStyle::None;
+ }
+ match options.pane_frame_style {
+ Some(PaneFrameStyle::Full) => PaneFrameStyle::Full,
+ _ => PaneFrameStyle::Titles,
+ }
+ }
+}
+
+impl FromStr for PaneFrameStyle {
+ type Err = Box<dyn std::error::Error>;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s.trim().to_lowercase().as_str() {
+ "full" => Ok(PaneFrameStyle::Full),
+ "titles" => Ok(PaneFrameStyle::Titles),
+ "none" => Ok(PaneFrameStyle::None),
+ e => Err(format!(
+ "Unknown pane frame style: '{}' (expected 'full', 'titles' or 'none')",
+ e
+ )
+ .into()),
+ }
+ }
+}
+
#[derive(Clone, Default, Debug, PartialEq, Deserialize, Serialize, Args)]
/// Options that can be set either through the config file,
/// or cli flags - cli flags should take precedence over the config file
@@ -146,6 +196,9 @@ pub struct Options {
#[serde(default)]
/// Set display of the pane frames (true or false)
pub pane_frames: Option<bool>,
+ #[clap(long, arg_enum, hide_possible_values = true, value_parser)]
+ #[serde(default)]
+ pub pane_frame_style: Option<PaneFrameStyle>,
#[clap(long, value_parser)]
#[serde(default)]
/// Mirror session when multiple users are connected (true or false)
@@ -393,6 +446,7 @@ impl Options {
pub fn merge(&self, other: Options) -> Options {
let mouse_mode = other.mouse_mode.or(self.mouse_mode);
let pane_frames = other.pane_frames.or(self.pane_frames);
+ let pane_frame_style = other.pane_frame_style.or(self.pane_frame_style);
let auto_layout = other.auto_layout.or(self.auto_layout);
let mirror_session = other.mirror_session.or(self.mirror_session);
let simplified_ui = other.simplified_ui.or(self.simplified_ui);
@@ -475,6 +529,7 @@ impl Options {
theme_dir,
mouse_mode,
pane_frames,
+ pane_frame_style,
mirror_session,
on_force_close,
scroll_buffer_size,
@@ -534,6 +589,7 @@ impl Options {
let simplified_ui = merge_bool(other.simplified_ui, self.simplified_ui);
let mouse_mode = merge_bool(other.mouse_mode, self.mouse_mode);
let pane_frames = merge_bool(other.pane_frames, self.pane_frames);
+ let pane_frame_style = other.pane_frame_style.or(self.pane_frame_style);
let auto_layout = merge_bool(other.auto_layout, self.auto_layout);
let mirror_session = merge_bool(other.mirror_session, self.mirror_session);
let session_serialization =
@@ -616,6 +672,7 @@ impl Options {
theme_dir,
mouse_mode,
pane_frames,
+ pane_frame_style,
mirror_session,
on_force_close,
scroll_buffer_size,
@@ -675,6 +732,27 @@ mod tests {
const TALL_NARROW: (usize, usize) = (40, 200);
const LARGE: (usize, usize) = (200, 200);
+ #[test]
+ fn pane_frame_style_from_str_accepts_all_variants() {
+ assert_eq!(
+ "full".parse::<PaneFrameStyle>().unwrap(),
+ PaneFrameStyle::Full
+ );
+ assert_eq!(
+ "titles".parse::<PaneFrameStyle>().unwrap(),
+ PaneFrameStyle::Titles
+ );
+ assert_eq!(
+ "none".parse::<PaneFrameStyle>().unwrap(),
+ PaneFrameStyle::None
+ );
+ assert_eq!(
+ "NONE".parse::<PaneFrameStyle>().unwrap(),
+ PaneFrameStyle::None
+ );
+ assert!("bogus".parse::<PaneFrameStyle>().is_err());
+ }
+
fn route(
layout: MobileLayoutConfiguration,
is_web: bool,
diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs
index c4941676..f1ad8118 100644
--- a/zellij-utils/src/ipc/protobuf_conversion.rs
+++ b/zellij-utils/src/ipc/protobuf_conversion.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
use crate::{
client_server_contract::client_server_contract::{
client_to_server_msg, server_to_client_msg, ActionMsg, AttachClientMsg,
@@ -766,6 +768,11 @@ impl From<crate::input::options::Options>
}),
mobile_threshold_cols: options.mobile_threshold_cols.map(|v| v as u32),
mobile_threshold_rows: options.mobile_threshold_rows.map(|v| v as u32),
+ pane_frame_style: options.pane_frame_style.map(|s| match s {
+ crate::input::options::PaneFrameStyle::Full => "full".to_owned(),
+ crate::input::options::PaneFrameStyle::Titles => "titles".to_owned(),
+ crate::input::options::PaneFrameStyle::None => "none".to_owned(),
+ }),
}
}
}
@@ -798,6 +805,12 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Options>
theme_dir: options.theme_dir.map(std::path::PathBuf::from),
mouse_mode: options.mouse_mode,
pane_frames: options.pane_frames,
+ pane_frame_style: options.pane_frame_style.as_deref().and_then(|s| match s {
+ "full" => Some(crate::input::options::PaneFrameStyle::Full),
+ "titles" => Some(crate::input::options::PaneFrameStyle::Titles),
+ "none" => Some(crate::input::options::PaneFrameStyle::None),
+ _ => None,
+ }),
mirror_session: options.mirror_session,
on_force_close: options
.on_force_close
@@ -999,6 +1012,7 @@ impl From<crate::input::actions::Action>
SetLightThemeAction,
SetPaneBorderlessAction,
SetPaneColorAction,
+ SetPaneFrameStyleAction,
ShowFloatingPanesAction,
SkipConfirmAction,
StackPanesAction,
@@ -1177,6 +1191,16 @@ impl From<crate::input::actions::Action>
crate::input::actions::Action::TogglePaneFrames => {
ActionType::TogglePaneFrames(TogglePaneFramesAction {})
},
+ crate::input::actions::Action::SetPaneFrameStyle(style) => {
+ let style = match style {
+ crate::input::options::PaneFrameStyle::Full => "full",
+ crate::input::options::PaneFrameStyle::Titles => "titles",
+ crate::input::options::PaneFrameStyle::None => "none",
+ };
+ ActionType::SetPaneFrameStyle(SetPaneFrameStyleAction {
+ style: style.to_owned(),
+ })
+ },
crate::input::actions::Action::ToggleActiveSyncTab => {
ActionType::ToggleActiveSyncTab(ToggleActiveSyncTabAction {})
},
@@ -2037,6 +2061,13 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action>
Ok(crate::input::actions::Action::ToggleFocusFullscreen)
},
ActionType::TogglePaneFrames(_) => Ok(crate::input::actions::Action::TogglePaneFrames),
+ ActionType::SetPaneFrameStyle(set_pane_frame_style_action) => {
+ let style = crate::input::options::PaneFrameStyle::from_str(
+ &set_pane_frame_style_action.style,
+ )
+ .map_err(|e| anyhow!("{}", e))?;
+ Ok(crate::input::actions::Action::SetPaneFrameStyle(style))
+ },
ActionType::ToggleActiveSyncTab(_) => {
Ok(crate::input::actions::Action::ToggleActiveSyncTab)
},
diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
index 280805ab..8ea01a5f 100644
--- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs
+++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
@@ -13,7 +13,9 @@ use crate::input::layout::{
TiledPaneLayout,
};
use crate::input::mouse::{MouseEvent, MouseEventType};
-use crate::input::options::{Clipboard, MobileLayoutConfiguration, OnForceClose, Options};
+use crate::input::options::{
+ Clipboard, MobileLayoutConfiguration, OnForceClose, Options, PaneFrameStyle,
+};
use crate::ipc::{
ClientToServerMsg, ColorRegister, ExitReason, PaneReference, PixelDimensions, ResizeCause,
ServerToClientMsg,
@@ -444,6 +446,7 @@ fn test_client_messages() {
theme_dir: Some(PathBuf::from("theme_dir")),
mouse_mode: Some(true),
pane_frames: Some(true),
+ pane_frame_style: Some(PaneFrameStyle::Full),
mirror_session: Some(true),
on_force_close: Some(OnForceClose::Quit),
scroll_buffer_size: Some(100000),
@@ -3536,6 +3539,24 @@ fn test_client_messages() {
client_id: Some(100),
is_cli_client: true,
});
+ test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::SetPaneFrameStyle(PaneFrameStyle::Full),
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::SetPaneFrameStyle(PaneFrameStyle::Titles),
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::SetPaneFrameStyle(PaneFrameStyle::None),
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
test_client_roundtrip!(ClientToServerMsg::ForwardedReplyFromHost {
token: 0,
reply_bytes: vec![],
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 14695f68..42ce65c5 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -12,7 +12,7 @@ use crate::input::keybinds::Keybinds;
use crate::input::layout::{
Layout, PercentOrFixed, PluginUserConfiguration, RunPlugin, RunPluginOrAlias, TabLayoutInfo,
};
-use crate::input::options::{Clipboard, OnForceClose, Options};
+use crate::input::options::{Clipboard, OnForceClose, Options, PaneFrameStyle};
use crate::input::permission::{GrantedPermission, PermissionCache};
use crate::input::plugins::PluginAliases;
use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
@@ -455,6 +455,16 @@ impl Action {
) -> Result<Self, ConfigError> {
match action_name {
"WriteChars" => Ok(Action::WriteChars { chars: string }),
+ "SetPaneFrameStyle" => {
+ let style = PaneFrameStyle::from_str(string.as_str()).map_err(|e| {
+ ConfigError::new_kdl_error(
+ format!("{}", e),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::SetPaneFrameStyle(style))
+ },
"SwitchToMode" => match InputMode::from_str(string.as_str()) {
Ok(input_mode) => Ok(Action::SwitchToMode { input_mode }),
Err(_e) => {
@@ -734,6 +744,16 @@ impl Action {
Action::HalfPageScrollDown => Some(KdlNode::new("HalfPageScrollDown")),
Action::ToggleFocusFullscreen => Some(KdlNode::new("ToggleFocusFullscreen")),
Action::TogglePaneFrames => Some(KdlNode::new("TogglePaneFrames")),
+ Action::SetPaneFrameStyle(style) => {
+ let mut node = KdlNode::new("SetPaneFrameStyle");
+ let style = match style {
+ PaneFrameStyle::Full => "full",
+ PaneFrameStyle::Titles => "titles",
+ PaneFrameStyle::None => "none",
+ };
+ node.push(style);
+ Some(node)
+ },
Action::ToggleActiveSyncTab => Some(KdlNode::new("ToggleActiveSyncTab")),
Action::NewPane {
direction,
@@ -1652,6 +1672,11 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
action_arguments,
kdl_action
),
+ "SetPaneFrameStyle" => parse_kdl_action_char_or_string_arguments!(
+ action_name,
+ action_arguments,
+ kdl_action
+ ),
"Search" => parse_kdl_action_char_or_string_arguments!(
action_name,
action_arguments,
@@ -2683,6 +2708,16 @@ impl Options {
.map(|(string, _entry)| PathBuf::from(string));
let pane_frames =
kdl_property_first_arg_as_bool_or_error!(kdl_options, "pane_frames").map(|(v, _)| v);
+ let pane_frame_style =
+ match kdl_property_first_arg_as_string_or_error!(kdl_options, "pane_frame_style") {
+ Some((string, entry)) => Some(PaneFrameStyle::from_str(string).map_err(|_| {
+ kdl_parsing_error!(
+ format!("Invalid value for pane_frame_style: '{}'", string),
+ entry
+ )
+ })?),
+ None => None,
+ };
let auto_layout =
kdl_property_first_arg_as_bool_or_error!(kdl_options, "auto_layout").map(|(v, _)| v);
let theme = kdl_property_first_arg_as_string_or_error!(kdl_options, "theme")
@@ -2881,6 +2916,7 @@ impl Options {
theme_dir,
mouse_mode,
pane_frames,
+ pane_frame_style,
mirror_session,
on_force_close,
scroll_buffer_size,
@@ -3295,6 +3331,44 @@ impl Options {
None
}
}
+ fn pane_frame_style_to_kdl(&self, add_comments: bool) -> Option<KdlNode> {
+ let comment_text = format!(
+ "{}\n{}\n{}\n{}\n{}\n{}",
+ " ",
+ "// Set the pane frame style when pane_frames is enabled",
+ "// Options:",
+ "// - full",
+ "// - titles (default)",
+ "// ",
+ );
+
+ let style_as_str = |style: &PaneFrameStyle| -> &'static str {
+ match style {
+ PaneFrameStyle::Full => "full",
+ PaneFrameStyle::Titles => "titles",
+ PaneFrameStyle::None => "none",
+ }
+ };
+
+ let create_node = |node_value: &str| -> KdlNode {
+ let mut node = KdlNode::new("pane_frame_style");
+ node.push(node_value.to_owned());
+ node
+ };
+ if let Some(pane_frame_style) = &self.pane_frame_style {
+ let mut node = create_node(style_as_str(pane_frame_style));
+ if add_comments {
+ node.set_leading(format!("{}\n", comment_text));
+ }
+ Some(node)
+ } else if add_comments {
+ let mut node = create_node("titles");
+ node.set_leading(format!("{}\n// ", comment_text));
+ Some(node)
+ } else {
+ None
+ }
+ }
fn mirror_session_to_kdl(&self, add_comments: bool) -> Option<KdlNode> {
let comment_text = format!(
"{}\n{}\n{}\n{}\n{}\n{}\n{}",
@@ -4419,6 +4493,9 @@ impl Options {
if let Some(pane_frames) = self.pane_frames_to_kdl(add_comments) {
nodes.push(pane_frames);
}
+ if let Some(pane_frame_style) = self.pane_frame_style_to_kdl(add_comments) {
+ nodes.push(pane_frame_style);
+ }
if let Some(mirror_session) = self.mirror_session_to_kdl(add_comments) {
nodes.push(mirror_session);
}
diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap
index 5dbede33..2d0063ce 100644
--- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap
+++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap
@@ -359,6 +359,13 @@ web_client {
//
// pane_frames false
+// Set the pane frame style when pane_frames is enabled
+// Options:
+// - full
+// - titles (default)
+//
+// pane_frame_style "titles"
+
// When attaching to an existing session with other users,
// should the session be mirrored (true)
// or should each user have their own cursor (false)
diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap
index 347a2074..a69641fe 100644
--- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap
+++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap
@@ -77,6 +77,13 @@ mouse_mode false
//
pane_frames false
+// Set the pane frame style when pane_frames is enabled
+// Options:
+// - full
+// - titles (default)
+//
+// pane_frame_style "titles"
+
// When attaching to an existing session with other users,
// should the session be mirrored (true)
// or should each user have their own cursor (false)
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto
index 68c859b8..f9370961 100644
--- a/zellij-utils/src/plugin_api/action.proto
+++ b/zellij-utils/src/plugin_api/action.proto
@@ -2,6 +2,7 @@ syntax = "proto3";
import "input_mode.proto";
import "resize.proto";
+import "pane_frame_style.proto";
package api.action;
@@ -245,9 +246,14 @@ message Action {
ShowFloatingPanesPayload show_floating_panes_payload = 58;
HideFloatingPanesPayload hide_floating_panes_payload = 59;
AreFloatingPanesVisiblePayload are_floating_panes_visible_payload = 60;
+ SetPaneFrameStylePayload set_pane_frame_style_payload = 61;
}
}
+message SetPaneFrameStylePayload {
+ pane_frame_style.PaneFrameStyle pane_frame_style = 1;
+}
+
message CliPipePayload {
optional string name = 1;
string payload = 2;
@@ -494,6 +500,7 @@ enum ActionName {
SetLightTheme = 102;
ToggleTheme = 103;
FocusLastPane = 104;
+ SetPaneFrameStyle = 105;
}
message Position {
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index f4e35d84..209bff3f 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -58,6 +58,7 @@ pub use super::generated_api::api::{
ScrollAtPayload,
SearchDirection as ProtobufSearchDirection,
SearchOption as ProtobufSearchOption,
+ SetPaneFrameStylePayload,
ShowFloatingPanesPayload,
SplitDirection as ProtobufSplitDirection,
SplitSize as ProtobufSplitSize,
@@ -74,6 +75,7 @@ pub use super::generated_api::api::{
WritePayload,
},
input_mode::InputMode as ProtobufInputMode,
+ pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle,
resize::{Resize as ProtobufResize, ResizeDirection as ProtobufResizeDirection},
};
use crate::data::{
@@ -300,6 +302,17 @@ impl TryFrom<ProtobufAction> for Action {
Some(_) => Err("TogglePaneFrames should not have a payload"),
None => Ok(Action::TogglePaneFrames),
},
+ Some(ProtobufActionName::SetPaneFrameStyle) => match protobuf_action.optional_payload {
+ Some(OptionalPayload::SetPaneFrameStylePayload(payload)) => {
+ match ProtobufPaneFrameStyle::from_i32(payload.pane_frame_style) {
+ Some(protobuf_pane_frame_style) => Ok(Action::SetPaneFrameStyle(
+ protobuf_pane_frame_style.try_into()?,
+ )),
+ None => Err("Malformed payload for Action::SetPaneFrameStyle"),
+ }
+ },
+ _ => Err("Wrong payload for Action::SetPaneFrameStyle"),
+ },
Some(ProtobufActionName::ToggleActiveSyncTab) => {
match protobuf_action.optional_payload {
Some(_) => Err("ToggleActiveSyncTab should not have a payload"),
@@ -1301,6 +1314,15 @@ impl TryFrom<Action> for ProtobufAction {
name: ProtobufActionName::TogglePaneFrames as i32,
optional_payload: None,
}),
+ Action::SetPaneFrameStyle(pane_frame_style) => Ok(ProtobufAction {
+ name: ProtobufActionName::SetPaneFrameStyle as i32,
+ optional_payload: Some(OptionalPayload::SetPaneFrameStylePayload(
+ SetPaneFrameStylePayload {
+ pane_frame_style: ProtobufPaneFrameStyle::try_from(pane_frame_style)?
+ as i32,
+ },
+ )),
+ }),
Action::ToggleActiveSyncTab => Ok(ProtobufAction {
name: ProtobufActionName::ToggleActiveSyncTab as i32,
optional_payload: None,
@@ -3235,3 +3257,23 @@ impl TryFrom<SwapFloatingLayout> for ProtobufSwapFloatingLayout {
})
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::input::options::PaneFrameStyle;
+
+ #[test]
+ fn set_pane_frame_style_action_protobuf_round_trip() {
+ for style in [
+ PaneFrameStyle::Full,
+ PaneFrameStyle::Titles,
+ PaneFrameStyle::None,
+ ] {
+ let original = Action::SetPaneFrameStyle(style);
+ let protobuf: ProtobufAction = original.clone().try_into().expect("encode");
+ let decoded: Action = protobuf.try_into().expect("decode");
+ assert_eq!(original, decoded);
+ }
+ }
+}
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto
index 2567c657..d3148edf 100644
--- a/zellij-utils/src/plugin_api/event.proto
+++ b/zellij-utils/src/plugin_api/event.proto
@@ -70,6 +70,8 @@ enum EventType {
CommandChanged = 45;
HostTerminalThemeChanged = 46;
SoftKeyboardVisibilityChanged = 47;
+ HintText = 48;
+ ActivePaneScroll = 49;
}
message EventNameList {
@@ -119,9 +121,29 @@ message Event {
CommandChangedPayload command_changed_payload = 39;
HostTerminalThemeChangedPayload host_terminal_theme_changed_payload = 40;
SoftKeyboardVisibilityChangedPayload soft_keyboard_visibility_changed_payload = 41;
+ HintTextPayload hint_text_payload = 42;
+ ActivePaneScrollPayload active_pane_scroll_payload = 43;
}
}
+message HintTextPayload {
+ map<uint32, StyledText> hint_text = 1;
+}
+
+message ActivePaneScrollPayload {
+ optional uint32 position = 1;
+ optional uint32 length = 2;
+}
+
+message StyledText {
+ string text = 1;
+ repeated StyledTextIndices indices = 2;
+}
+
+message StyledTextIndices {
+ repeated uint32 indices = 1;
+}
+
message HostTerminalThemeChangedPayload {
HostTerminalThemeIndication mode = 1;
}
@@ -488,6 +510,7 @@ message ModeUpdatePayload {
optional string web_server_ip = 13;
optional uint32 web_server_port = 14;
optional bool web_server_capability = 15;
+ optional PaneFrameStyle pane_frame_style = 16;
}
enum WebSharing {
@@ -496,6 +519,12 @@ enum WebSharing {
Disabled = 2;
}
+enum PaneFrameStyle {
+ Full = 0;
+ Titles = 1;
+ None = 2;
+}
+
message InputModeKeybinds {
input_mode.InputMode mode = 1;
repeated KeyBind key_bind = 2;
diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs
index 5ba106d0..190552d4 100644
--- a/zellij-utils/src/plugin_api/event.rs
+++ b/zellij-utils/src/plugin_api/event.rs
@@ -4,6 +4,7 @@ pub use super::generated_api::api::{
event::Payload as ProtobufEventPayload,
layout_parsing_error::ErrorType as ProtobufLayoutParsingErrorType,
pane_scrollback_response, ActionCompletePayload as ProtobufActionCompletePayload,
+ ActivePaneScrollPayload as ProtobufActivePaneScrollPayload,
AvailableLayoutInfoPayload as ProtobufAvailableLayoutInfoPayload,
ClientInfo as ProtobufClientInfo, ClientPaneHistory as ProtobufClientPaneHistory,
ClientTabHistory as ProtobufClientTabHistory,
@@ -11,6 +12,7 @@ pub use super::generated_api::api::{
CopyDestination as ProtobufCopyDestination, CwdChangedPayload as ProtobufCwdChangedPayload,
Event as ProtobufEvent, EventNameList as ProtobufEventNameList,
EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
+ HintTextPayload as ProtobufHintTextPayload,
HostTerminalThemeChangedPayload as ProtobufHostTerminalThemeChangedPayload,
HostTerminalThemeIndication as ProtobufHostTerminalThemeIndication,
InputModeKeybinds as ProtobufInputModeKeybinds, KdlError as ProtobufKdlError,
@@ -19,14 +21,16 @@ pub use super::generated_api::api::{
LayoutParsingError as ProtobufLayoutParsingError,
LayoutWithError as ProtobufLayoutWithError, ModeUpdatePayload as ProtobufModeUpdatePayload,
PaneContents as ProtobufPaneContents, PaneContentsEntry as ProtobufPaneContentsEntry,
- PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo,
- PaneManifest as ProtobufPaneManifest, PaneMetadata as ProtobufPaneMetadata,
+ PaneFrameStyle as ProtobufPaneFrameStyle, PaneId as ProtobufPaneId,
+ PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest,
+ PaneMetadata as ProtobufPaneMetadata,
PaneRenderReportPayload as ProtobufPaneRenderReportPayload,
PaneScrollbackResponse as ProtobufPaneScrollbackResponse, PaneType as ProtobufPaneType,
PluginConfigurationChangedPayload as ProtobufPluginConfigurationChangedPayload,
PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession,
SelectedText as ProtobufSelectedText, SessionManifest as ProtobufSessionManifest,
SoftKeyboardVisibilityChangedPayload as ProtobufSoftKeyboardVisibilityChangedPayload,
+ StyledText as ProtobufStyledText, StyledTextIndices as ProtobufStyledTextIndices,
SyntaxError as ProtobufSyntaxError, TabInfo as ProtobufTabInfo,
TabMetadata as ProtobufTabMetadata, UserActionPayload as ProtobufUserActionPayload,
WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing,
@@ -41,8 +45,8 @@ use crate::data::{
ClientId, ClientInfo, CopyDestination, Event, EventType, FileMetadata, HostTerminalThemeMode,
InputMode, KeyWithModifier, LayoutInfo, LayoutMetadata, ModeInfo, Mouse, PaneContents, PaneId,
PaneInfo, PaneManifest, PaneMetadata, PaneScrollbackResponse, PermissionStatus,
- PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, TabInfo, TabMetadata,
- WebServerStatus, WebSharing,
+ PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, StyledText, TabInfo,
+ TabMetadata, WebServerStatus, WebSharing,
};
use crate::errors::prelude::*;
@@ -597,6 +601,28 @@ impl TryFrom<ProtobufEvent> for Event {
_ => Err("Malformed payload for SoftKeyboardVisibilityChanged Event"),
}
},
+ Some(ProtobufEventType::HintText) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::HintTextPayload(p)) => {
+ let mut hint_text = BTreeMap::new();
+ for (width, styled_text) in p.hint_text {
+ hint_text.insert(width as usize, StyledText::from(styled_text));
+ }
+ Ok(Event::HintText(hint_text))
+ },
+ _ => Err("Malformed payload for HintText Event"),
+ },
+ Some(ProtobufEventType::ActivePaneScroll) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::ActivePaneScrollPayload(p)) => {
+ let scroll = match (p.position, p.length) {
+ (Some(position), Some(length)) => {
+ Some((position as usize, length as usize))
+ },
+ _ => None,
+ };
+ Ok(Event::ActivePaneScroll(scroll))
+ },
+ _ => Err("Malformed payload for ActivePaneScroll Event"),
+ },
None => Err("Unknown Protobuf Event"),
}
}
@@ -1147,6 +1173,35 @@ impl TryFrom<Event> for ProtobufEvent {
)),
})
},
+ Event::HintText(hint_text) => {
+ let mut proto_hint_text = HashMap::new();
+ for (width, styled_text) in hint_text {
+ proto_hint_text.insert(width as u32, ProtobufStyledText::from(styled_text));
+ }
+ let payload = ProtobufHintTextPayload {
+ hint_text: proto_hint_text,
+ };
+ Ok(ProtobufEvent {
+ name: ProtobufEventType::HintText as i32,
+ payload: Some(event::Payload::HintTextPayload(payload)),
+ })
+ },
+ Event::ActivePaneScroll(scroll) => {
+ let payload = match scroll {
+ Some((position, length)) => ProtobufActivePaneScrollPayload {
+ position: Some(position as u32),
+ length: Some(length as u32),
+ },
+ None => ProtobufActivePaneScrollPayload {
+ position: None,
+ length: None,
+ },
+ };
+ Ok(ProtobufEvent {
+ name: ProtobufEventType::ActivePaneScroll as i32,
+ payload: Some(event::Payload::ActivePaneScrollPayload(payload)),
+ })
+ },
Event::InitialKeybinds(keybinds) => {
let mut protobuf_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
for (input_mode, input_mode_keybinds) in keybinds {
@@ -1960,6 +2015,11 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
let web_server_capability = protobuf_mode_update_payload.web_server_capability;
+ let pane_frame_style = protobuf_mode_update_payload
+ .pane_frame_style
+ .and_then(|p| ProtobufPaneFrameStyle::from_i32(p))
+ .map(|p| p.into());
+
let mode_info = ModeInfo {
mode: current_mode,
keybinds,
@@ -1976,6 +2036,7 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
web_server_ip,
web_server_port,
web_server_capability,
+ pane_frame_style,
};
Ok(mode_info)
}
@@ -2000,6 +2061,10 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i));
let web_server_port = mode_info.web_server_port.map(|p| p as u32);
let web_server_capability = mode_info.web_server_capability;
+ let pane_frame_style = mode_info.pane_frame_style.map(|p| {
+ let protobuf_pane_frame_style: ProtobufPaneFrameStyle = p.into();
+ protobuf_pane_frame_style as i32
+ });
let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
for (input_mode, input_mode_keybinds) in mode_info.keybinds {
let mode: ProtobufInputMode = input_mode.try_into()?;
@@ -2040,6 +2105,7 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
web_server_ip,
web_server_port,
web_server_capability,
+ pane_frame_style,
})
}
}
@@ -2127,6 +2193,8 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::SoftKeyboardVisibilityChanged => {
EventType::SoftKeyboardVisibilityChanged
},
+ ProtobufEventType::HintText => EventType::HintText,
+ ProtobufEventType::ActivePaneScroll => EventType::ActivePaneScroll,
})
}
}
@@ -2184,10 +2252,40 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::SoftKeyboardVisibilityChanged => {
ProtobufEventType::SoftKeyboardVisibilityChanged
},
+ EventType::HintText => ProtobufEventType::HintText,
+ EventType::ActivePaneScroll => ProtobufEventType::ActivePaneScroll,
})
}
}
+impl From<StyledText> for ProtobufStyledText {
+ fn from(styled_text: StyledText) -> Self {
+ ProtobufStyledText {
+ text: styled_text.text,
+ indices: styled_text
+ .indices
+ .into_iter()
+ .map(|inner| ProtobufStyledTextIndices {
+ indices: inner.into_iter().map(|i| i as u32).collect(),
+ })
+ .collect(),
+ }
+ }
+}
+
+impl From<ProtobufStyledText> for StyledText {
+ fn from(styled_text: ProtobufStyledText) -> Self {
+ StyledText {
+ text: styled_text.text,
+ indices: styled_text
+ .indices
+ .into_iter()
+ .map(|inner| inner.indices.into_iter().map(|i| i as usize).collect())
+ .collect(),
+ }
+ }
+}
+
impl From<HostTerminalThemeMode> for ProtobufHostTerminalThemeIndication {
fn from(mode: HostTerminalThemeMode) -> Self {
match mode {
@@ -2361,6 +2459,7 @@ fn serialize_mode_update_event_with_non_default_values() {
web_server_ip: IpAddr::from_str("127.0.0.1").ok(),
web_server_port: Some(8082),
web_server_capability: Some(true),
+ pane_frame_style: Some(crate::input::options::PaneFrameStyle::Titles),
});
let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
let serialized_protobuf_event = protobuf_event.encode_to_vec();
@@ -2463,6 +2562,55 @@ fn serialize_pane_update_event() {
}
#[test]
+fn serialize_hint_text_event() {
+ use prost::Message;
+ let hint_text_event = Event::HintText(BTreeMap::from([
+ (
+ 10,
+ StyledText {
+ text: "group".to_owned(),
+ indices: vec![vec![0]],
+ },
+ ),
+ (
+ 42,
+ StyledText {
+ text: "resize".to_owned(),
+ indices: vec![vec![0, 1], vec![3]],
+ },
+ ),
+ ]));
+ let protobuf_event: ProtobufEvent = hint_text_event.clone().try_into().unwrap();
+ let serialized_protobuf_event = protobuf_event.encode_to_vec();
+ let deserialized_protobuf_event: ProtobufEvent =
+ Message::decode(serialized_protobuf_event.as_slice()).unwrap();
+ let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
+ assert_eq!(
+ hint_text_event, deserialized_event,
+ "Event properly serialized/deserialized without change"
+ );
+}
+
+#[test]
+fn serialize_active_pane_scroll_event() {
+ use prost::Message;
+ for active_pane_scroll_event in [
+ Event::ActivePaneScroll(Some((3, 12))),
+ Event::ActivePaneScroll(None),
+ ] {
+ let protobuf_event: ProtobufEvent = active_pane_scroll_event.clone().try_into().unwrap();
+ let serialized_protobuf_event = protobuf_event.encode_to_vec();
+ let deserialized_protobuf_event: ProtobufEvent =
+ Message::decode(serialized_protobuf_event.as_slice()).unwrap();
+ let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
+ assert_eq!(
+ active_pane_scroll_event, deserialized_event,
+ "Event properly serialized/deserialized without change"
+ );
+ }
+}
+
+#[test]
fn serialize_key_event() {
use crate::data::BareKey;
use prost::Message;
@@ -2946,6 +3094,26 @@ impl Into<WebSharing> for ProtobufWebSharing {
}
}
+impl Into<ProtobufPaneFrameStyle> for crate::input::options::PaneFrameStyle {
+ fn into(self) -> ProtobufPaneFrameStyle {
+ match self {
+ crate::input::options::PaneFrameStyle::Full => ProtobufPaneFrameStyle::Full,
+ crate::input::options::PaneFrameStyle::Titles => ProtobufPaneFrameStyle::Titles,
+ crate::input::options::PaneFrameStyle::None => ProtobufPaneFrameStyle::None,
+ }
+ }
+}
+
+impl Into<crate::input::options::PaneFrameStyle> for ProtobufPaneFrameStyle {
+ fn into(self) -> crate::input::options::PaneFrameStyle {
+ match self {
+ ProtobufPaneFrameStyle::Full => crate::input::options::PaneFrameStyle::Full,
+ ProtobufPaneFrameStyle::Titles => crate::input::options::PaneFrameStyle::Titles,
+ ProtobufPaneFrameStyle::None => crate::input::options::PaneFrameStyle::None,
+ }
+ }
+}
+
impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload {
type Error = &'static str;
fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> {
diff --git a/zellij-utils/src/plugin_api/mod.rs b/zellij-utils/src/plugin_api/mod.rs
index 0e26485e..918ad4ae 100644
--- a/zellij-utils/src/plugin_api/mod.rs
+++ b/zellij-utils/src/plugin_api/mod.rs
@@ -5,6 +5,7 @@ pub mod file;
pub mod input_mode;
pub mod key;
pub mod message;
+pub mod pane_frame_style;
pub mod pipe_message;
pub mod plugin_command;
pub mod plugin_ids;
diff --git a/zellij-utils/src/plugin_api/pane_frame_style.proto b/zellij-utils/src/plugin_api/pane_frame_style.proto
new file mode 100644
index 00000000..0acd8bee
--- /dev/null
+++ b/zellij-utils/src/plugin_api/pane_frame_style.proto
@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package api.pane_frame_style;
+
+enum PaneFrameStyle {
+ Full = 0;
+ Titles = 1;
+ None = 2;
+}
diff --git a/zellij-utils/src/plugin_api/pane_frame_style.rs b/zellij-utils/src/plugin_api/pane_frame_style.rs
new file mode 100644
index 00000000..392f2e89
--- /dev/null
+++ b/zellij-utils/src/plugin_api/pane_frame_style.rs
@@ -0,0 +1,49 @@
+pub use super::generated_api::api::pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle;
+use crate::input::options::PaneFrameStyle;
+
+use std::convert::TryFrom;
+
+impl TryFrom<ProtobufPaneFrameStyle> for PaneFrameStyle {
+ type Error = &'static str;
+ fn try_from(protobuf_pane_frame_style: ProtobufPaneFrameStyle) -> Result<Self, &'static str> {
+ match protobuf_pane_frame_style {
+ ProtobufPaneFrameStyle::Full => Ok(PaneFrameStyle::Full),
+ ProtobufPaneFrameStyle::Titles => Ok(PaneFrameStyle::Titles),
+ ProtobufPaneFrameStyle::None => Ok(PaneFrameStyle::None),
+ }
+ }
+}
+
+impl TryFrom<PaneFrameStyle> for ProtobufPaneFrameStyle {
+ type Error = &'static str;
+ fn try_from(pane_frame_style: PaneFrameStyle) -> Result<Self, &'static str> {
+ Ok(match pane_frame_style {
+ PaneFrameStyle::Full => ProtobufPaneFrameStyle::Full,
+ PaneFrameStyle::Titles => ProtobufPaneFrameStyle::Titles,
+ PaneFrameStyle::None => ProtobufPaneFrameStyle::None,
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn pane_frame_style_roundtrips_through_protobuf() {
+ for style in [
+ PaneFrameStyle::Full,
+ PaneFrameStyle::Titles,
+ PaneFrameStyle::None,
+ ] {
+ let protobuf: ProtobufPaneFrameStyle = style.try_into().unwrap();
+ let roundtripped: PaneFrameStyle = protobuf.try_into().unwrap();
+ assert_eq!(style, roundtripped);
+ }
+ }
+
+ #[test]
+ fn unknown_pane_frame_style_value_is_rejected() {
+ assert!(ProtobufPaneFrameStyle::from_i32(99).is_none());
+ }
+}
diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto
index 82f4d835..8d31727d 100644
--- a/zellij-utils/src/plugin_api/plugin_command.proto
+++ b/zellij-utils/src/plugin_api/plugin_command.proto
@@ -9,6 +9,7 @@ import "resize.proto";
import "plugin_permission.proto";
import "input_mode.proto";
import "key.proto";
+import "pane_frame_style.proto";
package api.plugin_command;
@@ -214,6 +215,9 @@ enum CommandName {
NewTiledPaneInTab = 221;
ExitMobileMode = 222;
FocusLastPane = 223;
+ SetPaneFrameStyle = 224;
+ ToggleFloatingPanes = 225;
+ NewPane = 226;
}
message PluginCommand {
@@ -373,9 +377,19 @@ message PluginCommand {
PaneId set_shadow_focus_payload = 167;
NewTabUnfocusedPayload new_tab_unfocused_payload = 168;
NewTiledPaneInTabPayload new_tiled_pane_in_tab_payload = 169;
+ SetPaneFrameStylePayload set_pane_frame_style_payload = 170;
+ ToggleFloatingPanesPayload toggle_floating_panes_payload = 171;
}
}
+message SetPaneFrameStylePayload {
+ pane_frame_style.PaneFrameStyle pane_frame_style = 1;
+}
+
+message ToggleFloatingPanesPayload {
+ optional uint64 tab_id = 1;
+}
+
message NewTabPayload {
optional string name = 1;
optional string cwd = 2;
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index 546c3586..38c42565 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -6,6 +6,7 @@ pub use super::generated_api::api::{
SessionManifest as ProtobufSessionManifest,
},
input_mode::InputMode as ProtobufInputMode,
+ pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle,
plugin_command::{
break_panes_to_new_tab_response, break_panes_to_tab_with_id_response,
break_panes_to_tab_with_index_response, delete_layout_response, dump_layout_response,
@@ -120,16 +121,18 @@ pub use super::generated_api::api::{
SaveSessionResponse as ProtobufSaveSessionResponse, ScrollDownInPaneIdPayload,
ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload,
SessionListSnapshot as ProtobufSessionListSnapshot, SetFloatingPanePinnedPayload,
- SetPaneBorderlessPayload, SetPaneColorPayload, SetPaneRegexHighlightsPayload,
- SetSelfMouseSelectionSupportPayload,
+ SetPaneBorderlessPayload, SetPaneColorPayload,
+ SetPaneFrameStylePayload as ProtobufSetPaneFrameStylePayload,
+ SetPaneRegexHighlightsPayload, SetSelfMouseSelectionSupportPayload,
SetSoftKeyboardPayload as ProtobufSetSoftKeyboardPayload,
SetTabFitPayload as ProtobufSetTabFitPayload, SetTimeoutPayload, ShowCursorPayload,
ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload,
ShowFloatingPanesResponse as ProtobufShowFloatingPanesResponse, ShowPaneWithIdPayload,
Size as ProtobufSize, StackPanesPayload, SubscribePayload, SwitchSessionPayload,
- SwitchTabToIdPayload, SwitchTabToPayload, TogglePaneBorderlessPayload,
- TogglePaneEmbedOrEjectForPaneIdPayload, TogglePaneIdFullscreenPayload, UnsubscribePayload,
- WebRequestPayload, WriteCharsToPaneIdPayload, WriteToPaneIdPayload,
+ SwitchTabToIdPayload, SwitchTabToPayload, ToggleFloatingPanesPayload,
+ TogglePaneBorderlessPayload, TogglePaneEmbedOrEjectForPaneIdPayload,
+ TogglePaneIdFullscreenPayload, UnsubscribePayload, WebRequestPayload,
+ WriteCharsToPaneIdPayload, WriteToPaneIdPayload,
},
plugin_permission::PermissionType as ProtobufPermissionType,
resize::ResizeAction as ProtobufResizeAction,
@@ -940,6 +943,20 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for NewTiledPaneInTab"),
},
+ Some(CommandName::ToggleFloatingPanes) => match protobuf_plugin_command.payload {
+ Some(Payload::ToggleFloatingPanesPayload(payload)) => {
+ Ok(PluginCommand::ToggleFloatingPanes {
+ tab_id: payload.tab_id,
+ })
+ },
+ _ => Ok(PluginCommand::ToggleFloatingPanes { tab_id: None }),
+ },
+ Some(CommandName::NewPane) => {
+ if protobuf_plugin_command.payload.is_some() {
+ return Err("NewPane should not have a payload");
+ }
+ Ok(PluginCommand::NewPane)
+ },
Some(CommandName::GoToNextTab) => {
if protobuf_plugin_command.payload.is_some() {
return Err("GoToNextTab should not have a payload");
@@ -1099,6 +1116,17 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
}
Ok(PluginCommand::TogglePaneFrames)
},
+ Some(CommandName::SetPaneFrameStyle) => match protobuf_plugin_command.payload {
+ Some(Payload::SetPaneFrameStylePayload(payload)) => {
+ match ProtobufPaneFrameStyle::from_i32(payload.pane_frame_style) {
+ Some(protobuf_pane_frame_style) => Ok(PluginCommand::SetPaneFrameStyle(
+ protobuf_pane_frame_style.try_into()?,
+ )),
+ None => Err("Malformed SetPaneFrameStyle payload"),
+ }
+ },
+ _ => Err("Mismatched payload for SetPaneFrameStyle"),
+ },
Some(CommandName::TogglePaneEmbedOrEject) => {
if protobuf_plugin_command.payload.is_some() {
return Err("TogglePaneEmbedOrEject should not have a payload");
@@ -2983,6 +3011,16 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
},
)),
}),
+ PluginCommand::ToggleFloatingPanes { tab_id } => Ok(ProtobufPluginCommand {
+ name: CommandName::ToggleFloatingPanes as i32,
+ payload: Some(Payload::ToggleFloatingPanesPayload(
+ ToggleFloatingPanesPayload { tab_id },
+ )),
+ }),
+ PluginCommand::NewPane => Ok(ProtobufPluginCommand {
+ name: CommandName::NewPane as i32,
+ payload: None,
+ }),
PluginCommand::GoToNextTab => Ok(ProtobufPluginCommand {
name: CommandName::GoToNextTab as i32,
payload: None,
@@ -3093,6 +3131,15 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
name: CommandName::TogglePaneFrames as i32,
payload: None,
}),
+ PluginCommand::SetPaneFrameStyle(pane_frame_style) => Ok(ProtobufPluginCommand {
+ name: CommandName::SetPaneFrameStyle as i32,
+ payload: Some(Payload::SetPaneFrameStylePayload(
+ ProtobufSetPaneFrameStylePayload {
+ pane_frame_style: ProtobufPaneFrameStyle::try_from(pane_frame_style)?
+ as i32,
+ },
+ )),
+ }),
PluginCommand::TogglePaneEmbedOrEject => Ok(ProtobufPluginCommand {
name: CommandName::TogglePaneEmbedOrEject as i32,
payload: None,
@@ -5265,4 +5312,57 @@ mod tests {
other => panic!("expected SetTabFit, got {:?}", other),
}
}
+
+ #[test]
+ fn set_pane_frame_style_protobuf_round_trip() {
+ use crate::input::options::PaneFrameStyle;
+ for style in [
+ PaneFrameStyle::Full,
+ PaneFrameStyle::Titles,
+ PaneFrameStyle::None,
+ ] {
+ let original = PluginCommand::SetPaneFrameStyle(style);
+ let protobuf: ProtobufPluginCommand = original.try_into().expect("encode");
+ let decoded: PluginCommand = protobuf.try_into().expect("decode");
+ match decoded {
+ PluginCommand::SetPaneFrameStyle(decoded_style) => {
+ assert_eq!(decoded_style, style)
+ },
+ other => panic!("expected SetPaneFrameStyle, got {:?}", other),
+ }
+ }
+ }
+
+ #[test]
+ fn new_pane_protobuf_round_trip() {
+ let original = PluginCommand::NewPane;
+ let protobuf: ProtobufPluginCommand = original.try_into().expect("encode");
+ let decoded: PluginCommand = protobuf.try_into().expect("decode");
+ match decoded {
+ PluginCommand::NewPane => {},
+ other => panic!("expected NewPane, got {:?}", other),
+ }
+ }
+
+ #[test]
+ fn toggle_floating_panes_focused_tab_protobuf_round_trip() {
+ let original = PluginCommand::ToggleFloatingPanes { tab_id: None };
+ let protobuf: ProtobufPluginCommand = original.try_into().expect("encode");
+ let decoded: PluginCommand = protobuf.try_into().expect("decode");
+ match decoded {
+ PluginCommand::ToggleFloatingPanes { tab_id } => assert_eq!(tab_id, None),
+ other => panic!("expected ToggleFloatingPanes, got {:?}", other),
+ }
+ }
+
+ #[test]
+ fn toggle_floating_panes_with_tab_id_protobuf_round_trip() {
+ let original = PluginCommand::ToggleFloatingPanes { tab_id: Some(2) };
+ let protobuf: ProtobufPluginCommand = original.try_into().expect("encode");
+ let decoded: PluginCommand = protobuf.try_into().expect("decode");
+ match decoded {
+ PluginCommand::ToggleFloatingPanes { tab_id } => assert_eq!(tab_id, Some(2)),
+ other => panic!("expected ToggleFloatingPanes, got {:?}", other),
+ }
+ }
}
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap
index 0d51e89b..4d16821f 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap
@@ -17,6 +17,7 @@ Options {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap
index 1b0c154a..d8378848 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap
@@ -17,6 +17,7 @@ Options {
pane_frames: Some(
true,
),
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap
index 08b89aac..79a656a5 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap
@@ -15,6 +15,7 @@ Options {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
index a8a144a8..2f8c1964 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
@@ -5993,6 +5993,7 @@ Config {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
index 4792ab0c..e4a22a82 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
@@ -5993,6 +5993,7 @@ Config {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap
index 8f5baed6..f703371c 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap
@@ -102,6 +102,7 @@ Config {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap
index 40822e6e..0830a4b6 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap
@@ -17,6 +17,7 @@ Options {
pane_frames: Some(
false,
),
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
index 2cb1c9af..e8e1b3ee 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
@@ -5993,6 +5993,7 @@ Config {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
index 431c8fc4..ff3a4fda 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
@@ -5993,6 +5993,7 @@ Config {
theme_dir: None,
mouse_mode: None,
pane_frames: None,
+ pane_frame_style: None,
mirror_session: None,
on_force_close: None,
scroll_buffer_size: None,