From 693fa082def5ef0fe030cd7fdc3b1df051b35dc6 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Thu, 11 Dec 2025 14:25:42 +0100 Subject: [PATCH] Command Sequences, Blocking CLI Commands, New Plugin APIs (#4546) * fix deadlocks * initial logging to plugin implementation * only log actions, include keys as Action::Write * send actions to plugins as a new Event::UserAction * add Action::Write metadata to plugin API * run_action plugin command and permission * block-until-exit/success/failure in the cli * fix tests * add NewBlockingPane to the plugin API * run actions in a different thread so as not to block plugin execution * add custom context to run_action flow * fixes for floating pane z_index sorting and unknown protobuf events not crashing plugins * always render the frame of pinned panes * macros module * add macros to config * KDL macro parsing * thread macros to the plugin thread * get/update/delete macros from plugins * add macros updated event * add ability to rename macros * fix deadlock * fix z_indices with pinned unselectable panes bug * allow plugins to opt-in to show_cursor * change show_cursor(bool) to show_cursor(Option) * test * upgrade strum to allow proper enum iteration and case insensitive fromstr implementation for Actions * better cwd tracking for exited command panes * add initial panes to NewTab Action (no-op for now) * add initial panes to cli newtab action * make initial panes work * add close_on_exit and start_suspended to the cli * properly convert newtab action (potentially breaking for plugins) * allow first pane in tab to block * make distinction between opening panes with the last active client and the current pane in the cli * improve some apis * fix fixed size closing pane bug * fix plugin cursor coordinates * fix issues with launch-or-focus-plugin having to do with in-place and suppressed panes * fix: set affected pane in replace pane * allow setting a pane in place when it is suppressed and being focused (tests failing) * fix tests * some fixes for unsuppression of panes * some fixes for completion_tx in new tab action * allow replace/suppressed rather than replace/close only * fixes for inserting suppressed panes without conflicts * pane focus history and explicit unsuppress plugin api * fix: prefer explicitly provided pane id in placement in actions that provide it * fix floating pane coordinate change and z_index * fix plugin cache dir to persist between sessions * fix some stack focusing issues when adding panes without a client id * make sure pinned panes are always above non-pinned floating panes * allow plugins to copy to clipboard * initial text styling additions implementations - buggy * fix dimming issues * remove extras, stay with just dim and unbold * unbold and dim as indices * allow ui components to render success/error colors * allow plugins to send sigint/sigkill to processes, as well as receive their pid * ui component fixes and send originating plugin context with run_action * originating plugin for new tab too * make plugn show pane command also expand stacked panes * add sequence plugin * remove macros * remove snapshots * add shortcut for sequence plugin * fix plugin tests * plugin tests for new apis * update snapshots for sequence shortcut * cleanups and formatting * Event::CwdChanged * moar cleanups * remove some warnings * remove mroe warnings * remove dead code * remove more dead code * fix minor bugs in sequence plugin * update sequence help and format codebase * fix conditional blocking cli commands * fix initial-command new-tab cli flag * add client_ids to CwdChanged Event * last fixes * add pr --- CHANGELOG.md | 1 + Cargo.lock | 35 +- Cargo.toml | 5 +- .../compact-bar/src/keybind_utils.rs | 7 +- default-plugins/configuration/src/presets.rs | 36 + .../fixture-plugin-for-tests/src/main.rs | 42 +- default-plugins/plugin-manager/src/main.rs | 2 +- default-plugins/sequence/.cargo/config.toml | 2 + default-plugins/sequence/.gitignore | 1 + default-plugins/sequence/Cargo.toml | 16 + default-plugins/sequence/LICENSE.md | 1 + default-plugins/sequence/src/lib.rs | 5 + default-plugins/sequence/src/main.rs | 1131 ++++++++++++++ .../sequence/src/path_formatting.rs | 71 + .../sequence/src/state/chain_type.rs | 45 + .../sequence/src/state/command_entry.rs | 86 ++ .../sequence/src/state/command_parser.rs | 327 ++++ .../sequence/src/state/command_status.rs | 26 + default-plugins/sequence/src/state/editing.rs | 80 + .../sequence/src/state/execution.rs | 265 ++++ default-plugins/sequence/src/state/layout.rs | 73 + default-plugins/sequence/src/state/mod.rs | 446 ++++++ .../sequence/src/state/positioning.rs | 48 + .../sequence/src/state/selection.rs | 214 +++ default-plugins/sequence/src/ui/components.rs | 596 ++++++++ .../sequence/src/ui/fuzzy_complete.rs | 321 ++++ .../sequence/src/ui/layout_calculations.rs | 28 + default-plugins/sequence/src/ui/mod.rs | 5 + default-plugins/sequence/src/ui/text_input.rs | 997 ++++++++++++ default-plugins/sequence/src/ui/truncation.rs | 373 +++++ default-plugins/session-manager/src/main.rs | 4 +- default-plugins/status-bar/src/one_line_ui.rs | 26 +- default-plugins/status-bar/src/second_line.rs | 24 +- example/default.kdl | 1 + src/main.rs | 31 + xtask/src/main.rs | 4 + .../src/old_config_converter/old_config.rs | 49 +- zellij-client/src/web_client/types.rs | 16 - zellij-server/src/background_jobs.rs | 2 + zellij-server/src/lib.rs | 2 + zellij-server/src/os_input_output.rs | 6 + zellij-server/src/panes/floating_panes/mod.rs | 59 +- zellij-server/src/panes/plugin_pane.rs | 29 +- zellij-server/src/panes/terminal_pane.rs | 22 +- zellij-server/src/panes/tiled_panes/mod.rs | 8 +- .../src/panes/tiled_panes/tiled_pane_grid.rs | 8 + .../tiled_panes/unit/stacked_panes_tests.rs | 2 +- ..._grid__grid_tests__table_ui_component.snap | 14 +- zellij-server/src/plugins/mod.rs | 70 +- .../src/plugins/unit/plugin_tests.rs | 667 ++++++++ ...in_tests__clear_screen_plugin_command.snap | 2 + ...gin_tests__close_focus_plugin_command.snap | 2 + ...sts__close_focused_tab_plugin_command.snap | 2 + ...sts__close_plugin_pane_plugin_command.snap | 2 + ...s__close_terminal_pane_plugin_command.snap | 2 + ...sts__copy_to_clipboard_plugin_command.snap | 10 + ..._copy_to_clipboard_without_permission.snap | 5 + ...__plugin_tests__detach_plugin_command.snap | 2 + ...tests__edit_scrollback_plugin_command.snap | 2 + ...tests__focus_next_pane_plugin_command.snap | 2 + ...s__focus_or_create_tab_plugin_command.snap | 2 + ...sts__focus_plugin_pane_plugin_command.snap | 3 + ...s__focus_previous_pane_plugin_command.snap | 2 + ...s__focus_terminal_pane_plugin_command.snap | 3 + ..._tests__go_to_next_tab_plugin_command.snap | 2 + ...ts__go_to_previous_tab_plugin_command.snap | 2 + ...ver__plugins__plugin_tests__go_to_tab.snap | 2 + ..._tests__go_to_tab_name_plugin_command.snap | 2 + ...ts__granted_permission_request_result.snap | 3 +- ...gin_tests__hide_cursor_plugin_command.snap | 11 + ...sts__move_focus_or_tab_plugin_command.snap | 2 + ...ugin_tests__move_focus_plugin_command.snap | 2 + ...lugin_tests__move_pane_plugin_command.snap | 2 + ...ve_pane_with_direction_plugin_command.snap | 2 + ..._plugin_tests__new_tab_plugin_command.snap | 4 + ...new_tabs_with_layout_plugin_command-2.snap | 4 + ...__new_tabs_with_layout_plugin_command.snap | 4 + ...ests__next_swap_layout_plugin_command.snap | 2 + ..._command_pane_floating_plugin_command.snap | 2 + ...sts__open_command_pane_plugin_command.snap | 2 + ...ts__open_file_floating_plugin_command.snap | 2 + ...lugin_tests__open_file_plugin_command.snap | 2 + ...ile_with_line_floating_plugin_command.snap | 2 + ...s__open_file_with_line_plugin_command.snap | 2 + ...open_terminal_floating_plugin_command.snap | 2 + ...n_tests__open_terminal_plugin_command.snap | 2 + ...ests__page_scroll_down_plugin_command.snap | 2 + ..._tests__page_scroll_up_plugin_command.snap | 2 + ...__previous_swap_layout_plugin_command.snap | 2 + ...gin_tests__quit_zellij_plugin_command.snap | 2 + ...ts__rename_plugin_pane_plugin_command.snap | 2 + ...ugin_tests__rename_tab_plugin_command.snap | 2 + ...__rename_terminal_pane_plugin_command.snap | 2 + ...gin_tests__request_plugin_permissions.snap | 3 +- ...s__resize_focused_pane_plugin_command.snap | 2 + ...ed_pane_with_direction_plugin_command.snap | 2 + ...ugin_tests__run_action_plugin_command.snap | 17 + ..._tests__run_action_without_permission.snap | 5 + ...gin_tests__scroll_down_plugin_command.snap | 2 + ...ests__scroll_to_bottom_plugin_command.snap | 2 + ...n_tests__scroll_to_top_plugin_command.snap | 2 + ...lugin_tests__scroll_up_plugin_command.snap | 2 + ..._tests__send_configuration_to_plugins.snap | 2 + ...send_sigint_to_pane_id_plugin_command.snap | 9 + ...end_sigkill_to_pane_id_plugin_command.snap | 9 + ...gin_tests__show_cursor_plugin_command.snap | 16 + ...sts__show_pane_with_id_plugin_command.snap | 1 + ...lugin_tests__show_self_plugin_command.snap | 3 + ..._plugin_tests__start_or_reload_plugin.snap | 2 + ..._tests__switch_to_mode_plugin_command.snap | 2 + ...toggle_active_tab_sync_plugin_command.snap | 2 + ...oggle_focus_fullscreen_plugin_command.snap | 2 + ...le_pane_embed_or_eject_plugin_command.snap | 2 + ...ts__toggle_pane_frames_plugin_command.snap | 2 + ...ugin_tests__toggle_tab_plugin_command.snap | 2 + ...ests__undo_rename_pane_plugin_command.snap | 2 + ...tests__undo_rename_tab_plugin_command.snap | 2 + ...gin_tests__write_chars_plugin_command.snap | 2 + ...s__plugin_tests__write_plugin_command.snap | 2 + zellij-server/src/plugins/wasm_bridge.rs | 109 +- zellij-server/src/plugins/zellij_exports.rs | 320 +++- zellij-server/src/pty.rs | 318 +++- zellij-server/src/route.rs | 435 ++++-- zellij-server/src/screen.rs | 273 ++-- zellij-server/src/tab/layout_applier.rs | 19 +- zellij-server/src/tab/mod.rs | 262 +++- .../src/tab/unit/tab_integration_tests.rs | 18 +- zellij-server/src/tab/unit/tab_tests.rs | 6 + .../src/ui/components/nested_list.rs | 1 + zellij-server/src/ui/components/ribbon.rs | 1 + zellij-server/src/ui/components/table.rs | 24 +- zellij-server/src/ui/components/text.rs | 71 +- zellij-server/src/ui/mod.rs | 1 - zellij-server/src/ui/overlay/mod.rs | 97 -- zellij-server/src/ui/overlay/prompt.rs | 65 - zellij-server/src/ui/pane_contents_and_ui.rs | 3 +- zellij-server/src/unit/screen_tests.rs | 42 + ...i_edit_action_with_default_parameters.snap | 2 +- ...send_cli_edit_action_with_line_number.snap | 2 +- ..._cli_edit_action_with_split_direction.snap | 2 +- ...end_cli_launch_or_focus_plugin_action.snap | 2 + ..._new_pane_action_with_command_and_cwd.snap | 2 +- ...w_pane_action_with_default_parameters.snap | 2 +- ...on_with_floating_pane_and_coordinates.snap | 2 +- ..._new_pane_action_with_split_direction.snap | 2 +- ...end_cli_new_tab_action_default_params.snap | 2 + ...i_new_tab_action_with_name_and_layout.snap | 4 + ...ests__send_cli_query_tab_names_action.snap | 2 + zellij-tile/src/shim.rs | 140 +- zellij-tile/src/ui_components/nested_list.rs | 52 + zellij-tile/src/ui_components/text.rs | 221 ++- zellij-utils/assets/config/default.kdl | 7 + zellij-utils/assets/plugins/about.wasm | Bin 1231744 -> 1390199 bytes zellij-utils/assets/plugins/compact-bar.wasm | Bin 1343193 -> 1548034 bytes .../assets/plugins/configuration.wasm | Bin 1304492 -> 1450980 bytes .../plugins/fixture-plugin-for-tests.wasm | Bin 1245311 -> 1445407 bytes .../assets/plugins/multiple-select.wasm | Bin 1224537 -> 1382984 bytes .../assets/plugins/plugin-manager.wasm | Bin 1189169 -> 1363473 bytes zellij-utils/assets/plugins/sequence.wasm | Bin 0 -> 1419868 bytes .../assets/plugins/session-manager.wasm | Bin 1273228 -> 1445706 bytes zellij-utils/assets/plugins/share.wasm | Bin 1184473 -> 1353298 bytes zellij-utils/assets/plugins/status-bar.wasm | Bin 1432227 -> 1558406 bytes zellij-utils/assets/plugins/strider.wasm | Bin 1308344 -> 1512515 bytes zellij-utils/assets/plugins/tab-bar.wasm | Bin 1261905 -> 1438990 bytes zellij-utils/assets/prost/api.action.rs | 710 ++++++++- zellij-utils/assets/prost/api.event.rs | 59 +- .../assets/prost/api.plugin_command.rs | 87 +- .../assets/prost/api.plugin_permission.rs | 6 + .../prost_ipc/client_server_contract.rs | 79 + zellij-utils/src/cli.rs | 128 +- .../client_server_contract/common_types.proto | 29 + zellij-utils/src/consts.rs | 1 + zellij-utils/src/data.rs | 115 +- zellij-utils/src/errors.rs | 13 +- zellij-utils/src/input/actions.rs | 169 ++- zellij-utils/src/input/command.rs | 28 + zellij-utils/src/input/layout.rs | 38 + zellij-utils/src/input/mouse.rs | 6 + zellij-utils/src/input/plugins.rs | 1 + zellij-utils/src/ipc.rs | 16 +- zellij-utils/src/ipc/protobuf_conversion.rs | 165 +- zellij-utils/src/ipc/tests/roundtrip_tests.rs | 119 +- zellij-utils/src/kdl/mod.rs | 101 +- ..._config_from_default_assets_to_string.snap | 7 + ...efault_assets_to_string_with_comments.snap | 7 + ...erialize_and_deserialize_session_info.snap | 2 + ...nd_deserialize_session_info_with_data.snap | 2 + zellij-utils/src/plugin_api/action.proto | 295 ++++ zellij-utils/src/plugin_api/action.rs | 1340 ++++++++++++++++- zellij-utils/src/plugin_api/event.proto | 31 + zellij-utils/src/plugin_api/event.rs | 173 ++- .../src/plugin_api/plugin_command.proto | 43 + zellij-utils/src/plugin_api/plugin_command.rs | 259 +++- .../src/plugin_api/plugin_permission.proto | 2 + .../src/plugin_api/plugin_permission.rs | 4 + zellij-utils/src/position.rs | 6 + ..._default_config_with_no_cli_arguments.snap | 47 + ...out_env_vars_override_config_env_vars.snap | 47 + ...out_keybinds_override_config_keybinds.snap | 12 + ..._layout_themes_override_config_themes.snap | 47 + ..._ui_config_overrides_config_ui_config.snap | 47 + 201 files changed, 12403 insertions(+), 890 deletions(-) create mode 100644 default-plugins/sequence/.cargo/config.toml create mode 100644 default-plugins/sequence/.gitignore create mode 100644 default-plugins/sequence/Cargo.toml create mode 120000 default-plugins/sequence/LICENSE.md create mode 100644 default-plugins/sequence/src/lib.rs create mode 100644 default-plugins/sequence/src/main.rs create mode 100644 default-plugins/sequence/src/path_formatting.rs create mode 100644 default-plugins/sequence/src/state/chain_type.rs create mode 100644 default-plugins/sequence/src/state/command_entry.rs create mode 100644 default-plugins/sequence/src/state/command_parser.rs create mode 100644 default-plugins/sequence/src/state/command_status.rs create mode 100644 default-plugins/sequence/src/state/editing.rs create mode 100644 default-plugins/sequence/src/state/execution.rs create mode 100644 default-plugins/sequence/src/state/layout.rs create mode 100644 default-plugins/sequence/src/state/mod.rs create mode 100644 default-plugins/sequence/src/state/positioning.rs create mode 100644 default-plugins/sequence/src/state/selection.rs create mode 100644 default-plugins/sequence/src/ui/components.rs create mode 100644 default-plugins/sequence/src/ui/fuzzy_complete.rs create mode 100644 default-plugins/sequence/src/ui/layout_calculations.rs create mode 100644 default-plugins/sequence/src/ui/mod.rs create mode 100644 default-plugins/sequence/src/ui/text_input.rs create mode 100644 default-plugins/sequence/src/ui/truncation.rs create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap delete mode 100644 zellij-server/src/ui/overlay/mod.rs delete mode 100644 zellij-server/src/ui/overlay/prompt.rs create mode 100755 zellij-utils/assets/plugins/sequence.wasm diff --git a/CHANGELOG.md b/CHANGELOG.md index 828f43c57..d28657f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * infra: migrate wasm runtime from wasmtime to wasmi (https://github.com/zellij-org/zellij/pull/4449) * feat: allow attaching to sessions as "read-only" (https://github.com/zellij-org/zellij/pull/4487) * feat: improve cli interface (add detach, switch-session and more) (https://github.com/zellij-org/zellij/pull/4492) +* feat: command sequences, conditionally blocking CLI commands, new plugin APIs (https://github.com/zellij-org/zellij/pull/4546) ## [0.43.1] - 2025-08-08 * fix: pane rename backspace regression (https://github.com/zellij-org/zellij/pull/4346) diff --git a/Cargo.lock b/Cargo.lock index e7fc87d2a..3c7b4b875 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1618,15 +1618,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.0" @@ -3379,6 +3370,20 @@ dependencies = [ "pest", ] +[[package]] +name = "sequence" +version = "0.1.0" +dependencies = [ + "fuzzy-matcher", + "regex", + "serde", + "serde_json", + "strum", + "unicode-width 0.1.10", + "uuid", + "zellij-tile", +] + [[package]] name = "serde" version = "1.0.217" @@ -3724,20 +3729,20 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.20.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" [[package]] name = "strum_macros" -version = "0.20.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck 0.3.3", + "heck 0.5.0", "proc-macro2", "quote", - "syn 1.0.96", + "syn 2.0.96", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 41f220889..3fb2b188b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ members = [ "default-plugins/about", "default-plugins/share", "default-plugins/multiple-select", + "default-plugins/sequence", "zellij-client", "zellij-server", "zellij-utils", @@ -90,8 +91,8 @@ regex = { version = "1.5.5", default-features = false, features = ["perf", "std" serde = { version = "1.0", default-features = false, features = ["derive", "std"] } serde_json = { version = "1.0", default-features = false, features = ["std"] } signal-hook = { version = "0.3", default-features = false, features = ["iterator"] } -strum = { version = "0.20.0", default-features = false } -strum_macros = { version = "0.20.0", default-features = false } +strum = { version = "0.27.2", default-features = false, features = ["std"] } +strum_macros = { version = "0.27.2", default-features = false } suggest = { version = "0.4.0", default-features = false } tempfile = { version = "3.2.0", default-features = false } termwiz = { version = "0.23.2", default-features = false } diff --git a/default-plugins/compact-bar/src/keybind_utils.rs b/default-plugins/compact-bar/src/keybind_utils.rs index aeb862d11..2f84497ce 100644 --- a/default-plugins/compact-bar/src/keybind_utils.rs +++ b/default-plugins/compact-bar/src/keybind_utils.rs @@ -440,7 +440,8 @@ impl KeybindProcessor { action, Action::NewStackedPane { command: None, - pane_name: None + pane_name: None, + near_current_pane: false, } ) }, @@ -481,7 +482,9 @@ impl KeybindProcessor { swap_floating_layouts: None, tab_name: None, should_change_focus_to_new_tab: true, - cwd: None + cwd: None, + initial_panes: _, + first_pane_unblock_condition: _, } ) }, diff --git a/default-plugins/configuration/src/presets.rs b/default-plugins/configuration/src/presets.rs index 0c972a1de..7e875073d 100644 --- a/default-plugins/configuration/src/presets.rs +++ b/default-plugins/configuration/src/presets.rs @@ -155,6 +155,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Locked" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Locked" + }} }} shared_except "locked" "renametab" "renamepane" {{ bind "{primary_modifier} g" {{ SwitchToMode "Locked"; }} @@ -371,6 +377,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Normal" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Normal" + }} }} tmux {{ bind "[" {{ SwitchToMode "Scroll"; }} @@ -587,6 +599,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Normal" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Normal" + }} }} tmux {{ bind "[" {{ SwitchToMode "Scroll"; }} @@ -784,6 +802,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Normal" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Normal" + }} }} tmux {{ bind "[" {{ SwitchToMode "Scroll"; }} @@ -981,6 +1005,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Normal" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Normal" + }} }} tmux {{ bind "[" {{ SwitchToMode "Scroll"; }} @@ -1173,6 +1203,12 @@ keybinds clear-defaults=true {{ }}; SwitchToMode "Normal" }} + bind "q" {{ + LaunchPlugin "zellij:sequence" {{ + floating true + }}; + SwitchToMode "Normal" + }} }} tmux {{ bind "[" {{ SwitchToMode "Scroll"; }} diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs index 014898606..9f5b7e93d 100644 --- a/default-plugins/fixture-plugin-for-tests/src/main.rs +++ b/default-plugins/fixture-plugin-for-tests/src/main.rs @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; #[allow(unused_imports)] use std::io::prelude::*; +use zellij_tile::prelude::actions::Action; use zellij_tile::prelude::*; // This is a fixture plugin used only for tests in Zellij @@ -59,6 +60,8 @@ impl ZellijPlugin for State { PermissionType::ReadCliPipes, PermissionType::MessageAndLaunchOtherPlugins, PermissionType::Reconfigure, + PermissionType::WriteToClipboard, + PermissionType::RunActionsAsUser, ]); self.configuration = configuration; subscribe(&[ @@ -258,11 +261,13 @@ impl ZellijPlugin for State { }, BareKey::Char('t') if key.has_modifiers(&[KeyModifier::Ctrl]) => { let should_float_if_hidden = false; - focus_terminal_pane(1, should_float_if_hidden); + let should_be_in_place_if_hidden = false; + focus_terminal_pane(1, should_float_if_hidden, should_be_in_place_if_hidden); }, BareKey::Char('u') if key.has_modifiers(&[KeyModifier::Ctrl]) => { let should_float_if_hidden = false; - focus_plugin_pane(1, should_float_if_hidden); + let should_be_in_place_if_hidden = false; + focus_plugin_pane(1, should_float_if_hidden, should_be_in_place_if_hidden); }, BareKey::Char('v') if key.has_modifiers(&[KeyModifier::Ctrl]) => { rename_terminal_pane(1, "new terminal_pane_name"); @@ -354,7 +359,7 @@ impl ZellijPlugin for State { hide_pane_with_id(PaneId::Terminal(1)); }, BareKey::Char('b') if key.has_modifiers(&[KeyModifier::Alt]) => { - show_pane_with_id(PaneId::Terminal(1), true); + show_pane_with_id(PaneId::Terminal(1), true, true); }, BareKey::Char('c') if key.has_modifiers(&[KeyModifier::Alt]) => { open_command_pane_background( @@ -549,6 +554,37 @@ impl ZellijPlugin for State { BareKey::Char('z') if key.has_modifiers(&[KeyModifier::Alt]) => { list_clients(); }, + BareKey::Char('a') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test show_cursor with coordinates + show_cursor(Some((5, 10))); + }, + BareKey::Char('b') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test hide_cursor + show_cursor(None); + }, + BareKey::Char('c') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test copy_to_clipboard + copy_to_clipboard("test clipboard text"); + }, + BareKey::Char('d') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test run_action with MoveFocus + let mut context = BTreeMap::new(); + context.insert("test_key".to_string(), "test_value".to_string()); + run_action( + Action::MoveFocus { + direction: Direction::Left, + }, + context, + ); + }, + BareKey::Char('e') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test send_sigint_to_pane_id + send_sigint_to_pane_id(PaneId::Terminal(1)); + }, + BareKey::Char('f') if key.has_modifiers(&[KeyModifier::Super]) => { + // Test send_sigkill_to_pane_id + send_sigkill_to_pane_id(PaneId::Terminal(1)); + }, _ => {}, }, Event::CustomMessage(message, payload) => { diff --git a/default-plugins/plugin-manager/src/main.rs b/default-plugins/plugin-manager/src/main.rs index 8e1c91a88..5cd243f5a 100644 --- a/default-plugins/plugin-manager/src/main.rs +++ b/default-plugins/plugin-manager/src/main.rs @@ -910,7 +910,7 @@ impl State { } pub fn focus_selected(&self) { if let Some(selected_plugin_id) = self.selected_plugin_id() { - focus_pane_with_id(PaneId::Plugin(selected_plugin_id), true); + focus_pane_with_id(PaneId::Plugin(selected_plugin_id), true, false); } } pub fn reload_selected(&self) { diff --git a/default-plugins/sequence/.cargo/config.toml b/default-plugins/sequence/.cargo/config.toml new file mode 100644 index 000000000..6b509f5b7 --- /dev/null +++ b/default-plugins/sequence/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-wasip1" diff --git a/default-plugins/sequence/.gitignore b/default-plugins/sequence/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/default-plugins/sequence/.gitignore @@ -0,0 +1 @@ +/target diff --git a/default-plugins/sequence/Cargo.toml b/default-plugins/sequence/Cargo.toml new file mode 100644 index 000000000..4f97ae6c6 --- /dev/null +++ b/default-plugins/sequence/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sequence" +version = "0.1.0" +authors = ["Aram Drevekenin "] +edition = "2018" + +[dependencies] +zellij-tile = { path = "../../zellij-tile" } +unicode-width = "0.1" +fuzzy-matcher = "0.3" +# TODO: get this from Zellij so that we don't have to match versions +strum = "0.27" +regex = "1" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +uuid = { version = "1.0", features = ["v4"] } diff --git a/default-plugins/sequence/LICENSE.md b/default-plugins/sequence/LICENSE.md new file mode 120000 index 000000000..f0608a63a --- /dev/null +++ b/default-plugins/sequence/LICENSE.md @@ -0,0 +1 @@ +../../LICENSE.md \ No newline at end of file diff --git a/default-plugins/sequence/src/lib.rs b/default-plugins/sequence/src/lib.rs new file mode 100644 index 000000000..1e1249791 --- /dev/null +++ b/default-plugins/sequence/src/lib.rs @@ -0,0 +1,5 @@ +pub mod path_formatting; +pub mod state; +pub mod ui; + +pub use state::State; diff --git a/default-plugins/sequence/src/main.rs b/default-plugins/sequence/src/main.rs new file mode 100644 index 000000000..0ac286d99 --- /dev/null +++ b/default-plugins/sequence/src/main.rs @@ -0,0 +1,1131 @@ +mod path_formatting; +mod state; +mod ui; + +use crate::state::CommandStatus; +use crate::ui::components; +use crate::ui::fuzzy_complete; +use crate::ui::layout_calculations::calculate_viewport; +use crate::ui::text_input::InputAction; +use crate::ui::truncation::truncate_middle; +use state::State; +use zellij_tile::prelude::actions::Action; +use zellij_tile::prelude::*; + +use std::collections::BTreeMap; +use std::path::PathBuf; + +use unicode_width::UnicodeWidthStr; + +register_plugin!(State); + +impl ZellijPlugin for State { + fn load(&mut self, _configuration: BTreeMap) { + subscribe(&[ + EventType::ModeUpdate, + EventType::SessionUpdate, + EventType::Key, + EventType::PermissionRequestResult, + EventType::HostFolderChanged, + EventType::RunCommandResult, + EventType::ActionComplete, + EventType::PaneUpdate, + EventType::Timer, + EventType::PastedText, + EventType::TabUpdate, + EventType::CommandPaneOpened, + ]); + + // Store our own plugin ID and client ID + let plugin_ids = get_plugin_ids(); + self.plugin_id = Some(plugin_ids.plugin_id); + self.client_id = Some(plugin_ids.client_id); + self.cwd = Some(plugin_ids.initial_cwd); + update_title(self); + } + + fn update(&mut self, event: Event) -> bool { + handle_event(self, event) + } + + fn render(&mut self, rows: usize, cols: usize) { + // Store dimensions for use in cursor calculations + self.own_rows = Some(rows); + self.own_columns = Some(cols); + + let max_visible_rows = rows.saturating_sub(5); + + let base_x = 1; + let base_y = 0; + + let (offset, visible_count, hidden_above, hidden_below) = calculate_viewport( + self.execution.all_commands.len(), + max_visible_rows, + self.selection.current_selected_command_index, + self.execution.current_running_command_index, + ); + + let mut table = components::build_table_header(hidden_above > 0 || hidden_below > 0); + + for index in offset..offset + visible_count { + table = components::add_command_row( + table, + self, + index, + offset, + visible_count, + hidden_above, + hidden_below, + ); + } + + print_table_with_coordinates( + table, + base_x, + base_y, + self.own_columns.map(|o| o.saturating_sub(base_x)), + None, + ); + + let help_y = base_y + visible_count + 2; + let (first_help, _, second_help) = components::render_help_lines(self, Some(cols)); + print_text_with_coordinates(first_help, base_x, help_y, None, None); + + if let Some((second_help_text, _)) = second_help { + print_text_with_coordinates(second_help_text, base_x, help_y + 1, None, None); + } + } +} + +pub fn handle_event(state: &mut State, event: Event) -> bool { + use std::path::PathBuf; + + match event { + Event::PermissionRequestResult(_) => { + change_host_folder(PathBuf::from("/")); + update_title(state); + true + }, + Event::ModeUpdate(mode_info) => { + state.shell = mode_info.shell.clone(); + + false + }, + Event::Key(key) => { + let mut should_render = handle_key_event(state, key); + let repositioned = state.reposition_plugin(); + if repositioned { + // we only want to render once we have repositioned, we will do this in TabUpdate + should_render = false; + } + update_cursor(state); + should_render + }, + Event::SessionUpdate(session_infos, _resurrectable_sessions) => { + if state.is_first_run { + // Find the current session + let current_session = session_infos.iter().find(|s| s.is_current_session); + + if let Some(session) = current_session { + // Get the pane history for this client + if let Some(client_id) = state.client_id { + if let Some(pane_history) = session.pane_history.get(&client_id) { + let own_pane_id = state.plugin_id.map(|id| PaneId::Plugin(id)); + state.primary_pane_id = select_primary_pane_from_history( + pane_history, + &session.panes, + own_pane_id, + ); + state.original_pane_id = state.primary_pane_id; // pane id focused + // before plugin + // launched + state.is_first_run = false; + } + } + } + } + false + }, + Event::Timer(_elapsed) => { + // Timer events are used for lock backoff + + let should_render = update_spinner(state); + + should_render + }, + Event::PastedText(pasted_text) => { + // Split pasted text into lines + let mut should_render = true; + let lines: Vec<&str> = pasted_text + .lines() + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .collect(); + + if lines.is_empty() { + return false; + } + state.pasted_lines(lines); + let repositioned = state.reposition_plugin(); + if repositioned { + // we only want to render once we have repositioned, we will do this in TabUpdate + should_render = false; + } + update_cursor(state); + + should_render + }, + Event::TabUpdate(tab_infos) => { + if let Some(tab_info) = tab_infos.iter().find(|t| t.active) { + let new_cols = Some(tab_info.viewport_columns); + let new_rows = Some(tab_info.viewport_rows); + + // Check if dimensions changed + let dimensions_changed = new_cols != state.total_viewport_columns + || new_rows != state.total_viewport_rows; + + state.total_viewport_columns = new_cols; + state.total_viewport_rows = new_rows; + + if dimensions_changed { + state.reposition_plugin(); + } + update_cursor(state); + } + + false + }, + Event::PaneUpdate(pane_manifest) => handle_pane_update(state, pane_manifest), + Event::ActionComplete(_action, pane_id, context) => { + let should_render = handle_action_complete(state, pane_id, context); + update_title(state); + should_render + }, + Event::CommandPaneOpened(terminal_pane_id, context) => { + // we get this event immediately as the pane opens, we use it to associate the + // pane's id with our state + + if !is_running_sequence(&context, state.execution.sequence_id) { + // action from previous sequence or unrelated + return false; + } + if let Some(command_text) = context.get("command_text") { + state.update_pane_id_for_command(PaneId::Terminal(terminal_pane_id), command_text); + if !state.layout.spinner_timer_scheduled { + set_timeout(0.1); + state.layout.spinner_timer_scheduled = true; + } + update_title(state); + } + + true + }, + _ => false, + } +} + +fn handle_key_event(state: &mut State, key: KeyWithModifier) -> bool { + // Ctrl+Enter - Insert command after current with AND chain type + if key.has_modifiers(&[KeyModifier::Ctrl]) && matches!(key.bare_key, BareKey::Enter) { + let mut is_cd = false; + if let Some(current_text) = state.editing_input_text() { + if let Some(path) = state::detect_cd_command(¤t_text) { + if let Some(new_cwd) = path_formatting::resolve_path(state.cwd.as_ref(), &path) { + state.current_selected_command_mut().map(|c| { + c.set_cwd(Some(new_cwd)); + c.set_text("".to_owned()); + }); + state.editing.editing_input.as_mut().map(|i| i.clear()); + is_cd = true + } + } + }; + + state.add_empty_command_after_current_selected(); + if is_cd { + state.start_editing_selected(); + } + return true; + } + + // Ctrl+X - Cycle chain type + if key.has_modifiers(&[KeyModifier::Ctrl]) && matches!(key.bare_key, BareKey::Char('x')) { + // return state.ui.command_sequence.cycle_current_chain_type(); + state.cycle_chain_type(); + return true; + } + + // Ctrl+Space, copy to clipboard + if key.has_modifiers(&[KeyModifier::Ctrl]) && matches!(key.bare_key, BareKey::Char(' ')) { + state.copy_to_clipboard(); + return false; + } + + // Ctrl+w, close all panes and clear sequence + if key.has_modifiers(&[KeyModifier::Ctrl]) && matches!(key.bare_key, BareKey::Char('w')) { + if !state.execution.is_running && !state.all_commands_are_pending() { + close_panes_and_return_to_shell(state); + } + return true; + } + + if matches!(key.bare_key, BareKey::Up) + && !key.has_modifiers(&[KeyModifier::Ctrl]) + && !key.has_modifiers(&[KeyModifier::Alt]) + { + state.move_selection_up(); + return true; + } + + if matches!(key.bare_key, BareKey::Down) + && !key.has_modifiers(&[KeyModifier::Ctrl]) + && !key.has_modifiers(&[KeyModifier::Alt]) + { + state.move_selection_down(); + return true; + } + + // Del - delete current command + if matches!(key.bare_key, BareKey::Delete) + && !key.has_modifiers(&[KeyModifier::Ctrl]) + && !key.has_modifiers(&[KeyModifier::Alt]) + { + state.remove_current_selected_command(); + return true; + } + + // Ctrl+C - Clear currently focused command, or remove it if already empty + if key.has_modifiers(&[KeyModifier::Ctrl]) && matches!(key.bare_key, BareKey::Char('c')) { + if state.execution.is_running { + interrupt_sequence(state); + return true; + } else if state.editing.editing_input.is_some() { + let is_empty = state.current_selected_command_is_empty(); + let has_more_than_one_command = state.execution.all_commands.len() > 1; + + if is_empty && has_more_than_one_command { + state.remove_current_selected_command(); + } else if is_empty { + // last command, return to shell + close_panes_and_return_to_shell(state); + } else { + // If not empty, clear it + state.clear_current_selected_command(); + } + return true; + } + } + + if state.editing.editing_input.is_none() + && key.has_no_modifiers() + && matches!(key.bare_key, BareKey::Char('e')) + { + state.start_editing_selected(); + return true; + } + + if state.editing.editing_input.is_none() + && key.has_no_modifiers() + && matches!(key.bare_key, BareKey::Enter) + { + rerun_sequence(state); + return true; + } + + // Handle input actions from TextInput + let is_backspace = matches!(key.bare_key, BareKey::Backspace); + + if let Some(action) = state + .editing + .editing_input + .as_mut() + .map(|i| i.handle_key(key)) + { + match action { + InputAction::Submit => { + return handle_submit(state); + }, + InputAction::Cancel => { + state.cancel_editing_selected(); + if state.all_commands_are_pending() { + // we always want to stay in editing mode in main screen + state.start_editing_selected(); + } + true + }, + InputAction::Complete => { + state + .editing_input_text() + .map(|current_text| { + if let Some(completed) = fuzzy_complete::fuzzy_complete( + ¤t_text, + &Default::default(), // TODO: get rid of this whoel thing? + state.cwd.as_ref(), + ) { + state.set_editing_input_text(completed); + true + } else { + false + } + }) + .unwrap_or(false) + }, + InputAction::Continue => { + if let Some(current_text) = state.editing_input_text() { + if let Some((cmd_text, chain_type)) = + state::detect_chain_operator_at_end(¤t_text) + { + let mut should_add_empty_line = true; + if let Some(path) = state::detect_cd_command(&cmd_text) { + if let Some(new_cwd) = + path_formatting::resolve_path(state.cwd.as_ref(), &path) + { + let remaining_text = + state::get_remaining_after_first_segment(¤t_text) + .unwrap_or_else(|| "".to_owned()); + if remaining_text.len() > 0 { + should_add_empty_line = false; + } + state.current_selected_command_mut().map(|c| { + c.set_cwd(Some(new_cwd)); + c.set_text(remaining_text); + }); + } + } else { + state.current_selected_command_mut().map(|c| { + c.set_text(cmd_text); + c.set_chain_type(chain_type); + }); + }; + state.cancel_editing_selected(); + if should_add_empty_line { + state.add_empty_command_after_current_selected(); + } + state.start_editing_selected(); + } + } + + // Handle backspace on empty command + if is_backspace { + let is_empty = state.current_selected_command_is_empty() + || state + .editing_input_text() + .map(|i| i.is_empty()) + .unwrap_or(false); + let has_more_than_one_command = state.execution.all_commands.len() > 1; + + if is_empty && has_more_than_one_command { + let current_index = + state.selection.current_selected_command_index.unwrap_or(0); + if current_index > 0 { + state.remove_current_selected_command(); + return true; + } + } else if is_empty { + // last command + close_panes_and_return_to_shell(state); + } + } + + true + }, + InputAction::NoAction => false, + } + } else { + false + } +} + +/// Handle Enter key - submit and execute the command sequence +fn handle_submit(state: &mut State) -> bool { + let cwd = state.cwd.clone(); + if state.handle_editing_submit(&cwd) { + // handled the command internally (eg. cd) no need to run sequence + return true; + } + + if state.execution.all_commands.len() == 1 && state.can_run_sequence() { + rerun_sequence(state); + } else if state.execution.all_commands.len() == 1 { + state.move_selection_down(); + state.start_editing_selected(); + } + true +} + +pub fn handle_pane_update(state: &mut State, pane_manifest: PaneManifest) -> bool { + // Store the manifest for later use + state.pane_manifest = Some(pane_manifest.clone()); + let mut needs_rerender = false; + if state.update_exited_command_statuses(&pane_manifest) { + needs_rerender = true; + } + if state.update_sequence_stopped_state() { + needs_rerender = true; + } + state.reposition_plugin(); + update_primary_and_original_pane_ids(state, &pane_manifest); + needs_rerender +} + +pub fn calculate_cursor_position(state: &mut State) -> Option<(usize, usize)> { + // Get pane dimensions from state (must be set by render) + let Some(cols) = state.own_columns else { + eprintln!("Warning: own_columns not set"); + return None; + }; + let Some(rows) = state.own_rows else { + eprintln!("Warning: own_rows not set"); + return None; + }; + + // Only show cursor if in edit mode + let (text, cursor_pos) = if let Some(text_input) = &state.editing.editing_input { + ( + text_input.get_text().to_string(), + text_input.cursor_position(), + ) + } else { + return None; + }; + + let Some(edit_index) = state.selection.current_selected_command_index else { + return None; + }; + + // Calculate folder column width using the longest cwd across all commands + let longest_cwd_display = state.execution.longest_cwd_display(&state.cwd); + let folder_display = format!("{} >", longest_cwd_display); + let folder_col_width = folder_display.width().max(1); + + let base_x = 1; + let base_y = 0; + + adjust_scroll_offset(state, rows); + + let max_visible_rows = state.own_rows.map(|r| r.saturating_sub(5)).unwrap_or(0); + + let (offset, visible_count, hidden_above, hidden_below) = calculate_viewport( + state.execution.all_commands.len(), + max_visible_rows, + state.selection.current_selected_command_index, + state.execution.current_running_command_index, + ); + + let (max_chain_width, max_status_width) = + components::calculate_max_widths(&state.execution.all_commands, state.layout.spinner_frame); + + let Some((_, available_cmd_width)) = components::calculate_row_layout_info( + edit_index, + offset, + visible_count, + hidden_above, + hidden_below, + cols, + folder_col_width, + max_chain_width, + max_status_width, + ) else { + return None; + }; + + // Get cursor position in truncated text + let (_, cursor_in_truncated) = truncate_middle(&text, available_cmd_width, Some(cursor_pos)); + let Some(cursor_in_truncated) = cursor_in_truncated else { + return None; + }; + + // Calculate relative coordinates within the visible table + let relative_y = edit_index.saturating_sub(offset) + 1; // +1 for header row + let relative_x = folder_col_width + 1 + cursor_in_truncated; + + let x = base_x + relative_x; + let y = base_y + relative_y; + + Some((x, y)) +} + +pub fn handle_action_complete( + state: &mut State, + pane_id: Option, + context: BTreeMap, +) -> bool { + // Update primary_pane_id to the pane that just completed the action + // This ensures we always have a valid pane to target for InPlace launches + // But only if it's not a floating pane + if let (Some(pane_id), Some(manifest)) = (pane_id, &state.pane_manifest) { + if !is_pane_floating(pane_id, manifest) { + state.primary_pane_id = Some(pane_id); + } else { + eprintln!("Not setting primary_pane_id to floating pane {:?}", pane_id); + } + } + + if !is_running_sequence(&context, state.execution.sequence_id) { + // action from previous sequence or unrelated + return false; + } + + // If the sequence has been stopped (e.g., via Ctrl+C), don't continue + if !state.execution.is_running { + return true; // Re-render to show the stopped state + } + + // Move to the next command + let next_index = state.execution.current_running_command_index + 1; + + if next_index < state.execution.all_commands.len() { + // Execute the next command + // let (next_command, next_chain_type) = &state.execution.all_commands[next_index]; + let Some(next_command) = state.execution.all_commands.get(next_index) else { + // invalid state + return true; + }; + let next_chain_type = next_command.get_chain_type(); + let next_command_cwd = next_command.get_cwd(); + let next_command_text = next_command.get_text(); + + let shell = state + .shell + .clone() + .unwrap_or_else(|| PathBuf::from("/bin/bash")); + + let command = zellij_tile::prelude::actions::RunCommandAction { + command: shell, + args: vec!["-ic".to_string(), next_command_text.trim().to_string()], + cwd: next_command_cwd, + hold_on_close: true, + ..Default::default() + }; + + // Determine placement based on layout mode + let placement = NewPanePlacement::Stacked(pane_id); + + // Update status: mark current command as completed + // Use the pane_id from ActionComplete if the status is still Pending + let pane_id_to_mark = state + .execution + .all_commands + .get(state.execution.current_running_command_index) + .and_then(|c| match c.get_status() { + CommandStatus::Running(pid) => pid, + CommandStatus::Pending => pane_id, // Use the pane from ActionComplete + CommandStatus::Exited(_, pid) => pid, // Already marked, keep it + CommandStatus::Interrupted(pid) => pid, // Already marked, keep it + }); + + state + .execution + .all_commands + .get_mut(state.execution.current_running_command_index) + .map(|c| c.set_status(CommandStatus::Exited(None, pane_id_to_mark))); + state.execution.current_running_command_index = next_index; + + // Determine unblock_condition based on whether this is the last command + let unblock_condition = if next_index < state.execution.all_commands.len() - 1 { + // Not the last command - use the chain type's unblock condition + next_chain_type.to_unblock_condition() + } else { + // Last command - use UnblockCondition::OnAnyExit + Some(UnblockCondition::OnAnyExit) + }; + + let action = Action::NewBlockingPane { + placement, + command: Some(command), + pane_name: Some(next_command_text.trim().to_string()), + unblock_condition, + near_current_pane: true, + }; + + // Pass the sequence ID in the context + let mut context = BTreeMap::new(); + context.insert( + "sequence_id".to_string(), + state.execution.sequence_id.to_string(), + ); + context.insert("command_text".to_string(), next_command_text.to_string()); + + // Put the sequence back with updated index + run_action(action, context); + } else { + // Sequence complete - mark the last command as Exited + + let pane_id_to_mark = state + .execution + .all_commands + .get(state.execution.current_running_command_index) + .and_then(|c| match c.get_status() { + CommandStatus::Running(pid) => pid, + CommandStatus::Pending => pane_id, // Use the pane from ActionComplete + CommandStatus::Exited(_, pid) => pid, // Already marked, keep it + CommandStatus::Interrupted(pid) => pid, // Already marked, keep it + }); + + state + .execution + .all_commands + .get_mut(state.execution.current_running_command_index) + .map(|c| c.set_status(CommandStatus::Exited(None, pane_id_to_mark))); + } + true +} + +/// Adjust scroll offset to keep selected or running command visible +pub fn adjust_scroll_offset(sequence: &mut crate::state::State, rows: usize) { + let max_visible = rows.saturating_sub(6); + let total_commands = sequence.execution.all_commands.len(); + + if total_commands <= max_visible { + sequence.selection.scroll_offset = 0; + return; + } + + let focus_index = sequence + .selection + .current_selected_command_index + .unwrap_or(sequence.execution.current_running_command_index); + let half_visible = max_visible / 2; + + if focus_index < half_visible { + sequence.selection.scroll_offset = 0; + } else if focus_index >= total_commands.saturating_sub(half_visible) { + sequence.selection.scroll_offset = total_commands.saturating_sub(max_visible); + } else { + sequence.selection.scroll_offset = focus_index.saturating_sub(half_visible); + } + + sequence.selection.scroll_offset = sequence + .selection + .scroll_offset + .min(total_commands.saturating_sub(max_visible)); +} + +pub fn is_pane_floating(pane_id: PaneId, pane_manifest: &PaneManifest) -> bool { + pane_manifest + .panes + .iter() + .flat_map(|(_, panes)| panes.iter()) + .find(|pane_info| match pane_id { + PaneId::Terminal(id) => !pane_info.is_plugin && pane_info.id == id, + PaneId::Plugin(id) => pane_info.is_plugin && pane_info.id == id, + }) + .map(|pane_info| pane_info.is_floating) + .unwrap_or(false) +} + +fn is_running_sequence(context: &BTreeMap, running_sequence_id: u64) -> bool { + if let Some(context_sequence_id) = context.get("sequence_id") { + if let Ok(context_id) = context_sequence_id.parse::() { + if context_id != running_sequence_id { + // This action is from a different sequence, ignore it + return false; + } else { + return true; + } + } else { + // Failed to parse sequence_id, ignore this action + return false; + } + } else { + return false; + } +} + +fn update_primary_and_original_pane_ids(state: &mut State, pane_manifest: &PaneManifest) { + if let Some(primary_pane_id) = state.primary_pane_id { + let mut primary_pane_found = false; + + // Check if the primary pane still exists + for (_tab_index, panes) in &pane_manifest.panes { + for pane_info in panes { + let pane_matches = match primary_pane_id { + PaneId::Terminal(id) => !pane_info.is_plugin && pane_info.id == id, + PaneId::Plugin(id) => pane_info.is_plugin && pane_info.id == id, + }; + + if pane_matches { + primary_pane_found = true; + break; + } + } + if primary_pane_found { + break; + } + } + + // If primary pane was not found, select a new one + if !primary_pane_found { + state.primary_pane_id = None; + } + } + if let Some(original_pane_id) = state.original_pane_id { + let mut original_pane_found = false; + + // Check if the original pane still exists + for (_tab_index, panes) in &pane_manifest.panes { + for pane_info in panes { + let pane_matches = match original_pane_id { + PaneId::Terminal(id) => !pane_info.is_plugin && pane_info.id == id, + PaneId::Plugin(id) => pane_info.is_plugin && pane_info.id == id, + }; + + if pane_matches { + original_pane_found = true; + break; + } + } + if original_pane_found { + break; + } + } + + // If original pane was not found, select a new one + if !original_pane_found { + state.original_pane_id = None; + } + } +} + +pub fn select_primary_pane_from_history( + pane_history: &[PaneId], + pane_manifest: &PaneManifest, + own_pane_id: Option, +) -> Option { + pane_history + .iter() + .rev() // Most recent first + .find(|&id| { + // Skip self + if Some(*id) == own_pane_id { + return false; + } + + // Skip floating panes + !is_pane_floating(*id, pane_manifest) + }) + .copied() +} + +fn close_panes_and_return_to_shell(state: &mut State) -> bool { + // Close all panes in the sequence before clearing it + // Handle the first pane: replace it with the primary_pane_id_before_sequence if available + if let Some(first_pane_id) = state.execution.all_commands.iter().find_map(|command| { + // we look for the first command in the sequence that has a pane that's + // actually open + match command.get_status() { + CommandStatus::Running(pane_id) => pane_id, + CommandStatus::Exited(_, pane_id) => pane_id, + CommandStatus::Interrupted(pane_id) => pane_id, + _ => None, + } + }) { + if let Some(original_pane_id) = state.original_pane_id { + replace_pane_with_existing_pane( + first_pane_id, + original_pane_id, + true, // suppress_replaced_pane (closes the first pane) + ); + } else { + // Fallback: if we don't have a saved primary pane, just close it + close_pane_with_id(first_pane_id); + } + } + + // Close all other panes (starting from index 1) + for (idx, command) in state.execution.all_commands.iter().skip(1).enumerate() { + let pane_id = match command.get_status() { + CommandStatus::Running(pane_id) => pane_id, + CommandStatus::Exited(_, pane_id) => pane_id, + CommandStatus::Interrupted(pane_id) => pane_id, + _ => None, + }; + + if let Some(pane_id) = pane_id { + close_pane_with_id(pane_id); + } else { + eprintln!( + "Warning: Cannot close pane at index {}: pane_id is None", + idx + 1 + ); + } + } + + state.clear_all_commands(); + // Transition back to shell screen + if let Some(plugin_id) = state.plugin_id { + change_floating_pane_coordinates( + plugin_id, + Some(25), + Some(25), + Some(50), + Some(50), + false, // pinned (this should unpin it) + ); + } + update_title(state); + true +} + +fn change_floating_pane_coordinates( + own_plugin_id: u32, + x: Option, + y: Option, + width: Option, + height: Option, + should_be_pinned: bool, +) { + let coordinates = FloatingPaneCoordinates::new( + x.map(|x| format!("{}%", x)), + y.map(|y| format!("{}%", y)), + width.map(|width| format!("{}%", width)), + height.map(|height| format!("{}%", height)), + Some(should_be_pinned), + ); + if let Some(coordinates) = coordinates { + // TODO: better + // show_self(true); + change_floating_panes_coordinates(vec![(PaneId::Plugin(own_plugin_id), coordinates)]); + } +} + +fn update_spinner(state: &mut State) -> bool { + // Advance spinner frame for RUNNING animation + state.layout.spinner_frame = (state.layout.spinner_frame + 1) % 8; + + // Reset timer scheduled flag since this timer just fired + state.layout.spinner_timer_scheduled = false; + + // If we have a running command, schedule next timer event + let has_running = state + .execution + .all_commands + .iter() + .any(|command| matches!(command.get_status(), CommandStatus::Running(_))); + if has_running && !state.layout.spinner_timer_scheduled { + set_timeout(0.1); + state.layout.spinner_timer_scheduled = true; + } + has_running +} + +fn rerun_sequence(state: &mut State) { + if !state.can_run_sequence() { + return; + } + + state.execution.all_commands.retain(|c| !c.is_empty()); + + if state.execution.all_commands.is_empty() { + return; + } + + let selected_index = state + .selection + .current_selected_command_index + .unwrap_or(0) + .min(state.execution.all_commands.len().saturating_sub(1)); + + let mut close_replaced_pane = true; + + // Extract the selected pane's ID BEFORE resetting statuses (needed for in-place replacement) + let selected_pane_id_for_replacement = &state + .execution + .all_commands + .get(selected_index) + .and_then(|c| match c.get_status() { + CommandStatus::Running(pane_id) => pane_id, + CommandStatus::Exited(_, pane_id) => pane_id, + CommandStatus::Interrupted(pane_id) => pane_id, + _ => None, + }) + .or_else(|| { + if state.all_commands_are_pending() { + close_replaced_pane = false; // we should never close the original pane_id + state.original_pane_id + } else { + None + } + }); + + // Close all panes AFTER the selected one (selected will be replaced in-place) + for i in (selected_index + 1)..state.execution.all_commands.len() { + // Extract pane_id from the command status + let pane_id = state + .execution + .all_commands + .get(i) + .and_then(|c| match c.get_status() { + CommandStatus::Running(pane_id) => pane_id, + CommandStatus::Exited(_, pane_id) => pane_id, + CommandStatus::Interrupted(pane_id) => pane_id, + _ => None, + }); + + // Close the pane if we have a pane_id + if let Some(pane_id) = pane_id { + close_pane_with_id(pane_id); + } else { + eprintln!( + "Warning: Cannot close pane for command at index {}: pane_id is None", + i + ); + } + + // Reset the command status to Pending + state + .execution + .all_commands + .get_mut(i) + .map(|c| c.set_status(CommandStatus::Pending)); + } + + // Reset the selected pane's status to Pending (it will be replaced in-place) + state + .execution + .all_commands + .get_mut(selected_index) + .map(|c| c.set_status(CommandStatus::Pending)); + + // Set the current command index to the selected command + state.execution.current_running_command_index = selected_index; + + // Execute the command at the selected index + if let Some((command_text, chain_type, command_cwd)) = state + .execution + .all_commands + .get(selected_index) + .map(|c| (c.get_text(), c.get_chain_type(), c.get_cwd())) + { + let shell = state + .shell + .clone() + .unwrap_or_else(|| PathBuf::from("/bin/bash")); + + let command = zellij_tile::prelude::actions::RunCommandAction { + command: shell, + args: vec!["-ic".to_string(), command_text.trim().to_string()], + cwd: command_cwd, + hold_on_close: true, + ..Default::default() + }; + + // Determine placement - always replace the selected pane in-place if we have its ID + let placement = if let Some(pane_id) = selected_pane_id_for_replacement { + NewPanePlacement::InPlace { + pane_id_to_replace: Some(*pane_id), + close_replaced_pane, + } + } else { + let pane_id_to_stack_under = state + .execution + .all_commands + .iter() + .find_map(|c| c.get_pane_id()); + NewPanePlacement::Stacked(pane_id_to_stack_under) + }; + + // Determine unblock_condition based on whether this is the last command + let unblock_condition = if selected_index < state.execution.all_commands.len() - 1 { + // Not the last command - use the chain type's unblock condition + chain_type.to_unblock_condition() + } else { + // Last command - use UnblockCondition::OnAnyExit + Some(UnblockCondition::OnAnyExit) + }; + + let action = Action::NewBlockingPane { + placement, + command: Some(command), + pane_name: Some(command_text.trim().to_string()), + unblock_condition, + near_current_pane: true, + }; + + // Generate a new sequence ID for the restart + state.execution.sequence_id += 1; + + // Reset the stopped flag so the sequence can run + state.execution.is_running = true; + state.layout.needs_reposition = true; + state.execution.primary_pane_id_before_sequence = state.primary_pane_id; + + // Pass the sequence ID in the context + let mut context = BTreeMap::new(); + context.insert( + "sequence_id".to_string(), + state.execution.sequence_id.to_string(), + ); + context.insert("command_text".to_string(), command_text.to_string()); + run_action(action, context); + } +} + +fn interrupt_sequence(state: &mut State) { + if state.execution.is_running { + // Ctrl-C press when running - interrupt the running command + for command in state.execution.all_commands.iter_mut() { + if let CommandStatus::Running(pane_id) = command.get_status() { + if let Some(pane_id) = pane_id { + send_sigkill_to_pane_id(pane_id); + } + command.set_status(CommandStatus::Interrupted(pane_id)); + } + } + state.execution.is_running = false; + } else { + eprintln!("Cannot interrupt a sequence that is not running."); + } +} + +pub fn update_cursor(state: &mut State) { + // Calculate new cursor position + let new_coords = calculate_cursor_position(state); + + // Only update if the position changed + if new_coords != state.layout.cached_cursor_position { + match new_coords { + Some(coords) => show_cursor(Some(coords)), + None => show_cursor(None), + } + state.layout.cached_cursor_position = new_coords; + } +} + +pub fn update_title(state: &mut State) { + let Some(plugin_id) = state.plugin_id else { + return; + }; + + let title = if state.all_commands_are_pending() { + "Run one or more commands in sequence" + } else { + let has_running_commands = state + .execution + .all_commands + .iter() + .any(|c| matches!(c.get_status(), CommandStatus::Running(..))); + let has_interrupted_commands = state + .execution + .all_commands + .iter() + .any(|c| matches!(c.get_status(), CommandStatus::Interrupted(..))); + let all_commands_complete = state + .execution + .all_commands + .iter() + .all(|c| matches!(c.get_status(), CommandStatus::Exited(..))); + if has_running_commands { + let current = state.execution.current_running_command_index + 1; + let total = state.execution.all_commands.len(); + return rename_plugin_pane(plugin_id, &format!("Running {}/{}", current, total)); + } else if has_interrupted_commands { + "Sequence Interrupted" + } else if all_commands_complete { + "Sequence Complete" + } else { + "Stopped" + } + }; + rename_plugin_pane(plugin_id, title); +} diff --git a/default-plugins/sequence/src/path_formatting.rs b/default-plugins/sequence/src/path_formatting.rs new file mode 100644 index 000000000..01bf50e69 --- /dev/null +++ b/default-plugins/sequence/src/path_formatting.rs @@ -0,0 +1,71 @@ +use std::path::PathBuf; + +/// Expand a path string to an absolute PathBuf +/// Handles ~, ./, .., relative and absolute paths +pub fn expand_path(path_str: &str, current_cwd: Option<&PathBuf>) -> Option { + let expanded = if path_str.starts_with("~/") || path_str == "~" { + let home_dir = std::env::var("HOME").ok()?; + if path_str == "~" { + PathBuf::from(home_dir) + } else { + PathBuf::from(home_dir).join(&path_str[2..]) + } + } else if path_str.starts_with('/') { + PathBuf::from(path_str) + } else { + let base = current_cwd?; + base.join(path_str) + }; + + let mut normalized = PathBuf::new(); + for component in expanded.components() { + match component { + std::path::Component::ParentDir => { + normalized.pop(); + }, + std::path::Component::CurDir => {}, + _ => { + normalized.push(component); + }, + } + } + + Some(normalized) +} + +/// Format a path for display in the prompt +/// Example: /home/user/some/long/path -> ~/s/l/path +pub fn format_cwd(cwd: &PathBuf) -> String { + let path_str = cwd.to_string_lossy().to_string(); + + let home_dir = std::env::var("HOME").unwrap_or_default(); + let path_str = if !home_dir.is_empty() && path_str.starts_with(&home_dir) { + path_str.replacen(&home_dir, "~", 1) + } else { + path_str + }; + + let parts: Vec<&str> = path_str.split('/').collect(); + + if parts.len() <= 1 { + return path_str; + } + + let mut formatted_parts = Vec::new(); + for (i, part) in parts.iter().enumerate() { + if i == parts.len() - 1 { + formatted_parts.push(part.to_string()); + } else if part.is_empty() { + formatted_parts.push(String::new()); + } else { + formatted_parts.push(part.chars().next().unwrap_or_default().to_string()); + } + } + + formatted_parts.join("/") +} + +/// Alias for expand_path for backwards compatibility +pub fn resolve_path(current_cwd: Option<&PathBuf>, path_str: &str) -> Option { + expand_path(path_str, current_cwd) +} diff --git a/default-plugins/sequence/src/state/chain_type.rs b/default-plugins/sequence/src/state/chain_type.rs new file mode 100644 index 000000000..3da3316cb --- /dev/null +++ b/default-plugins/sequence/src/state/chain_type.rs @@ -0,0 +1,45 @@ +use serde::{Deserialize, Serialize}; +use zellij_tile::prelude::*; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum ChainType { + And, + Or, + Then, + None, +} + +impl Default for ChainType { + fn default() -> Self { + ChainType::None + } +} + +impl ChainType { + pub fn to_unblock_condition(&self) -> Option { + match self { + ChainType::And => Some(UnblockCondition::OnExitSuccess), + ChainType::Or => Some(UnblockCondition::OnExitFailure), + ChainType::Then => Some(UnblockCondition::OnAnyExit), + ChainType::None => None, + } + } + + pub fn as_str(&self) -> &str { + match self { + ChainType::And => "&&", + ChainType::Or => "||", + ChainType::Then => ";", + ChainType::None => "", + } + } + + pub fn cycle_next(&mut self) { + *self = match self { + ChainType::And => ChainType::Or, + ChainType::Or => ChainType::Then, + ChainType::Then => ChainType::And, + ChainType::None => ChainType::And, + }; + } +} diff --git a/default-plugins/sequence/src/state/command_entry.rs b/default-plugins/sequence/src/state/command_entry.rs new file mode 100644 index 000000000..96a0020b0 --- /dev/null +++ b/default-plugins/sequence/src/state/command_entry.rs @@ -0,0 +1,86 @@ +use super::{ChainType, CommandStatus}; +use std::path::PathBuf; +use std::time::Instant; +use zellij_tile::prelude::PaneId; + +#[derive(Debug, Clone)] +pub struct CommandEntry { + text: String, + cwd: Option, + pub(super) chain_type: ChainType, + pub(super) status: CommandStatus, + pub(super) start_time: std::time::Instant, +} + +impl Default for CommandEntry { + fn default() -> Self { + CommandEntry { + text: String::default(), + cwd: None, + chain_type: ChainType::default(), + status: CommandStatus::default(), + start_time: Instant::now(), + } + } +} + +impl CommandEntry { + pub fn new(text: &str, cwd: Option) -> Self { + CommandEntry { + text: text.to_owned(), + cwd, + ..Default::default() + } + } + pub fn with_and(mut self) -> Self { + self.chain_type = ChainType::And; + self + } + pub fn get_text(&self) -> String { + self.text.clone() + } + pub fn set_text(&mut self, text: String) { + self.text = text; + } + pub fn clear_text(&mut self) { + self.text.clear(); + } + pub fn get_chain_type(&self) -> ChainType { + self.chain_type + } + pub fn set_chain_type(&mut self, chain_type: ChainType) { + self.chain_type = chain_type; + } + pub fn get_status(&self) -> CommandStatus { + self.status.clone() + } + pub fn set_status(&mut self, status: CommandStatus) { + self.status = status; + } + pub fn get_pane_id(&self) -> Option { + self.status.get_pane_id() + } + pub fn is_empty(&self) -> bool { + self.text.trim().is_empty() + } + pub fn fill_chain_type_if_empty(&mut self) { + if let ChainType::None = self.chain_type { + self.chain_type = ChainType::And; + } + } + pub fn clear_chain_type(&mut self) { + self.chain_type = ChainType::None; + } + pub fn clear_status(&mut self) { + self.status = CommandStatus::Pending; + } + pub fn cycle_chain_type(&mut self) { + self.chain_type.cycle_next(); + } + pub fn get_cwd(&self) -> Option { + self.cwd.clone() + } + pub fn set_cwd(&mut self, cwd: Option) { + self.cwd = cwd; + } +} diff --git a/default-plugins/sequence/src/state/command_parser.rs b/default-plugins/sequence/src/state/command_parser.rs new file mode 100644 index 000000000..7f0898f53 --- /dev/null +++ b/default-plugins/sequence/src/state/command_parser.rs @@ -0,0 +1,327 @@ +use super::ChainType; + +#[derive(Debug, Clone, Copy, PartialEq)] +enum ParseState { + Normal, + InSingleQuote, + InDoubleQuote, + Escaped(EscapeContext), +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum EscapeContext { + Normal, + DoubleQuote, +} + +pub fn split_by_chain_operators(text: &str) -> Vec<(String, Option)> { + let mut segments = Vec::new(); + let mut current_segment = String::new(); + let mut state = ParseState::Normal; + let chars: Vec = text.chars().collect(); + let mut i = 0; + + while i < chars.len() { + let ch = chars[i]; + + match state { + ParseState::Normal => { + if ch == '\\' { + state = ParseState::Escaped(EscapeContext::Normal); + current_segment.push(ch); + i += 1; + } else if ch == '\'' { + state = ParseState::InSingleQuote; + current_segment.push(ch); + i += 1; + } else if ch == '"' { + state = ParseState::InDoubleQuote; + current_segment.push(ch); + i += 1; + } else if ch == '&' && i + 1 < chars.len() && chars[i + 1] == '&' { + let segment_text = current_segment.trim().to_string(); + if !segment_text.is_empty() { + segments.push((segment_text, Some(ChainType::And))); + } + current_segment.clear(); + i += 2; + } else if ch == '|' && i + 1 < chars.len() && chars[i + 1] == '|' { + let segment_text = current_segment.trim().to_string(); + if !segment_text.is_empty() { + segments.push((segment_text, Some(ChainType::Or))); + } + current_segment.clear(); + i += 2; + } else if ch == ';' { + let segment_text = current_segment.trim().to_string(); + if !segment_text.is_empty() { + segments.push((segment_text, Some(ChainType::Then))); + } + current_segment.clear(); + i += 1; + } else { + current_segment.push(ch); + i += 1; + } + }, + ParseState::InSingleQuote => { + current_segment.push(ch); + if ch == '\'' { + state = ParseState::Normal; + } + i += 1; + }, + ParseState::InDoubleQuote => { + if ch == '\\' { + state = ParseState::Escaped(EscapeContext::DoubleQuote); + current_segment.push(ch); + i += 1; + } else if ch == '"' { + current_segment.push(ch); + state = ParseState::Normal; + i += 1; + } else { + current_segment.push(ch); + i += 1; + } + }, + ParseState::Escaped(context) => { + current_segment.push(ch); + state = match context { + EscapeContext::Normal => ParseState::Normal, + EscapeContext::DoubleQuote => ParseState::InDoubleQuote, + }; + i += 1; + }, + } + } + + let final_segment = current_segment.trim().to_string(); + if !final_segment.is_empty() { + segments.push((final_segment, None)); + } + + segments +} + +pub fn detect_chain_operator_at_end(text: &str) -> Option<(String, ChainType)> { + let segments = split_by_chain_operators(text); + + if segments.is_empty() { + return None; + } + + if segments.len() == 1 { + if let Some((text, Some(chain_type))) = segments.first() { + return Some((text.clone(), *chain_type)); + } + return None; + } + + if let Some((first_text, Some(chain_type))) = segments.first() { + return Some((first_text.clone(), *chain_type)); + } + + None +} + +pub fn get_remaining_after_first_segment(text: &str) -> Option { + let segments = split_by_chain_operators(text); + + if segments.len() <= 1 { + return None; + } + + let mut result = String::new(); + for (i, (segment_text, chain_type_opt)) in segments.iter().enumerate().skip(1) { + if i > 1 { + if let Some(chain_type) = chain_type_opt { + result.push_str(&format!(" {} ", chain_type.as_str())); + } + } + result.push_str(segment_text); + if let Some(chain_type) = chain_type_opt { + result.push_str(&format!(" {} ", chain_type.as_str())); + } + } + + Some(result.trim().to_string()) +} + +pub fn detect_cd_command(text: &str) -> Option { + let trimmed = text.trim(); + + if trimmed == "cd" { + return Some("~".to_string()); + } + + if trimmed.starts_with("cd ") { + let path = trimmed[3..].trim(); + return Some(path.to_string()); + } + + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_single_command_no_operator() { + let result = split_by_chain_operators("ls"); + assert_eq!(result, vec![("ls".to_string(), None)]); + } + + #[test] + fn test_two_commands_with_and() { + let result = split_by_chain_operators("ls && pwd"); + assert_eq!( + result, + vec![ + ("ls".to_string(), Some(ChainType::And)), + ("pwd".to_string(), None) + ] + ); + } + + #[test] + fn test_two_commands_with_or() { + let result = split_by_chain_operators("cmd1 || cmd2"); + assert_eq!( + result, + vec![ + ("cmd1".to_string(), Some(ChainType::Or)), + ("cmd2".to_string(), None) + ] + ); + } + + #[test] + fn test_two_commands_with_semicolon() { + let result = split_by_chain_operators("echo hi ; ls"); + assert_eq!( + result, + vec![ + ("echo hi".to_string(), Some(ChainType::Then)), + ("ls".to_string(), None) + ] + ); + } + + #[test] + fn test_three_commands_mixed() { + let result = split_by_chain_operators("a && b || c"); + assert_eq!( + result, + vec![ + ("a".to_string(), Some(ChainType::And)), + ("b".to_string(), Some(ChainType::Or)), + ("c".to_string(), None) + ] + ); + } + + #[test] + fn test_operator_in_single_quotes() { + let result = split_by_chain_operators("echo '&&' && ls"); + assert_eq!( + result, + vec![ + ("echo '&&'".to_string(), Some(ChainType::And)), + ("ls".to_string(), None) + ] + ); + } + + #[test] + fn test_operator_in_double_quotes() { + let result = split_by_chain_operators("echo \"||\" || pwd"); + assert_eq!( + result, + vec![ + ("echo \"||\"".to_string(), Some(ChainType::Or)), + ("pwd".to_string(), None) + ] + ); + } + + #[test] + fn test_escaped_operator() { + let result = split_by_chain_operators("echo \\&& test"); + assert_eq!(result, vec![("echo \\&& test".to_string(), None)]); + } + + #[test] + fn test_complex_quoting() { + let result = split_by_chain_operators("cmd1 && echo \"a || b\" && cmd2"); + assert_eq!( + result, + vec![ + ("cmd1".to_string(), Some(ChainType::And)), + ("echo \"a || b\"".to_string(), Some(ChainType::And)), + ("cmd2".to_string(), None) + ] + ); + } + + #[test] + fn test_empty_segments_filtered() { + let result = split_by_chain_operators("cmd1 && && cmd2"); + assert_eq!( + result, + vec![ + ("cmd1".to_string(), Some(ChainType::And)), + ("cmd2".to_string(), None) + ] + ); + } + + #[test] + fn test_detect_operator_just_typed_and() { + let result = detect_chain_operator_at_end("ls &&"); + assert_eq!(result, Some(("ls".to_string(), ChainType::And))); + } + + #[test] + fn test_detect_operator_just_typed_or() { + let result = detect_chain_operator_at_end("cmd ||"); + assert_eq!(result, Some(("cmd".to_string(), ChainType::Or))); + } + + #[test] + fn test_detect_operator_just_typed_semicolon() { + let result = detect_chain_operator_at_end("echo ;"); + assert_eq!(result, Some(("echo".to_string(), ChainType::Then))); + } + + #[test] + fn test_detect_operator_no_operator() { + let result = detect_chain_operator_at_end("ls"); + assert_eq!(result, None); + } + + #[test] + fn test_detect_operator_in_quotes() { + let result = detect_chain_operator_at_end("echo '&&'"); + assert_eq!(result, None); + } + + #[test] + fn test_whitespace_trimming() { + let result = split_by_chain_operators(" cmd1 && cmd2 "); + assert_eq!( + result, + vec![ + ("cmd1".to_string(), Some(ChainType::And)), + ("cmd2".to_string(), None) + ] + ); + } + + #[test] + fn test_trailing_operator_with_space() { + let result = split_by_chain_operators("ls && "); + assert_eq!(result, vec![("ls".to_string(), Some(ChainType::And))]); + } +} diff --git a/default-plugins/sequence/src/state/command_status.rs b/default-plugins/sequence/src/state/command_status.rs new file mode 100644 index 000000000..39717e8bb --- /dev/null +++ b/default-plugins/sequence/src/state/command_status.rs @@ -0,0 +1,26 @@ +use zellij_tile::prelude::*; + +#[derive(Debug, Clone)] +pub enum CommandStatus { + Exited(Option, Option), + Running(Option), + Pending, + Interrupted(Option), +} + +impl CommandStatus { + pub fn get_pane_id(&self) -> Option { + match self { + CommandStatus::Exited(_, pane_id) => *pane_id, + CommandStatus::Running(pane_id) => *pane_id, + CommandStatus::Pending => None, + CommandStatus::Interrupted(pane_id) => *pane_id, + } + } +} + +impl Default for CommandStatus { + fn default() -> Self { + CommandStatus::Pending + } +} diff --git a/default-plugins/sequence/src/state/editing.rs b/default-plugins/sequence/src/state/editing.rs new file mode 100644 index 000000000..3deac619c --- /dev/null +++ b/default-plugins/sequence/src/state/editing.rs @@ -0,0 +1,80 @@ +use crate::path_formatting; +use crate::state::CommandEntry; +use crate::ui::text_input::TextInput; +use std::path::PathBuf; + +pub struct Editing { + pub editing_input: Option, +} + +impl Editing { + pub fn new() -> Self { + Self { + editing_input: Some(TextInput::new("".to_owned())), + } + } + + pub fn start_editing(&mut self, text: String) { + self.editing_input = Some(TextInput::new(text)); + } + + pub fn cancel_editing(&mut self) { + self.editing_input = None; + } + + pub fn input_text(&self) -> Option { + self.editing_input.as_ref().map(|e| e.get_text().to_owned()) + } + + pub fn set_input_text(&mut self, text: String) { + self.editing_input.as_mut().map(|e| e.set_text(text)); + } + + pub fn handle_submit( + &mut self, + selection_index: Option, + all_commands: &mut Vec, + current_cwd: &Option, + ) -> (bool, Option) { + let mut handled_internally = false; + let mut new_selection_index = None; + + if let Some(current_text) = self.editing_input.as_ref().map(|i| i.get_text()) { + if let Some(index) = selection_index { + if let Some(command) = all_commands.get_mut(index) { + if current_text.starts_with("cd ") || current_text == "cd" { + let path = if current_text == "cd" { + "~" + } else { + current_text[3..].trim() + }; + + if let Some(new_cwd) = + path_formatting::resolve_path(current_cwd.as_ref(), path) + { + command.set_cwd(Some(new_cwd)); + } + + command.set_text("".to_owned()); + self.editing_input.as_mut().map(|c| c.clear()); + new_selection_index = selection_index; // remain editing after a cd command + handled_internally = true; + return (handled_internally, new_selection_index); // avoid setting edit_input to None below, we + // still want to be in editing mode after + // changing directory with cd + } else { + command.set_text(current_text.to_owned()); + } + } + } + } + self.editing_input = None; + (handled_internally, new_selection_index) + } +} + +impl Default for Editing { + fn default() -> Self { + Self::new() + } +} diff --git a/default-plugins/sequence/src/state/execution.rs b/default-plugins/sequence/src/state/execution.rs new file mode 100644 index 000000000..ff630ec03 --- /dev/null +++ b/default-plugins/sequence/src/state/execution.rs @@ -0,0 +1,265 @@ +use crate::path_formatting::format_cwd; +use crate::state::{ChainType, CommandEntry, CommandStatus}; +use std::collections::BTreeMap; +use std::path::PathBuf; +use std::time::Duration; +use zellij_tile::prelude::*; + +pub struct Execution { + pub all_commands: Vec, + pub current_running_command_index: usize, + pub is_running: bool, + pub sequence_id: u64, + pub primary_pane_id_before_sequence: Option, +} + +impl Execution { + pub fn new() -> Self { + Self { + all_commands: vec![CommandEntry::default()], + current_running_command_index: 0, + is_running: false, + sequence_id: 0, + primary_pane_id_before_sequence: None, + } + } + + pub fn longest_cwd_display(&self, global_cwd: &Option) -> String { + self.all_commands + .iter() + .map(|cmd| { + let cwd = cmd.get_cwd().or_else(|| global_cwd.clone()); + if let Some(cwd) = &cwd { + format_cwd(cwd) + } else { + "~".to_string() + } + }) + .max_by_key(|s| s.len()) + .unwrap_or_else(|| "~".to_string()) + } + + pub fn remove_empty_commands(&mut self) { + if self.all_commands.iter().len() > 1 { + self.all_commands.retain(|c| !c.get_text().is_empty()); + } + } + + pub fn get_first_command(&self) -> Option { + self.all_commands.iter().next().cloned() + } + + pub fn set_command_status(&mut self, command_index: usize, status: CommandStatus) { + self.all_commands + .get_mut(command_index) + .map(|c| c.set_status(status)); + } + + pub fn set_current_running_command_status(&mut self, status: CommandStatus) { + self.all_commands + .get_mut(self.current_running_command_index) + .map(|c| c.set_status(status)); + } + + pub fn get_current_running_command_status(&self) -> Option { + self.all_commands + .get(self.current_running_command_index) + .map(|c| c.get_status()) + } + + pub fn can_run_sequence(&self) -> bool { + self.all_commands.iter().any(|command| !command.is_empty()) + } + + pub fn copy_to_clipboard(&self) { + let text_to_copy = self + .all_commands + .iter() + .map(|c| format!("{}", c.get_text())) + .collect::>() + .join("\n"); + if !text_to_copy.is_empty() { + copy_to_clipboard(text_to_copy); + } + } + + pub fn update_pane_id_for_command(&mut self, pane_id: PaneId, command_text: &str) { + for command in self.all_commands.iter_mut() { + if let CommandStatus::Pending | CommandStatus::Running(None) = command.get_status() { + let cmd_text = command.get_text(); + if cmd_text == command_text { + command.set_status(CommandStatus::Running(Some(pane_id))); + break; + } + } + } + } + + pub fn update_exited_command_statuses(&mut self, pane_manifest: &PaneManifest) -> bool { + let mut updated = false; + for command in self.all_commands.iter_mut() { + let status = command.get_status(); + let pane_id_opt = match &status { + CommandStatus::Running(pid) => *pid, + CommandStatus::Exited(_, pid) => *pid, + CommandStatus::Interrupted(pid) => *pid, + _ => None, + }; + + if let Some(pane_id) = pane_id_opt { + let mut pane_found = false; + for (_tab_index, panes) in &pane_manifest.panes { + for pane_info in panes { + let pane_matches = match pane_id { + PaneId::Terminal(id) => !pane_info.is_plugin && pane_info.id == id, + PaneId::Plugin(id) => pane_info.is_plugin && pane_info.id == id, + }; + + if pane_matches { + pane_found = true; + if pane_info.exited { + command.set_status(CommandStatus::Exited( + pane_info.exit_status, + Some(pane_id), + )); + updated = true; + } + break; + } + } + if pane_found { + break; + } + } + + if !pane_found && command.start_time.elapsed() > Duration::from_millis(400) { + match command.get_status() { + CommandStatus::Running(_) => { + eprintln!( + "Pane {:?} was closed while running, setting pane_id to None", + pane_id + ); + command.set_status(CommandStatus::Running(None)); + updated = true; + }, + CommandStatus::Exited(exit_code, _) => { + eprintln!( + "Pane {:?} was closed after exiting, setting pane_id to None", + pane_id + ); + command.set_status(CommandStatus::Exited(exit_code, None)); + updated = true; + }, + CommandStatus::Interrupted(_) => { + eprintln!("Pane {:?} was closed after being interrupted, setting pane_id to None", pane_id); + command.set_status(CommandStatus::Interrupted(None)); + updated = true; + }, + _ => {}, + } + } + } + } + updated + } + + pub fn update_sequence_stopped_state(&mut self) -> bool { + let mut needs_rerender = false; + if self.is_running { + let current_idx = self.current_running_command_index; + if let Some(command) = self.all_commands.get_mut(current_idx) { + if let CommandStatus::Exited(exit_code, _) = command.get_status() { + let should_stop; + if current_idx >= self.all_commands.len().saturating_sub(1) { + should_stop = true; + } else { + if let Some(chain_type) = &self + .all_commands + .get(current_idx) + .map(|c| c.get_chain_type()) + { + match chain_type { + ChainType::And => { + should_stop = exit_code.unwrap_or(0) != 0; + }, + ChainType::Or => { + should_stop = exit_code.unwrap_or(0) == 0; + }, + ChainType::Then => { + should_stop = false; + }, + ChainType::None => { + should_stop = true; + }, + } + } else { + should_stop = true; + } + }; + if should_stop { + self.is_running = false; + } + } + } + needs_rerender = true; + } + needs_rerender + } + + pub fn execute_command_sequence( + &mut self, + shell: &Option, + global_cwd: &Option, + primary_pane_id: Option, + ) { + use zellij_tile::prelude::actions::{Action, RunCommandAction}; + + self.all_commands.retain(|c| !c.is_empty()); + + let Some(first_active_sequence_command) = self.get_first_command() else { + return; + }; + + let shell = shell.clone().unwrap_or_else(|| PathBuf::from("/bin/bash")); + + let first_command = first_active_sequence_command.get_text(); + let first_chain_type = first_active_sequence_command.get_chain_type(); + let command_cwd = first_active_sequence_command + .get_cwd() + .or_else(|| global_cwd.clone()); + + let command = RunCommandAction { + command: shell.clone(), + args: vec!["-ic".to_string(), first_command.trim().to_string()], + cwd: command_cwd, + hold_on_close: true, + ..Default::default() + }; + + let placement = NewPanePlacement::InPlace { + pane_id_to_replace: primary_pane_id, + close_replaced_pane: false, + }; + + let action = Action::NewBlockingPane { + placement, + command: Some(command), + pane_name: Some(first_command.trim().to_string()), + unblock_condition: first_chain_type.to_unblock_condition(), + near_current_pane: true, + }; + + self.sequence_id += 1; + + let mut context = BTreeMap::new(); + context.insert("sequence_id".to_string(), self.sequence_id.to_string()); + run_action(action, context); + self.set_command_status(0, CommandStatus::Running(None)); + } +} + +impl Default for Execution { + fn default() -> Self { + Self::new() + } +} diff --git a/default-plugins/sequence/src/state/layout.rs b/default-plugins/sequence/src/state/layout.rs new file mode 100644 index 000000000..65a267e02 --- /dev/null +++ b/default-plugins/sequence/src/state/layout.rs @@ -0,0 +1,73 @@ +use crate::state::positioning; +use std::path::PathBuf; +use zellij_tile::prelude::*; + +pub struct Layout { + pub needs_reposition: bool, + pub cached_cursor_position: Option<(usize, usize)>, + pub spinner_frame: usize, + pub spinner_timer_scheduled: bool, +} + +impl Layout { + pub fn new() -> Self { + Self { + needs_reposition: false, + cached_cursor_position: None, + spinner_frame: 0, + spinner_timer_scheduled: false, + } + } + + pub fn reposition_plugin_based_on_sequence_state( + &mut self, + is_running: bool, + first_command_pane_id: Option, + pane_manifest: &PaneManifest, + plugin_id: Option, + total_viewport_columns: Option, + total_viewport_rows: Option, + total_commands: usize, + _selected_index: Option, + _running_index: usize, + _cwd: &Option, + ) { + let Some(plugin_id) = plugin_id else { + return; + }; + let (Some(total_cols), Some(total_rows)) = (total_viewport_columns, total_viewport_rows) + else { + return; + }; + + if !self.needs_reposition || !is_running { + return; + } + + let Some(first_pane_id) = first_command_pane_id else { + return; + }; + + for (_tab_index, panes) in &pane_manifest.panes { + for pane in panes { + if !pane.is_plugin && PaneId::Terminal(pane.id) == first_pane_id { + positioning::reposition_plugin_for_sequence( + plugin_id, + total_cols, + total_rows, + total_commands, + ); + + self.needs_reposition = false; + return; + } + } + } + } +} + +impl Default for Layout { + fn default() -> Self { + Self::new() + } +} diff --git a/default-plugins/sequence/src/state/mod.rs b/default-plugins/sequence/src/state/mod.rs new file mode 100644 index 000000000..19738be76 --- /dev/null +++ b/default-plugins/sequence/src/state/mod.rs @@ -0,0 +1,446 @@ +mod chain_type; +mod command_entry; +mod command_parser; +mod command_status; +mod editing; +mod execution; +mod layout; +pub mod positioning; +mod selection; + +pub use chain_type::ChainType; +pub use command_entry::CommandEntry; +pub use command_parser::{ + detect_cd_command, detect_chain_operator_at_end, get_remaining_after_first_segment, + split_by_chain_operators, +}; +pub use command_status::CommandStatus; +pub use editing::Editing; +pub use execution::Execution; +pub use layout::Layout; +pub use selection::Selection; + +use crate::ui::text_input::TextInput; +use std::path::PathBuf; +use zellij_tile::prelude::*; + +pub struct State { + pub shell: Option, + pub plugin_id: Option, + pub client_id: Option, + pub own_rows: Option, + pub own_columns: Option, + pub cwd: Option, + pub original_pane_id: Option, + pub primary_pane_id: Option, + pub is_first_run: bool, + pub pane_manifest: Option, + pub total_viewport_columns: Option, + pub total_viewport_rows: Option, + pub selection: Selection, + pub editing: Editing, + pub execution: Execution, + pub layout: Layout, + pub current_position: Option, +} + +impl State { + pub fn new() -> Self { + Self { + shell: None, + plugin_id: None, + client_id: None, + own_rows: None, + own_columns: None, + cwd: None, + original_pane_id: None, + primary_pane_id: None, + is_first_run: true, + pane_manifest: None, + total_viewport_columns: None, + total_viewport_rows: None, + selection: Selection::new(), + editing: Editing::new(), + execution: Execution::new(), + layout: Layout::new(), + current_position: None, + } + } + + pub fn set_plugin_id(&mut self, plugin_id: u32) { + self.plugin_id = Some(plugin_id); + } + + /// Check if the sequence has finished executing (all commands are done) + pub fn has_finished(&self) -> bool { + self.execution + .all_commands + .iter() + .all(|command| matches!(command.status, CommandStatus::Exited(_, _))) + } + pub fn add_empty_command_after_current_selected(&mut self) { + self.selection.add_empty_command_after_current_selected( + &mut self.execution.all_commands, + &mut self.editing, + &self.cwd, + ); + } + + pub fn current_selected_command_is_empty(&self) -> bool { + self.selection + .current_selected_command_is_empty(&self.execution.all_commands, &self.editing) + } + + pub fn remove_current_selected_command(&mut self) { + let removed_pane_id = self + .selection + .remove_current_selected_command(&mut self.execution.all_commands, &mut self.editing); + if let Some(removed_pane_id) = removed_pane_id { + close_pane_with_id(removed_pane_id); + } + } + + pub fn clear_current_selected_command(&mut self) { + self.selection + .clear_current_selected_command(&mut self.execution.all_commands, &mut self.editing); + } + + pub fn move_selection_up(&mut self) { + self.selection + .move_up(&mut self.execution.all_commands, &mut self.editing); + if let Some(pane_id) = self + .current_selected_command() + .and_then(|c| c.get_pane_id()) + { + show_pane_with_id(pane_id, true, false); + } + } + + pub fn move_selection_down(&mut self) { + self.selection + .move_down(&mut self.execution.all_commands, &mut self.editing); + if let Some(pane_id) = self + .current_selected_command() + .and_then(|c| c.get_pane_id()) + { + show_pane_with_id(pane_id, true, false); + } + } + pub fn start_editing_selected(&mut self) { + if let Some(current_command_text) = self.current_selected_command().map(|c| c.get_text()) { + self.editing.start_editing(current_command_text); + } + } + + pub fn cancel_editing_selected(&mut self) { + self.editing.cancel_editing(); + } + + pub fn editing_input_text(&self) -> Option { + self.editing.input_text() + } + + pub fn set_editing_input_text(&mut self, text: String) { + self.editing.set_input_text(text); + } + fn handle_first_pasted_segment( + &mut self, + current_text: &str, + segment_text: &str, + chain_type_opt: &Option, + ) { + let new_text = if current_text.trim().is_empty() { + segment_text.to_string() + } else { + format!("{}{}", current_text, segment_text) + }; + + if let Some(path) = detect_cd_command(&new_text) { + use crate::path_formatting; + if let Some(new_cwd) = path_formatting::resolve_path(self.cwd.as_ref(), &path) { + self.current_selected_command_mut().map(|c| { + c.set_cwd(Some(new_cwd)); + c.set_text("".to_owned()); + if let Some(chain_type) = chain_type_opt { + c.set_chain_type(*chain_type); + } + }); + return; + } + } + + self.current_selected_command_mut().map(|c| { + c.set_text(new_text); + if let Some(chain_type) = chain_type_opt { + c.set_chain_type(*chain_type); + } + }); + } + + fn insert_new_pasted_segment( + &mut self, + segment_text: &str, + chain_type_opt: &Option, + is_last_line: bool, + ) { + use crate::path_formatting; + + let cd_path = detect_cd_command(segment_text); + + if let Some(path) = cd_path { + if let Some(new_cwd) = path_formatting::resolve_path(self.cwd.as_ref(), &path) { + self.current_selected_command_mut().map(|c| { + c.set_cwd(Some(new_cwd)); + if let Some(chain_type) = chain_type_opt { + c.set_chain_type(*chain_type); + } + }); + return; + } + } + + let Some(new_selected_index) = self.selection.current_selected_command_index.map(|i| i + 1) + else { + return; + }; + + let mut new_command = CommandEntry::new(segment_text, self.cwd.clone()); + if let Some(chain_type) = chain_type_opt { + new_command.set_chain_type(*chain_type); + } else if !is_last_line { + new_command.set_chain_type(ChainType::And); + } + + self.execution + .all_commands + .insert(new_selected_index, new_command); + self.selection.current_selected_command_index = Some(new_selected_index); + } + + fn ensure_line_end_chain_type(&mut self) { + if let Some(last_cmd_index) = self.selection.current_selected_command_index { + self.execution + .all_commands + .get_mut(last_cmd_index) + .map(|c| { + if matches!(c.get_chain_type(), ChainType::None) { + c.set_chain_type(ChainType::And); + } + }); + } + } + + pub fn pasted_lines(&mut self, lines: Vec<&str>) { + let Some(current_text) = self.editing_input_text() else { + return; + }; + + for (line_index, line) in lines.iter().enumerate() { + let segments = split_by_chain_operators(line); + let is_last_line = line_index == lines.len().saturating_sub(1); + + for (seg_index, (segment_text, chain_type_opt)) in segments.iter().enumerate() { + if line_index == 0 && seg_index == 0 { + self.handle_first_pasted_segment(¤t_text, segment_text, chain_type_opt); + } else { + self.insert_new_pasted_segment(segment_text, chain_type_opt, is_last_line); + } + } + + if !is_last_line { + self.ensure_line_end_chain_type(); + } + } + + self.start_editing_selected(); + } + pub fn remove_empty_commands(&mut self) { + self.execution.remove_empty_commands(); + } + + pub fn get_first_command(&self) -> Option { + self.execution.get_first_command() + } + + pub fn set_command_status(&mut self, command_index: usize, status: CommandStatus) { + self.execution.set_command_status(command_index, status); + } + + pub fn set_current_running_command_status(&mut self, status: CommandStatus) { + self.execution.set_current_running_command_status(status); + } + + pub fn get_current_running_command_status(&mut self) -> Option { + self.execution.get_current_running_command_status() + } + + pub fn handle_editing_submit(&mut self, current_cwd: &Option) -> bool { + let (handled_internally, new_selection_index) = self.editing.handle_submit( + self.selection.current_selected_command_index, + &mut self.execution.all_commands, + current_cwd, + ); + self.selection.current_selected_command_index = new_selection_index; + handled_internally + } + + pub fn update_pane_id_for_command(&mut self, pane_id: PaneId, command_text: &str) { + self.execution + .update_pane_id_for_command(pane_id, command_text); + } + pub fn update_exited_command_statuses(&mut self, pane_manifest: &PaneManifest) -> bool { + self.execution.update_exited_command_statuses(pane_manifest) + } + pub fn update_sequence_stopped_state(&mut self) -> bool { + self.execution.update_sequence_stopped_state() + } + + pub fn cycle_chain_type(&mut self) { + self.current_selected_command_mut() + .map(|c| c.cycle_chain_type()); + } + + pub fn set_primary_pane_id_before_sequence(&mut self, pane_id: Option) { + if pane_id.is_some() { + self.execution.primary_pane_id_before_sequence = pane_id; + } + } + pub fn clear_all_commands(&mut self) { + self.execution.all_commands = vec![CommandEntry::new("", self.cwd.clone())]; + self.editing.editing_input = Some(TextInput::new("".to_owned())); + self.selection.current_selected_command_index = Some(0); + self.execution.current_running_command_index = 0; + } + pub fn update_running_state(&mut self, primary_pane_id: Option) { + self.remove_empty_commands(); + self.set_primary_pane_id_before_sequence(primary_pane_id); + self.layout.needs_reposition = true; + self.execution.is_running = true; + } + + pub fn can_run_sequence(&self) -> bool { + self.execution.can_run_sequence() + } + + pub fn copy_to_clipboard(&mut self) { + self.execution.copy_to_clipboard(); + } + + pub fn current_selected_command_mut(&mut self) -> Option<&mut CommandEntry> { + let Some(i) = self.selection.current_selected_command_index else { + return None; + }; + self.execution.all_commands.get_mut(i) + } + pub fn reposition_plugin(&mut self) -> bool { + let mut repositioned = false; + let Some(plugin_id) = self.plugin_id else { + return repositioned; + }; + let Some(total_viewport_rows) = self.total_viewport_rows else { + return repositioned; + }; + let Some(total_viewport_columns) = self.total_viewport_columns else { + return repositioned; + }; + let total_commands = std::cmp::max(self.execution.all_commands.iter().len(), 1); + let height_padding = 7; + if self.all_commands_are_pending() { + let initial_height = total_commands + height_padding; + let y = total_viewport_rows.saturating_sub(initial_height) / 2; + let coordinates = FloatingPaneCoordinates::new( + Some(format!("25%")), + Some(format!("{}", y)), + Some(format!("50%")), + Some(format!("{}", initial_height)), + Some(false), // should not be pinned when running sequence + ); + coordinates.map(|coordinates| { + if Some(&coordinates) != self.current_position.as_ref() { + repositioned = true; + self.current_position = Some(coordinates.clone()); + change_floating_panes_coordinates(vec![( + PaneId::Plugin(plugin_id), + coordinates, + )]); + } + }); + } else { + // Calculate longest table row width + let longest_cwd_display = self.execution.longest_cwd_display(&self.cwd); + let longest_command = self + .execution + .all_commands + .iter() + .map(|cmd| cmd.get_text().chars().count()) + .max() + .unwrap_or(1); + + let (max_chain_width, max_status_width) = crate::ui::components::calculate_max_widths( + &self.execution.all_commands, + self.layout.spinner_frame, + ); + + let longest_line = crate::ui::components::calculate_longest_line( + &longest_cwd_display, + longest_command, + max_chain_width, + max_status_width, + ); + + let ui_width = std::cmp::max(longest_line, 50) + 4; // 2 for ui-padding, 2 for pane frame + let width = std::cmp::min(ui_width, total_viewport_columns / 2); + + let height = (height_padding + total_commands).min((total_viewport_rows * 25) / 100); + + // Position: top-right with 1-space margins + let x = total_viewport_columns.saturating_sub(width); + let y = 1; + + let coordinates = FloatingPaneCoordinates::new( + Some(x.to_string()), + Some(y.to_string()), + Some(width.to_string()), + Some(height.to_string()), + Some(true), // should be pinned for sequence + ); + coordinates.map(|coordinates| { + if Some(&coordinates) != self.current_position.as_ref() { + self.current_position = Some(coordinates.clone()); + repositioned = true; + change_floating_panes_coordinates(vec![( + PaneId::Plugin(plugin_id), + coordinates, + )]); + } + }); + } + repositioned + } + pub fn all_commands_are_pending(&self) -> bool { + self.execution + .all_commands + .iter() + .all(|command| matches!(command.get_status(), CommandStatus::Pending)) + } + + fn current_selected_command(&self) -> Option<&CommandEntry> { + let Some(i) = self.selection.current_selected_command_index else { + return None; + }; + self.execution.all_commands.get(i) + } + + pub fn execute_command_sequence(&mut self) { + self.execution + .execute_command_sequence(&self.shell, &self.cwd, self.primary_pane_id); + } +} + +impl Default for State { + fn default() -> Self { + let mut state = Self::new(); + state.is_first_run = true; + state + } +} diff --git a/default-plugins/sequence/src/state/positioning.rs b/default-plugins/sequence/src/state/positioning.rs new file mode 100644 index 000000000..6acadfff5 --- /dev/null +++ b/default-plugins/sequence/src/state/positioning.rs @@ -0,0 +1,48 @@ +use zellij_tile::prelude::*; + +pub fn reposition_plugin_for_sequence( + plugin_id: u32, + total_cols: usize, + total_rows: usize, + total_commands: usize, +) { + // Width: 30% of viewport + let width = std::cmp::max((total_cols * 30) / 100, 50); + + // Height: UI overhead + commands, capped at 25% of viewport + let overhead_rows = 6; + let height = (overhead_rows + total_commands).min((total_rows * 25) / 100); + + // Position: top-right with 1-space margins + let x = total_cols.saturating_sub(width); + let y = 1; + + change_floating_pane_coordinates_absolute( + plugin_id, + Some(x), + Some(y), + Some(width), + Some(height), + true, + ); +} + +pub fn change_floating_pane_coordinates_absolute( + own_plugin_id: u32, + x: Option, + y: Option, + width: Option, + height: Option, + should_be_pinned: bool, +) { + let coordinates = FloatingPaneCoordinates::new( + x.map(|x| x.to_string()), + y.map(|y| y.to_string()), + width.map(|width| width.to_string()), + height.map(|height| height.to_string()), + Some(should_be_pinned), + ); + if let Some(coordinates) = coordinates { + change_floating_panes_coordinates(vec![(PaneId::Plugin(own_plugin_id), coordinates)]); + } +} diff --git a/default-plugins/sequence/src/state/selection.rs b/default-plugins/sequence/src/state/selection.rs new file mode 100644 index 000000000..18f83bcd7 --- /dev/null +++ b/default-plugins/sequence/src/state/selection.rs @@ -0,0 +1,214 @@ +use crate::state::{CommandEntry, Editing}; +use std::path::PathBuf; +use zellij_tile::prelude::*; + +pub struct Selection { + pub current_selected_command_index: Option, + pub scroll_offset: usize, +} + +impl Selection { + pub fn new() -> Self { + Self { + current_selected_command_index: Some(0), + scroll_offset: 0, + } + } + + pub fn add_empty_command_after_current_selected( + &mut self, + all_commands: &mut Vec, + editing: &mut Editing, + cwd: &Option, + ) { + self.save_editing_buffer_to_current_selected(all_commands, editing); + editing.editing_input.as_mut().map(|i| i.clear()); + if !self.current_selected_command_is_empty(all_commands, editing) { + self.current_selected_command_mut(all_commands) + .map(|c| c.fill_chain_type_if_empty()); + + if let Some(current_selected_command_index) = self.current_selected_command_index.take() + { + let new_command = CommandEntry::new("", cwd.clone()); + if current_selected_command_index == all_commands.len().saturating_sub(1) { + all_commands.push(new_command); + } else { + all_commands.insert(current_selected_command_index + 1, new_command); + } + + self.current_selected_command_index = Some(current_selected_command_index + 1); + } + } + } + + pub fn current_selected_command_is_empty( + &self, + all_commands: &[CommandEntry], + editing: &Editing, + ) -> bool { + let text_input_is_empty = editing + .editing_input + .as_ref() + .map(|i| i.is_empty()) + .unwrap_or(true); + let current_selected_command_is_empty = self + .current_selected_command_index + .and_then(|i| all_commands.get(i).map(|c| c.is_empty())) + .unwrap_or(true); + text_input_is_empty && current_selected_command_is_empty + } + + pub fn remove_current_selected_command( + &mut self, + all_commands: &mut Vec, + editing: &mut Editing, + ) -> Option { + // returns the pane_id of the removed command, if any + let mut removed_pane_id = None; + let Some(mut current_selected_command_index) = self.current_selected_command_index else { + return removed_pane_id; + }; + if all_commands.len() > 1 && all_commands.len() > current_selected_command_index { + let command = all_commands.remove(current_selected_command_index); + removed_pane_id = command.get_pane_id(); + } else { + self.clear_current_selected_command(all_commands, editing); + } + if current_selected_command_index >= all_commands.len() + && current_selected_command_index > 0 + { + current_selected_command_index -= 1; + } + self.update_current_selected_command_index( + current_selected_command_index, + all_commands, + editing, + ); + if current_selected_command_index == all_commands.len().saturating_sub(1) { + self.current_selected_command_mut(all_commands) + .map(|c| c.clear_chain_type()); + } + removed_pane_id + } + + pub fn clear_current_selected_command( + &mut self, + all_commands: &mut [CommandEntry], + editing: &mut Editing, + ) { + let Some(current_selected_command_index) = self.current_selected_command_index else { + return; + }; + self.current_selected_command_mut(all_commands) + .map(|c| c.clear_text()); + self.clear_editing_buffer(editing); + if current_selected_command_index == all_commands.len().saturating_sub(1) { + self.current_selected_command_mut(all_commands) + .map(|c| c.clear_chain_type()); + } + } + + pub fn move_up(&mut self, all_commands: &mut [CommandEntry], editing: &mut Editing) { + self.save_editing_buffer_to_current_selected(all_commands, editing); + match self.current_selected_command_index.as_mut() { + Some(i) if *i > 0 => { + *i -= 1; + }, + None => { + self.current_selected_command_index = Some(all_commands.len().saturating_sub(1)); + }, + _ => { + self.current_selected_command_index = None; + }, + } + self.update_editing_buffer_to_current_selected(all_commands, editing); + } + + pub fn move_down(&mut self, all_commands: &mut [CommandEntry], editing: &mut Editing) { + self.save_editing_buffer_to_current_selected(all_commands, editing); + match self.current_selected_command_index.as_mut() { + Some(i) if *i < all_commands.len().saturating_sub(1) => { + *i += 1; + }, + None => { + self.current_selected_command_index = Some(0); + }, + _ => { + self.current_selected_command_index = None; + }, + } + self.update_editing_buffer_to_current_selected(all_commands, editing); + } + + fn current_selected_command_mut<'a>( + &self, + all_commands: &'a mut [CommandEntry], + ) -> Option<&'a mut CommandEntry> { + let Some(i) = self.current_selected_command_index else { + return None; + }; + all_commands.get_mut(i) + } + + fn current_selected_command<'a>( + &self, + all_commands: &'a [CommandEntry], + ) -> Option<&'a CommandEntry> { + let Some(i) = self.current_selected_command_index else { + return None; + }; + all_commands.get(i) + } + + fn clear_editing_buffer(&self, editing: &mut Editing) { + editing.editing_input.as_mut().map(|c| c.clear()); + } + + fn update_current_selected_command_index( + &mut self, + new_index: usize, + all_commands: &[CommandEntry], + editing: &mut Editing, + ) { + self.current_selected_command_index = Some(new_index); + self.update_editing_buffer_to_current_selected(all_commands, editing); + } + + fn get_text_of_current_selected_command( + &self, + all_commands: &[CommandEntry], + ) -> Option { + self.current_selected_command(all_commands) + .map(|c| c.get_text()) + } + + fn save_editing_buffer_to_current_selected( + &self, + all_commands: &mut [CommandEntry], + editing: &mut Editing, + ) { + if let Some(text_input) = editing.editing_input.as_ref().map(|i| i.get_text()) { + self.current_selected_command_mut(all_commands) + .map(|c| c.set_text(text_input.to_owned())); + } + } + + fn update_editing_buffer_to_current_selected( + &self, + all_commands: &[CommandEntry], + editing: &mut Editing, + ) { + let new_text_of_current_selected_command = self + .get_text_of_current_selected_command(all_commands) + .unwrap_or_else(|| String::new()); + if let Some(editing_input) = editing.editing_input.as_mut() { + editing_input.set_text(new_text_of_current_selected_command); + } + } +} + +impl Default for Selection { + fn default() -> Self { + Self::new() + } +} diff --git a/default-plugins/sequence/src/ui/components.rs b/default-plugins/sequence/src/ui/components.rs new file mode 100644 index 000000000..3fe2ae1a0 --- /dev/null +++ b/default-plugins/sequence/src/ui/components.rs @@ -0,0 +1,596 @@ +use crate::path_formatting::format_cwd; +use crate::state::{CommandStatus, State}; +use crate::ui::truncation::{calculate_available_cmd_width, truncate_middle}; +use std::path::PathBuf; +use zellij_tile::prelude::*; + +const SPINNER_FRAMES: &[&str] = &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧"]; + +const HELP_RUNNING_WITH_SELECTION: &str = " - interrupt, - run from selected"; +const HELP_RUNNING_NO_SELECTION: &str = " - interrupt, <↓↑> - navigate"; +const HELP_STOPPED_WITH_SELECTION: &str = + " - close all, - run from selected, - edit"; +const HELP_STOPPED_NO_SELECTION: &str = + " - close all, <↓↑> - navigate, - run from first"; + +const HELP_ONE_PENDING_COMMAND: &str = " - run, - add command"; + +const HELP_ALL_COMMANDS_PENDING: &str = + " - run, - add command, <↓↑> - navigate"; +const HELP_ALL_COMMANDS_PENDING_WITH_SELECTION: &str = + " - run, - add command, <↓↑> - navigate, - edit selected"; + +const HELP_EDITING_FIRST_LINE: &str = + " - accept, - add command, <↓↑> - navigate"; + +fn select_help_text(sequence: &State) -> &'static str { + let is_running = sequence + .execution + .all_commands + .iter() + .any(|command| matches!(command.get_status(), CommandStatus::Running(_))); + let all_pending = sequence + .execution + .all_commands + .iter() + .all(|command| matches!(command.get_status(), CommandStatus::Pending)); + let has_selection = sequence.selection.current_selected_command_index.is_some(); + let is_editing = sequence.editing.editing_input.is_some(); + + if all_pending && !sequence.execution.is_running { + if sequence.execution.all_commands.len() == 1 { + HELP_ONE_PENDING_COMMAND + } else if has_selection && !is_editing { + HELP_ALL_COMMANDS_PENDING_WITH_SELECTION + } else if is_editing { + HELP_EDITING_FIRST_LINE + } else { + HELP_ALL_COMMANDS_PENDING + } + } else if is_running { + if has_selection { + HELP_RUNNING_WITH_SELECTION + } else { + HELP_RUNNING_NO_SELECTION + } + } else { + if has_selection && !is_editing { + HELP_STOPPED_WITH_SELECTION + } else if is_editing { + HELP_EDITING_FIRST_LINE + } else { + HELP_STOPPED_NO_SELECTION + } + } +} + +fn style_help_text(text: &str) -> Text { + Text::new(text) + .color_substring(3, "") + .color_substring(3, "") + .color_substring(3, "<↓↑>") + .color_substring(3, "") + .color_substring(3, "") + .color_substring(3, "") + .color_substring(3, "") +} + +pub fn render_help_lines( + sequence: &State, + max_width: Option, +) -> (Text, usize, Option<(Text, usize)>) { + let is_editing = sequence.editing.editing_input.is_some(); + + if is_editing { + let help_text = select_help_text(sequence); + let (truncated_text, help_len) = if let Some(width) = max_width { + truncate_help_line(help_text, width) + } else { + (help_text.to_string(), help_text.chars().count()) + }; + let first_line = (style_help_text(&truncated_text).unbold_all(), help_len); + + let editing_help_text = "Navigate with cd, chain with ||, &&, ; "; + let editing_help = Text::new(editing_help_text) + .color_substring(3, "cd") + .color_substring(3, "||") + .color_substring(3, "&&") + .color_substring(3, ";") + .unbold_all(); + let editing_len = editing_help_text.len(); + + return ( + first_line.0, + first_line.1, + Some((editing_help, editing_len)), + ); + } + + let help_text = select_help_text(sequence); + + if let Some(width) = max_width { + if let Some((first_line, second_line)) = split_help_line(help_text, width) { + let first_len = first_line.chars().count(); + let first_styled = style_help_text(&first_line).unbold_all(); + + let second_line_width = second_line.chars().count(); + let (second_styled, second_len) = if second_line_width > width { + let (truncated, len) = truncate_help_line(&second_line, width); + (style_help_text(&truncated).unbold_all(), len) + } else { + ( + style_help_text(&second_line).unbold_all(), + second_line_width, + ) + }; + + return (first_styled, first_len, Some((second_styled, second_len))); + } + + let (truncated_text, help_len) = truncate_help_line(help_text, width); + ( + style_help_text(&truncated_text).unbold_all(), + help_len, + None, + ) + } else { + let help_len = help_text.chars().count(); + (style_help_text(help_text).unbold_all(), help_len, None) + } +} + +fn split_help_line(help_text: &str, max_width: usize) -> Option<(String, String)> { + let text_width = help_text.chars().count(); + + if text_width <= max_width { + return None; + } + + let keybindings = parse_help_keybindings(help_text); + + if keybindings.is_empty() { + return None; + } + + for split_point in 1..keybindings.len() { + let first_part: Vec = keybindings + .iter() + .take(split_point) + .map(|(key, _, action)| format!("{} - {}", key, action)) + .collect(); + let first_line = first_part.join(", "); + + let second_part: Vec = keybindings + .iter() + .skip(split_point) + .map(|(key, _, action)| format!("{} - {}", key, action)) + .collect(); + let second_line = second_part.join(", "); + + if first_line.chars().count() <= max_width && second_line.chars().count() <= max_width { + return Some((first_line, second_line)); + } + } + + None +} + +fn folder_cell(cwd: &Option) -> (Text, String) { + let cwd_display = if let Some(cwd) = cwd { + format_cwd(cwd) + } else { + "~".to_string() + }; + let folder_display = format!("{} >", cwd_display); + let text = Text::new(&folder_display).color_range(0, 0..cwd_display.len()); + (text, folder_display) +} + +fn command_cell(text: &str) -> Text { + let text = if text.is_empty() { " " } else { text }; + Text::new(text) +} + +fn chain_cell(chain_type: &crate::state::ChainType) -> Text { + let text = chain_type_to_str(chain_type); + if !text.is_empty() { + Text::new(text).color_range(1, 0..text.len()) + } else { + Text::new(text) + } +} + +fn get_spinner_frame(frame: usize) -> &'static str { + SPINNER_FRAMES[frame % SPINNER_FRAMES.len()] +} + +pub fn format_status_text(status: &CommandStatus, spinner_frame: usize) -> String { + match status { + CommandStatus::Running(_) => { + let spinner = get_spinner_frame(spinner_frame); + format!("[RUNNING] {}", spinner) + }, + CommandStatus::Interrupted(_) => "[INTERRUPTED]".to_string(), + CommandStatus::Exited(Some(code), _) => format!("[EXIT CODE: {}]", code), + CommandStatus::Exited(None, _) => "[EXITED]".to_string(), + CommandStatus::Pending => " ".to_string(), + } +} + +fn apply_status_color(text: Text, status: &CommandStatus, status_str: &str) -> Text { + match status { + CommandStatus::Running(_) => text.color_range(3, 0..status_str.len()), + CommandStatus::Interrupted(_) => text.error_color_range(0..status_str.len()), + CommandStatus::Exited(Some(0), _) => { + let number_start = 12; + let number_end = status_str.len() - 1; + text.success_color_range(number_start..number_end) + }, + CommandStatus::Exited(Some(_), _) => { + let number_start = 12; + let number_end = status_str.len() - 1; + text.error_color_range(number_start..number_end) + }, + _ => text, + } +} + +fn status_cell(status: &CommandStatus, spinner_frame: usize) -> Text { + let status_str = format_status_text(status, spinner_frame); + let text = Text::new(&status_str); + apply_status_color(text, status, &status_str) +} + +fn apply_row_styles(cells: Vec, is_selected: bool) -> Vec { + let mut styled_cells = cells; + + if is_selected { + styled_cells = styled_cells.into_iter().map(|c| c.selected()).collect(); + } + + styled_cells +} + +fn overflow_cell(indicator: &str, is_selected: bool) -> Text { + let mut text = Text::new(indicator).dim_all(); + if is_selected { + text = text.selected(); + } + text +} + +fn command_sequence_row( + state: &State, + cwd: &Option, + truncated_cmd_text: &str, + chain_type: &crate::state::ChainType, + status: &crate::state::CommandStatus, + is_selected: bool, + overflow_indicator: Option, +) -> (Vec, usize) { + let (folder_text, folder_display) = folder_cell(cwd); + + let mut cells = vec![ + folder_text, + command_cell(truncated_cmd_text), + chain_cell(chain_type), + status_cell(status, state.layout.spinner_frame), + ]; + + cells = apply_row_styles(cells, is_selected); + + let truncated_cmd_text = if truncated_cmd_text.is_empty() { + " " + } else { + truncated_cmd_text + }; + let mut row_length = folder_display.chars().count() + + truncated_cmd_text.chars().count() + + chain_type_to_str(chain_type).chars().count() + + format_status_text(status, state.layout.spinner_frame) + .chars() + .count() + + 3; + + if let Some(indicator) = overflow_indicator { + let indicator_len = indicator.chars().count(); + cells.push(overflow_cell(&indicator, is_selected)); + row_length += indicator_len + 1; + } + + (cells, row_length) +} + +pub fn build_table_header(has_overflow: bool) -> Table { + let header_cols = if has_overflow { + vec![" ", " ", " ", " ", " "] + } else { + vec![" ", " ", " ", " "] + }; + Table::new().add_row(header_cols) +} + +fn calculate_overflow_indicator( + visible_idx: usize, + visible_count: usize, + hidden_above: usize, + hidden_below: usize, +) -> Option { + if visible_idx == 0 && hidden_above > 0 { + Some(format!("[+{}]", hidden_above)) + } else if visible_idx == visible_count.saturating_sub(1) && hidden_below > 0 { + Some(format!("[+{}]", hidden_below)) + } else if hidden_above > 0 || hidden_below > 0 { + Some(format!(" ")) + } else { + None + } +} + +pub fn calculate_row_layout_info( + index: usize, + offset: usize, + visible_count: usize, + hidden_above: usize, + hidden_below: usize, + cols: usize, + folder_width: usize, + max_chain_width: usize, + max_status_width: usize, +) -> Option<(Option, usize)> { + if index < offset || index >= offset + visible_count { + return None; + } + + let visible_idx = index.saturating_sub(offset); + let overflow_indicator = + calculate_overflow_indicator(visible_idx, visible_count, hidden_above, hidden_below); + + let available_cmd_width = calculate_available_cmd_width( + cols, + folder_width, + overflow_indicator.as_ref(), + max_chain_width, + max_status_width, + ); + + Some((overflow_indicator, available_cmd_width)) +} + +pub fn add_command_row( + table: Table, + state: &State, + index: usize, + offset: usize, + visible_count: usize, + hidden_above: usize, + hidden_below: usize, +) -> Table { + let command = match state.execution.all_commands.get(index) { + Some(cmd) => cmd, + None => return table, + }; + + let cmd_text = &command.get_text(); + let chain_type = &command.get_chain_type(); + let status = &command.get_status(); + let command_cwd = command.get_cwd().or_else(|| state.cwd.clone()); + + let cols = state.own_columns.unwrap_or(80); + let longest_cwd_display = state.execution.longest_cwd_display(&state.cwd); + let folder_display = format!("{} >", longest_cwd_display); + let folder_width = folder_display.chars().count(); + + let (max_chain_width, max_status_width) = + calculate_max_widths(&state.execution.all_commands, state.layout.spinner_frame); + + let Some((overflow_indicator, available_cmd_width)) = calculate_row_layout_info( + index, + offset, + visible_count, + hidden_above, + hidden_below, + cols, + folder_width, + max_chain_width, + max_status_width, + ) else { + return table; + }; + + if let Some(text_input) = &state.editing.editing_input { + if state.selection.current_selected_command_index == Some(index) { + let (truncated_editing_text, _) = truncate_middle( + text_input.get_text(), + available_cmd_width, + Some(text_input.cursor_position()), + ); + let (row, _) = command_sequence_row( + state, + &command_cwd, + &truncated_editing_text, + chain_type, + &CommandStatus::Pending, + false, + overflow_indicator, + ); + return table.add_styled_row(row); + } + } + + let truncated_cmd_text = truncate_middle(cmd_text, available_cmd_width, None).0; + + let (row, _) = command_sequence_row( + state, + &command_cwd, + &truncated_cmd_text, + chain_type, + status, + state.selection.current_selected_command_index == Some(index), + overflow_indicator, + ); + + table.add_styled_row(row) +} + +pub fn calculate_max_widths( + commands: &[crate::state::CommandEntry], + spinner_frame: usize, +) -> (usize, usize) { + let max_chain_width = commands + .iter() + .map(|cmd| chain_type_to_str(&cmd.get_chain_type()).chars().count()) + .max() + .unwrap_or(0); + + let max_status_width = commands + .iter() + .map(|cmd| { + format_status_text(&cmd.get_status(), spinner_frame) + .chars() + .count() + }) + .max() + .unwrap_or(0); + + (max_chain_width, max_status_width) +} + +pub fn calculate_longest_line( + longest_cwd_display: &str, + longest_command: usize, + max_chain_width: usize, + max_status_width: usize, +) -> usize { + let folder_display = format!("{} >", longest_cwd_display); + let cell_padding = 3; + folder_display.chars().count() + + longest_command + + max_chain_width + + max_status_width + + cell_padding +} + +pub fn chain_type_to_str(chain_type: &crate::state::ChainType) -> &'static str { + match chain_type { + crate::state::ChainType::And => "AND", + crate::state::ChainType::Or => "OR", + crate::state::ChainType::Then => "THEN", + crate::state::ChainType::None => " ", + } +} + +pub fn truncate_help_line(help_text: &str, max_width: usize) -> (String, usize) { + let text_width = help_text.chars().count(); + + if text_width <= max_width { + return (help_text.to_string(), text_width); + } + + let keybindings = parse_help_keybindings(help_text); + + if let Some(result) = try_shortened_help(&keybindings, max_width) { + return result; + } + + if let Some(result) = try_keys_spaced(&keybindings, max_width) { + return result; + } + + if let Some(result) = try_keys_tight(&keybindings, max_width) { + return result; + } + + truncate_with_ellipsis( + &keybindings + .iter() + .map(|(k, _, _)| *k) + .collect::>() + .join("/"), + max_width, + ) +} + +fn parse_help_keybindings(help_text: &str) -> Vec<(&str, &str, &str)> { + help_text + .split(", ") + .filter_map(|part| { + part.find(" - ").map(|dash_pos| { + let key = &part[..dash_pos]; + let action = &part[dash_pos + 3..]; + let first_word = action.split_whitespace().next().unwrap_or(action); + (key, first_word, action) + }) + }) + .collect() +} + +fn try_shortened_help( + keybindings: &[(&str, &str, &str)], + max_width: usize, +) -> Option<(String, usize)> { + let shortened: Vec = keybindings + .iter() + .map(|(key, first_word, _)| format!("{} - {}", key, first_word)) + .collect(); + let shortened_text = shortened.join(", "); + let shortened_width = shortened_text.chars().count(); + + if shortened_width <= max_width { + Some((shortened_text, shortened_width)) + } else { + None + } +} + +fn try_keys_spaced( + keybindings: &[(&str, &str, &str)], + max_width: usize, +) -> Option<(String, usize)> { + let keys_spaced_text = keybindings + .iter() + .map(|(key, _, _)| *key) + .collect::>() + .join(" / "); + let keys_spaced_width = keys_spaced_text.chars().count(); + + if keys_spaced_width <= max_width { + Some((keys_spaced_text, keys_spaced_width)) + } else { + None + } +} + +fn try_keys_tight(keybindings: &[(&str, &str, &str)], max_width: usize) -> Option<(String, usize)> { + let keys_tight_text = keybindings + .iter() + .map(|(key, _, _)| *key) + .collect::>() + .join("/"); + let keys_tight_width = keys_tight_text.chars().count(); + + if keys_tight_width <= max_width { + Some((keys_tight_text, keys_tight_width)) + } else { + None + } +} + +fn truncate_with_ellipsis(text: &str, max_width: usize) -> (String, usize) { + let available = max_width.saturating_sub(3); + let mut truncated = String::new(); + let mut current_width = 0; + + for ch in text.chars() { + if current_width + 1 <= available { + truncated.push(ch); + current_width += 1; + } else { + break; + } + } + + truncated.push_str("..."); + let truncated_width = truncated.chars().count(); + (truncated, truncated_width) +} diff --git a/default-plugins/sequence/src/ui/fuzzy_complete.rs b/default-plugins/sequence/src/ui/fuzzy_complete.rs new file mode 100644 index 000000000..0feae7e43 --- /dev/null +++ b/default-plugins/sequence/src/ui/fuzzy_complete.rs @@ -0,0 +1,321 @@ +use fuzzy_matcher::skim::SkimMatcherV2; +use fuzzy_matcher::FuzzyMatcher; +use std::collections::BTreeMap; +use std::fs; +use std::path::PathBuf; + +/// Result of a fuzzy completion operation +#[derive(Debug, Clone)] +pub struct CompletionResult { + pub completed_text: String, + pub score: i64, + pub is_directory: bool, + pub is_prefix_completion: bool, // True if this is the shortest of multiple matches with same prefix +} + +/// Type of completion +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum CompletionType { + Command, + Path, +} + +/// Fuzzy match executables (commands) from the PATH +pub fn fuzzy_complete_command( + query: &str, + executables: &BTreeMap, +) -> Option { + if query.is_empty() { + return None; + } + + let matcher = SkimMatcherV2::default().ignore_case(); + + // Collect all matches with their scores + let mut all_matches: Vec<(String, i64)> = Vec::new(); + + for executable_name in executables.keys() { + if let Some((score, _indices)) = matcher.fuzzy_indices(executable_name, query) { + all_matches.push((executable_name.clone(), score)); + } + } + + if all_matches.is_empty() { + return None; + } + + // Sort by score (highest first), then by length (shortest first) + all_matches.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.len().cmp(&b.0.len()))); + + // Get the best match + let (best_name, best_score) = &all_matches[0]; + + // Check if there are multiple matches that share the same prefix + let is_prefix_completion = check_for_prefix_matches(&all_matches, best_name); + + Some(CompletionResult { + completed_text: best_name.clone(), + score: *best_score, + is_directory: false, // Commands are not directories + is_prefix_completion, + }) +} + +/// Fuzzy match paths (directories and files) relative to the current working directory +pub fn fuzzy_complete_path(query: &str, cwd: Option<&PathBuf>) -> Option { + if query.is_empty() { + return None; + } + + let matcher = SkimMatcherV2::default().ignore_case(); + + // Determine the base directory to search in + let (base_dir, search_prefix) = if query.starts_with('/') { + // Absolute path + let parts: Vec<&str> = query.rsplitn(2, '/').collect(); + if parts.len() == 2 { + // Has a directory component + let dir = parts[1]; + let prefix = parts[0]; + (PathBuf::from(dir), prefix.to_string()) + } else { + // Just "/" + (PathBuf::from("/"), String::new()) + } + } else if query.starts_with("~/") { + // Home directory + let home_dir = std::env::var("HOME").ok()?; + let query_without_tilde = &query[2..]; + let parts: Vec<&str> = query_without_tilde.rsplitn(2, '/').collect(); + if parts.len() == 2 { + let dir = PathBuf::from(&home_dir).join(parts[1]); + let prefix = parts[0]; + (dir, prefix.to_string()) + } else { + // Just "~/" or "~/something" + (PathBuf::from(home_dir), query_without_tilde.to_string()) + } + } else { + // Relative path + let base = cwd?; + let parts: Vec<&str> = query.rsplitn(2, '/').collect(); + if parts.len() == 2 { + // Has a directory component + let dir = base.join(parts[1]); + let prefix = parts[0]; + (dir, prefix.to_string()) + } else { + // Just a name in the current directory + (base.clone(), query.to_string()) + } + }; + + // Convert to host path + let host_base_dir = + PathBuf::from("/host").join(base_dir.strip_prefix("/").unwrap_or(&base_dir)); + + // Read directory entries + let entries = fs::read_dir(&host_base_dir).ok()?; + + // Collect all matches with their scores and directory status + let mut all_matches: Vec<(String, i64, bool)> = Vec::new(); + + for entry in entries.flatten() { + if let Some(name) = entry.file_name().to_str() { + // Skip hidden files unless the query starts with a dot + if name.starts_with('.') && !search_prefix.starts_with('.') { + continue; + } + + if let Some((score, _indices)) = matcher.fuzzy_indices(name, &search_prefix) { + // Check if this entry is a directory + let is_dir = entry.metadata().ok().map(|m| m.is_dir()).unwrap_or(false); + all_matches.push((name.to_string(), score, is_dir)); + } + } + } + + if all_matches.is_empty() { + return None; + } + + // Sort by score (highest first), then by length (shortest first) + all_matches.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.len().cmp(&b.0.len()))); + + // Get the best match + let (name, score, is_directory) = all_matches[0].clone(); + + // Check if there are multiple matches that share the same prefix + let name_matches: Vec<(String, i64)> = all_matches + .iter() + .map(|(n, s, _)| (n.clone(), *s)) + .collect(); + let is_prefix_completion = check_for_prefix_matches(&name_matches, &name); + + // Reconstruct the full path + let completed_text = if query.starts_with('/') { + // Absolute path + let dir_part = query.rsplitn(2, '/').nth(1).unwrap_or(""); + if dir_part.is_empty() { + format!("/{}", name) + } else { + format!("{}/{}", dir_part, name) + } + } else if query.starts_with("~/") { + // Home directory + let query_without_tilde = &query[2..]; + let dir_part = query_without_tilde.rsplitn(2, '/').nth(1).unwrap_or(""); + if dir_part.is_empty() { + format!("~/{}", name) + } else { + format!("~/{}/{}", dir_part, name) + } + } else { + // Relative path + let dir_part = query.rsplitn(2, '/').nth(1).unwrap_or(""); + if dir_part.is_empty() { + name.clone() + } else { + format!("{}/{}", dir_part, name) + } + }; + + Some(CompletionResult { + completed_text, + score, + is_directory, + is_prefix_completion, + }) +} + +/// Check if there are multiple matches that start with the best match's name +/// Returns true if the best match is a prefix of other matches +fn check_for_prefix_matches(matches: &[(String, i64)], best_match: &str) -> bool { + if matches.len() <= 1 { + return false; + } + + // Count how many matches start with the best_match text + let prefix_count = matches + .iter() + .filter(|(name, _)| name.starts_with(best_match) && name != best_match) + .count(); + + prefix_count > 0 +} + +/// Perform fuzzy completion on the current input +/// Returns the best completion (command or path) with appropriate suffix (space or slash) +pub fn fuzzy_complete( + input: &str, + executables: &BTreeMap, + cwd: Option<&PathBuf>, +) -> Option { + // If input is empty, nothing to complete + if input.is_empty() { + return None; + } + + // Extract the last word/token to complete + // For simplicity, we'll complete the entire input if it's a single word, + // or the last space-separated token if there are multiple words + let tokens: Vec<&str> = input.split_whitespace().collect(); + let to_complete = if tokens.is_empty() { + input + } else { + tokens.last().unwrap() + }; + + // Get both command and path completions + let command_result = fuzzy_complete_command(to_complete, executables); + let path_result = fuzzy_complete_path(to_complete, cwd); + + // Choose the better match based on score + match (command_result, path_result) { + (Some(cmd), Some(path)) => { + // Both matched, use the higher score + let (result, completion_type, is_dir, is_prefix) = if cmd.score >= path.score { + ( + cmd.completed_text, + CompletionType::Command, + false, + cmd.is_prefix_completion, + ) + } else { + ( + path.completed_text, + CompletionType::Path, + path.is_directory, + path.is_prefix_completion, + ) + }; + + // Add appropriate suffix (skip slash if this is a prefix completion) + let suffix = get_completion_suffix(completion_type, is_dir, is_prefix); + let completed = format!("{}{}", result, suffix); + + // Replace the last token with the completion + Some(replace_last_token(input, &completed)) + }, + (Some(cmd), None) => { + // Command completion - add space (unless it's a prefix completion) + let suffix = if cmd.is_prefix_completion { "" } else { " " }; + let completed = format!("{}{}", cmd.completed_text, suffix); + Some(replace_last_token(input, &completed)) + }, + (None, Some(path)) => { + // Path completion - add slash if directory (unless it's a prefix completion) + let suffix = if path.is_prefix_completion { + "" + } else if path.is_directory { + "/" + } else { + "" + }; + let completed = format!("{}{}", path.completed_text, suffix); + Some(replace_last_token(input, &completed)) + }, + (None, None) => None, + } +} + +/// Get the appropriate suffix for a completion +fn get_completion_suffix( + completion_type: CompletionType, + is_directory: bool, + is_prefix_completion: bool, +) -> &'static str { + // No suffix for prefix completions + if is_prefix_completion { + return ""; + } + + match completion_type { + CompletionType::Command => " ", + CompletionType::Path => { + if is_directory { + "/" + } else { + "" + } + }, + } +} + +/// Replace the last whitespace-separated token in the input with the completion +fn replace_last_token(input: &str, completion: &str) -> String { + let tokens: Vec<&str> = input.split_whitespace().collect(); + if tokens.is_empty() { + return completion.to_string(); + } + + if tokens.len() == 1 { + completion.to_string() + } else { + // Join all tokens except the last one, then add the completion + let mut result = tokens[..tokens.len() - 1].join(" "); + result.push(' '); + result.push_str(completion); + result + } +} diff --git a/default-plugins/sequence/src/ui/layout_calculations.rs b/default-plugins/sequence/src/ui/layout_calculations.rs new file mode 100644 index 000000000..911dbc627 --- /dev/null +++ b/default-plugins/sequence/src/ui/layout_calculations.rs @@ -0,0 +1,28 @@ +pub fn calculate_viewport( + total_commands: usize, + max_visible: usize, + selected_index: Option, + running_index: usize, +) -> (usize, usize, usize, usize) { + if total_commands <= max_visible { + return (0, total_commands, 0, 0); + } + + let focus_index = selected_index.unwrap_or(running_index); + let half_visible = max_visible / 2; + + let offset = if focus_index < half_visible { + 0 + } else if focus_index >= total_commands.saturating_sub(half_visible) { + total_commands.saturating_sub(max_visible) + } else { + focus_index.saturating_sub(half_visible) + }; + + let offset = offset.min(total_commands.saturating_sub(max_visible)); + let visible_count = max_visible.min(total_commands.saturating_sub(offset)); + let hidden_above = offset; + let hidden_below = total_commands.saturating_sub(offset + visible_count); + + (offset, visible_count, hidden_above, hidden_below) +} diff --git a/default-plugins/sequence/src/ui/mod.rs b/default-plugins/sequence/src/ui/mod.rs new file mode 100644 index 000000000..6d1ec3035 --- /dev/null +++ b/default-plugins/sequence/src/ui/mod.rs @@ -0,0 +1,5 @@ +pub mod components; +pub mod fuzzy_complete; +pub mod layout_calculations; +pub mod text_input; +pub mod truncation; diff --git a/default-plugins/sequence/src/ui/text_input.rs b/default-plugins/sequence/src/ui/text_input.rs new file mode 100644 index 000000000..2694e17ae --- /dev/null +++ b/default-plugins/sequence/src/ui/text_input.rs @@ -0,0 +1,997 @@ +use zellij_tile::prelude::*; + +const MAX_UNDO_STACK_SIZE: usize = 100; + +/// Action returned by TextInput after handling a key event +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(test, derive(Eq))] +pub enum InputAction { + /// Continue editing + Continue, + /// User pressed Enter to submit + Submit, + /// User pressed Esc to cancel + Cancel, + /// User pressed Tab to request completion + Complete, + /// Key was not handled by the input + NoAction, +} + +/// A reusable text input component with cursor support and standard editing keybindings +#[derive(Debug, Clone)] +pub struct TextInput { + buffer: String, + cursor_position: usize, // Character position (0-based), NOT byte position + undo_stack: Vec<(String, usize)>, // (buffer, cursor) snapshots + redo_stack: Vec<(String, usize)>, + last_edit_was_insert: bool, // For coalescing consecutive inserts +} + +impl TextInput { + /// Create a new TextInput with the given initial text + /// Cursor is positioned at the end of the text + pub fn new(initial_text: String) -> Self { + let cursor_position = initial_text.chars().count(); + Self { + buffer: initial_text, + cursor_position, + undo_stack: Vec::new(), + redo_stack: Vec::new(), + last_edit_was_insert: false, + } + } + + /// Create an empty TextInput + pub fn empty() -> Self { + Self::new(String::new()) + } + + /// Get the current text + pub fn get_text(&self) -> &str { + &self.buffer + } + + /// Get the cursor position (in characters, not bytes) + pub fn get_cursor_position(&self) -> usize { + self.cursor_position + } + + /// Check if the input is empty + pub fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + /// Get a shorthand for cursor_position + pub fn cursor_position(&self) -> usize { + self.cursor_position + } + + /// Get mutable access to the underlying buffer for direct manipulation + pub fn get_text_mut(&mut self) -> &mut String { + &mut self.buffer + } + + /// Set the text and move cursor to the end + pub fn set_text(&mut self, text: String) { + self.break_coalescing(); + self.save_undo_state(); + self.cursor_position = text.chars().count(); + self.buffer = text; + } + + /// Set cursor position (clamped to text length) + pub fn set_cursor_position(&mut self, pos: usize) { + let text_len = self.buffer.chars().count(); + self.cursor_position = pos.min(text_len); + } + + /// Clear all text and reset cursor + pub fn clear(&mut self) { + self.break_coalescing(); + self.save_undo_state(); + self.buffer.clear(); + self.cursor_position = 0; + } + + /// Insert a character at the current cursor position + pub fn insert_char(&mut self, c: char) { + self.save_undo_state_unless_coalescing(); + // Convert cursor position (char index) to byte index + let byte_index = self.char_index_to_byte_index(self.cursor_position); + self.buffer.insert(byte_index, c); + self.cursor_position += 1; + } + + /// Delete the character before the cursor (backspace) + pub fn backspace(&mut self) { + if self.cursor_position > 0 { + self.break_coalescing(); + self.save_undo_state(); + self.cursor_position -= 1; + let byte_index = self.char_index_to_byte_index(self.cursor_position); + self.buffer.remove(byte_index); + } + } + + /// Delete the character at the cursor position (delete key) + pub fn delete(&mut self) { + let len = self.buffer.chars().count(); + if self.cursor_position < len { + self.break_coalescing(); + self.save_undo_state(); + let byte_index = self.char_index_to_byte_index(self.cursor_position); + self.buffer.remove(byte_index); + } + } + + /// Delete the word before the cursor (Ctrl/Alt + Backspace) + pub fn delete_word_backward(&mut self) { + if self.cursor_position == 0 { + return; + } + + self.break_coalescing(); + self.save_undo_state(); + + let old_position = self.cursor_position; + self.move_word_left(); + let new_position = self.cursor_position; + + // Delete from new position to old position + let start_byte = self.char_index_to_byte_index(new_position); + let end_byte = self.char_index_to_byte_index(old_position); + self.buffer.drain(start_byte..end_byte); + } + + /// Delete the word after the cursor (Ctrl/Alt + Delete) + pub fn delete_word_forward(&mut self) { + let chars: Vec = self.buffer.chars().collect(); + let len = chars.len(); + + if self.cursor_position >= len { + return; + } + + self.break_coalescing(); + self.save_undo_state(); + + let start_position = self.cursor_position; + let mut end_position = start_position; + + // Skip the current word + while end_position < len && !chars[end_position].is_whitespace() { + end_position += 1; + } + + // Skip any whitespace after the word + while end_position < len && chars[end_position].is_whitespace() { + end_position += 1; + } + + // Delete from start to end position + let start_byte = self.char_index_to_byte_index(start_position); + let end_byte = self.char_index_to_byte_index(end_position); + self.buffer.drain(start_byte..end_byte); + } + + /// Move cursor one position to the left + pub fn move_left(&mut self) { + if self.cursor_position > 0 { + self.break_coalescing(); + self.cursor_position -= 1; + } + } + + /// Move cursor one position to the right + pub fn move_right(&mut self) { + let len = self.buffer.chars().count(); + if self.cursor_position < len { + self.break_coalescing(); + self.cursor_position += 1; + } + } + + /// Move cursor to the start of the text (Ctrl-A / Home) + pub fn move_to_start(&mut self) { + self.break_coalescing(); + self.cursor_position = 0; + } + + /// Move cursor to the end of the text (Ctrl-E / End) + pub fn move_to_end(&mut self) { + self.break_coalescing(); + self.cursor_position = self.buffer.chars().count(); + } + + /// Move cursor to the start of the previous word (Ctrl/Alt + Left) + pub fn move_word_left(&mut self) { + if self.cursor_position == 0 { + return; + } + + self.break_coalescing(); + + let chars: Vec = self.buffer.chars().collect(); + let mut pos = self.cursor_position; + + // Skip any whitespace immediately to the left + while pos > 0 && chars[pos - 1].is_whitespace() { + pos -= 1; + } + + // Skip the word characters + while pos > 0 && !chars[pos - 1].is_whitespace() { + pos -= 1; + } + + self.cursor_position = pos; + } + + /// Move cursor to the start of the next word (Ctrl/Alt + Right) + pub fn move_word_right(&mut self) { + let chars: Vec = self.buffer.chars().collect(); + let len = chars.len(); + + if self.cursor_position >= len { + return; + } + + self.break_coalescing(); + + let mut pos = self.cursor_position; + + // Skip the current word + while pos < len && !chars[pos].is_whitespace() { + pos += 1; + } + + // Skip any whitespace + while pos < len && chars[pos].is_whitespace() { + pos += 1; + } + + self.cursor_position = pos; + } + + /// Handle a key event and return the appropriate action + /// This is the main entry point for key handling + pub fn handle_key(&mut self, key: KeyWithModifier) -> InputAction { + // Check for Ctrl modifiers + if key.has_modifiers(&[KeyModifier::Ctrl]) { + match key.bare_key { + BareKey::Char('a') => { + self.move_to_start(); + return InputAction::Continue; + }, + BareKey::Char('e') => { + self.move_to_end(); + return InputAction::Continue; + }, + BareKey::Char('c') => { + // Ctrl-C clears the prompt + return InputAction::Cancel; + }, + BareKey::Char('z') => { + // Ctrl-Z: Undo + self.undo(); + return InputAction::Continue; + }, + BareKey::Char('y') => { + // Ctrl-Y: Redo + self.redo(); + return InputAction::Continue; + }, + BareKey::Left => { + self.move_word_left(); + return InputAction::Continue; + }, + BareKey::Right => { + self.move_word_right(); + return InputAction::Continue; + }, + BareKey::Backspace => { + self.delete_word_backward(); + return InputAction::Continue; + }, + BareKey::Delete => { + self.delete_word_forward(); + return InputAction::Continue; + }, + _ => {}, + } + } + + // Check for Ctrl+Shift modifiers (alternative redo: Ctrl+Shift+Z) + if key.has_modifiers(&[KeyModifier::Ctrl, KeyModifier::Shift]) { + match key.bare_key { + BareKey::Char('Z') => { + // Ctrl-Shift-Z: Redo (alternative) + self.redo(); + return InputAction::Continue; + }, + _ => {}, + } + } + + // Check for Alt modifiers + if key.has_modifiers(&[KeyModifier::Alt]) { + match key.bare_key { + BareKey::Left => { + self.move_word_left(); + return InputAction::Continue; + }, + BareKey::Right => { + self.move_word_right(); + return InputAction::Continue; + }, + BareKey::Backspace => { + self.delete_word_backward(); + return InputAction::Continue; + }, + BareKey::Delete => { + self.delete_word_forward(); + return InputAction::Continue; + }, + _ => {}, + } + } + + // Handle bare keys (no modifiers) + match key.bare_key { + BareKey::Enter => InputAction::Submit, + BareKey::Esc => InputAction::Cancel, + BareKey::Tab => InputAction::Complete, + BareKey::Backspace => { + self.backspace(); + InputAction::Continue + }, + BareKey::Delete => { + self.delete(); + InputAction::Continue + }, + BareKey::Left => { + self.move_left(); + InputAction::Continue + }, + BareKey::Right => { + self.move_right(); + InputAction::Continue + }, + BareKey::Home => { + self.move_to_start(); + InputAction::Continue + }, + BareKey::End => { + self.move_to_end(); + InputAction::Continue + }, + BareKey::Char(c) => { + self.insert_char(c); + InputAction::Continue + }, + _ => InputAction::NoAction, + } + } + + /// Helper: Convert character index to byte index + fn char_index_to_byte_index(&self, char_index: usize) -> usize { + self.buffer + .char_indices() + .nth(char_index) + .map(|(byte_idx, _)| byte_idx) + .unwrap_or(self.buffer.len()) + } + + /// Save current state to undo stack before making changes + fn save_undo_state(&mut self) { + if self.undo_stack.len() >= MAX_UNDO_STACK_SIZE { + self.undo_stack.remove(0); + } + self.undo_stack + .push((self.buffer.clone(), self.cursor_position)); + self.redo_stack.clear(); + } + + /// Save state only if not coalescing with previous insert + fn save_undo_state_unless_coalescing(&mut self) { + if !self.last_edit_was_insert { + self.save_undo_state(); + } + self.last_edit_was_insert = true; + } + + /// Mark that a non-insert edit occurred (breaks coalescing) + fn break_coalescing(&mut self) { + self.last_edit_was_insert = false; + } + + /// Undo last change + pub fn undo(&mut self) -> bool { + if let Some((buffer, cursor)) = self.undo_stack.pop() { + self.redo_stack + .push((self.buffer.clone(), self.cursor_position)); + self.buffer = buffer; + self.cursor_position = cursor; + self.break_coalescing(); + true + } else { + false + } + } + + /// Redo last undone change + pub fn redo(&mut self) -> bool { + if let Some((buffer, cursor)) = self.redo_stack.pop() { + self.undo_stack + .push((self.buffer.clone(), self.cursor_position)); + self.buffer = buffer; + self.cursor_position = cursor; + self.break_coalescing(); + true + } else { + false + } + } + + /// Check if undo is available + pub fn can_undo(&self) -> bool { + !self.undo_stack.is_empty() + } + + /// Check if redo is available + pub fn can_redo(&self) -> bool { + !self.redo_stack.is_empty() + } + + pub fn drain_text(&mut self) -> String { + self.cursor_position = 0; + self.buffer.drain(..).collect() + } +} + +// run with: +// cargo test --lib --target x86_64-unknown-linux-gnu +// +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_new_and_empty() { + let input = TextInput::new("hello".to_string()); + assert_eq!(input.get_text(), "hello"); + assert_eq!(input.get_cursor_position(), 5); + + let empty = TextInput::empty(); + assert_eq!(empty.get_text(), ""); + assert_eq!(empty.get_cursor_position(), 0); + } + + #[test] + fn test_insert_char() { + let mut input = TextInput::new("helo".to_string()); + input.cursor_position = 3; // Position after "hel" + input.insert_char('l'); + assert_eq!(input.get_text(), "hello"); + assert_eq!(input.get_cursor_position(), 4); + } + + #[test] + fn test_backspace() { + let mut input = TextInput::new("hello".to_string()); + input.backspace(); + assert_eq!(input.get_text(), "hell"); + assert_eq!(input.get_cursor_position(), 4); + + // Backspace at start does nothing + input.cursor_position = 0; + input.backspace(); + assert_eq!(input.get_text(), "hell"); + assert_eq!(input.get_cursor_position(), 0); + } + + #[test] + fn test_delete() { + let mut input = TextInput::new("hello".to_string()); + input.cursor_position = 0; + input.delete(); + assert_eq!(input.get_text(), "ello"); + assert_eq!(input.get_cursor_position(), 0); + + // Delete at end does nothing + input.move_to_end(); + input.delete(); + assert_eq!(input.get_text(), "ello"); + } + + #[test] + fn test_cursor_movement() { + let mut input = TextInput::new("hello".to_string()); + assert_eq!(input.get_cursor_position(), 5); + + input.move_left(); + assert_eq!(input.get_cursor_position(), 4); + + input.move_right(); + assert_eq!(input.get_cursor_position(), 5); + + input.move_to_start(); + assert_eq!(input.get_cursor_position(), 0); + + input.move_to_end(); + assert_eq!(input.get_cursor_position(), 5); + } + + #[test] + fn test_unicode_support() { + let mut input = TextInput::new("hello 🦀 world".to_string()); + assert_eq!(input.get_cursor_position(), 13); // 13 characters + + input.cursor_position = 6; // After "hello " + input.insert_char('🐱'); + assert_eq!(input.get_text(), "hello 🐱🦀 world"); + } + + #[test] + fn test_word_jump_right() { + let mut input = TextInput::new("hello world foo bar".to_string()); + input.cursor_position = 0; + + // Jump from start to "world" + input.move_word_right(); + assert_eq!(input.get_cursor_position(), 6); // After "hello " + + // Jump to "foo" + input.move_word_right(); + assert_eq!(input.get_cursor_position(), 12); // After "world " + + // Jump to "bar" + input.move_word_right(); + assert_eq!(input.get_cursor_position(), 16); // After "foo " + + // Jump to end + input.move_word_right(); + assert_eq!(input.get_cursor_position(), 19); // At end + } + + #[test] + fn test_word_jump_left() { + let mut input = TextInput::new("hello world foo bar".to_string()); + input.move_to_end(); + assert_eq!(input.get_cursor_position(), 19); + + // Jump back to "bar" + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 16); // Start of "bar" + + // Jump back to "foo" + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 12); // Start of "foo" + + // Jump back to "world" + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 6); // Start of "world" + + // Jump back to "hello" + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 0); // Start of "hello" + } + + #[test] + fn test_word_jump_with_multiple_spaces() { + let mut input = TextInput::new("hello world".to_string()); + input.cursor_position = 0; + + // Jump over multiple spaces + input.move_word_right(); + assert_eq!(input.get_cursor_position(), 8); // After "hello ", at start of "world" + + // Jump back should skip spaces + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 0); // Back to start of "hello" + } + + #[test] + fn test_word_jump_boundaries() { + let mut input = TextInput::new("test".to_string()); + + // At start - word left does nothing + input.cursor_position = 0; + input.move_word_left(); + assert_eq!(input.get_cursor_position(), 0); + + // At end - word right does nothing + input.move_to_end(); + let end_pos = input.get_cursor_position(); + input.move_word_right(); + assert_eq!(input.get_cursor_position(), end_pos); + } + + #[test] + fn test_up_down_arrows() { + let mut input = TextInput::new("hello world".to_string()); + + // Start in the middle + input.cursor_position = 5; + assert_eq!(input.get_cursor_position(), 5); + + // Up arrow should go to start + input.move_to_start(); + assert_eq!(input.get_cursor_position(), 0); + + // Move back to middle + input.cursor_position = 5; + + // Down arrow should go to end + input.move_to_end(); + assert_eq!(input.get_cursor_position(), 11); + } + + #[test] + fn test_delete_word_backward() { + let mut input = TextInput::new("hello world foo".to_string()); + + // Delete "foo" from end + input.move_to_end(); + input.delete_word_backward(); + assert_eq!(input.get_text(), "hello world "); + assert_eq!(input.get_cursor_position(), 12); + + // Delete "world " + input.delete_word_backward(); + assert_eq!(input.get_text(), "hello "); + assert_eq!(input.get_cursor_position(), 6); + + // Delete "hello " + input.delete_word_backward(); + assert_eq!(input.get_text(), ""); + assert_eq!(input.get_cursor_position(), 0); + + // Delete on empty buffer does nothing + input.delete_word_backward(); + assert_eq!(input.get_text(), ""); + assert_eq!(input.get_cursor_position(), 0); + } + + #[test] + fn test_delete_word_backward_middle() { + let mut input = TextInput::new("hello world foo".to_string()); + + // Position in middle of "world" + input.cursor_position = 8; // After "hello wo" + input.delete_word_backward(); + assert_eq!(input.get_text(), "hello rld foo"); + assert_eq!(input.get_cursor_position(), 6); // After "hello " + } + + #[test] + fn test_delete_word_forward() { + let mut input = TextInput::new("hello world foo".to_string()); + + // Delete "hello " from start + input.cursor_position = 0; + input.delete_word_forward(); + assert_eq!(input.get_text(), "world foo"); + assert_eq!(input.get_cursor_position(), 0); + + // Delete "world " + input.delete_word_forward(); + assert_eq!(input.get_text(), "foo"); + assert_eq!(input.get_cursor_position(), 0); + + // Delete "foo" + input.delete_word_forward(); + assert_eq!(input.get_text(), ""); + assert_eq!(input.get_cursor_position(), 0); + + // Delete on empty buffer does nothing + input.delete_word_forward(); + assert_eq!(input.get_text(), ""); + assert_eq!(input.get_cursor_position(), 0); + } + + #[test] + fn test_delete_word_forward_middle() { + let mut input = TextInput::new("hello world foo".to_string()); + + // Position in middle of "world" + input.cursor_position = 8; // After "hello wo" + input.delete_word_forward(); + assert_eq!(input.get_text(), "hello wofoo"); + assert_eq!(input.get_cursor_position(), 8); // Same position, text deleted forward + } + + #[test] + fn test_delete_word_with_multiple_spaces() { + let mut input = TextInput::new("hello world".to_string()); + + // Delete forward includes trailing spaces + input.cursor_position = 0; + input.delete_word_forward(); + assert_eq!(input.get_text(), "world"); + assert_eq!(input.get_cursor_position(), 0); + } + + #[test] + fn test_undo_redo_basic() { + let mut input = TextInput::empty(); + + // Type "hello" + input.insert_char('h'); + input.insert_char('e'); + input.insert_char('l'); + input.insert_char('l'); + input.insert_char('o'); + assert_eq!(input.get_text(), "hello"); + + // Undo should remove all characters (coalesced into one undo entry) + assert!(input.can_undo()); + assert!(input.undo()); + assert_eq!(input.get_text(), ""); + assert_eq!(input.get_cursor_position(), 0); + + // Redo should restore "hello" + assert!(input.can_redo()); + assert!(input.redo()); + assert_eq!(input.get_text(), "hello"); + assert_eq!(input.get_cursor_position(), 5); + } + + #[test] + fn test_undo_coalescing_breaks_on_cursor_move() { + let mut input = TextInput::empty(); + + // Type "he" + input.insert_char('h'); + input.insert_char('e'); + + // Move cursor to start (breaks coalescing) + input.move_to_start(); + + // Type "llo" + input.insert_char('l'); + input.insert_char('l'); + input.insert_char('o'); + + assert_eq!(input.get_text(), "llohe"); + + // First undo removes "llo" (second coalesced group) + input.undo(); + assert_eq!(input.get_text(), "he"); + + // Second undo removes "he" (first coalesced group) + input.undo(); + assert_eq!(input.get_text(), ""); + } + + #[test] + fn test_undo_backspace() { + let mut input = TextInput::new("hello".to_string()); + + // Backspace once + input.backspace(); + assert_eq!(input.get_text(), "hell"); + + // Undo should restore "hello" + input.undo(); + assert_eq!(input.get_text(), "hello"); + assert_eq!(input.get_cursor_position(), 5); + } + + #[test] + fn test_undo_delete() { + let mut input = TextInput::new("hello".to_string()); + input.cursor_position = 0; + + // Delete first character + input.delete(); + assert_eq!(input.get_text(), "ello"); + + // Undo should restore "hello" + input.undo(); + assert_eq!(input.get_text(), "hello"); + assert_eq!(input.get_cursor_position(), 0); + } + + #[test] + fn test_undo_word_delete() { + let mut input = TextInput::new("hello world".to_string()); + + // Delete "world" backward + input.delete_word_backward(); + assert_eq!(input.get_text(), "hello "); + + // Undo should restore "hello world" + input.undo(); + assert_eq!(input.get_text(), "hello world"); + assert_eq!(input.get_cursor_position(), 11); + } + + #[test] + fn test_undo_clear() { + let mut input = TextInput::new("hello world".to_string()); + + // Clear the buffer + input.clear(); + assert_eq!(input.get_text(), ""); + + // Undo should restore the text + input.undo(); + assert_eq!(input.get_text(), "hello world"); + } + + #[test] + fn test_undo_set_text() { + let mut input = TextInput::new("hello".to_string()); + + // Replace with new text + input.set_text("goodbye".to_string()); + assert_eq!(input.get_text(), "goodbye"); + + // Undo should restore "hello" + input.undo(); + assert_eq!(input.get_text(), "hello"); + } + + #[test] + fn test_redo_clears_on_new_edit() { + let mut input = TextInput::empty(); + + // Type "hello" + input.insert_char('h'); + input.insert_char('e'); + input.insert_char('l'); + input.insert_char('l'); + input.insert_char('o'); + + // Undo + input.undo(); + assert_eq!(input.get_text(), ""); + assert!(input.can_redo()); + + // Make a new edit (should clear redo stack) + input.insert_char('x'); + assert!(!input.can_redo()); + } + + #[test] + fn test_multiple_undo_redo() { + let mut input = TextInput::empty(); + + // First edit: type "hello" + for c in "hello".chars() { + input.insert_char(c); + } + + // Break coalescing + input.move_left(); + + // Second edit: type "world" + for c in "world".chars() { + input.insert_char(c); + } + + assert_eq!(input.get_text(), "hellworldo"); + + // Undo "world" + input.undo(); + assert_eq!(input.get_text(), "hello"); + + // Undo "hello" + input.undo(); + assert_eq!(input.get_text(), ""); + + // Redo "hello" + input.redo(); + assert_eq!(input.get_text(), "hello"); + + // Redo "world" + input.redo(); + assert_eq!(input.get_text(), "hellworldo"); + } + + #[test] + fn test_undo_stack_limit() { + let mut input = TextInput::empty(); + + // Perform 102 separate edits (breaking coalescing each time) + for _i in 0..102 { + input.backspace(); // Break coalescing + input.insert_char('x'); + } + + // Should have at most 100 undo entries + let mut undo_count = 0; + while input.undo() { + undo_count += 1; + } + + // We should have 100 undo entries (the stack limit) + // Plus the final state change from the last coalescing break + assert!( + undo_count <= 100, + "Undo count should be at most 100, got {}", + undo_count + ); + } + + #[test] + fn test_undo_redo_empty_stack() { + let mut input = TextInput::empty(); + + // Undo on empty stack should return false + assert!(!input.can_undo()); + assert!(!input.undo()); + + // Redo on empty stack should return false + assert!(!input.can_redo()); + assert!(!input.redo()); + } + + #[test] + fn test_undo_restores_cursor_position() { + let mut input = TextInput::new("hello world".to_string()); + + // Move cursor to position 5 (before "world") + input.cursor_position = 5; + + // Insert a space + input.insert_char(' '); + assert_eq!(input.get_text(), "hello world"); + assert_eq!(input.get_cursor_position(), 6); + + // Undo should restore both text and cursor position + input.undo(); + assert_eq!(input.get_text(), "hello world"); + assert_eq!(input.get_cursor_position(), 5); + } + + #[test] + fn test_coalescing_consecutive_inserts() { + let mut input = TextInput::empty(); + + // Type several characters + input.insert_char('a'); + input.insert_char('b'); + input.insert_char('c'); + + assert_eq!(input.get_text(), "abc"); + + // Single undo should remove all three (they were coalesced) + input.undo(); + assert_eq!(input.get_text(), ""); + + // No more undo available + assert!(!input.can_undo()); + } + + #[test] + fn test_backspace_breaks_coalescing() { + let mut input = TextInput::empty(); + + // Type "ab" + input.insert_char('a'); + input.insert_char('b'); + + // Backspace + input.backspace(); + assert_eq!(input.get_text(), "a"); + + // Type "c" + input.insert_char('c'); + assert_eq!(input.get_text(), "ac"); + + // Undo should remove just "c" + input.undo(); + assert_eq!(input.get_text(), "a"); + + // Undo should remove backspace operation + input.undo(); + assert_eq!(input.get_text(), "ab"); + + // Undo should remove "ab" + input.undo(); + assert_eq!(input.get_text(), ""); + } +} diff --git a/default-plugins/sequence/src/ui/truncation.rs b/default-plugins/sequence/src/ui/truncation.rs new file mode 100644 index 000000000..0c4073a35 --- /dev/null +++ b/default-plugins/sequence/src/ui/truncation.rs @@ -0,0 +1,373 @@ +use unicode_width::UnicodeWidthStr; + +const BASE_SEPARATOR_WIDTH: usize = 2; + +pub fn calculate_available_cmd_width( + cols: usize, + folder_width: usize, + overflow_indicator: Option<&String>, + chain_width: usize, + status_width: usize, +) -> usize { + let mut separator_width = BASE_SEPARATOR_WIDTH; + if overflow_indicator.is_some() { + separator_width += 1; + } + if status_width > 0 { + separator_width += 1; + } + + let overflow_width = overflow_indicator.map(|s| s.chars().count()).unwrap_or(0); + + cols.saturating_sub(folder_width) + .saturating_sub(chain_width) + .saturating_sub(status_width) + .saturating_sub(separator_width) + .saturating_sub(overflow_width) + .saturating_sub(2) + .max(1) +} + +pub fn truncate_middle( + text: &str, + max_width: usize, + cursor_position: Option, +) -> (String, Option) { + let text_width = text.width(); + + if text_width <= max_width { + return (text.to_string(), cursor_position); + } + + if max_width < 5 { + return truncate_minimal(text, max_width, cursor_position); + } + + if let Some(cursor_char_idx) = cursor_position { + return truncate_with_cursor(text, max_width, cursor_char_idx); + } + + truncate_no_cursor(text, max_width) +} + +fn truncate_minimal( + text: &str, + max_width: usize, + cursor_position: Option, +) -> (String, Option) { + let mut result = String::new(); + let mut current_width = 0; + let mut new_cursor_pos = None; + let mut char_pos = 0; + + for ch in text.chars() { + let ch_width = ch.to_string().width(); + if current_width + ch_width <= max_width { + result.push(ch); + if let Some(cursor_char) = cursor_position { + if char_pos == cursor_char { + new_cursor_pos = Some(char_pos); + } + } + char_pos += 1; + current_width += ch_width; + } else { + break; + } + } + (result, new_cursor_pos) +} + +fn truncate_no_cursor(text: &str, max_width: usize) -> (String, Option) { + let available_for_text = max_width.saturating_sub(3); + let left_width = available_for_text / 2; + let right_width = available_for_text - left_width; + + let mut left_part = String::new(); + let mut current_width = 0; + for ch in text.chars() { + let ch_width = ch.to_string().width(); + if current_width + ch_width <= left_width { + left_part.push(ch); + current_width += ch_width; + } else { + break; + } + } + + let chars: Vec = text.chars().collect(); + let mut right_part = String::new(); + let mut current_width = 0; + for ch in chars.iter().rev() { + let ch_width = ch.to_string().width(); + if current_width + ch_width <= right_width { + right_part.insert(0, *ch); + current_width += ch_width; + } else { + break; + } + } + + (format!("{}...{}", left_part, right_part), None) +} + +fn truncate_with_cursor( + text: &str, + max_width: usize, + cursor_char_idx: usize, +) -> (String, Option) { + let chars: Vec = text.chars().collect(); + let char_widths: Vec = chars.iter().map(|ch| ch.to_string().width()).collect(); + + let width_before_cursor: usize = char_widths[..cursor_char_idx].iter().sum(); + let width_after_cursor: usize = char_widths[cursor_char_idx..].iter().sum(); + let available_one_ellipsis = max_width.saturating_sub(3); + + let (start_idx, end_idx) = if width_before_cursor <= available_one_ellipsis { + calculate_end_truncation(&chars, &char_widths, available_one_ellipsis) + } else if width_after_cursor <= available_one_ellipsis { + calculate_start_truncation(&chars, &char_widths, available_one_ellipsis) + } else { + calculate_middle_truncation(&char_widths, max_width, cursor_char_idx) + }; + + let (start_idx, end_idx) = + adjust_small_truncations(start_idx, end_idx, &char_widths, cursor_char_idx, &chars); + let (start_idx, end_idx) = + trim_excess(&char_widths, start_idx, end_idx, max_width, cursor_char_idx); + + build_truncated_result(&chars, start_idx, end_idx, cursor_char_idx) +} + +fn calculate_end_truncation( + chars: &[char], + char_widths: &[usize], + available: usize, +) -> (usize, usize) { + let mut end_idx = 0; + let mut width = 0; + while end_idx < chars.len() && width + char_widths[end_idx] <= available { + width += char_widths[end_idx]; + end_idx += 1; + } + (0, end_idx) +} + +fn calculate_start_truncation( + chars: &[char], + char_widths: &[usize], + available: usize, +) -> (usize, usize) { + let mut start_idx = chars.len(); + let mut width = 0; + while start_idx > 0 && width + char_widths[start_idx - 1] <= available { + start_idx -= 1; + width += char_widths[start_idx]; + } + (start_idx, chars.len()) +} + +fn calculate_middle_truncation( + char_widths: &[usize], + max_width: usize, + cursor_char_idx: usize, +) -> (usize, usize) { + let available_both_ellipsis = max_width.saturating_sub(6); + let target_before = available_both_ellipsis / 2; + let target_after = available_both_ellipsis - target_before; + + let mut start_idx = cursor_char_idx; + let mut width_before = 0; + while start_idx > 0 && width_before + char_widths[start_idx - 1] <= target_before { + start_idx -= 1; + width_before += char_widths[start_idx]; + } + + let mut end_idx = cursor_char_idx; + let mut width_after = 0; + while end_idx < char_widths.len() && width_after + char_widths[end_idx] <= target_after { + width_after += char_widths[end_idx]; + end_idx += 1; + } + + let leftover_before = target_before.saturating_sub(width_before); + let leftover_after = target_after.saturating_sub(width_after); + + if leftover_before > 0 { + let mut extra = leftover_before; + while end_idx < char_widths.len() && char_widths[end_idx] <= extra { + extra -= char_widths[end_idx]; + end_idx += 1; + } + } + if leftover_after > 0 { + let mut extra = leftover_after; + while start_idx > 0 && char_widths[start_idx - 1] <= extra { + start_idx -= 1; + extra -= char_widths[start_idx]; + } + } + + (start_idx, end_idx) +} + +fn adjust_small_truncations( + start_idx: usize, + end_idx: usize, + char_widths: &[usize], + cursor_char_idx: usize, + chars: &[char], +) -> (usize, usize) { + let width_truncated_start: usize = char_widths[..start_idx].iter().sum(); + let width_truncated_end: usize = char_widths[end_idx..].iter().sum(); + + let mut start_idx = start_idx; + let mut end_idx = end_idx; + + if width_truncated_start > 0 && width_truncated_start < 3 && end_idx < chars.len() { + let gained = width_truncated_start; + start_idx = 0; + let mut removed = 0; + while end_idx > cursor_char_idx + 1 && removed < gained { + end_idx -= 1; + removed += char_widths[end_idx]; + } + } else if width_truncated_end > 0 && width_truncated_end < 3 && start_idx > 0 { + let gained = width_truncated_end; + end_idx = chars.len(); + let mut removed = 0; + while start_idx < cursor_char_idx && removed < gained { + removed += char_widths[start_idx]; + start_idx += 1; + } + } + + (start_idx, end_idx) +} + +fn trim_excess( + char_widths: &[usize], + start_idx: usize, + end_idx: usize, + max_width: usize, + cursor_char_idx: usize, +) -> (usize, usize) { + let truncate_start = start_idx > 0; + let truncate_end = end_idx < char_widths.len(); + let ellipsis_width = match (truncate_start, truncate_end) { + (true, true) => 6, + (true, false) | (false, true) => 3, + (false, false) => 0, + }; + + let visible_width: usize = char_widths[start_idx..end_idx].iter().sum(); + let mut start_idx = start_idx; + let mut end_idx = end_idx; + + if visible_width + ellipsis_width > max_width { + let mut excess = visible_width + ellipsis_width - max_width; + if truncate_end { + while excess > 0 && end_idx > cursor_char_idx + 1 { + end_idx -= 1; + excess = excess.saturating_sub(char_widths[end_idx]); + } + } + if excess > 0 && truncate_start { + while excess > 0 && start_idx < cursor_char_idx { + excess = excess.saturating_sub(char_widths[start_idx]); + start_idx += 1; + } + } + } + + (start_idx, end_idx) +} + +fn build_truncated_result( + chars: &[char], + start_idx: usize, + end_idx: usize, + cursor_char_idx: usize, +) -> (String, Option) { + let mut result = String::new(); + let mut new_cursor_char_pos = 0; + let mut current_char_pos = 0; + + if start_idx > 0 { + result.push_str("..."); + current_char_pos = 3; + } + + for i in start_idx..end_idx { + if i == cursor_char_idx { + new_cursor_char_pos = current_char_pos; + } + result.push(chars[i]); + current_char_pos += 1; + } + + if cursor_char_idx >= end_idx { + new_cursor_char_pos = current_char_pos; + } + + if end_idx < chars.len() { + result.push_str("..."); + } + + (result, Some(new_cursor_char_pos)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_truncate_middle_no_truncation_needed() { + let text = "hello world"; + let (result, cursor_pos) = truncate_middle(text, 20, Some(6)); + assert_eq!(result, "hello world"); + assert_eq!(cursor_pos, Some(6)); + } + + #[test] + fn test_truncate_middle_no_cursor() { + let text = "this is a very long string that needs truncation"; + let (result, cursor_pos) = truncate_middle(text, 20, None); + assert!(result.contains("...")); + assert_eq!(cursor_pos, None); + } + + #[test] + fn test_truncate_middle_cursor_at_start() { + let text = "this is a very long string that needs truncation"; + let (result, cursor_pos) = truncate_middle(text, 20, Some(0)); + assert!(result.starts_with("this")); + assert!(result.ends_with("...")); + assert_eq!(cursor_pos, Some(0)); + } + + #[test] + fn test_truncate_middle_cursor_at_end() { + let text = "this is a very long string that needs truncation"; + let cursor_char = text.chars().count(); + let (result, _cursor_pos) = truncate_middle(text, 20, Some(cursor_char)); + assert!(result.starts_with("...")); + assert!(result.ends_with("truncation")); + } + + #[test] + fn test_truncate_middle_cursor_in_middle() { + let text = "this is a very long string that needs truncation"; + let cursor_char = "this is a very ".chars().count(); + let (result, cursor_pos) = truncate_middle(text, 20, Some(cursor_char)); + assert!(result.contains("very")); + assert!(cursor_pos.is_some()); + } + + #[test] + fn test_truncate_middle_wide_chars() { + let text = "こんにちは世界"; + let (result, _) = truncate_middle(text, 10, None); + assert!(result.width() <= 10); + } +} diff --git a/default-plugins/session-manager/src/main.rs b/default-plugins/session-manager/src/main.rs index 6be29dc50..5c014779f 100644 --- a/default-plugins/session-manager/src/main.rs +++ b/default-plugins/session-manager/src/main.rs @@ -508,9 +508,9 @@ impl State { if is_current_session { if let Some((pane_id, is_plugin)) = selected_pane { if is_plugin { - focus_plugin_pane(pane_id, true); + focus_plugin_pane(pane_id, true, false); } else { - focus_terminal_pane(pane_id, true); + focus_terminal_pane(pane_id, true, false); } } else if let Some(tab_position) = selected_tab { go_to_tab(tab_position as u32); diff --git a/default-plugins/status-bar/src/one_line_ui.rs b/default-plugins/status-bar/src/one_line_ui.rs index a3fdec774..a73c7b80b 100644 --- a/default-plugins/status-bar/src/one_line_ui.rs +++ b/default-plugins/status-bar/src/one_line_ui.rs @@ -1386,7 +1386,7 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec Vec<(String, String, Vec Vec<(String, String, Vec Vec<(String, String, Vec Vec<(String, String, Vec &'static Vec { crate_name: "default-plugins/share", build: true, }, + WorkspaceMember { + crate_name: "default-plugins/sequence", + build: true, + }, WorkspaceMember { crate_name: "zellij-utils", build: false, diff --git a/zellij-client/src/old_config_converter/old_config.rs b/zellij-client/src/old_config_converter/old_config.rs index bfe345dfc..b5083c17f 100644 --- a/zellij-client/src/old_config_converter/old_config.rs +++ b/zellij-client/src/old_config_converter/old_config.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use serde::de::{Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use url::Url; const ON_FORCE_CLOSE_DESCRIPTION: &'static str = " @@ -560,23 +560,6 @@ struct OldUnbindFromYaml { unbind: OldUnbind, } -/// Main configuration. -#[derive(Debug, Clone, PartialEq, Deserialize)] -struct OldConfig { - pub keybinds: OldKeybinds, - pub options: OldOptions, - pub themes: Option, - pub plugins: OldPluginsConfig, - pub ui: Option, - pub env: OldEnvironmentVariablesFromYaml, -} - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -struct OldKeybinds(HashMap); - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -struct OldModeKeybinds(BTreeMap>); - #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct OldThemesFromYamlIntermediate(HashMap); @@ -720,36 +703,6 @@ impl Default for OldPluginTypeFromYaml { #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] struct OldPluginTag(String); -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -struct OldPluginsConfig(HashMap); - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -struct OldPluginConfig { - /// Path of the plugin, see resolve_wasm_bytes for resolution semantics - pub path: PathBuf, - /// Plugin type - pub run: OldPluginType, - /// Allow command execution from plugin - pub _allow_exec_host_cmd: bool, - /// Original location of the - pub location: OldRunPluginLocation, -} - -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] -enum OldRunPluginLocation { - File(PathBuf), - Zellij(OldPluginTag), -} - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -enum OldPluginType { - /// Starts immediately when Zellij is started and runs without a visible pane - Headless, - /// Runs once per pane declared inside a layout file - Pane(Option), // tab_index -} - #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize)] pub enum OldOnForceClose { #[serde(alias = "quit")] diff --git a/zellij-client/src/web_client/types.rs b/zellij-client/src/web_client/types.rs index 201a0cf4d..32676fd35 100644 --- a/zellij-client/src/web_client/types.rs +++ b/zellij-client/src/web_client/types.rs @@ -168,22 +168,6 @@ pub struct AppState { pub is_https: bool, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StdinMessage { - pub web_client_id: String, - pub stdin: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ShutdownSignal { - Shutdown, -} - -#[derive(Serialize, Debug)] -pub struct SendShutdownSignalResponse { - pub status: String, -} - #[derive(Serialize)] pub struct CreateClientIdResponse { pub web_client_id: String, diff --git a/zellij-server/src/background_jobs.rs b/zellij-server/src/background_jobs.rs index 9bc8a9384..629070488 100644 --- a/zellij-server/src/background_jobs.rs +++ b/zellij-server/src/background_jobs.rs @@ -24,6 +24,7 @@ use std::time::{Duration, Instant}; use crate::panes::PaneId; use crate::plugins::{PluginId, PluginInstruction}; +use crate::pty::PtyInstruction; use crate::screen::ScreenInstruction; use crate::thread_bus::Bus; use crate::ClientId; @@ -228,6 +229,7 @@ pub(crate) fn background_jobs_main( session_infos_on_machine, resurrectable_sessions, )); + let _ = senders.send_to_pty(PtyInstruction::UpdateAndReportCwds); if last_serialization_time .lock() .unwrap() diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 1861fb68a..dd0939196 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -784,6 +784,8 @@ pub fn start_server(mut os_input: Box, socket_path: PathBuf) { floating_panes_layout, tab_name, swap_layouts, + None, // initial_panes + false, // block_on_first_terminal should_focus_tab, (client_id, is_web_client), None, diff --git a/zellij-server/src/os_input_output.rs b/zellij-server/src/os_input_output.rs index adcca9740..46010493e 100644 --- a/zellij-server/src/os_input_output.rs +++ b/zellij-server/src/os_input_output.rs @@ -500,6 +500,8 @@ pub trait ServerOsApi: Send + Sync { fn kill(&self, pid: Pid) -> Result<()>; /// Terminate the process with process ID `pid`. (SIGKILL) fn force_kill(&self, pid: Pid) -> Result<()>; + /// Send SIGINT to the process with process ID `pid` + fn send_sigint(&self, pid: Pid) -> Result<()>; /// Returns a [`Box`] pointer to this [`ServerOsApi`] struct. fn box_clone(&self) -> Box; fn send_to_client(&self, client_id: ClientId, msg: ServerToClientMsg) -> Result<()>; @@ -697,6 +699,10 @@ impl ServerOsApi for ServerOsInputOutput { let _ = kill(pid, Some(Signal::SIGKILL)); Ok(()) } + fn send_sigint(&self, pid: Pid) -> Result<()> { + let _ = kill(pid, Some(Signal::SIGINT)); + Ok(()) + } fn send_to_client(&self, client_id: ClientId, msg: ServerToClientMsg) -> Result<()> { let err_context = || format!("failed to send message to client {client_id}"); diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index 6ae71b438..d347dcd04 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -18,6 +18,7 @@ use crate::{ ClientId, }; use std::cell::RefCell; +use std::cmp::Ordering; use std::collections::{BTreeMap, HashMap, HashSet}; use std::rc::Rc; use std::time::Instant; @@ -129,6 +130,7 @@ impl FloatingPanes { .insert(pane_id, pane.position_and_size()); self.panes.insert(pane_id, pane); self.z_indices.push(pane_id); + self.make_sure_pinned_panes_are_on_top(); } pub fn replace_active_pane( &mut self, @@ -169,6 +171,7 @@ impl FloatingPanes { .with_context(err_context)?; self.z_indices.remove(z_index); self.z_indices.insert(z_index, with_pane_id); + self.make_sure_pinned_panes_are_on_top(); Ok(removed_pane) }); @@ -415,21 +418,10 @@ impl FloatingPanes { vec![] }; floating_panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| { - self.z_indices - .iter() - .position(|id| id == *a_id) - .with_context(err_context) - .fatal() - .cmp( - &self - .z_indices - .iter() - .position(|id| id == *b_id) - .with_context(err_context) - .fatal(), - ) + let a_pos = self.z_indices.iter().position(|id| id == *a_id); + let b_pos = self.z_indices.iter().position(|id| id == *b_id); + a_pos.cmp(&b_pos) }); - for (z_index, (kind, pane)) in floating_panes.iter_mut().enumerate() { let mut active_panes = active_panes.clone(); let multiple_users_exist_in_session = @@ -806,6 +798,16 @@ impl FloatingPanes { pane_geom.adjust_coordinates(new_coordinates, viewport); pane.set_geom(pane_geom); pane.set_should_render(true); + + // we do this in case this moves the pane under another pane so that the pane user's + // are focused on will always be on top + let is_focused = self.active_panes.pane_id_is_focused(&pane_id); + if is_focused { + self.z_indices.retain(|p_id| *p_id != pane_id); + self.z_indices.push(pane_id); + self.make_sure_pinned_panes_are_on_top(); + } + self.desired_pane_positions.insert(pane_id, pane_geom); } let _ = self.set_pane_frames(); @@ -840,7 +842,7 @@ impl FloatingPanes { self.focus_pane(next_active_pane_id, client_id); }, None => { - self.defocus_pane(pane_id, client_id); + self.defocus_pane(client_id); }, } } @@ -855,6 +857,7 @@ impl FloatingPanes { } self.z_indices.retain(|p_id| *p_id != pane_id); self.z_indices.push(pane_id); + self.make_sure_pinned_panes_are_on_top(); self.set_pane_active_at(pane_id); self.set_force_render(); } @@ -888,8 +891,7 @@ impl FloatingPanes { }, } } - pub fn defocus_pane(&mut self, pane_id: PaneId, client_id: ClientId) { - self.z_indices.retain(|p_id| *p_id != pane_id); + pub fn defocus_pane(&mut self, client_id: ClientId) { self.active_panes.remove(&client_id, &mut self.panes); self.set_force_render(); } @@ -1244,4 +1246,27 @@ impl FloatingPanes { ); floating_pane_grid.next_selectable_pane_id_to_the_right(&pane_id) } + fn make_sure_pinned_panes_are_on_top(&mut self) { + let pinned_status: std::collections::HashMap<_, _> = self + .z_indices + .iter() + .map(|id| (id.clone(), self.pane_id_is_pinned(id))) + .collect(); + + self.z_indices.sort_by(|a_id, b_id| { + let a_is_pinned = pinned_status.get(a_id).copied().unwrap_or(false); + let b_is_pinned = pinned_status.get(b_id).copied().unwrap_or(false); + match (a_is_pinned, b_is_pinned) { + (true, false) => Ordering::Greater, + (false, true) => Ordering::Less, + _ => Ordering::Equal, + } + }); + } + fn pane_id_is_pinned(&self, pane_id: &PaneId) -> bool { + self.panes + .get(pane_id) + .map(|p| p.position_and_size().is_pinned) + .unwrap_or(false) + } } diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs index 0e74a9def..ffad3d84d 100644 --- a/zellij-server/src/panes/plugin_pane.rs +++ b/zellij-server/src/panes/plugin_pane.rs @@ -90,6 +90,7 @@ pub(crate) struct PluginPane { character_cell_size: Rc>>, vte_parsers: HashMap, grids: HashMap, + cursor_visibility: HashMap>, prev_pane_name: String, frame: HashMap, borderless: bool, @@ -149,6 +150,7 @@ impl PluginPane { sixel_image_store, vte_parsers: HashMap::new(), grids: HashMap::new(), + cursor_visibility: HashMap::new(), style, pane_frame_color_override: None, invoked_with, @@ -248,8 +250,25 @@ impl Pane for PluginPane { self.should_render.insert(client_id, true); } - fn cursor_coordinates(&self) -> Option<(usize, usize)> { - None + fn cursor_coordinates(&self, client_id: Option) -> Option<(usize, usize)> { + let own_content_columns = self.get_content_columns(); + let own_content_rows = self.get_content_rows(); + let Offset { top, left, .. } = self.content_offset; + if let Some(coordinates) = + client_id.and_then(|client_id| self.cursor_visibility.get(&client_id)) + { + coordinates + .map(|(x, y)| (x + left, y + top)) + .and_then(|(x, y)| { + if x >= own_content_columns || y >= own_content_rows { + None + } else { + Some((x, y)) // these are 0 indexed + } + }) + } else { + None + } } fn adjust_input_to_terminal( &mut self, @@ -360,6 +379,10 @@ impl Pane for PluginPane { fn set_selectable(&mut self, selectable: bool) { self.selectable = selectable; } + fn show_cursor(&mut self, client_id: ClientId, cursor_position: Option<(usize, usize)>) { + self.cursor_visibility.insert(client_id, cursor_position); + self.should_render.insert(client_id, true); + } fn request_permissions_from_user(&mut self, permissions: Option) { self.requesting_permissions = permissions; self.handle_plugin_bytes_for_all_clients(Default::default()); // to trigger the render of @@ -440,7 +463,7 @@ impl Pane for PluginPane { let res = match self.frame.get(&client_id) { // TODO: use and_then or something? Some(last_frame) => { - if &frame != last_frame { + if &frame != last_frame || is_pinned { if !self.borderless { let frame_output = frame.render().with_context(err_context)?; self.frame.insert(client_id, frame); diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index 1c5667a50..97bf5dcce 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -197,7 +197,7 @@ impl Pane for TerminalPane { self.vte_parser.advance(&mut self.grid, byte); } } - fn cursor_coordinates(&self) -> Option<(usize, usize)> { + fn cursor_coordinates(&self, _client_id: Option) -> Option<(usize, usize)> { // (x, y) if self.get_content_rows() < 1 || self.get_content_columns() < 1 { // do not render cursor if there's no room for it @@ -740,6 +740,14 @@ impl Pane for TerminalPane { if let Some(notification_end) = self.notification_end.as_mut() { if let Some(exit_status) = exit_status { notification_end.set_exit_status(exit_status); + + // Check if unblock condition is met + if let Some(condition) = notification_end.unblock_condition() { + if condition.is_met(exit_status) { + // Condition met - drop the NotificationEnd now to unblock + drop(self.notification_end.take()); + } + } } } if is_first_run { @@ -899,6 +907,13 @@ impl Pane for TerminalPane { fn update_exit_status(&mut self, exit_status: i32) { if let Some(notification_end) = self.notification_end.as_mut() { notification_end.set_exit_status(exit_status); + // Check if unblock condition is met + if let Some(condition) = notification_end.unblock_condition() { + if condition.is_met(exit_status) { + // Condition met - drop the NotificationEnd now to unblock + drop(self.notification_end.take()); + } + } } } } @@ -922,7 +937,7 @@ impl TerminalPane { arrow_fonts: bool, styled_underlines: bool, explicitly_disable_keyboard_protocol: bool, - notification_end: Option, + mut notification_end: Option, ) -> TerminalPane { let initial_pane_title = initial_pane_title.unwrap_or_else(|| format!("Pane #{}", pane_index)); @@ -940,6 +955,9 @@ impl TerminalPane { styled_underlines, explicitly_disable_keyboard_protocol, ); + if let Some(notification_end) = notification_end.as_mut() { + notification_end.set_affected_pane_id(PaneId::Terminal(pid)); + } TerminalPane { frame: HashMap::new(), content_offset: Offset::default(), diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs index fb73a90d2..4df68db46 100644 --- a/zellij-server/src/panes/tiled_panes/mod.rs +++ b/zellij-server/src/panes/tiled_panes/mod.rs @@ -313,6 +313,7 @@ impl TiledPanes { Ok(new_pane_geom) => { pane.set_geom(new_pane_geom); self.panes.insert(pane_id, pane); // TODO: is set_geom the right one? + self.expand_pane_in_stack(pane_id); }, Err(e) => { log::error!("Failed to add pane to stack: {:?}", e); @@ -349,7 +350,8 @@ impl TiledPanes { Ok(new_pane_geom) => { pane.set_geom(new_pane_geom); self.panes.insert(pane_id, pane); - self.set_force_render(); // TODO: why do we need this? + + self.expand_pane_in_stack(pane_id); return; }, Err(_e) => { @@ -447,7 +449,9 @@ impl TiledPanes { .map(|p| p.is_stacked()) .unwrap_or(false); if !pane_id_is_stacked { - let _ = pane_grid.make_pane_stacked(&root_pane_id); + if let Err(e) = pane_grid.make_pane_stacked(&root_pane_id) { + log::error!("Failed to make pane stacked: {:?}", e); + } } match pane_grid.make_room_in_stack_of_pane_id_for_pane(&root_pane_id) { Ok(new_pane_geom) => { 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 ddb225a48..0c989a9e7 100644 --- a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs +++ b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs @@ -1344,6 +1344,14 @@ impl<'a> TiledPaneGrid<'a> { let _ = pane_resizer.layout(direction, side_length); return true; } + } else { + // best effort resize - we just remove the pane and relayout everything + // this might happen if we are closing a fixed pane + self.panes.borrow_mut().remove(&id); + let mut pane_resizer = PaneResizer::new(self.panes.clone()); + let _ = pane_resizer.layout(SplitDirection::Horizontal, self.display_area.cols); + let _ = pane_resizer.layout(SplitDirection::Vertical, self.display_area.rows); + return true; } false } diff --git a/zellij-server/src/panes/tiled_panes/unit/stacked_panes_tests.rs b/zellij-server/src/panes/tiled_panes/unit/stacked_panes_tests.rs index 6b4edf40e..e4adfbe44 100644 --- a/zellij-server/src/panes/tiled_panes/unit/stacked_panes_tests.rs +++ b/zellij-server/src/panes/tiled_panes/unit/stacked_panes_tests.rs @@ -1085,7 +1085,7 @@ impl Pane for MockPane { fn handle_plugin_bytes(&mut self, _client_id: ClientId, _bytes: VteBytes) { unimplemented!() } - fn cursor_coordinates(&self) -> Option<(usize, usize)> { + fn cursor_coordinates(&self, _client_id: Option) -> Option<(usize, usize)> { unimplemented!() } diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap index 7ab7a56c5..530592404 100644 --- a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap @@ -2,13 +2,13 @@ source: zellij-server/src/panes/./unit/grid_tests.rs expression: "format!(\"{:?}\", grid)" --- -00 (C): title1 title2 title3 title4 title5 -01 (C): 1lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lkjdslkjsdf -02 (C): 2lksdjflksdjf lkjdsflksjdf lkj😳😳sdlkfjsfd lkjsdlkjfd lkjdslkjsdf -03 (C): 3lksdjflksdjf lkjdsflksjdf lkjsd😳lkfjsfd lkjsdlkjfd lkjdslkjsdf -04 (C): 4lksdjflks222djf lk😳222jdsflksjdf lk222jsdlkfjsfd lkwwwjsdlkjfd lkjdslkjsdf -05 (C): 5lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lksdjflksjfdlkjsdlkjfd lkjdrrrrslkjsdf -06 (C): 6lksdjflk😳sdjf l😳kjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lwwkwkjdslkjsdf +00 (C): title1 title2 title3 title4 title5 +01 (C): 1lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lkjdslkjsdf +02 (C): 2lksdjflksdjf lkjdsflksjdf lkj😳😳sdlkfjsfd lkjsdlkjfd lkjdslkjsdf +03 (C): 3lksdjflksdjf lkjdsflksjdf lkjsd😳lkfjsfd lkjsdlkjfd lkjdslkjsdf +04 (C): 4lksdjflks222djf lk😳222jdsflksjdf lk222jsdlkfjsfd lkwwwjsdlkjfd lkjdslkjsdf +05 (C): 5lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lksdjflksjfdlkjsdlkjfd lkjdrrrrslkjsdf +06 (C): 6lksdjflk😳sdjf l😳kjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lwwkwkjdslkjsdf 07 (C): 08 (C): 09 (C): diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index cede7901f..24a1e8111 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -30,12 +30,13 @@ use wasm_bridge::WasmBridge; use async_std::{channel, future::timeout, task}; use zellij_utils::{ data::{ - ClientInfo, Event, EventType, FloatingPaneCoordinates, InputMode, MessageToPlugin, - PermissionStatus, PermissionType, PipeMessage, PipeSource, PluginCapabilities, - WebServerStatus, + ClientInfo, CommandOrPlugin, Event, EventType, FloatingPaneCoordinates, InputMode, + MessageToPlugin, PermissionStatus, PermissionType, PipeMessage, PipeSource, + PluginCapabilities, WebServerStatus, }, errors::{prelude::*, ContextType, PluginContext}, input::{ + actions::Action, command::TerminalAction, keybinds::Keybinds, layout::{FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginOrAlias, TiledPaneLayout}, @@ -86,10 +87,12 @@ pub enum PluginInstruction { Option, Option, Vec, - usize, // tab_index - bool, // should change focus to new tab - (ClientId, bool), // bool -> is_web_client - Option, // completion signal + usize, // tab_index + Option>, // initial_panes + bool, // block_on_first_terminal + bool, // should change focus to new tab + (ClientId, bool), // bool -> is_web_client + Option, // completion signal ), ApplyCachedEvents { plugin_ids: Vec, @@ -175,6 +178,12 @@ pub enum PluginInstruction { WebServerStarted(String), // String -> the base url of the web server FailedToStartWebServer(String), PaneRenderReport(PaneRenderReport), + UserInput { + client_id: ClientId, + action: Action, + terminal_id: Option, + cli_client_id: Option, + }, Exit, } @@ -225,6 +234,7 @@ impl From<&PluginInstruction> for PluginContext { PluginInstruction::WebServerStarted(..) => PluginContext::WebServerStarted, PluginInstruction::FailedToStartWebServer(..) => PluginContext::FailedToStartWebServer, PluginInstruction::PaneRenderReport(..) => PluginContext::PaneRenderReport, + PluginInstruction::UserInput { .. } => PluginContext::UserInput, } } } @@ -453,6 +463,8 @@ pub(crate) fn plugin_thread_main( mut tab_layout, mut floating_panes_layout, tab_index, + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, (client_id, is_web_client), completion_tx, @@ -469,6 +481,26 @@ pub(crate) fn plugin_thread_main( let mut plugin_ids: HashMap> = HashMap::new(); tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0)); + + // Match initial_panes plugins to empty slots in the layout + if let Some(ref initial_panes_vec) = initial_panes { + if let Some(ref mut tiled_layout) = tab_layout { + for initial_pane in initial_panes_vec.iter() { + if let CommandOrPlugin::Plugin(run_plugin_or_alias) = initial_pane { + if !tiled_layout.replace_next_empty_slot_with_run(Run::Plugin( + run_plugin_or_alias.clone(), + )) { + log::warn!( + "More initial_panes provided than empty slots available" + ); + break; + } + } + // Skip CommandOrPlugin::Command entries (handled by pty thread) + } + } + } + tab_layout.as_mut().map(|t| { t.populate_plugin_aliases_in_layout(&plugin_aliases); if let Some(cwd) = cwd.as_ref() { @@ -481,7 +513,7 @@ pub(crate) fn plugin_thread_main( .as_mut() .map(|f| f.populate_run_plugin_if_needed(&plugin_aliases)); }); - let mut extracted_run_instructions = tab_layout + let extracted_run_instructions = tab_layout .clone() .unwrap_or_else(|| layout.new_tab().0) .extract_run_instructions(); @@ -496,8 +528,10 @@ pub(crate) fn plugin_thread_main( .filter(|f| !f.already_running) .map(|f| f.run.clone()) .collect(); - extracted_run_instructions.append(&mut extracted_floating_plugins); - for run_instruction in extracted_run_instructions { + let mut all_run_instructions = extracted_run_instructions; + all_run_instructions.append(&mut extracted_floating_plugins); + + for run_instruction in all_run_instructions { if let Some(Run::Plugin(run_plugin_or_alias)) = run_instruction { let run_plugin = run_plugin_or_alias.get_run_plugin(); let cwd = run_plugin_or_alias @@ -525,6 +559,8 @@ pub(crate) fn plugin_thread_main( floating_panes_layout, tab_index, plugin_ids, + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, (client_id, is_web_client), completion_tx, @@ -989,6 +1025,20 @@ pub(crate) fn plugin_thread_main( .handle_pane_render_report(pane_render_report, shutdown_send.clone()) .non_fatal(); }, + PluginInstruction::UserInput { + client_id, + action, + terminal_id, + cli_client_id, + } => { + // Fire Event::UserAction to all subscribed plugins with InterceptInput permission + let updates = vec![( + None, + None, + Event::UserAction(action, client_id, terminal_id, cli_client_id), + )]; + wasm_bridge.update_plugins(updates, shutdown_send.clone())?; + }, PluginInstruction::Exit => { break; }, diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 5f90ebbef..c0368fbcd 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -9137,3 +9137,670 @@ pub fn before_close_plugin_event() { .unwrap(); assert_snapshot!(format!("{:#?}", sent_instruction)); } + +#[test] +#[ignore] +pub fn show_cursor_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + 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)); + 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::ShowPluginCursor, + 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, + 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('a')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let show_cursor_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ShowPluginCursor(plugin_id, client_id, cursor_position) = i { + Some((*plugin_id, *client_id, *cursor_position)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", show_cursor_instruction)); +} + +#[test] +#[ignore] +pub fn hide_cursor_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + 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)); + 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::ShowPluginCursor, + 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, + 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('b')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let hide_cursor_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ShowPluginCursor(plugin_id, client_id, cursor_position) = i { + Some((*plugin_id, *client_id, *cursor_position)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", hide_cursor_instruction)); +} + +#[test] +#[ignore] +pub fn copy_to_clipboard_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + 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)); + 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::CopyTextToClipboard, + screen_receiver, + 1, + &PermissionType::WriteToClipboard, + 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, + 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('c')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let copy_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::CopyTextToClipboard(text, plugin_id) = i { + Some((text.clone(), *plugin_id)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", copy_instruction)); +} + +#[test] +#[ignore] +pub fn run_action_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + 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)); + 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::MoveFocusLeft, + screen_receiver, + 1, + &PermissionType::RunActionsAsUser, + 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, + 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('d')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let move_focus_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::MoveFocusLeft(client_id, notification_end) = i { + Some((*client_id, notification_end.clone())) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", move_focus_instruction)); +} + +#[test] +#[ignore] +pub fn send_sigint_to_pane_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, pty_receiver, screen_receiver, teardown) = + create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); + + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::SendSigintToPaneId, + 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_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 size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + 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('e')).with_super_modifier()), + )])); + + pty_thread.join().unwrap(); + teardown(); + + let sigint_instruction = received_pty_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let PtyInstruction::SendSigintToPaneId(pane_id) = i { + Some(*pane_id) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", sigint_instruction)); +} + +#[test] +#[ignore] +pub fn send_sigkill_to_pane_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, pty_receiver, screen_receiver, teardown) = + create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); + + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::SendSigkillToPaneId, + 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_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 size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + 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('f')).with_super_modifier()), + )])); + + pty_thread.join().unwrap(); + teardown(); + + let sigkill_instruction = received_pty_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let PtyInstruction::SendSigkillToPaneId(pane_id) = i { + Some(*pane_id) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", sigkill_instruction)); +} + +#[test] +#[ignore] +pub fn copy_to_clipboard_without_permission() { + 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)); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + // This test denies the permission and expects no CopyTextToClipboard instruction + let screen_thread = deny_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::CopyTextToClipboard, + screen_receiver, + 1, + &PermissionType::WriteToClipboard, + cache_path, + plugin_thread_sender, + client_id + ); + + 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 size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + 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('c')).with_super_modifier()), + )])); + + // Give it time to potentially (incorrectly) send the instruction + std::thread::sleep(std::time::Duration::from_millis(1000)); + + let _ = plugin_thread_sender.send(PluginInstruction::Exit); + screen_thread.join().unwrap(); + teardown(); + + let copy_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::CopyTextToClipboard(text, plugin_id) = i { + Some((text.clone(), *plugin_id)) + } else { + None + } + }); + + // Should be None because permission was denied + assert_snapshot!(format!("{:#?}", copy_instruction)); +} + +#[test] +#[ignore] +pub fn run_action_without_permission() { + 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)); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let screen_thread = deny_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::MoveFocusLeft, + screen_receiver, + 1, + &PermissionType::RunActionsAsUser, + cache_path, + plugin_thread_sender, + client_id + ); + + 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 size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + 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('d')).with_super_modifier()), + )])); + + std::thread::sleep(std::time::Duration::from_millis(1000)); + + let _ = plugin_thread_sender.send(PluginInstruction::Exit); + screen_thread.join().unwrap(); + teardown(); + + let move_focus_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::MoveFocusLeft(client_id, notification_end) = i { + Some((*client_id, notification_end.clone())) + } else { + None + } + }); + + // Should be None because permission was denied + assert_snapshot!(format!("{:#?}", move_focus_instruction)); +} diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap index 975e20a3b..88023c4b1 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap index 133b23fff..38179b854 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap index cdaa2362f..d03122184 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap index cbf3c8c22..b795da466 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap index 1041e20fa..97e61a45f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap new file mode 100644 index 000000000..cc4717e37 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap @@ -0,0 +1,10 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", copy_instruction)" +--- +Some( + ( + "test clipboard text", + 0, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap new file mode 100644 index 000000000..333c0389c --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap @@ -0,0 +1,5 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", copy_instruction)" +--- +None diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap index ea71beac4..1de9477d4 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap @@ -11,6 +11,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap index cc572e0cf..370a7bbff 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap index f8cf46237..3ef17f9d9 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap index 305eb5a57..fbd45fd08 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap index 6b98856a7..31a63f734 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap @@ -8,11 +8,14 @@ Some( 1, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap index 0b37d3188..8073ceb87 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap index 345f04794..0a3a1d236 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap @@ -8,11 +8,14 @@ Some( 1, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap index ca2edc5fe..c76a5eccf 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap index 1451fa506..f4653b620 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap index 13bbdb4af..48cf0870d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap index 3fd2e40f2..7e45c1fc6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap index 28c7dedc5..91ec8a9bc 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 5505 expression: "format!(\"{:#?}\", permissions)" --- Some( @@ -15,5 +14,7 @@ Some( ReadCliPipes, MessageAndLaunchOtherPlugins, Reconfigure, + RunActionsAsUser, + WriteToClipboard, ], ) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap new file mode 100644 index 000000000..31880c737 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap @@ -0,0 +1,11 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", hide_cursor_instruction)" +--- +Some( + ( + 0, + 1, + None, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap index c3b1d5f22..944191992 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap index 72b7dc153..f901ba75f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap index b9306571f..1c2a8fc6a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap index 9da828559..51f2cc158 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap index 1213308e9..128c7abe4 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap @@ -17,6 +17,8 @@ Some( [], [], ), + None, + false, true, ( 1, @@ -26,6 +28,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap index bc4faa999..1c74a94b7 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap @@ -63,6 +63,8 @@ Some( [], [], ), + None, + false, false, ( 1, @@ -72,6 +74,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap index 2ba4de2af..889a6e9d9 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap @@ -63,6 +63,8 @@ Some( [], [], ), + None, + false, true, ( 1, @@ -72,6 +74,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap index 21c4257cd..87c3264c3 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap index ac0838cc7..3afcead66 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap index ca751a220..596700c59 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap index eb598cf0a..be8503def 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap @@ -36,6 +36,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap index d235c4167..b899e596f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap @@ -36,6 +36,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap index cde191a5f..fc2087d67 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap index 89986fd25..4d2689db2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap index b2f0f9ae9..b42943fcd 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap @@ -31,6 +31,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap index 5cc2ce7cc..dd197b763 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap @@ -31,6 +31,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap index d85ffc61a..5292281bf 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap index 014ac3d3c..5709731cb 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap index b35b3b0b7..523e76fd8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap index d00a76630..5057701a7 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap index 5816c2830..119444e2f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap @@ -33,6 +33,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap index 9450f7c0b..4846cd65d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap @@ -23,6 +23,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap index f23a792c9..53b81db86 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap @@ -35,6 +35,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap index 75f47da7b..1400f0813 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 5414 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -17,5 +16,7 @@ Some( ReadCliPipes, MessageAndLaunchOtherPlugins, Reconfigure, + WriteToClipboard, + RunActionsAsUser, ], ) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap index 37275f434..0184c9a66 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap @@ -14,6 +14,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap index d9fa542d1..71766b1ed 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap new file mode 100644 index 000000000..dcbf70044 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap @@ -0,0 +1,17 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", move_focus_instruction)" +--- +Some( + ( + 1, + Some( + NotificationEnd { + channel: None, + exit_status: None, + unblock_condition: None, + affected_pane_id: None, + }, + ), + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap new file mode 100644 index 000000000..102abab0e --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap @@ -0,0 +1,5 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", move_focus_instruction)" +--- +None diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap index c8605a1c5..738a76255 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap index 410902d59..339ea8c4f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap index 9f2effacd..5c0b90889 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap index acc0d6a64..d0250b34a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap index aa9592c28..14438cf8a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap new file mode 100644 index 000000000..a7558487e --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap @@ -0,0 +1,9 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", sigint_instruction)" +--- +Some( + Terminal( + 1, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap new file mode 100644 index 000000000..fb7dc0a11 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap @@ -0,0 +1,9 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", sigkill_instruction)" +--- +Some( + Terminal( + 1, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap new file mode 100644 index 000000000..5b53f360b --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap @@ -0,0 +1,16 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", show_cursor_instruction)" +--- +Some( + ( + 0, + 1, + Some( + ( + 5, + 10, + ), + ), + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap index 24f6c12f3..457bebdc1 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap @@ -8,6 +8,7 @@ Some( 1, ), true, + false, 1, None, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap index a99b02303..41396ddb6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap @@ -8,11 +8,14 @@ Some( 0, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap index 290247c05..845f37ba0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap @@ -21,6 +21,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap index 6df0b5df5..b4ff3c006 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap @@ -330,6 +330,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap index f8959104d..06cde2560 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap index 34e96dae9..44747b668 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap index 8f375b9c4..8e24bff8d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap index e1bded4d9..c91f66aa0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap @@ -8,6 +8,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap index e088770bf..32965d58f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap index 6c500286b..99df84750 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap index 54566d681..7836e7d29 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap index 8bb05ce1c..abf3d1a2a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap index 8bb05ce1c..abf3d1a2a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 5dd78d13e..2453a0a15 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -113,7 +113,7 @@ impl LoadingContext { let plugin_own_data_dir = ZELLIJ_SESSION_CACHE_DIR .join(Url::from(&plugin_config.location).to_string()) .join(format!("{}-{}", plugin_id, client_id)); - let plugin_own_cache_dir = ZELLIJ_SESSION_CACHE_DIR + let plugin_own_cache_dir = ZELLIJ_CACHE_DIR .join(Url::from(&plugin_config.location).to_string()) .join(format!("plugin_cache")); let default_mode = wasm_bridge @@ -1901,9 +1901,11 @@ fn check_event_permission( | Event::EditPaneExited(..) | Event::FailedToWriteConfigToDisk(..) | Event::CommandPaneReRun(..) + | Event::CwdChanged(..) | Event::InputReceived => PermissionType::ReadApplicationState, Event::WebServerStatus(..) => PermissionType::StartWebServer, Event::PaneRenderReport(..) => PermissionType::ReadPaneContents, + Event::UserAction(..) => PermissionType::InterceptInput, _ => return (PermissionStatus::Granted, None), }; @@ -1943,54 +1945,63 @@ pub fn apply_event_to_plugin( mode_info.keybinds = running_plugin.store.data().keybinds.to_keybinds_vec(); mode_info.base_mode = Some(running_plugin.store.data().default_mode); } - let protobuf_event: ProtobufEvent = event - .clone() - .try_into() - .map_err(|e| anyhow!("Failed to convert to protobuf: {:?}", e))?; - let update = instance - .get_typed_func::<(), i32>(&mut running_plugin.store, "update") - .with_context(err_context)?; - wasi_write_object(running_plugin.store.data(), &protobuf_event.encode_to_vec()) - .with_context(err_context)?; - let should_render = update - .call(&mut running_plugin.store, ()) - .with_context(err_context)?; - let mut should_render = should_render == 1; - if let Event::PermissionRequestResult(..) = event { - // we always render in this case, otherwise the request permission screen stays on - // screen - should_render = true; - } - if rows > 0 && columns > 0 && should_render { - let rendered_bytes = instance - .get_typed_func::<(i32, i32), ()>(&mut running_plugin.store, "render") - .and_then(|render| { - render.call(&mut running_plugin.store, (rows as i32, columns as i32)) - }) - .map_err(|e| anyhow!(e)) - .and_then(|_| { - wasi_read_string(running_plugin.store.data()).map_err(|e| anyhow!(e)) - }) - .with_context(err_context)?; - let pipes_to_block_or_unblock = pipes_to_block_or_unblock(running_plugin, None); - let plugin_render_asset = PluginRenderAsset::new( - plugin_id, - client_id, - rendered_bytes.as_bytes().to_vec(), - ) - .with_pipes(pipes_to_block_or_unblock); - plugin_render_assets.push(plugin_render_asset); - } else { - // This is a bit of a hack to get around the fact that plugins are allowed not to - // render and still unblock CLI pipes - let pipes_to_block_or_unblock = pipes_to_block_or_unblock(running_plugin, None); - let plugin_render_asset = PluginRenderAsset::new(plugin_id, client_id, vec![]) - .with_pipes(pipes_to_block_or_unblock); - let _ = senders - .send_to_plugin(PluginInstruction::UnblockCliPipes(vec![ - plugin_render_asset, - ])) - .context("failed to unblock input pipe"); + let protobuf_event: Result = event.clone().try_into(); + match protobuf_event { + Ok(protobuf_event) => { + let update = instance + .get_typed_func::<(), i32>(&mut running_plugin.store, "update") + .with_context(err_context)?; + wasi_write_object(running_plugin.store.data(), &protobuf_event.encode_to_vec()) + .with_context(err_context)?; + let should_render = update + .call(&mut running_plugin.store, ()) + .with_context(err_context)?; + let mut should_render = should_render == 1; + if let Event::PermissionRequestResult(..) = event { + // we always render in this case, otherwise the request permission screen stays on + // screen + should_render = true; + } + if rows > 0 && columns > 0 && should_render { + let rendered_bytes = instance + .get_typed_func::<(i32, i32), ()>(&mut running_plugin.store, "render") + .and_then(|render| { + render + .call(&mut running_plugin.store, (rows as i32, columns as i32)) + }) + .map_err(|e| anyhow!(e)) + .and_then(|_| { + wasi_read_string(running_plugin.store.data()) + .map_err(|e| anyhow!(e)) + }) + .with_context(err_context)?; + let pipes_to_block_or_unblock = + pipes_to_block_or_unblock(running_plugin, None); + let plugin_render_asset = PluginRenderAsset::new( + plugin_id, + client_id, + rendered_bytes.as_bytes().to_vec(), + ) + .with_pipes(pipes_to_block_or_unblock); + plugin_render_assets.push(plugin_render_asset); + } else { + // This is a bit of a hack to get around the fact that plugins are allowed not to + // render and still unblock CLI pipes + let pipes_to_block_or_unblock = + pipes_to_block_or_unblock(running_plugin, None); + let plugin_render_asset = + PluginRenderAsset::new(plugin_id, client_id, vec![]) + .with_pipes(pipes_to_block_or_unblock); + let _ = senders + .send_to_plugin(PluginInstruction::UnblockCliPipes(vec![ + plugin_render_asset, + ])) + .context("failed to unblock input pipe"); + } + }, + Err(e) => { + log::error!("Failed to convert to protobuf: {:?}", e); + }, } }, (PermissionStatus::Denied, permission) => { diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 526b4bcb1..f64a9e18a 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -20,9 +20,9 @@ use std::{ }; use wasmi::{Caller, Linker}; use zellij_utils::data::{ - CommandType, ConnectToSession, FloatingPaneCoordinates, HttpVerb, KeyWithModifier, LayoutInfo, - MessageToPlugin, NewPanePlacement, OriginatingPlugin, PaneScrollbackResponse, PermissionStatus, - PermissionType, PluginPermission, + CommandType, ConnectToSession, Event, FloatingPaneCoordinates, GetPanePidResponse, HttpVerb, + KeyWithModifier, LayoutInfo, MessageToPlugin, NewPanePlacement, OriginatingPlugin, + PaneScrollbackResponse, PermissionStatus, PermissionType, PluginPermission, }; use zellij_utils::input::permission::PermissionCache; use zellij_utils::ipc::{ClientToServerMsg, IpcSenderWithContext}; @@ -39,7 +39,7 @@ use prost::Message; use zellij_utils::{ consts::{VERSION, ZELLIJ_SESSION_INFO_CACHE_DIR, ZELLIJ_SOCK_DIR}, data::{ - CommandToRun, Direction, Event, EventType, FileToOpen, InputMode, PluginCommand, PluginIds, + CommandToRun, Direction, EventType, FileToOpen, InputMode, PluginCommand, PluginIds, PluginMessage, Resize, ResizeStrategy, }, errors::prelude::*, @@ -50,7 +50,7 @@ use zellij_utils::{ }, plugin_api::{ event::ProtobufPaneScrollbackResponse, - plugin_command::ProtobufPluginCommand, + plugin_command::{ProtobufGetPanePidResponse, ProtobufPluginCommand}, plugin_ids::{ProtobufPluginIds, ProtobufZellijVersion}, }, }; @@ -104,6 +104,7 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::Subscribe(event_list) => subscribe(env, event_list)?, PluginCommand::Unsubscribe(event_list) => unsubscribe(env, event_list)?, PluginCommand::SetSelectable(selectable) => set_selectable(env, selectable), + PluginCommand::ShowCursor(cursor_position) => show_cursor(env, cursor_position), PluginCommand::GetPluginIds => get_plugin_ids(env), PluginCommand::GetZellijVersion => get_zellij_version(env), PluginCommand::OpenFile(file_to_open, context) => { @@ -198,6 +199,7 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::EditScrollback => edit_scrollback(env), PluginCommand::Write(bytes) => write(env, bytes), PluginCommand::WriteChars(chars) => write_chars(env, chars), + PluginCommand::CopyToClipboard(text) => copy_to_clipboard(env, text)?, PluginCommand::ToggleTab => toggle_tab(env), PluginCommand::MovePane => move_pane(env), PluginCommand::MovePaneWithDirection(direction) => { @@ -233,12 +235,26 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::ClosePluginPane(plugin_pane_id) => { close_plugin_pane(env, plugin_pane_id) }, - PluginCommand::FocusTerminalPane(terminal_pane_id, should_float_if_hidden) => { - focus_terminal_pane(env, terminal_pane_id, should_float_if_hidden) - }, - PluginCommand::FocusPluginPane(plugin_pane_id, should_float_if_hidden) => { - focus_plugin_pane(env, plugin_pane_id, should_float_if_hidden) - }, + PluginCommand::FocusTerminalPane( + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ) => focus_terminal_pane( + env, + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), + PluginCommand::FocusPluginPane( + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ) => focus_plugin_pane( + env, + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), PluginCommand::RenameTerminalPane(terminal_pane_id, new_name) => { rename_terminal_pane(env, terminal_pane_id, &new_name) }, @@ -317,9 +333,16 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::HidePaneWithId(pane_id) => { hide_pane_with_id(env, pane_id.into())? }, - PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden) => { - show_pane_with_id(env, pane_id.into(), should_float_if_hidden) - }, + PluginCommand::ShowPaneWithId( + pane_id, + should_float_if_hidden, + should_focus_pane, + ) => show_pane_with_id( + env, + pane_id.into(), + should_float_if_hidden, + should_focus_pane, + ), PluginCommand::OpenCommandPaneBackground(command_to_run, context) => { open_command_pane_background(env, command_to_run, context) }, @@ -342,6 +365,13 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::WriteCharsToPaneId(chars, pane_id) => { write_chars_to_pane_id(env, chars, pane_id.into()) }, + PluginCommand::SendSigintToPaneId(pane_id) => { + send_sigint_to_pane_id(env, pane_id.into()) + }, + PluginCommand::SendSigkillToPaneId(pane_id) => { + send_sigkill_to_pane_id(env, pane_id.into()) + }, + PluginCommand::GetPanePid { pane_id } => get_pane_pid(env, pane_id.into()), PluginCommand::MovePaneWithPaneId(pane_id) => { move_pane_with_pane_id(env, pane_id.into()) }, @@ -509,11 +539,14 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::ReplacePaneWithExistingPane( pane_id_to_replace, existing_pane_id, + suppress_replaced_pane, ) => replace_pane_with_existing_pane( &mut env, pane_id_to_replace.into(), existing_pane_id.into(), + suppress_replaced_pane, ), + PluginCommand::RunAction(action, context) => run_action(&env, action, context), }, (PermissionStatus::Denied, permission) => { log::error!( @@ -595,6 +628,27 @@ fn set_selectable(env: &PluginEnv, selectable: bool) { .non_fatal(); } +fn show_cursor(env: &PluginEnv, cursor_position: Option<(usize, usize)>) { + env.senders + .send_to_screen(ScreenInstruction::ShowPluginCursor( + env.plugin_id, + env.client_id, + cursor_position, + )) + .with_context(|| { + format!( + "failed to {} plugin cursor from plugin {}", + if cursor_position.is_some() { + "show" + } else { + "hide" + }, + env.name() + ) + }) + .non_fatal(); +} + fn request_permission(env: &PluginEnv, permissions: Vec) -> Result<()> { if PermissionCache::from_path_or_default(None) .check_permissions(env.plugin.location.to_string(), &permissions) @@ -680,10 +734,74 @@ fn open_file(env: &PluginEnv, file_to_open: FileToOpen, context: BTreeMap) { + // Clone the necessary data to move into the thread + action.populate_originating_plugin(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context.clone(), + )); + let action_clone = action.clone(); + let client_id = env.client_id; + let plugin_id = env.plugin_id; + let senders = env.senders.clone(); + let capabilities = env.capabilities.clone(); + let client_attributes = env.client_attributes.clone(); + let default_shell = env.default_shell.clone(); + let default_layout = env.default_layout.clone(); + let keybinds = env.keybinds.clone(); + let default_mode = env.default_mode.clone(); + let plugin_name = env.name().to_string(); + + // Spawn a new thread to execute the action + thread::spawn(move || { + // Execute the action and capture the result + let pane_id = match route_action( + action, + client_id, + None, + Some(PaneId::Plugin(plugin_id)), + senders.clone(), + capabilities, + client_attributes, + default_shell, + default_layout, + None, + keybinds, + default_mode, + None, + ) { + Ok((_should_break, result)) => { + // Extract pane_id from ActionCompletionResult + result.and_then(|r| r.affected_pane_id) + }, + Err(e) => { + log::error!("failed to run action in plugin {}: {:?}", plugin_name, e); + None + }, + }; + + // After action completes, send ActionComplete event with context + // Convert server PaneId to zellij_utils PaneId + let pane_id_for_event = pane_id.map(|p| p.into()); + let updates = vec![( + Some(plugin_id), + Some(client_id), + Event::ActionComplete(action_clone, pane_id_for_event, context), + )]; + + // Send the ActionComplete event back to the plugin + if let Err(e) = senders.send_to_plugin(PluginInstruction::Update(updates)) { + log::error!("Failed to send ActionComplete event: {:?}", e); + } + }); +} + fn open_file_floating( env: &PluginEnv, file_to_open: FileToOpen, @@ -708,6 +826,7 @@ fn open_file_floating( in_place, start_suppressed, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -736,6 +855,7 @@ fn open_file_in_place( in_place, start_suppressed, coordinates: None, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -845,6 +965,7 @@ fn open_terminal(env: &PluginEnv, cwd: PathBuf) { direction: None, command: run_command_action, pane_name: None, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -894,6 +1015,7 @@ fn open_terminal_floating( command: run_command_action, pane_name: None, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -942,6 +1064,9 @@ fn open_terminal_in_place(env: &PluginEnv, cwd: PathBuf) { let action = Action::NewInPlacePane { command: run_command_action, pane_name: None, + near_current_pane: false, + pane_id_to_replace: None, + close_replace_pane: false, }; apply_action!(action, error_msg, env); } @@ -1044,6 +1169,7 @@ fn open_command_pane( direction, command: Some(run_command_action), pane_name: name, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -1120,6 +1246,7 @@ fn open_command_pane_floating( command: Some(run_command_action), pane_name: name, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -1195,6 +1322,9 @@ fn open_command_pane_in_place( let action = Action::NewInPlacePane { command: Some(run_command_action), pane_name: name, + near_current_pane: false, + pane_id_to_replace: None, + close_replace_pane: false, }; apply_action!(action, error_msg, env); } @@ -1418,20 +1548,36 @@ fn show_self(env: &PluginEnv, should_float_if_hidden: bool) { let action = Action::FocusPluginPaneWithId { pane_id: env.plugin_id, should_float_if_hidden, + should_be_in_place_if_hidden: false, }; let error_msg = || format!("Failed to show self for plugin"); apply_action!(action, error_msg, env); } -fn show_pane_with_id(env: &PluginEnv, pane_id: PaneId, should_float_if_hidden: bool) { - let _ = env - .senders - .send_to_screen(ScreenInstruction::FocusPaneWithId( - pane_id, - should_float_if_hidden, - env.client_id, - None, - )); +fn show_pane_with_id( + env: &PluginEnv, + pane_id: PaneId, + should_float_if_hidden: bool, + should_focus_pane: bool, +) { + if should_focus_pane { + let _ = env + .senders + .send_to_screen(ScreenInstruction::FocusPaneWithId( + pane_id, + should_float_if_hidden, + false, + env.client_id, + None, + )); + } else { + let _ = env + .senders + .send_to_screen(ScreenInstruction::UnsuppressOrExpandPane( + pane_id, + should_float_if_hidden, + )); + } } fn close_self(env: &PluginEnv) { @@ -1524,6 +1670,8 @@ fn apply_layout(env: &PluginEnv, layout: Layout) { tab_name: None, should_change_focus_to_new_tab: true, cwd, + initial_panes: None, + first_pane_unblock_condition: None, }; tabs_to_open.push(action); } else { @@ -1542,6 +1690,8 @@ fn apply_layout(env: &PluginEnv, layout: Layout) { tab_name, should_change_focus_to_new_tab: should_focus_tab, cwd: cwd.clone(), + initial_panes: None, + first_pane_unblock_condition: None, }; tabs_to_open.push(action); } @@ -1562,6 +1712,8 @@ fn new_tab(env: &PluginEnv, name: Option, cwd: Option) { tab_name: name, should_change_focus_to_new_tab: true, cwd, + initial_panes: None, + first_pane_unblock_condition: None, }; let error_msg = || format!("Failed to open new tab"); apply_action!(action, error_msg, env); @@ -1741,6 +1893,12 @@ fn write_chars(env: &PluginEnv, chars_to_write: String) { apply_action!(action, error_msg, env); } +fn copy_to_clipboard(env: &PluginEnv, text: String) -> Result<()> { + env.senders + .send_to_screen(ScreenInstruction::CopyTextToClipboard(text, env.plugin_id)) + .with_context(|| format!("failed to copy to clipboard in plugin {}", env.name())) +} + fn toggle_tab(env: &PluginEnv) { let error_msg = || format!("Failed to toggle tab"); let action = Action::ToggleTab; @@ -1938,19 +2096,31 @@ fn close_plugin_pane(env: &PluginEnv, plugin_pane_id: u32) { .non_fatal(); } -fn focus_terminal_pane(env: &PluginEnv, terminal_pane_id: u32, should_float_if_hidden: bool) { +fn focus_terminal_pane( + env: &PluginEnv, + terminal_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { let action = Action::FocusTerminalPaneWithId { pane_id: terminal_pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, }; let error_msg = || format!("Failed to focus terminal pane"); apply_action!(action, error_msg, env); } -fn focus_plugin_pane(env: &PluginEnv, plugin_pane_id: u32, should_float_if_hidden: bool) { +fn focus_plugin_pane( + env: &PluginEnv, + plugin_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { let action = Action::FocusPluginPaneWithId { pane_id: plugin_pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, }; let error_msg = || format!("Failed to focus plugin pane"); apply_action!(action, error_msg, env); @@ -2237,6 +2407,92 @@ fn write_chars_to_pane_id(env: &PluginEnv, chars: String, pane_id: PaneId) { .send_to_screen(ScreenInstruction::WriteToPaneId(bytes, pane_id)); } +fn send_sigint_to_pane_id(env: &PluginEnv, pane_id: PaneId) { + let err_context = || { + format!( + "failed to send SIGINT to pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + env.senders + .send_to_pty(PtyInstruction::SendSigintToPaneId(pane_id)) + .with_context(err_context) + .non_fatal(); +} + +fn send_sigkill_to_pane_id(env: &PluginEnv, pane_id: PaneId) { + let err_context = || { + format!( + "failed to send SIGKILL to pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + env.senders + .send_to_pty(PtyInstruction::SendSigkillToPaneId(pane_id)) + .with_context(err_context) + .non_fatal(); +} + +fn get_pane_pid(env: &PluginEnv, pane_id: PaneId) { + use crossbeam::channel::RecvTimeoutError; + use std::time::Duration; + + let err_context = || { + format!( + "failed to get PID for pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + // Create oneshot channel for response + let (response_sender, response_receiver) = crossbeam::channel::bounded(1); + + // Send request directly to PTY thread + env.senders + .send_to_pty(PtyInstruction::GetPanePid { + pane_id, + response_channel: response_sender, + }) + .with_context(err_context) + .non_fatal(); + + // Block waiting for response with 100ms timeout + let response = match response_receiver.recv_timeout(Duration::from_millis(100)) { + Ok(response) => response, + Err(RecvTimeoutError::Timeout) => { + log::error!( + "GetPanePid timed out after 5s for plugin {} requesting pane {:?}", + env.plugin_id, + pane_id + ); + GetPanePidResponse::Err(format!("Timeout retrieving PID for pane {:?}", pane_id)) + }, + Err(RecvTimeoutError::Disconnected) => { + log::error!( + "GetPanePid channel disconnected for plugin {} requesting pane {:?}", + env.plugin_id, + pane_id + ); + GetPanePidResponse::Err(format!( + "Channel disconnected while retrieving PID for pane {:?}", + pane_id + )) + }, + }; + + // Encode response and write to plugin's stdin + let protobuf_response = ProtobufGetPanePidResponse::from(response); + let serialized = protobuf_response.encode_to_vec(); + wasi_write_object(env, &serialized) + .with_context(err_context) + .non_fatal(); +} + fn move_pane_with_pane_id(env: &PluginEnv, pane_id: PaneId) { let _ = env .senders @@ -2666,12 +2922,14 @@ fn replace_pane_with_existing_pane( env: &mut PluginEnv, pane_to_replace: PaneId, existing_pane: PaneId, + suppress_replaced_pane: bool, ) { let _ = env .senders .send_to_screen(ScreenInstruction::ReplacePaneWithExistingPane( pane_to_replace, existing_pane, + suppress_replaced_pane, )); } @@ -2762,6 +3020,7 @@ fn check_command_permission( | PluginCommand::WriteChars(..) | PluginCommand::WriteToPaneId(..) | PluginCommand::WriteCharsToPaneId(..) => PermissionType::WriteToStdin, + PluginCommand::CopyToClipboard(..) => PermissionType::WriteToClipboard, PluginCommand::SwitchTabTo(..) | PluginCommand::SwitchToMode(..) | PluginCommand::NewTabsWithLayout(..) @@ -2842,14 +3101,16 @@ fn check_command_permission( | PluginCommand::FloatMultiplePanes(..) | PluginCommand::EmbedMultiplePanes(..) | PluginCommand::ReplacePaneWithExistingPane(..) - | PluginCommand::KillSessions(..) => PermissionType::ChangeApplicationState, + | PluginCommand::KillSessions(..) + | PluginCommand::SendSigintToPaneId(..) + | PluginCommand::SendSigkillToPaneId(..) => PermissionType::ChangeApplicationState, PluginCommand::UnblockCliPipeInput(..) | PluginCommand::BlockCliPipeInput(..) | PluginCommand::CliPipeOutput(..) => PermissionType::ReadCliPipes, PluginCommand::MessageToPlugin(..) => PermissionType::MessageAndLaunchOtherPlugins, - PluginCommand::ListClients | PluginCommand::DumpSessionLayout => { - PermissionType::ReadApplicationState - }, + PluginCommand::ListClients + | PluginCommand::DumpSessionLayout + | PluginCommand::GetPanePid { .. } => PermissionType::ReadApplicationState, PluginCommand::RebindKeys { .. } | PluginCommand::Reconfigure(..) => { PermissionType::Reconfigure }, @@ -2868,6 +3129,7 @@ fn check_command_permission( PermissionType::InterceptInput }, PluginCommand::GetPaneScrollback { .. } => PermissionType::ReadPaneContents, + PluginCommand::RunAction(..) => PermissionType::RunActionsAsUser, _ => return (PermissionStatus::Granted, None), }; diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 39bf4668c..fee6054e5 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -17,7 +17,10 @@ use nix::unistd::Pid; use std::sync::Arc; use std::{collections::HashMap, os::unix::io::RawFd, path::PathBuf}; use zellij_utils::{ - data::{Direction, Event, FloatingPaneCoordinates, NewPanePlacement, OriginatingPlugin}, + data::{ + CommandOrPlugin, Event, FloatingPaneCoordinates, GetPanePidResponse, NewPanePlacement, + OriginatingPlugin, + }, errors::prelude::*, errors::{ContextType, PtyContext}, input::{ @@ -66,6 +69,8 @@ pub enum PtyInstruction { Vec, usize, // tab_index HashMap>, // plugin_ids + Option>, // initial_panes + bool, // block_on_first_terminal bool, // should change focus to new tab (ClientId, bool), // bool -> is_web_client Option, // completion signal @@ -112,6 +117,13 @@ pub enum PtyInstruction { }, ListClientsToPlugin(SessionLayoutMetadata, PluginId, ClientId), ReportPluginCwd(PluginId, PathBuf), + SendSigintToPaneId(PaneId), + SendSigkillToPaneId(PaneId), + GetPanePid { + pane_id: PaneId, + response_channel: crossbeam::channel::Sender, + }, + UpdateAndReportCwds, Exit, } @@ -136,6 +148,10 @@ impl From<&PtyInstruction> for PtyContext { PtyInstruction::Reconfigure { .. } => PtyContext::Reconfigure, PtyInstruction::ListClientsToPlugin(..) => PtyContext::ListClientsToPlugin, PtyInstruction::ReportPluginCwd(..) => PtyContext::ReportPluginCwd, + PtyInstruction::SendSigintToPaneId(..) => PtyContext::SendSigintToPaneId, + PtyInstruction::SendSigkillToPaneId(..) => PtyContext::SendSigkillToPaneId, + PtyInstruction::GetPanePid { .. } => PtyContext::GetPanePid, + PtyInstruction::UpdateAndReportCwds => PtyContext::UpdateAndReportCwds, PtyInstruction::Exit => PtyContext::Exit, } } @@ -150,7 +166,8 @@ pub(crate) struct Pty { task_handles: HashMap>, // terminal_id to join-handle default_editor: Option, post_command_discovery_hook: Option, - plugin_cwds: HashMap, // plugin_id -> cwd + plugin_cwds: HashMap, // plugin_id -> cwd + terminal_cwds: HashMap, // terminal_id -> cwd } pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { @@ -430,6 +447,8 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { floating_panes_layout, tab_index, plugin_ids, + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, client_id_and_is_web_client, completion_tx, @@ -447,7 +466,9 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { floating_panes_layout, terminal_action.clone(), plugin_ids, + initial_panes, tab_index, + block_on_first_terminal, should_change_focus_to_new_tab, client_id_and_is_web_client, completion_tx, @@ -702,6 +723,22 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { } => { pty.reconfigure(default_editor, post_command_discovery_hook); }, + PtyInstruction::SendSigintToPaneId(pane_id) => { + pty.send_sigint_to_pane(pane_id); + }, + PtyInstruction::SendSigkillToPaneId(pane_id) => { + pty.send_sigkill_to_pane(pane_id); + }, + PtyInstruction::GetPanePid { + pane_id, + response_channel, + } => { + let response = pty.get_pane_pid(pane_id); + let _ = response_channel.send(response); + }, + PtyInstruction::UpdateAndReportCwds => { + pty.update_and_report_cwds(); + }, PtyInstruction::Exit => break, } } @@ -725,6 +762,7 @@ impl Pty { originating_plugins: HashMap::new(), post_command_discovery_hook, plugin_cwds: HashMap::new(), + terminal_cwds: HashMap::new(), } } pub fn get_default_terminal( @@ -774,12 +812,18 @@ impl Pty { .get(&client_id) .and_then(|pane| match pane { PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(), - PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| { - self.bus - .os_input - .as_ref() - .and_then(|input| input.get_cwd(Pid::from_raw(id))) - }), + PaneId::Terminal(id) => { + // Try to get CWD from OS, fall back to cached value + self.id_to_child_pid + .get(id) + .and_then(|&pid| { + self.bus + .os_input + .as_ref() + .and_then(|input| input.get_cwd(Pid::from_raw(pid))) + }) + .or_else(|| self.terminal_cwds.get(id).cloned()) + }, }) }; }; @@ -789,12 +833,16 @@ impl Pty { if run_command.cwd.is_none() { run_command.cwd = match pane_id { PaneId::Terminal(terminal_pane_id) => { - self.id_to_child_pid.get(terminal_pane_id).and_then(|&id| { - self.bus - .os_input - .as_ref() - .and_then(|input| input.get_cwd(Pid::from_raw(id))) - }) + // Try to get CWD from OS, fall back to cached value + self.id_to_child_pid + .get(terminal_pane_id) + .and_then(|&pid| { + self.bus + .os_input + .as_ref() + .and_then(|input| input.get_cwd(Pid::from_raw(pid))) + }) + .or_else(|| self.terminal_cwds.get(terminal_pane_id).cloned()) }, PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(), }; @@ -938,6 +986,8 @@ impl Pty { self.task_handles.insert(terminal_id, terminal_bytes); self.id_to_child_pid.insert(terminal_id, child_fd); + self.capture_initial_cwd(terminal_id, child_fd); + let starts_held = false; Ok((terminal_id, starts_held)) } @@ -948,7 +998,9 @@ impl Pty { floating_panes_layout: Vec, default_shell: Option, plugin_ids: HashMap>, + initial_panes: Option>, tab_index: usize, + block_on_first_terminal: bool, should_change_focus_to_new_tab: bool, client_id_and_is_web_client: (ClientId, bool), completion_tx: Option, @@ -959,6 +1011,22 @@ impl Pty { default_shell.unwrap_or_else(|| self.get_default_terminal(cwd, None)); let (client_id, is_web_client) = client_id_and_is_web_client; self.fill_cwd(&mut default_shell, client_id); + + // Match initial_panes commands to empty slots in the layout + let mut layout = layout; + if let Some(ref initial_panes_vec) = initial_panes { + for initial_pane in initial_panes_vec.iter() { + if let CommandOrPlugin::Command(run_command_action) = initial_pane { + let run_command: RunCommand = run_command_action.clone().into(); + if !layout.replace_next_empty_slot_with_run(Run::Command(run_command)) { + log::warn!("More initial_panes provided than empty slots available"); + break; + } + } + // Skip CommandOrPlugin::Plugin entries (already handled by plugin thread) + } + } + let extracted_run_instructions = layout.extract_run_instructions(); let extracted_floating_run_instructions = floating_panes_layout .iter() @@ -968,24 +1036,55 @@ impl Pty { // starts_held, // run_command, // file_descriptor) + let mut new_floating_panes_pids: Vec<(u32, bool, Option, Result)> = vec![]; // same // as // new_pane_pids + + let mut originating_plugins_to_inform = vec![]; + for run_instruction in extracted_run_instructions { + let originating_plugin = run_instruction.as_ref().and_then(|r| { + if let Run::Command(run_command) = r { + run_command.originating_plugin.clone() + } else { + None + } + }); + let mut terminal_id = None; if let Some(new_pane_data) = self.apply_run_instruction(run_instruction, default_shell.clone())? { + terminal_id = Some(new_pane_data.0); new_pane_pids.push(new_pane_data); } + if let (Some(originating_plugin), Some(terminal_id)) = (originating_plugin, terminal_id) + { + originating_plugins_to_inform.push((terminal_id, originating_plugin)); + } } for run_instruction in extracted_floating_run_instructions { + let originating_plugin = run_instruction.as_ref().and_then(|r| { + if let Run::Command(run_command) = r { + run_command.originating_plugin.clone() + } else { + None + } + }); + let mut terminal_id = None; if let Some(new_pane_data) = self.apply_run_instruction(run_instruction, default_shell.clone())? { + terminal_id = Some(new_pane_data.0); new_floating_panes_pids.push(new_pane_data); } + if let (Some(originating_plugin), Some(terminal_id)) = (originating_plugin, terminal_id) + { + originating_plugins_to_inform.push((terminal_id, originating_plugin)); + } } + // Option should only be Some if the pane starts held let new_tab_pane_ids: Vec<(u32, Option)> = new_pane_pids .iter() @@ -1007,21 +1106,40 @@ impl Pty { } }) .collect(); + + // Track the first terminal_id if blocking is requested + let first_initial_pane_terminal_id = if block_on_first_terminal && !new_pane_pids.is_empty() + { + Some(new_pane_pids[0].0) + } else { + None + }; + + // Prepare blocking_terminal for ApplyLayout + let (direct_completion_tx, blocking_terminal) = + if let Some(terminal_id) = first_initial_pane_terminal_id { + (None, completion_tx.map(|tx| (terminal_id, tx))) + } else { + (completion_tx, None) + }; + self.bus .senders .send_to_screen(ScreenInstruction::ApplyLayout( layout, floating_panes_layout, - new_tab_pane_ids, - new_tab_floating_pane_ids, + new_tab_pane_ids.clone(), + new_tab_floating_pane_ids.clone(), plugin_ids, tab_index, should_change_focus_to_new_tab, (client_id, is_web_client), - completion_tx, + direct_completion_tx, + blocking_terminal, )) .with_context(err_context)?; let mut terminals_to_start = vec![]; + terminals_to_start.append(&mut new_pane_pids); terminals_to_start.append(&mut new_floating_panes_pids); for (terminal_id, starts_held, run_command, pid_primary) in terminals_to_start { @@ -1077,8 +1195,29 @@ impl Pty { }, } } + for (terminal_id, originating_plugin) in originating_plugins_to_inform { + self.inform_originating_plugin_of_open(terminal_id, originating_plugin); + } Ok(()) } + fn inform_originating_plugin_of_open( + &mut self, + terminal_id: u32, + originating_plugin: OriginatingPlugin, + ) { + self.originating_plugins + .insert(terminal_id, originating_plugin.clone()); + let update_event = Event::CommandPaneOpened(terminal_id, originating_plugin.context); + let _ = self + .bus + .senders + .send_to_plugin(PluginInstruction::Update(vec![( + Some(originating_plugin.plugin_id), + Some(originating_plugin.client_id), + update_event, + )])); + } + fn apply_run_instruction( &mut self, run_instruction: Option, @@ -1162,6 +1301,7 @@ impl Pty { { Ok((terminal_id, pid_primary, child_fd)) => { self.id_to_child_pid.insert(terminal_id, child_fd); + self.capture_initial_cwd(terminal_id, child_fd); Ok(Some(( terminal_id, starts_held, @@ -1194,6 +1334,7 @@ impl Pty { { Ok((terminal_id, pid_primary, child_fd)) => { self.id_to_child_pid.insert(terminal_id, child_fd); + self.capture_initial_cwd(terminal_id, child_fd); Ok(Some((terminal_id, starts_held, None, Ok(pid_primary)))) }, Err(err) => match err.downcast_ref::() { @@ -1225,6 +1366,7 @@ impl Pty { { Ok((terminal_id, pid_primary, child_fd)) => { self.id_to_child_pid.insert(terminal_id, child_fd); + self.capture_initial_cwd(terminal_id, child_fd); Ok(Some((terminal_id, starts_held, None, Ok(pid_primary)))) }, Err(err) => match err.downcast_ref::() { @@ -1248,6 +1390,7 @@ impl Pty { { Ok((terminal_id, pid_primary, child_fd)) => { self.id_to_child_pid.insert(terminal_id, child_fd); + self.capture_initial_cwd(terminal_id, child_fd); Ok(Some((terminal_id, starts_held, None, Ok(pid_primary)))) }, Err(err) => match err.downcast_ref::() { @@ -1389,6 +1532,7 @@ impl Pty { self.task_handles.insert(id, terminal_bytes); self.id_to_child_pid.insert(id, child_fd); + self.capture_initial_cwd(id, child_fd); if let Some(originating_plugin) = self.originating_plugins.get(&id) { self.bus .senders @@ -1405,9 +1549,10 @@ impl Pty { } } pub fn populate_session_layout_metadata( - &self, + &mut self, session_layout_metadata: &mut SessionLayoutMetadata, ) { + log::info!("populate_session_layout_metadata"); let terminal_ids = session_layout_metadata.all_terminal_ids(); let mut terminal_ids_to_commands: HashMap> = HashMap::new(); let mut terminal_ids_to_cwds: HashMap = HashMap::new(); @@ -1476,12 +1621,18 @@ impl Pty { .get(&client_id) .and_then(|pane| match pane { PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(), - PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| { - self.bus - .os_input - .as_ref() - .and_then(|input| input.get_cwd(Pid::from_raw(id))) - }), + PaneId::Terminal(id) => { + // Try to get CWD from OS, fall back to cached value + self.id_to_child_pid + .get(id) + .and_then(|&pid| { + self.bus + .os_input + .as_ref() + .and_then(|input| input.get_cwd(Pid::from_raw(pid))) + }) + .or_else(|| self.terminal_cwds.get(id).cloned()) + }, }) }; @@ -1516,6 +1667,59 @@ impl Pty { ))?; Ok(()) } + fn capture_initial_cwd(&mut self, terminal_id: u32, child_fd: RawFd) { + if let Some(os_input) = self.bus.os_input.as_ref() { + if let Some(cwd) = os_input.get_cwd(Pid::from_raw(child_fd)) { + self.terminal_cwds.insert(terminal_id, cwd); + } + } + } + + pub fn update_and_report_cwds(&mut self) { + let terminal_ids: Vec = self.id_to_child_pid.keys().copied().collect(); + + let pids: Vec<_> = terminal_ids + .iter() + .filter_map(|id| self.id_to_child_pid.get(&id)) + .map(|pid| Pid::from_raw(*pid)) + .collect(); + + let (pids_to_cwds, _) = self + .bus + .os_input + .as_ref() + .map(|os_input| os_input.get_cwds(pids)) + .unwrap_or_default(); + + for terminal_id in terminal_ids { + let process_id = self.id_to_child_pid.get(&terminal_id); + let cwd = process_id + .as_ref() + .and_then(|pid| pids_to_cwds.get(&Pid::from_raw(**pid))); + + if let Some(cwd) = cwd { + if self.terminal_cwds.get(&terminal_id) != Some(cwd) { + let pane_id = PaneId::Terminal(terminal_id); + let focused_client_ids: Vec = self + .active_panes + .iter() + .filter(|(_, active_pane)| *active_pane == &pane_id) + .map(|(client_id, _)| *client_id) + .collect(); + let _ = self + .bus + .senders + .send_to_plugin(PluginInstruction::Update(vec![( + None, + None, + Event::CwdChanged(pane_id.into(), cwd.clone(), focused_client_ids), + )])); + } + self.terminal_cwds.insert(terminal_id, cwd.clone()); + } + } + } + pub fn reconfigure( &mut self, default_editor: Option, @@ -1524,6 +1728,72 @@ impl Pty { self.default_editor = default_editor; self.post_command_discovery_hook = post_command_discovery_hook; } + + pub fn send_sigint_to_pane(&self, pane_id: PaneId) { + let err_context = || format!("failed to send SIGINT to pane {:?}", pane_id); + + match pane_id { + PaneId::Terminal(terminal_id) => { + if let Some(&child_fd) = self.id_to_child_pid.get(&terminal_id) { + let pid = Pid::from_raw(child_fd); + self.bus + .os_input + .as_ref() + .context("no OS I/O interface found") + .and_then(|os_input| os_input.send_sigint(pid)) + .with_context(err_context) + .non_fatal(); + } else { + log::warn!("Terminal pane {} not found or not running", terminal_id); + } + }, + PaneId::Plugin(plugin_id) => { + log::warn!("Cannot send SIGINT to plugin pane {}", plugin_id); + }, + } + } + + pub fn send_sigkill_to_pane(&self, pane_id: PaneId) { + let err_context = || format!("failed to send SIGKILL to pane {:?}", pane_id); + + match pane_id { + PaneId::Terminal(terminal_id) => { + if let Some(&child_fd) = self.id_to_child_pid.get(&terminal_id) { + let pid = Pid::from_raw(child_fd); + self.bus + .os_input + .as_ref() + .context("no OS I/O interface found") + .and_then(|os_input| os_input.force_kill(pid)) + .with_context(err_context) + .non_fatal(); + } else { + log::warn!("Terminal pane {} not found or not running", terminal_id); + } + }, + PaneId::Plugin(plugin_id) => { + log::warn!("Cannot send SIGKILL to plugin pane {}", plugin_id); + }, + } + } + + pub fn get_pane_pid(&self, pane_id: PaneId) -> GetPanePidResponse { + match pane_id { + PaneId::Terminal(terminal_id) => { + if let Some(&child_fd) = self.id_to_child_pid.get(&terminal_id) { + GetPanePidResponse::Ok(child_fd) + } else { + GetPanePidResponse::Err(format!( + "Terminal pane {} not found or not running", + terminal_id + )) + } + }, + PaneId::Plugin(plugin_id) => { + GetPanePidResponse::Err(format!("Cannot get PID for plugin pane {}", plugin_id)) + }, + } + } } impl Drop for Pty { diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 7d11ba658..ead4282d4 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -19,7 +19,7 @@ use zellij_utils::{ channels::SenderWithContext, data::{ BareKey, ConnectToSession, Direction, Event, InputMode, KeyModifier, NewPanePlacement, - PluginCapabilities, ResizeStrategy, + PluginCapabilities, ResizeStrategy, UnblockCondition, }, envs, errors::prelude::*, @@ -39,21 +39,28 @@ use crate::ClientId; const ACTION_COMPLETION_TIMEOUT: Duration = Duration::from_secs(1); +#[derive(Debug, Clone)] +pub struct ActionCompletionResult { + pub exit_status: Option, + pub affected_pane_id: Option, +} + fn wait_for_action_completion( - receiver: oneshot::Receiver>, // currently i32 signals an exit status, can be expanded as - // needed + receiver: oneshot::Receiver, action_name: &str, wait_forever: bool, -) -> Option { +) -> ActionCompletionResult { let runtime = get_tokio_runtime(); if wait_forever { runtime.block_on(async { match receiver.await { - Ok(Some(payload)) => Some(payload), - Ok(None) => None, + Ok(result) => result, Err(e) => { log::error!("Failed to wait for action {}: {}", action_name, e); - None + ActionCompletionResult { + exit_status: None, + affected_pane_id: None, + } }, } }) @@ -61,15 +68,17 @@ fn wait_for_action_completion( match runtime .block_on(async { tokio::time::timeout(ACTION_COMPLETION_TIMEOUT, receiver).await }) { - Ok(Ok(Some(payload))) => Some(payload), - Ok(Ok(None)) => None, + Ok(Ok(result)) => result, Err(_) | Ok(Err(_)) => { log::error!( "Action {} did not complete within {:?} timeout", action_name, ACTION_COMPLETION_TIMEOUT ); - None + ActionCompletionResult { + exit_status: None, + affected_pane_id: None, + } }, } } @@ -83,8 +92,10 @@ fn wait_for_action_completion( // that it can be included in various other larger structs - DO NOT RELY ON CLONING IT! #[derive(Debug)] pub struct NotificationEnd { - channel: Option>>, + channel: Option>, exit_status: Option, + unblock_condition: Option, + affected_pane_id: Option, // optional payload of the pane id affected by this action } impl Clone for NotificationEnd { @@ -93,26 +104,55 @@ impl Clone for NotificationEnd { NotificationEnd { channel: None, exit_status: self.exit_status, + unblock_condition: self.unblock_condition, + affected_pane_id: self.affected_pane_id, } } } impl NotificationEnd { - pub fn new(sender: oneshot::Sender>) -> Self { + pub fn new(sender: oneshot::Sender) -> Self { NotificationEnd { channel: Some(sender), exit_status: None, + unblock_condition: None, + affected_pane_id: None, } } + + pub fn new_with_condition( + sender: oneshot::Sender, + unblock_condition: UnblockCondition, + ) -> Self { + NotificationEnd { + channel: Some(sender), + exit_status: None, + unblock_condition: Some(unblock_condition), + affected_pane_id: None, + } + } + pub fn set_exit_status(&mut self, exit_status: i32) { self.exit_status = Some(exit_status); } + + pub fn set_affected_pane_id(&mut self, pane_id: PaneId) { + self.affected_pane_id = Some(pane_id); + } + + pub fn unblock_condition(&self) -> Option { + self.unblock_condition + } } impl Drop for NotificationEnd { fn drop(&mut self) { if let Some(tx) = self.channel.take() { - let _ = tx.send(self.exit_status); + let result = ActionCompletionResult { + exit_status: self.exit_status, + affected_pane_id: self.affected_pane_id, + }; + let _ = tx.send(result); } } } @@ -131,7 +171,7 @@ pub(crate) fn route_action( client_keybinds: Keybinds, default_mode: InputMode, os_input: Option>, -) -> Result { +) -> Result<(bool, Option)> { let mut should_break = false; let err_context = || format!("failed to route action for client {client_id}"); let action_name = action.to_string(); @@ -480,19 +520,51 @@ pub(crate) fn route_action( placement, pane_name, command, + unblock_condition, + near_current_pane, } => { let command = command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); let set_pane_blocking = true; + + let notification_end = if let Some(condition) = unblock_condition { + Some(NotificationEnd::new_with_condition( + completion_tx, + condition, + )) + } else { + Some(NotificationEnd::new(completion_tx)) + }; + + // we prefer the pane id provided by the action explicitly over the one that originated + // it (this might be a bit misleading with "near_current_pane", but it's still the + // right behavior - in the latter case, if the originator does not wish for this + // behavior, they should not provide pane + // inside the placement, but rather have the current pane id be picked up instead) + let pane_id = match placement { + NewPanePlacement::Stacked(pane_id_to_stack_under) => { + pane_id_to_stack_under.map(|p| p.into()).or(pane_id) + }, + NewPanePlacement::InPlace { + pane_id_to_replace, .. + } => pane_id_to_replace.map(|p| p.into()).or(pane_id), + _ => pane_id, + }; + + let client_tab_index_or_paneid = if near_current_pane && pane_id.is_some() { + ClientTabIndexOrPaneId::PaneId(pane_id.unwrap()) + } else { + ClientTabIndexOrPaneId::ClientId(client_id) + }; senders .send_to_pty(PtyInstruction::SpawnTerminal( command, pane_name, placement, false, - ClientTabIndexOrPaneId::ClientId(client_id), - Some(NotificationEnd::new(completion_tx)), + client_tab_index_or_paneid, + notification_end, set_pane_blocking, )) .with_context(err_context)?; @@ -505,19 +577,20 @@ pub(crate) fn route_action( in_place: should_open_in_place, start_suppressed, coordinates: floating_pane_coordinates, + near_current_pane, } => { let title = format!("Editing: {}", open_file_payload.path.display()); let open_file = TerminalAction::OpenFile(open_file_payload); let pty_instr = if should_open_in_place { match pane_id { - Some(pane_id) => PtyInstruction::SpawnInPlaceTerminal( + Some(pane_id) if near_current_pane => PtyInstruction::SpawnInPlaceTerminal( Some(open_file), Some(title), false, ClientTabIndexOrPaneId::PaneId(pane_id), Some(NotificationEnd::new(completion_tx)), ), - None => PtyInstruction::SpawnInPlaceTerminal( + _ => PtyInstruction::SpawnInPlaceTerminal( Some(open_file), Some(title), false, @@ -579,17 +652,23 @@ pub(crate) fn route_action( command: run_command, pane_name: name, coordinates: floating_pane_coordinates, + near_current_pane, } => { let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); + let client_tab_index_or_paneid = if near_current_pane && pane_id.is_some() { + ClientTabIndexOrPaneId::PaneId(pane_id.unwrap()) + } else { + ClientTabIndexOrPaneId::ClientId(client_id) + }; senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, name, NewPanePlacement::Floating(floating_pane_coordinates), false, - ClientTabIndexOrPaneId::ClientId(client_id), + client_tab_index_or_paneid, Some(NotificationEnd::new(completion_tx)), false, // set_blocking )) @@ -598,28 +677,35 @@ pub(crate) fn route_action( Action::NewInPlacePane { command: run_command, pane_name: name, + near_current_pane, + pane_id_to_replace, + close_replace_pane, } => { 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, + }; match pane_id { - Some(pane_id) => { + Some(pane_id) if near_current_pane => { senders .send_to_pty(PtyInstruction::SpawnInPlaceTerminal( run_cmd, name, - false, + close_replace_pane, ClientTabIndexOrPaneId::PaneId(pane_id), Some(NotificationEnd::new(completion_tx)), )) .with_context(err_context)?; }, - None => { + _ => { senders .send_to_pty(PtyInstruction::SpawnInPlaceTerminal( run_cmd, name, - false, + close_replace_pane, ClientTabIndexOrPaneId::ClientId(client_id), Some(NotificationEnd::new(completion_tx)), )) @@ -630,12 +716,14 @@ pub(crate) fn route_action( Action::NewStackedPane { command: run_command, pane_name: name, + near_current_pane, } => { let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); + match pane_id { - Some(pane_id) => { + Some(pane_id) if near_current_pane => { senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, @@ -648,7 +736,7 @@ pub(crate) fn route_action( )) .with_context(err_context)?; }, - None => { + _ => { senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, @@ -667,17 +755,23 @@ pub(crate) fn route_action( direction, command: run_command, pane_name: name, + near_current_pane, } => { let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); + let client_tab_index_or_paneid = if near_current_pane && pane_id.is_some() { + ClientTabIndexOrPaneId::PaneId(pane_id.unwrap()) + } else { + ClientTabIndexOrPaneId::ClientId(client_id) + }; senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, name, NewPanePlacement::Tiled(direction), false, - ClientTabIndexOrPaneId::ClientId(client_id), + client_tab_index_or_paneid, Some(NotificationEnd::new(completion_tx)), false, // set_blocking )) @@ -717,15 +811,23 @@ pub(crate) fn route_action( )) .with_context(err_context)?; }, - Action::Run { command } => { + Action::Run { + command, + near_current_pane, + } => { let run_cmd = Some(TerminalAction::RunCommand(command.clone().into())); + let client_tab_index_or_paneid = if near_current_pane && pane_id.is_some() { + ClientTabIndexOrPaneId::PaneId(pane_id.unwrap()) + } else { + ClientTabIndexOrPaneId::ClientId(client_id) + }; senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, None, NewPanePlacement::Tiled(command.direction), false, - ClientTabIndexOrPaneId::ClientId(client_id), + client_tab_index_or_paneid, Some(NotificationEnd::new(completion_tx)), false, // set_blocking )) @@ -747,6 +849,8 @@ pub(crate) fn route_action( tab_name, should_change_focus_to_new_tab, cwd, + initial_panes, + first_pane_unblock_condition, } => { let shell = default_shell.clone(); let swap_tiled_layouts = @@ -755,6 +859,17 @@ pub(crate) fn route_action( .unwrap_or_else(|| default_layout.swap_floating_layouts.clone()); let is_web_client = false; // actions cannot be initiated directly from the web + // Construct completion_tx conditionally + let (completion_tx, block_on_first_terminal) = if let Some(condition) = + first_pane_unblock_condition + { + let notification = NotificationEnd::new_with_condition(completion_tx, condition); + wait_forever = true; + (notification, true) + } else { + (NotificationEnd::new(completion_tx), false) + }; + senders .send_to_screen(ScreenInstruction::NewTab( cwd, @@ -763,9 +878,11 @@ pub(crate) fn route_action( floating_panes_layout, tab_name, (swap_tiled_layouts, swap_floating_layouts), + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, (client_id, is_web_client), - Some(NotificationEnd::new(completion_tx)), + Some(completion_tx), )) .with_context(err_context)?; }, @@ -921,20 +1038,12 @@ pub(crate) fn route_action( .with_context(err_context)?; }, Action::Confirm => { - senders - .send_to_screen(ScreenInstruction::ConfirmPrompt( - client_id, - Some(NotificationEnd::new(completion_tx)), - )) - .with_context(err_context)?; + // no-op, these are deprecated and should be removed when we upgrade the server/client + // contract }, Action::Deny => { - senders - .send_to_screen(ScreenInstruction::DenyPrompt( - client_id, - Some(NotificationEnd::new(completion_tx)), - )) - .with_context(err_context)?; + // no-op, these are deprecated and should be removed when we upgrade the server/client + // contract }, #[allow(clippy::single_match)] Action::SkipConfirm { action } => match *action { @@ -1147,11 +1256,13 @@ pub(crate) fn route_action( Action::FocusTerminalPaneWithId { pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, } => { senders .send_to_screen(ScreenInstruction::FocusPaneWithId( PaneId::Terminal(pane_id), should_float_if_hidden, + should_be_in_place_if_hidden, client_id, Some(NotificationEnd::new(completion_tx)), )) @@ -1160,11 +1271,13 @@ pub(crate) fn route_action( Action::FocusPluginPaneWithId { pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, } => { senders .send_to_screen(ScreenInstruction::FocusPaneWithId( PaneId::Plugin(pane_id), should_float_if_hidden, + should_be_in_place_if_hidden, client_id, Some(NotificationEnd::new(completion_tx)), )) @@ -1400,8 +1513,8 @@ pub(crate) fn route_action( .with_context(err_context)?; }, } - let exit_status = wait_for_action_completion(completion_rx, &action_name, wait_forever); - if let Some(exit_status) = exit_status { + let result = wait_for_action_completion(completion_rx, &action_name, wait_forever); + if let Some(exit_status) = result.exit_status { if let Some(cli_client_id) = cli_client_id { if let Some(os_input) = os_input { let _ = os_input.send_to_client( @@ -1413,14 +1526,14 @@ pub(crate) fn route_action( } } } - Ok(should_break) + Ok((should_break, Some(result))) } // this should only be used for one-off startup instructions macro_rules! send_to_screen_or_retry_queue { - ($rlocked_sessions:expr, $message:expr, $instruction: expr, $retry_queue:expr) => {{ - match $rlocked_sessions.as_ref() { - Some(session_metadata) => session_metadata.senders.send_to_screen($message), + ($senders:expr, $message:expr, $instruction: expr, $retry_queue:expr) => {{ + match $senders.as_ref() { + Some(senders) => senders.send_to_screen($message), None => { log::warn!("Server not ready, trying to place instruction in retry queue..."); if let Some(retry_queue) = $retry_queue.as_mut() { @@ -1455,8 +1568,11 @@ pub(crate) fn route_thread_main( >| -> Result { let mut should_break = false; - let rlocked_sessions = - session_data.read().to_anyhow().with_context(err_context)?; + let senders = session_data + .read() + .to_anyhow() + .ok() + .and_then(|r| r.as_ref().map(|r| r.senders.clone())); // Check if this is a watcher client and ignore input messages let is_watcher = session_state.read().unwrap().is_watcher(&client_id); @@ -1475,10 +1591,10 @@ pub(crate) fn route_thread_main( exit_reason: ExitReason::Normal, }, ); - let _ = rlocked_sessions.as_ref().map(|r| { - r.senders.send_to_screen( - ScreenInstruction::RemoveWatcherClient(client_id), - ) + let _ = senders.as_ref().map(|s| { + s.send_to_screen(ScreenInstruction::RemoveWatcherClient( + client_id, + )) }); should_break = true; } @@ -1487,7 +1603,7 @@ pub(crate) fn route_thread_main( // For watchers: send size to Screen for rendering adjustments, but // this does not affect the screen size send_to_screen_or_retry_queue!( - rlocked_sessions, + senders, ScreenInstruction::WatcherTerminalResize(client_id, *new_size), instruction.clone(), retry_queue @@ -1514,46 +1630,75 @@ pub(crate) fn route_thread_main( .unwrap() .set_last_active_client(client_id); - if let Some(rlocked_sessions) = rlocked_sessions.as_ref() { - match rlocked_sessions.get_client_keybinds_and_mode(&client_id) { - Some((keybinds, input_mode, default_input_mode)) => { - for action in keybinds - .get_actions_for_key_in_mode_or_default_action( - &input_mode, - &key, - raw_bytes, - default_input_mode, - is_kitty_keyboard_protocol, - ) - { - if route_action( - action, + let session_data_assets = + session_data.read().as_ref().unwrap().as_ref().map(|s| { + ( + s.senders.clone(), + s.capabilities.clone(), + s.client_attributes.clone(), + s.default_shell.clone(), + s.layout.clone(), + s.session_configuration + .get_client_configuration(&client_id) + .options + .default_mode + .unwrap_or(InputMode::Normal) + .clone(), + ) + }); + if let Some((keybinds, input_mode, default_input_mode)) = session_data + .read() + .unwrap() + .as_ref() + .and_then(|s| s.get_client_keybinds_and_mode(&client_id)) + { + if let Some(( + senders, + capabilities, + client_attributes, + default_shell, + layout, + client_input_mode, + )) = session_data_assets + { + for action in keybinds + .get_actions_for_key_in_mode_or_default_action( + &input_mode, + &key, + raw_bytes, + default_input_mode, + is_kitty_keyboard_protocol, + ) + { + // Send user input to plugin thread for logging + let _ = + senders.send_to_plugin(PluginInstruction::UserInput { client_id, - None, - None, - rlocked_sessions.senders.clone(), - rlocked_sessions.capabilities.clone(), - rlocked_sessions.client_attributes.clone(), - rlocked_sessions.default_shell.clone(), - rlocked_sessions.layout.clone(), - Some(&mut seen_cli_pipes), - keybinds.clone(), - rlocked_sessions - .session_configuration - .get_client_configuration(&client_id) - .options - .default_mode - .unwrap_or(InputMode::Normal) - .clone(), - Some(os_input.clone()), - )? { - should_break = true; - } + action: action.clone(), + terminal_id: None, + cli_client_id: None, + }); + + if route_action( + action, + client_id, + None, + None, + senders.clone(), + capabilities, + client_attributes.clone(), + default_shell.clone(), + layout.clone(), + Some(&mut seen_cli_pipes), + keybinds.clone(), + client_input_mode, + Some(os_input.clone()), + )? + .0 + { + should_break = true; } - }, - None => { - log::error!("Failed to get keybindings for client"); - }, + } } } }, @@ -1580,31 +1725,67 @@ pub(crate) fn route_thread_main( } else { maybe_client_id.unwrap_or(client_id) }; - if let Some(rlocked_sessions) = rlocked_sessions.as_ref() { + + // Send user input to plugin thread for logging + if let Some(ref senders) = senders { + let _ = senders.send_to_plugin(PluginInstruction::UserInput { + client_id, + action: action.clone(), + terminal_id: maybe_pane_id, + cli_client_id: if is_cli_client { + Some(cli_client_id) + } else { + None + }, + }); + } + + let session_data_assets = + session_data.read().unwrap().as_ref().map(|s| { + ( + s.senders.clone(), + s.capabilities.clone(), + s.client_attributes.clone(), + s.default_shell.clone(), + s.layout.clone(), + s.session_configuration + .get_client_configuration(&client_id) + .options + .default_mode + .unwrap_or(InputMode::Normal) + .clone(), + s.session_configuration + .get_client_keybinds(&client_id) + .clone(), + ) + }); + if let Some(( + senders, + capabilities, + client_attributes, + default_shell, + layout, + client_input_mode, + client_keybinds, + )) = session_data_assets + { if route_action( action, client_id, Some(cli_client_id), maybe_pane_id.map(|p| PaneId::Terminal(p)), - rlocked_sessions.senders.clone(), - rlocked_sessions.capabilities.clone(), - rlocked_sessions.client_attributes.clone(), - rlocked_sessions.default_shell.clone(), - rlocked_sessions.layout.clone(), + senders, + capabilities, + client_attributes, + default_shell, + layout, Some(&mut seen_cli_pipes), - rlocked_sessions - .session_configuration - .get_client_keybinds(&client_id) - .clone(), - rlocked_sessions - .session_configuration - .get_client_configuration(&client_id) - .options - .default_mode - .unwrap_or(InputMode::Normal) - .clone(), + client_keybinds, + client_input_mode, Some(os_input.clone()), - )? { + )? + .0 + { should_break = true; } } @@ -1614,7 +1795,7 @@ pub(crate) fn route_thread_main( if is_watcher { // For watchers: send size to Screen for tracking, don't affect screen size send_to_screen_or_retry_queue!( - rlocked_sessions, + senders.clone(), ScreenInstruction::WatcherTerminalResize(client_id, new_size), instruction, retry_queue @@ -1635,22 +1816,19 @@ pub(crate) fn route_thread_main( )) }) .and_then(|min_size| { - rlocked_sessions - .as_ref() - .context( - "couldn't get reference to read-locked session", - )? - .senders - .send_to_screen(ScreenInstruction::TerminalResize( + let _ = senders.as_ref().map(|s| { + s.send_to_screen(ScreenInstruction::TerminalResize( min_size, )) + }); + Ok(()) }) .with_context(err_context)?; } }, ClientToServerMsg::TerminalPixelDimensions { pixel_dimensions } => { send_to_screen_or_retry_queue!( - rlocked_sessions, + senders, ScreenInstruction::TerminalPixelDimensions(pixel_dimensions), instruction, retry_queue @@ -1661,7 +1839,7 @@ pub(crate) fn route_thread_main( color: ref background_color_instruction, } => { send_to_screen_or_retry_queue!( - rlocked_sessions, + senders, ScreenInstruction::TerminalBackgroundColor( background_color_instruction.clone() ), @@ -1674,7 +1852,7 @@ pub(crate) fn route_thread_main( color: ref foreground_color_instruction, } => { send_to_screen_or_retry_queue!( - rlocked_sessions, + senders, ScreenInstruction::TerminalForegroundColor( foreground_color_instruction.clone() ), @@ -1687,7 +1865,7 @@ pub(crate) fn route_thread_main( ref color_registers, } => { send_to_screen_or_retry_queue!( - rlocked_sessions, + senders, ScreenInstruction::TerminalColorRegisters( color_registers .iter() @@ -1718,10 +1896,11 @@ pub(crate) fn route_thread_main( pane_to_focus: pane_id_to_focus, is_web_client, } => { - let allow_web_connections = rlocked_sessions - .as_ref() - .map(|rlocked_sessions| { - rlocked_sessions.web_sharing.web_clients_allowed() + let allow_web_connections = session_data + .read() + .ok() + .and_then(|s| { + s.as_ref().map(|s| s.web_sharing.web_clients_allowed()) }) .unwrap_or(false); let should_allow_connection = !is_web_client || allow_web_connections; @@ -1801,7 +1980,9 @@ pub(crate) fn route_thread_main( }, None => { consecutive_unknown_messages_received += 1; - log::error!("Received unknown message from client."); + if consecutive_unknown_messages_received == 1 { + log::error!("Received unknown message from client."); + } if consecutive_unknown_messages_received >= 1000 { log::error!("Client sent over 1000 consecutive unknown messages, this is probably an infinite loop, logging client out"); let _ = os_input.send_to_client( diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 3c83d6b03..c89988315 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -12,9 +12,9 @@ use crate::route::NotificationEnd; use log::{debug, warn}; use zellij_utils::data::{ - Direction, FloatingPaneCoordinates, KeyWithModifier, NewPanePlacement, PaneContents, - PaneManifest, PaneScrollbackResponse, PluginPermission, Resize, ResizeStrategy, SessionInfo, - Styling, WebSharing, + CommandOrPlugin, Direction, FloatingPaneCoordinates, KeyWithModifier, NewPanePlacement, + PaneContents, PaneManifest, PaneScrollbackResponse, PluginPermission, Resize, ResizeStrategy, + SessionInfo, Styling, WebSharing, }; use zellij_utils::errors::prelude::*; use zellij_utils::input::command::RunCommand; @@ -51,10 +51,7 @@ use crate::{ pty::{get_default_shell, ClientTabIndexOrPaneId, PtyInstruction, VteBytes}, tab::{SuppressedPanes, Tab}, thread_bus::Bus, - ui::{ - loading_indication::LoadingIndication, - overlay::{Overlay, OverlayWindow}, - }, + ui::loading_indication::LoadingIndication, ClientId, ServerInstruction, }; use zellij_utils::{ @@ -218,6 +215,7 @@ pub enum ScreenInstruction { ToggleActiveTerminalFullscreen(ClientId, Option), TogglePaneFrames(Option), SetSelectable(PaneId, bool), + ShowPluginCursor(u32, ClientId, Option<(usize, usize)>), ClosePane( PaneId, Option, @@ -235,6 +233,8 @@ pub enum ScreenInstruction { Vec, Option, (Vec, Vec), // swap layouts + Option>, // initial_panes + bool, // block_on_first_terminal bool, // should_change_focus_to_new_tab (ClientId, bool), // bool -> is_web_client Option, // completion signal @@ -245,10 +245,11 @@ pub enum ScreenInstruction { Vec<(u32, HoldForCommand)>, // new pane pids Vec<(u32, HoldForCommand)>, // new floating pane pids HashMap>, - usize, // tab_index - bool, // should change focus to new tab - (ClientId, bool), // bool -> is_web_client - Option, // completion signal + usize, // tab_index + bool, // should change focus to new tab + (ClientId, bool), // bool -> is_web_client + Option, // regular completion signal + Option<(u32, NotificationEnd)>, // blocking_terminal (terminal_id, completion_tx) ), SwitchTabNext(ClientId, Option), SwitchTabPrev(ClientId, Option), @@ -284,10 +285,6 @@ pub enum ScreenInstruction { Option<(u32, bool)>, // (pane_id, is_plugin) => pane_id to focus ), RemoveClient(ClientId), - AddOverlay(Overlay, ClientId), - RemoveOverlay(ClientId), - ConfirmPrompt(ClientId, Option), - DenyPrompt(ClientId, Option), UpdateSearch(Vec, ClientId, Option), SearchDown(ClientId, Option), SearchUp(ClientId, Option), @@ -368,8 +365,12 @@ pub enum ScreenInstruction { ClientId, Option, ), // bools are: should_float, should_open_in_place Option is the pane id to replace, Option is an optional cwd, bool after is skip_cache - SuppressPane(PaneId, ClientId), // bool is should_float - FocusPaneWithId(PaneId, bool, ClientId, Option), // bool is should_float + SuppressPane(PaneId, ClientId), + UnsuppressPane(PaneId, bool), // bool -> should float if hidden + UnsuppressOrExpandPane(PaneId, bool), // bool -> should float if hidden + FocusPaneWithId(PaneId, bool, bool, ClientId, Option), // bools: + // should_float_if_hidden, + // should_be_in_place_if_hidden RenamePane(PaneId, Vec, Option), RenameTab(usize, Vec, Option), RequestPluginPermissions( @@ -422,6 +423,7 @@ pub enum ScreenInstruction { ResizePaneWithId(ResizeStrategy, PaneId), EditScrollbackForPaneWithId(PaneId, Option), WriteToPaneId(Vec, PaneId), + CopyTextToClipboard(String, u32), // String - text to copy, u32 - plugin_id MovePaneWithPaneId(PaneId), MovePaneWithPaneIdInDirection(PaneId, Direction), ClearScreenForPaneId(PaneId), @@ -467,7 +469,7 @@ pub enum ScreenInstruction { SetMouseSelectionSupport(PaneId, bool), InterceptKeyPresses(PluginId, ClientId), ClearKeyPressesIntercepts(ClientId), - ReplacePaneWithExistingPane(PaneId, PaneId), + ReplacePaneWithExistingPane(PaneId, PaneId, bool), // bool -> suppress_replaced_pane AddWatcherClient(ClientId, Size), RemoveWatcherClient(ClientId), SetFollowedClient(ClientId), @@ -553,6 +555,7 @@ impl From<&ScreenInstruction> for ScreenContext { }, ScreenInstruction::TogglePaneFrames(..) => ScreenContext::TogglePaneFrames, ScreenInstruction::SetSelectable(..) => ScreenContext::SetSelectable, + ScreenInstruction::ShowPluginCursor(..) => ScreenContext::ShowPluginCursor, ScreenInstruction::ClosePane(..) => ScreenContext::ClosePane, ScreenInstruction::HoldPane(..) => ScreenContext::HoldPane, ScreenInstruction::UpdatePaneName(..) => ScreenContext::UpdatePaneName, @@ -591,10 +594,6 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::ToggleTab(..) => ScreenContext::ToggleTab, ScreenInstruction::AddClient(..) => ScreenContext::AddClient, ScreenInstruction::RemoveClient(..) => ScreenContext::RemoveClient, - ScreenInstruction::AddOverlay(..) => ScreenContext::AddOverlay, - ScreenInstruction::RemoveOverlay(..) => ScreenContext::RemoveOverlay, - ScreenInstruction::ConfirmPrompt(..) => ScreenContext::ConfirmPrompt, - ScreenInstruction::DenyPrompt(..) => ScreenContext::DenyPrompt, ScreenInstruction::UpdateSearch(..) => ScreenContext::UpdateSearch, ScreenInstruction::SearchDown(..) => ScreenContext::SearchDown, ScreenInstruction::SearchUp(..) => ScreenContext::SearchUp, @@ -633,6 +632,8 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::LaunchOrFocusPlugin(..) => ScreenContext::LaunchOrFocusPlugin, ScreenInstruction::LaunchPlugin(..) => ScreenContext::LaunchPlugin, ScreenInstruction::SuppressPane(..) => ScreenContext::SuppressPane, + ScreenInstruction::UnsuppressPane(..) => ScreenContext::UnsuppressPane, + ScreenInstruction::UnsuppressOrExpandPane(..) => ScreenContext::UnsuppressOrExpandPane, ScreenInstruction::FocusPaneWithId(..) => ScreenContext::FocusPaneWithId, ScreenInstruction::RenamePane(..) => ScreenContext::RenamePane, ScreenInstruction::RenameTab(..) => ScreenContext::RenameTab, @@ -657,6 +658,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenContext::EditScrollbackForPaneWithId }, ScreenInstruction::WriteToPaneId(..) => ScreenContext::WriteToPaneId, + ScreenInstruction::CopyTextToClipboard(..) => ScreenContext::CopyTextToClipboard, ScreenInstruction::MovePaneWithPaneId(..) => ScreenContext::MovePaneWithPaneId, ScreenInstruction::MovePaneWithPaneIdInDirection(..) => { ScreenContext::MovePaneWithPaneIdInDirection @@ -848,14 +850,13 @@ pub(crate) struct Screen { character_cell_size: Rc>>, stacked_resize: Rc>, sixel_image_store: Rc>, - /// The overlay that is drawn on top of [`Pane`]'s', [`Tab`]'s and the [`Screen`] - overlay: OverlayWindow, terminal_emulator_colors: Rc>, terminal_emulator_color_codes: Rc>>, connected_clients: Rc>>, // bool -> is_web_client /// The indices of this [`Screen`]'s active [`Tab`]s. active_tab_indices: BTreeMap, tab_history: BTreeMap>, + pane_history: BTreeMap>, mode_info: BTreeMap, default_mode_info: ModeInfo, // TODO: restructure ModeInfo to prevent this duplication style: Style, @@ -942,10 +943,10 @@ impl Screen { connected_clients: Rc::new(RefCell::new(HashMap::new())), active_tab_indices: BTreeMap::new(), tabs: BTreeMap::new(), - overlay: OverlayWindow::default(), 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, @@ -1644,11 +1645,6 @@ impl Screen { } } - /// Returns a mutable reference to this [`Screen`]'s active [`Overlays`]. - pub fn get_active_overlays_mut(&mut self) -> &mut Vec { - &mut self.overlay.overlay_stack - } - /// Returns a mutable reference to this [`Screen`]'s indexed [`Tab`]. pub fn get_indexed_tab_mut(&mut self, tab_index: usize) -> Option<&mut Tab> { self.get_tabs_mut().get_mut(&tab_index) @@ -1733,6 +1729,7 @@ impl Screen { tab_index: usize, should_change_client_focus: bool, client_id_and_is_web_client: (ClientId, bool), + blocking_terminal: Option<(u32, NotificationEnd)>, ) -> Result<()> { if self.tabs.get(&tab_index).is_none() { // TODO: we should prevent this situation with a UI - eg. cannot close tabs with a @@ -1817,6 +1814,7 @@ impl Screen { new_floating_terminal_ids, new_plugin_ids, client_id, + blocking_terminal, )?; tab.update_input_modes()?; @@ -1949,18 +1947,6 @@ impl Screen { } } - // Optional: getter for debugging/monitoring - pub fn get_watcher_size(&self, client_id: &ClientId) -> Option { - self.watcher_clients - .get(client_id) - .map(|state| state.size()) - } - - // Optional: get all watcher sizes - pub fn get_all_watcher_sizes(&self) -> &HashMap { - &self.watcher_clients - } - pub fn generate_and_report_tab_state(&mut self) -> Result> { let mut plugin_updates = vec![]; let mut tab_infos_for_screen_state = BTreeMap::new(); @@ -2063,6 +2049,8 @@ impl Screen { } fn log_and_report_session_state(&mut self) -> Result<()> { let err_context = || format!("Failed to log and report session state"); + + self.update_active_pane_ids(); // generate own session info let pane_manifest = self.generate_and_report_pane_state()?; let tab_infos = self.generate_and_report_tab_state()?; @@ -2090,6 +2078,11 @@ impl Screen { .count(), plugins: Default::default(), // these are filled in by the wasm thread tab_history: self.tab_history.clone(), + pane_history: self + .pane_history + .iter() + .map(|(k, v)| (*k, v.iter().map(|v| (*v).into()).collect())) + .collect(), }; self.bus .senders @@ -2496,6 +2489,7 @@ impl Screen { run_plugin: &RunPluginOrAlias, should_float: bool, move_to_focused_tab: bool, + should_be_in_place: bool, client_id: ClientId, ) -> Result { // true => found and focused, false => not @@ -2526,6 +2520,7 @@ impl Screen { None, true, )?; + // TODO: also should_be_in_place } else { new_active_tab.hide_floating_panes(); new_active_tab.add_tiled_pane( @@ -2542,7 +2537,7 @@ impl Screen { self.tabs .get_mut(&tab_index) .with_context(err_context)? - .focus_pane_with_id(plugin_pane_id, should_float, client_id) + .focus_pane_with_id(plugin_pane_id, should_float, should_be_in_place, client_id) .context("failed to focus plugin pane")?; self.log_and_report_session_state() .with_context(err_context)?; @@ -2556,6 +2551,7 @@ impl Screen { &mut self, pane_id: PaneId, should_float_if_hidden: bool, + should_open_in_place: bool, client_id: ClientId, ) -> Result<()> { let err_context = || format!("failed to focus_plugin_pane"); @@ -2570,7 +2566,14 @@ impl Screen { self.tabs .iter_mut() .find(|(_, t)| t.position == tab_index) - .map(|(_, t)| t.focus_pane_with_id(pane_id, should_float_if_hidden, client_id)) + .map(|(_, t)| { + t.focus_pane_with_id( + pane_id, + should_float_if_hidden, + should_open_in_place, + client_id, + ) + }) .with_context(err_context) .non_fatal(); }, @@ -2666,6 +2669,8 @@ impl Screen { Some(tiled_panes_layout), floating_panes_layout, tab_index, + None, // initial_panes + false, // block_on_first_terminal should_change_focus_to_new_tab, (client_id, is_web_client), None, @@ -2742,6 +2747,8 @@ impl Screen { Some(tiled_panes_layout), floating_panes_layout, tab_index, + None, // initial_panes + false, // block_on_first_terminal should_change_focus_to_new_tab, (client_id, is_web_client), None, @@ -2942,6 +2949,7 @@ impl Screen { &mut self, pane_id_to_replace: PaneId, pane_id_of_existing_pane: PaneId, + suppress_replaced_pane: bool, ) { let Some(tab_index_of_pane_id_to_replace) = self .tabs @@ -2965,7 +2973,7 @@ impl Screen { .tabs .iter_mut() .find(|(_, t)| t.position == tab_index_of_existing_pane) - .and_then(|(_, t)| t.extract_pane(pane_id_of_existing_pane, false)) + .and_then(|(_, t)| t.extract_pane(pane_id_of_existing_pane, true)) else { log::error!("Failed to find pane"); return; @@ -2975,11 +2983,19 @@ impl Screen { .iter_mut() .find(|(_, t)| t.position == tab_index_of_pane_id_to_replace) { - tab.1.close_pane_and_replace_with_other_pane( - pane_id_to_replace, - extracted_pane_from_other_tab, - None, - ); + if suppress_replaced_pane { + tab.1.suppress_pane_and_replace_with_other_pane( + pane_id_to_replace, + extracted_pane_from_other_tab, + None, + ); + } else { + tab.1.close_pane_and_replace_with_other_pane( + pane_id_to_replace, + extracted_pane_from_other_tab, + None, + ); + } } let _ = self.log_and_report_session_state(); } @@ -3505,6 +3521,18 @@ impl Screen { } } } + fn update_active_pane_ids(&mut self) { + let connected_clients: Vec = + self.connected_clients.borrow().keys().copied().collect(); + for client_id in connected_clients { + if let Some(active_pane_id) = self.get_active_pane_id(&client_id) { + let active_pane_id: PaneId = active_pane_id.into(); + let history = self.pane_history.entry(client_id).or_insert_with(|| vec![]); + history.retain(|e| e != &active_pane_id); + history.push(active_pane_id.into()); + } + } + } } #[cfg(not(test))] @@ -3692,9 +3720,11 @@ pub(crate) fn screen_thread_main( new_pane_placement, start_suppressed, client_or_tab_index, - completion_tx, + mut completion_tx, set_blocking, ) => { + completion_tx.as_mut().map(|c| c.set_affected_pane_id(pid)); + let blocking_notification = if set_blocking { completion_tx } else { None }; match client_or_tab_index { @@ -3747,6 +3777,7 @@ pub(crate) fn screen_thread_main( ClientTabIndexOrPaneId::PaneId(pane_id) => { let mut found = false; let all_tabs = screen.get_tabs_mut(); + let should_focus_pane = false; for tab in all_tabs.values_mut() { if tab.has_pane_with_pid(&pane_id) { tab.new_pane( @@ -3754,7 +3785,7 @@ pub(crate) fn screen_thread_main( initial_pane_title, invoked_with, start_suppressed, - true, + should_focus_pane, new_pane_placement, None, blocking_notification, // TODO: is this correct? @@ -4426,6 +4457,26 @@ pub(crate) fn screen_thread_main( screen.render(None)?; screen.log_and_report_session_state()?; }, + ScreenInstruction::ShowPluginCursor(pid, client_id, cursor_position) => { + let all_tabs = screen.get_tabs_mut(); + let mut found_plugin = false; + for tab in all_tabs.values_mut() { + if tab.has_plugin(pid) { + tab.show_plugin_cursor(pid, client_id, cursor_position); + found_plugin = true; + break; + } + } + if !found_plugin { + pending_events_waiting_for_tab.push(ScreenInstruction::ShowPluginCursor( + pid, + client_id, + cursor_position, + )); + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, ScreenInstruction::SetMouseSelectionSupport(pid, selection_support) => { let all_tabs = screen.get_tabs_mut(); let mut found_plugin = false; @@ -4564,6 +4615,8 @@ pub(crate) fn screen_thread_main( floating_panes_layout, tab_name, swap_layouts, + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, (client_id, is_web_client), completion_tx, @@ -4590,6 +4643,8 @@ pub(crate) fn screen_thread_main( layout, floating_panes_layout, tab_index, + initial_panes, + block_on_first_terminal, should_change_focus_to_new_tab, (client_id, is_web_client), completion_tx, @@ -4604,9 +4659,14 @@ pub(crate) fn screen_thread_main( tab_index, should_change_focus_to_new_tab, (client_id, is_web_client), - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it + mut completion_tx, + blocking_terminal, ) => { + if let Some(first_terminal_pane) = new_pane_pids.iter().next() { + completion_tx + .as_mut() + .map(|c| c.set_affected_pane_id(PaneId::Terminal(first_terminal_pane.0))); + } screen.apply_layout( layout, floating_panes_layout, @@ -4616,6 +4676,7 @@ pub(crate) fn screen_thread_main( tab_index, should_change_focus_to_new_tab, (client_id, is_web_client), + blocking_terminal, )?; pending_tab_ids.remove(&tab_index); if pending_tab_ids.is_empty() { @@ -4749,6 +4810,8 @@ pub(crate) fn screen_thread_main( None, vec![], tab_index, + None, // initial_panes + false, // block_on_first_terminal should_change_focus_to_new_tab, (client_id, is_web_client), completion_tx, @@ -4885,7 +4948,7 @@ pub(crate) fn screen_thread_main( } }); if let Some(pane_id) = pane_id { - screen.focus_pane_with_id(pane_id, true, client_id)?; + screen.focus_pane_with_id(pane_id, true, false, client_id)?; } else if let Some(tab_position_to_focus) = tab_position_to_focus { screen.go_to_tab(tab_position_to_focus, client_id)?; } @@ -4915,37 +4978,6 @@ pub(crate) fn screen_thread_main( screen.log_and_report_session_state()?; screen.render(None)?; }, - ScreenInstruction::AddOverlay(overlay, _client_id) => { - screen.get_active_overlays_mut().pop(); - screen.get_active_overlays_mut().push(overlay); - }, - ScreenInstruction::RemoveOverlay(_client_id) => { - screen.get_active_overlays_mut().pop(); - screen.render(None)?; - }, - ScreenInstruction::ConfirmPrompt( - _client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - let overlay = screen.get_active_overlays_mut().pop(); - let instruction = overlay.and_then(|o| o.prompt_confirm()); - if let Some(instruction) = instruction { - screen - .bus - .senders - .send_to_server(*instruction) - .context("failed to confirm prompt")?; - } - }, - ScreenInstruction::DenyPrompt( - _client_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it - ) => { - screen.get_active_overlays_mut().pop(); - screen.render(None)?; - }, ScreenInstruction::UpdateSearch( c, client_id, @@ -5441,6 +5473,7 @@ pub(crate) fn screen_thread_main( &run_plugin, should_float, move_to_focused_tab, + should_open_in_place, client_id, )? { screen.render(None)?; @@ -5560,14 +5593,42 @@ pub(crate) fn screen_thread_main( } screen.log_and_report_session_state()?; }, + ScreenInstruction::UnsuppressPane(pane_id, should_float_if_hidden) => { + let all_tabs = screen.get_tabs_mut(); + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.unsuppress_pane(pane_id, should_float_if_hidden); + drop(screen.render(None)); + break; + } + } + screen.log_and_report_session_state()?; + }, + ScreenInstruction::UnsuppressOrExpandPane(pane_id, should_float_if_hidden) => { + let all_tabs = screen.get_tabs_mut(); + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.unsuppress_or_expand_pane(pane_id, should_float_if_hidden); + drop(screen.render(None)); + break; + } + } + screen.log_and_report_session_state()?; + }, ScreenInstruction::FocusPaneWithId( pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, client_id, _completion_tx, // the action ends here, dropping this will release anything // waiting for it ) => { - screen.focus_pane_with_id(pane_id, should_float_if_hidden, client_id)?; + screen.focus_pane_with_id( + pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + client_id, + )?; screen.log_and_report_session_state()?; }, ScreenInstruction::RenamePane( @@ -5655,9 +5716,11 @@ pub(crate) fn screen_thread_main( invoked_with, close_replaced_pane, client_id_tab_index_or_pane_id, - _completion_tx, // the action ends here, dropping this will release anything - // waiting for it + mut completion_tx, ) => { + completion_tx + .as_mut() + .map(|c| c.set_affected_pane_id(new_pane_id)); screen.replace_pane( new_pane_id, hold_for_command, @@ -5822,6 +5885,24 @@ pub(crate) fn screen_thread_main( } screen.render(None)?; }, + ScreenInstruction::CopyTextToClipboard(text, plugin_id) => { + let plugin_pane_id = PaneId::Plugin(plugin_id); + let all_tabs = screen.get_tabs_mut(); + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&plugin_pane_id) { + tab.copy_text_to_clipboard(&text) + .with_context(|| { + format!( + "failed to copy text to clipboard from plugin {}", + plugin_id + ) + }) + .non_fatal(); + break; + } + } + screen.render(None)?; + }, ScreenInstruction::MovePaneWithPaneId(pane_id) => { let all_tabs = screen.get_tabs_mut(); for tab in all_tabs.values_mut() { @@ -6053,7 +6134,7 @@ pub(crate) fn screen_thread_main( // waiting for it ) => { if let Some(last_pane_id) = screen.stack_panes(pane_ids_to_stack) { - let _ = screen.focus_pane_with_id(last_pane_id, false, client_id); + let _ = screen.focus_pane_with_id(last_pane_id, false, false, client_id); let _ = screen.render(None); let pane_group = screen.get_client_pane_group(&client_id); if !pane_group.is_empty() { @@ -6213,9 +6294,15 @@ pub(crate) fn screen_thread_main( ScreenInstruction::ClearKeyPressesIntercepts(client_id) => { keybind_intercepts.remove(&client_id); }, - ScreenInstruction::ReplacePaneWithExistingPane(old_pane_id, new_pane_id) => { - screen.replace_pane_with_existing_pane(old_pane_id, new_pane_id) - }, + ScreenInstruction::ReplacePaneWithExistingPane( + old_pane_id, + new_pane_id, + suppress_replaced_pane, + ) => screen.replace_pane_with_existing_pane( + old_pane_id, + new_pane_id, + suppress_replaced_pane, + ), ScreenInstruction::AddWatcherClient(client_id, size) => { screen .add_watcher_client(client_id) diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs index 5e52888ac..559dc5dbf 100644 --- a/zellij-server/src/tab/layout_applier.rs +++ b/zellij-server/src/tab/layout_applier.rs @@ -11,7 +11,7 @@ use crate::{ plugins::PluginInstruction, pty::PtyInstruction, thread_bus::ThreadSenders, - ClientId, + ClientId, NotificationEnd, }; use std::cell::RefCell; use std::collections::{BTreeMap, HashMap}; @@ -42,6 +42,7 @@ pub struct LayoutApplier<'a> { arrow_fonts: bool, styled_underlines: bool, explicitly_disable_kitty_keyboard_protocol: bool, + blocking_terminal: Option<(u32, NotificationEnd)>, } impl<'a> LayoutApplier<'a> { @@ -65,6 +66,7 @@ impl<'a> LayoutApplier<'a> { arrow_fonts: bool, styled_underlines: bool, explicitly_disable_kitty_keyboard_protocol: bool, + blocking_terminal: Option<(u32, NotificationEnd)>, ) -> Self { let viewport = viewport.clone(); let senders = senders.clone(); @@ -97,6 +99,7 @@ impl<'a> LayoutApplier<'a> { arrow_fonts, styled_underlines, explicitly_disable_kitty_keyboard_protocol, + blocking_terminal, } } pub fn apply_layout( @@ -496,6 +499,18 @@ impl<'a> LayoutApplier<'a> { Some(Run::Command(run_command)) => Some(run_command.to_string()), _ => None, }; + + // Check if this terminal should receive the blocking completion_tx + let notification_end = if let Some((blocking_pid, _)) = &self.blocking_terminal { + if *blocking_pid == pid { + self.blocking_terminal.take().map(|(_, tx)| tx) + } else { + None + } + } else { + None + }; + let mut new_pane = TerminalPane::new( pid, *position_and_size, @@ -513,7 +528,7 @@ impl<'a> LayoutApplier<'a> { self.arrow_fonts, self.styled_underlines, self.explicitly_disable_kitty_keyboard_protocol, - None, + notification_end, ); if let Some(pane_initial_contents) = &layout.pane_initial_contents { new_pane.handle_pty_bytes(pane_initial_contents.as_bytes().into()); diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index cd87b817e..7e441a0e3 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -7,7 +7,6 @@ mod layout_applier; mod swap_layouts; use copy_command::CopyCommand; -use serde; use std::env::temp_dir; use std::net::IpAddr; use std::path::PathBuf; @@ -46,7 +45,6 @@ use crate::{ thread_bus::ThreadSenders, ClientId, ServerInstruction, }; -use serde::{Deserialize, Serialize}; use std::cell::RefCell; use std::rc::Rc; use std::time::Instant; @@ -279,16 +277,6 @@ pub(crate) struct Tab { web_server_port: u16, } -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -#[serde(crate = "self::serde")] -pub(crate) struct TabData { - pub position: usize, - pub name: String, - pub active: bool, - pub mode_info: ModeInfo, - pub colors: Styling, -} - // FIXME: Use a struct that has a pane_type enum, to reduce all of the duplication pub trait Pane { fn x(&self) -> usize; @@ -304,7 +292,8 @@ pub trait Pane { fn set_geom_override(&mut self, pane_geom: PaneGeom); fn handle_pty_bytes(&mut self, _bytes: VteBytes) {} fn handle_plugin_bytes(&mut self, _client_id: ClientId, _bytes: VteBytes) {} - fn cursor_coordinates(&self) -> Option<(usize, usize)>; + fn show_cursor(&mut self, _client_id: ClientId, _cursor_position: Option<(usize, usize)>) {} + fn cursor_coordinates(&self, _client_id: Option) -> Option<(usize, usize)>; fn is_mid_frame(&self) -> bool { false } @@ -818,6 +807,7 @@ impl Tab { new_floating_terminal_ids: Vec<(u32, HoldForCommand)>, new_plugin_ids: HashMap>, client_id: ClientId, + blocking_terminal: Option<(u32, NotificationEnd)>, ) -> Result<()> { self.swap_layouts .set_base_layout((layout.clone(), floating_panes_layout.clone())); @@ -841,6 +831,7 @@ impl Tab { self.arrow_fonts, self.styled_underlines, self.explicitly_disable_kitty_keyboard_protocol, + blocking_terminal, ) .apply_layout( layout, @@ -911,6 +902,7 @@ impl Tab { self.arrow_fonts, self.styled_underlines, self.explicitly_disable_kitty_keyboard_protocol, + None, ) .apply_floating_panes_layout_to_existing_panes(&layout_candidate) .non_fatal(); @@ -949,6 +941,7 @@ impl Tab { self.arrow_fonts, self.styled_underlines, self.explicitly_disable_kitty_keyboard_protocol, + None, ) .apply_tiled_panes_layout_to_existing_panes(&layout_candidate); if application_res.is_err() { @@ -2080,6 +2073,26 @@ impl Tab { drop(replaced_pane); } } + pub fn suppress_pane_and_replace_with_other_pane( + &mut self, + pane_id_to_replace: PaneId, + pane_to_replace_with: Box, + _completion_tx: Option, + ) { + let mut replaced_pane = if self.floating_panes.panes_contain(&pane_id_to_replace) { + self.floating_panes + .replace_pane(pane_id_to_replace, pane_to_replace_with) + .ok() + } else { + self.tiled_panes + .replace_pane(pane_id_to_replace, pane_to_replace_with) + }; + + if let Some(replaced_pane) = replaced_pane.take() { + let is_scrollback_editor = false; + self.insert_suppressed_pane(replaced_pane.pid(), (is_scrollback_editor, replaced_pane)); + } + } pub fn horizontal_split( &mut self, pid: PaneId, @@ -2683,7 +2696,7 @@ impl Tab { .get(&active_pane_id) .or_else(|| self.tiled_panes.get_pane(active_pane_id))?; active_terminal - .cursor_coordinates() + .cursor_coordinates(Some(client_id)) .map(|(x_in_terminal, y_in_terminal)| { let x = active_terminal.x() + x_in_terminal; let y = active_terminal.y() + y_in_terminal; @@ -3381,21 +3394,16 @@ impl Tab { if let Some(pane) = self.tiled_panes.get_pane_mut(id) { pane.set_selectable(selectable); if !selectable { - // there are some edge cases in which this causes a hard crash when there are no - // other selectable panes - ideally this should never happen unless it's a - // configuration error - but this *does* sometimes happen with the default - // configuration as well since we set this at run time. I left this here because - // this should very rarely happen and I hope in my heart that we will stop setting - // this at runtime in the default configuration at some point - // - // If however this is not the case and we find this does cause crashes, we can - // solve it by adding a "dangling_clients" struct to Tab which we would fill with - // the relevant client ids in this case and drain as soon as a new selectable pane - // is opened self.tiled_panes.move_clients_out_of_pane(id); } } else if let Some(pane) = self.floating_panes.get_pane_mut(id) { pane.set_selectable(selectable); + if !selectable { + self.floating_panes.move_clients_out_of_pane(id); + if !self.floating_panes.has_selectable_panes() { + self.hide_floating_panes(); + } + } } // we do this here because if there is a non-selectable pane on the edge, we consider it // outside the viewport (a ui-pane, eg. the status-bar and tab-bar) and need to adjust for it @@ -3539,8 +3547,15 @@ impl Tab { closed_pane.reset_logical_position(); } closed_pane - } else if self.suppressed_panes.contains_key(&id) { - self.suppressed_panes.remove(&id).map(|s_p| s_p.1) + } else if let Some(suppressed_key_of_pane) = self + .suppressed_panes + .iter() + .find_map(|(key, (_, pane))| if &pane.pid() == &id { Some(*key) } else { None }) + { + // TODO: test this (from the path in screen.rs focus_plugin_pane ~line 2519 + self.suppressed_panes + .remove(&suppressed_key_of_pane) + .map(|s_p| s_p.1) } else { None } @@ -4674,6 +4689,19 @@ impl Tab { } Ok(()) } + pub fn copy_text_to_clipboard(&self, text: &str) -> Result<()> { + self.write_selection_to_clipboard(text) + .with_context(|| format!("failed to write text to clipboard"))?; + self.senders + .send_to_plugin(PluginInstruction::Update(vec![( + None, + None, + Event::CopyToClipboard(self.clipboard_provider.as_copy_destination()), + )])) + .with_context(|| "failed to inform plugins about clipboard copy") + .non_fatal(); + Ok(()) + } fn write_selection_to_clipboard(&self, selection: &str) -> Result<()> { let err_context = || format!("failed to write selection to clipboard: '{}'", selection); @@ -4950,6 +4978,26 @@ impl Tab { plugin_pane.update_loading_indication(loading_indication); } } + pub fn show_plugin_cursor( + &mut self, + pid: u32, + client_id: ClientId, + cursor_position: Option<(usize, usize)>, + ) { + if let Some(plugin_pane) = self + .tiled_panes + .get_pane_mut(PaneId::Plugin(pid)) + .or_else(|| self.floating_panes.get_pane_mut(PaneId::Plugin(pid))) + .or_else(|| { + self.suppressed_panes + .values_mut() + .find(|s_p| s_p.1.pid() == PaneId::Plugin(pid)) + .map(|s_p| &mut s_p.1) + }) + { + plugin_pane.show_cursor(client_id, cursor_position); + } + } pub fn start_plugin_loading_indication( &mut self, pid: u32, @@ -5009,7 +5057,7 @@ impl Tab { .find(|(_id, (_, pane))| { run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with()) }) - .map(|(id, _)| *id) + .map(|(_, (_, pane))| pane.pid()) // TODO: does this break things???? }) } @@ -5017,6 +5065,7 @@ impl Tab { &mut self, pane_id: PaneId, should_float: bool, + should_be_in_place: bool, client_id: ClientId, ) -> Result<()> { // TODO: should error if pane is not selectable @@ -5031,18 +5080,45 @@ impl Tab { }; focused_floating_pane }) - .or_else(|_| match self.suppressed_panes.remove(&pane_id) { - Some(mut pane) => { - pane.1.set_selectable(true); - if should_float { - self.show_floating_panes(); - self.add_floating_pane(pane.1, pane_id, None, true) - } else { - self.hide_floating_panes(); - self.add_tiled_pane(pane.1, pane_id, Some(client_id)) - } - }, - None => Ok(()), + // TODO: change suppressed_panes to be a proper struct with methods that make sense rather + // than doing this dance every time + .or_else(|_| { + match self + .suppressed_panes + .extract_if(|_key, (_, pane)| pane.pid() == pane_id) + .next() + .map(|(_key, (_, pane))| pane) + { + Some(mut pane) => { + pane.set_selectable(true); + if should_float { + self.show_floating_panes(); + self.add_floating_pane(pane, pane_id, None, true) + } else if should_be_in_place { + let replaced_pane = if self.are_floating_panes_visible() { + self.floating_panes + .replace_active_pane(pane, client_id) + .ok() + } else { + self.tiled_panes.replace_active_pane(pane, client_id) + }; + if let Some(replaced_pane) = replaced_pane { + let is_scrollback_editor = false; + self.insert_suppressed_pane( + pane_id, + (is_scrollback_editor, replaced_pane), + ); + } else { + log::error!("Could not find pane to replace, aborting."); + } + Ok(()) + } else { + self.hide_floating_panes(); + self.add_tiled_pane(pane, pane_id, Some(client_id)) + } + }, + None => Ok(()), + } }) } pub fn focus_suppressed_pane_for_all_clients(&mut self, pane_id: PaneId) { @@ -5064,11 +5140,101 @@ impl Tab { // scrollback editor), but it has to take itself out on its own (eg. a plugin using the // show_self() method) if let Some(pane) = self.extract_pane(pane_id, true) { - let is_scrollback_editor = false; - self.suppressed_panes - .insert(pane_id, (is_scrollback_editor, pane)); + self.insert_suppressed_pane(pane_id, (false, pane)); } } + pub fn unsuppress_pane(&mut self, pane_id: PaneId, should_float_if_hidden: bool) { + // removes a pane from being suppressed (hidden) but does not focus it + match self + .suppressed_panes + .extract_if(|_key, (_, pane)| pane.pid() == pane_id) + .next() + .map(|(_key, (_, pane))| pane) + { + Some(pane) => { + if should_float_if_hidden { + self.add_floating_pane(pane, pane_id, None, true) + .non_fatal(); + } else { + self.add_tiled_pane(pane, pane_id, None).non_fatal(); + } + }, + None => { + log::error!("Could not find suppressed pane with id: {:?}", pane_id); + }, + } + } + pub fn unsuppress_or_expand_pane(&mut self, pane_id: PaneId, should_float_if_hidden: bool) { + // removes a pane from being suppressed (hidden) but does not focus it + match self + .suppressed_panes + .extract_if(|_key, (_, pane)| pane.pid() == pane_id) + .next() + .map(|(_key, (_, pane))| pane) + { + Some(pane) => { + if should_float_if_hidden { + self.add_floating_pane(pane, pane_id, None, true) + .non_fatal(); + } else { + self.add_tiled_pane(pane, pane_id, None).non_fatal(); + } + }, + None => { + let expand_panes_success = self.tiled_panes.expand_pane_in_stack(pane_id).len() > 0; + if !expand_panes_success { + log::error!( + "Could not find suppressed or stacked pane with id: {:?}", + pane_id + ); + } + }, + } + } + fn insert_suppressed_pane( + &mut self, + suppressing_pane_id: PaneId, + pane_to_suppress: (bool, Box), + ) { + // bool -> is_scrollback_editor + // this method is intended to insert an existing provided pane into suppressed_panes, while + // making sure any existing panes already in suppressed_panes still remain there + // if there's a key collision (eg. the suppressing_pane_id already suppresses another + // pane), we fix the colliding pane so that it now becomes suppressed by its own id (i.e. + // needs to explicitly be removed from suppressed_panes by eg. a plugin action rather than + // being conditionally removed when its suppressing pane is closed or itself suppressed) + // + // - suppressing_pane_id: the id of the pane suppressing this pane - the pane that if + // closed, should trigger this pane being unsuppressed + // - pane_to_suppress: the pane itself that we want to suppress + + // this closure removes and returns an existing pane from the map if it exists under this key + // and inserts the given pane into the map under this key + let mut insert_and_return_existing_value = + |key: PaneId, value: (bool, Box)| -> Option<(bool, Box)> { + let existing = self.suppressed_panes.remove(&key); + self.suppressed_panes.insert(key, value); + existing + }; + + // here we try to insert a pane into the suppressed panes map while making sure not to drop + // (close) any existing panes in the map. We repeat the action of remapping existing panes + // under their own keys until all keys either reference the suppressing_pane_id (only one + // can do this) or themselves + let mut key_to_insert = suppressing_pane_id; + let mut pane_to_insert = Some(pane_to_suppress); + loop { + pane_to_insert = pane_to_insert + .take() + .and_then(|p| insert_and_return_existing_value(key_to_insert, p)); + if let Some(pane_to_insert) = pane_to_insert.as_ref() { + key_to_insert = pane_to_insert.1.pid(); + } else { + break; + } + } + } + pub fn pane_infos(&self) -> Vec { let mut pane_info = vec![]; let current_pane_group = { self.current_pane_group.borrow().clone_inner() }; @@ -5076,9 +5242,11 @@ impl Tab { let mut floating_pane_info = self.floating_panes.pane_info(¤t_pane_group); pane_info.append(&mut tiled_pane_info); pane_info.append(&mut floating_pane_info); - for (pane_id, (_is_scrollback_editor, pane)) in self.suppressed_panes.iter() { + for (_pane_id_of_suppressing_pane, (_is_scrollback_editor, pane)) in + self.suppressed_panes.iter() + { let mut pane_info_for_suppressed_pane = - pane_info_for_pane(pane_id, pane, ¤t_pane_group); + pane_info_for_pane(&pane.pid(), pane, ¤t_pane_group); pane_info_for_suppressed_pane.is_floating = false; pane_info_for_suppressed_pane.is_suppressed = true; pane_info_for_suppressed_pane.is_focused = false; @@ -5364,7 +5532,7 @@ impl Tab { } pub fn add_suppressed_panes(&mut self, mut suppressed_panes: SuppressedPanes) { for (pane_id, suppressed_pane_entry) in suppressed_panes.drain() { - self.suppressed_panes.insert(pane_id, suppressed_pane_entry); + self.insert_suppressed_pane(pane_id, suppressed_pane_entry); } } pub fn toggle_pane_pinned(&mut self, client_id: ClientId) { @@ -5531,7 +5699,7 @@ pub fn pane_info_for_pane( pane_info.pane_content_rows = pane.get_content_rows(); pane_info.pane_columns = pane.cols(); pane_info.pane_content_columns = pane.get_content_columns(); - pane_info.cursor_coordinates_in_pane = pane.cursor_coordinates(); + pane_info.cursor_coordinates_in_pane = pane.cursor_coordinates(None); pane_info.is_selectable = pane.selectable(); pane_info.title = pane.current_title(); pane_info.exited = pane.exited(); diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index 029df49df..6eb39eae2 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -138,6 +138,9 @@ impl ServerOsApi for FakeInputOutput { fn clear_terminal_id(&self, _terminal_id: u32) -> Result<()> { unimplemented!() } + fn send_sigint(&self, pid: Pid) -> Result<()> { + unimplemented!() + } } struct MockPtyInstructionBus { @@ -280,6 +283,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab { vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -361,6 +365,7 @@ fn create_new_tab_without_pane_frames(size: Size, default_mode: ModeInfo) -> Tab vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -469,6 +474,7 @@ fn create_new_tab_with_swap_layouts( new_floating_terminal_ids, new_plugin_ids, client_id, + None, ) .unwrap(); tab @@ -554,6 +560,7 @@ fn create_new_tab_with_os_api( vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -648,6 +655,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str) floating_pane_ids, HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -734,6 +742,7 @@ fn create_new_tab_with_mock_pty_writer( vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -822,6 +831,7 @@ fn create_new_tab_with_sixel_support( vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -1191,7 +1201,7 @@ fn render_stacks_without_pane_frames() { ) .unwrap(); } - tab.focus_pane_with_id(PaneId::Terminal(1), false, client_id); + tab.focus_pane_with_id(PaneId::Terminal(1), false, false, client_id); for i in 7..9 { let new_pane_id_1 = PaneId::Terminal(i); tab.new_pane( @@ -1206,7 +1216,7 @@ fn render_stacks_without_pane_frames() { ) .unwrap(); } - let _ = tab.focus_pane_with_id(PaneId::Terminal(1), false, client_id); + let _ = tab.focus_pane_with_id(PaneId::Terminal(1), false, false, client_id); for i in 9..11 { let new_pane_id_1 = PaneId::Terminal(i); tab.new_pane( @@ -1226,8 +1236,8 @@ fn render_stacks_without_pane_frames() { ResizeStrategy::new(Resize::Increase, Some(Direction::Right)), ) .unwrap(); - let _ = tab.focus_pane_with_id(PaneId::Terminal(7), false, client_id); - let _ = tab.focus_pane_with_id(PaneId::Terminal(5), false, client_id); + let _ = tab.focus_pane_with_id(PaneId::Terminal(7), false, false, client_id); + let _ = tab.focus_pane_with_id(PaneId::Terminal(5), false, false, client_id); tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index f5284b884..085f82114 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -106,6 +106,9 @@ impl ServerOsApi for FakeInputOutput { fn clear_terminal_id(&self, _terminal_id: u32) -> Result<()> { unimplemented!() } + fn send_sigint(&self, pid: Pid) -> Result<()> { + unimplemented!() + } } fn tab_resize_increase(tab: &mut Tab, id: ClientId) { @@ -220,6 +223,7 @@ fn create_new_tab(size: Size, stacked_resize: bool) -> Tab { vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -304,6 +308,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab { vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab @@ -386,6 +391,7 @@ fn create_new_tab_with_cell_size( vec![], HashMap::new(), client_id, + None, ) .unwrap(); tab diff --git a/zellij-server/src/ui/components/nested_list.rs b/zellij-server/src/ui/components/nested_list.rs index c2aa28603..b4b76b9b6 100644 --- a/zellij-server/src/ui/components/nested_list.rs +++ b/zellij-server/src/ui/components/nested_list.rs @@ -49,6 +49,7 @@ pub fn nested_list( Some(padding + bulletin.len()), &coordinates, &style_declaration, + &style.colors, text_style.bold(Some(AnsiCode::On)), ); text = pad_line(text, max_width, padding, text_width); diff --git a/zellij-server/src/ui/components/ribbon.rs b/zellij-server/src/ui/components/ribbon.rs index 98b681a56..adfa3a799 100644 --- a/zellij-server/src/ui/components/ribbon.rs +++ b/zellij-server/src/ui/components/ribbon.rs @@ -34,6 +34,7 @@ pub fn ribbon( padding, &component_coordinates, &declaration, + &colors, text_style, ); let mut stringified = component_coordinates diff --git a/zellij-server/src/ui/components/table.rs b/zellij-server/src/ui/components/table.rs index 978b741e2..80ab2a371 100644 --- a/zellij-server/src/ui/components/table.rs +++ b/zellij-server/src/ui/components/table.rs @@ -22,7 +22,8 @@ pub fn table( if is_too_high(row_index + 1, &coordinates) { break; } - for cell in row { + let cell_count = row.iter().len(); + for (cell_index, cell) in row.into_iter().enumerate() { let declaration = if is_title_row { style.colors.table_title } else { @@ -38,16 +39,21 @@ pub fn table( } else { CharacterStyles::from(declaration) }; + + // Default: bold + let text_style = text_style.bold(Some(AnsiCode::On)); + // here we intentionally don't pass our coordinates even if we have them, because // these cells have already been padded and truncated - let (text, _text_width) = stringify_text( - &cell, - None, - &None, - &declaration, - text_style.bold(Some(AnsiCode::On)), - ); - stringified.push_str(&format!("{}{} {}", text_style, text, RESET_STYLES)); + let (text, _text_width) = + stringify_text(&cell, None, &None, &declaration, &style.colors, text_style); + if cell_index == cell_count.saturating_sub(1) { + // do not add padding between columns for the last cell + stringified.push_str(&format!("{}{}{}", text_style, text, RESET_STYLES)); + } else { + // add padding between columns + stringified.push_str(&format!("{}{} {}", text_style, text, RESET_STYLES)); + } } let next_row_instruction = coordinates .as_ref() diff --git a/zellij-server/src/ui/components/text.rs b/zellij-server/src/ui/components/text.rs index c0088e605..eb8667f8a 100644 --- a/zellij-server/src/ui/components/text.rs +++ b/zellij-server/src/ui/components/text.rs @@ -15,6 +15,7 @@ pub fn text(content: Text, style: &Style, component_coordinates: Option, coordinates: &Option, style: &StyleDeclaration, + styling: &zellij_utils::data::Styling, component_text_style: CharacterStyles, ) -> (String, usize) { let mut text_width = 0; @@ -48,6 +51,7 @@ pub fn stringify_text( } else { component_text_style }; + stringified.push_str(&format!("{}", base_text_style)); for (i, character) in text.text.chars().enumerate() { let character_width = character.width().unwrap_or(0); if is_too_wide( @@ -67,7 +71,7 @@ pub fn stringify_text( if !text.indices.is_empty() || text.selected || text.opaque { let character_with_styling = - color_index_character(character, i, &text, style, base_text_style); + color_index_character(character, i, &text, style, styling, base_text_style); stringified.push_str(&character_with_styling); } else { stringified.push(character) @@ -100,12 +104,32 @@ pub fn color_index_character( index: usize, text: &Text, declaration: &StyleDeclaration, + styling: &zellij_utils::data::Styling, base_text_style: CharacterStyles, ) -> String { - let character_style = text - .style_of_index(index, declaration) + let mut character_style = text + .style_of_index(index, declaration, styling) .map(|foreground_style| base_text_style.foreground(Some(foreground_style.into()))) .unwrap_or(base_text_style); + + // Apply dim and unbold per-character based on index levels 4 and 5 + if text.is_unbold_at(index) { + // Remove bold for this character + character_style = character_style.bold(Some(AnsiCode::Reset)); + } else if text.is_dimmed_at(index) { + // Apply dim for this character + character_style = character_style + .foreground(Some(AnsiCode::Reset)) // some terminals (eg. alacritty) do not support dimming non 16 + // colors, so we have to defer to the terminal's default here + .dim(Some(AnsiCode::On)); + } else { + character_style = character_style + .bold(Some(AnsiCode::On)) + .dim(Some(AnsiCode::Reset)); // default, to reset any + // possible dim/bold values + // from previous indices + } + format!("{}{}{}", character_style, character, base_text_style) } @@ -141,7 +165,46 @@ impl Text { } } - pub fn style_of_index(&self, index: usize, style: &StyleDeclaration) -> Option { + pub fn is_dimmed_at(&self, index: usize) -> bool { + const DIM_LEVEL: usize = 4; + self.indices + .get(DIM_LEVEL) + .map(|indices| indices.contains(&index)) + .unwrap_or(false) + } + + pub fn is_unbold_at(&self, index: usize) -> bool { + const UNBOLD_LEVEL: usize = 5; + self.indices + .get(UNBOLD_LEVEL) + .map(|indices| indices.contains(&index)) + .unwrap_or(false) + } + + pub fn style_of_index( + &self, + index: usize, + style: &StyleDeclaration, + styling: &zellij_utils::data::Styling, + ) -> Option { + const ERROR_COLOR_LEVEL: usize = 6; + const SUCCESS_COLOR_LEVEL: usize = 7; + + // Check error color first (highest precedence) + if let Some(indices) = self.indices.get(ERROR_COLOR_LEVEL) { + if indices.contains(&index) { + return Some(styling.exit_code_error.base); + } + } + + // Check success color (second highest precedence) + if let Some(indices) = self.indices.get(SUCCESS_COLOR_LEVEL) { + if indices.contains(&index) { + return Some(styling.exit_code_success.base); + } + } + + // Check regular emphasis levels (existing code) let index_variant_styles = [ style.emphasis_0, style.emphasis_1, diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs index d9d5e3a04..1a17e7436 100644 --- a/zellij-server/src/ui/mod.rs +++ b/zellij-server/src/ui/mod.rs @@ -1,6 +1,5 @@ pub mod boundaries; pub mod components; pub mod loading_indication; -pub mod overlay; pub mod pane_boundaries_frame; pub mod pane_contents_and_ui; diff --git a/zellij-server/src/ui/overlay/mod.rs b/zellij-server/src/ui/overlay/mod.rs deleted file mode 100644 index 7e3f821b3..000000000 --- a/zellij-server/src/ui/overlay/mod.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! This module handles the overlay's over the [`Screen`] -//! -//! They consist of: -//! -//! prompt's: -//! -//! notification's: - -pub mod prompt; - -use crate::ServerInstruction; -use zellij_utils::errors::prelude::*; -use zellij_utils::pane_size::Size; - -#[derive(Clone, Debug)] -pub struct Overlay { - pub overlay_type: OverlayType, -} - -pub trait Overlayable { - /// Generates vte_output that can be passed into - /// the `render()` function - fn generate_overlay(&self, size: Size) -> Result; -} - -#[derive(Clone, Debug)] -pub enum OverlayType { - Prompt(prompt::Prompt), -} - -impl Overlayable for OverlayType { - fn generate_overlay(&self, size: Size) -> Result { - match &self { - OverlayType::Prompt(prompt) => prompt - .generate_overlay(size) - .context("failed to generate VTE output from overlay type"), - } - } -} - -/// Entrypoint from [`Screen`], which holds the context in which -/// the overlays are being rendered. -/// The most recent overlays draw over the previous overlays. -#[derive(Clone, Debug, Default)] -pub struct OverlayWindow { - pub overlay_stack: Vec, -} - -impl Overlayable for OverlayWindow { - fn generate_overlay(&self, size: Size) -> Result { - let mut output = String::new(); - //let clear_display = "\u{1b}[2J"; - //output.push_str(&clear_display); - for overlay in &self.overlay_stack { - let vte_output = overlay - .generate_overlay(size) - .context("failed to generate VTE output from overlay window")?; - output.push_str(&vte_output); - } - Ok(output) - } -} - -impl Overlay { - pub fn prompt_confirm(self) -> Option> { - match self.overlay_type { - OverlayType::Prompt(p) => p.confirm(), - } - } - pub fn prompt_deny(self) -> Option> { - match self.overlay_type { - OverlayType::Prompt(p) => p.deny(), - } - } -} - -impl Overlayable for Overlay { - fn generate_overlay(&self, size: Size) -> Result { - self.overlay_type - .generate_overlay(size) - .context("failed to generate VTE output from overlay") - } -} - -impl Overlay { - pub fn new(overlay_type: OverlayType) -> Self { - Self { overlay_type } - } - - fn pad_cols(output: &mut String, cols: usize) { - if let Some(padding) = cols.checked_sub(output.len()) { - for _ in 0..padding { - output.push(' '); - } - } - } -} diff --git a/zellij-server/src/ui/overlay/prompt.rs b/zellij-server/src/ui/overlay/prompt.rs deleted file mode 100644 index 0cbfe3516..000000000 --- a/zellij-server/src/ui/overlay/prompt.rs +++ /dev/null @@ -1,65 +0,0 @@ -use zellij_utils::pane_size::Size; - -use super::{Overlay, OverlayType, Overlayable}; -use crate::{ClientId, ServerInstruction}; -use zellij_utils::errors::prelude::*; - -use std::fmt::Write; - -#[derive(Clone, Debug)] -pub struct Prompt { - pub message: String, - on_confirm: Option>, - on_deny: Option>, -} - -impl Prompt { - pub fn new( - message: String, - on_confirm: Option>, - on_deny: Option>, - ) -> Self { - Self { - message, - on_confirm, - on_deny, - } - } - pub fn confirm(self) -> Option> { - self.on_confirm - } - pub fn deny(self) -> Option> { - self.on_deny - } -} - -impl Overlayable for Prompt { - fn generate_overlay(&self, size: Size) -> Result { - let mut output = String::new(); - let rows = size.rows; - let mut vte_output = self.message.clone(); - Overlay::pad_cols(&mut vte_output, size.cols); - for (x, h) in vte_output.chars().enumerate() { - write!( - &mut output, - "\u{1b}[{};{}H\u{1b}[48;5;238m{}", - rows, - x + 1, - h, - ) - .context("failed to generate VTE output from prompt")?; - } - Ok(output) - } -} - -pub fn _generate_quit_prompt(client_id: ClientId) -> Overlay { - let prompt = Prompt::new( - (" Do you want to quit zellij? [Y]es / [N]o").to_string(), - Some(Box::new(ServerInstruction::ClientExit(client_id, None))), - None, - ); - Overlay { - overlay_type: OverlayType::Prompt(prompt), - } -} diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs index c17a9b668..326dd96f1 100644 --- a/zellij-server/src/ui/pane_contents_and_ui.rs +++ b/zellij-server/src/ui/pane_contents_and_ui.rs @@ -159,7 +159,7 @@ impl<'a> PaneContentsAndUi<'a> { ) { let cursor_is_visible = self .pane - .cursor_coordinates() + .cursor_coordinates(Some(*fake_cursor_client_id)) .map(|(x, y)| { self.output .cursor_is_visible(self.pane.x() + x, self.pane.y() + y) @@ -279,6 +279,7 @@ impl<'a> PaneContentsAndUi<'a> { .add_post_vte_instruction_to_client(client_id, &vte_output); } } + Ok(()) } pub fn render_pane_boundaries( diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 171096f77..6345d6b84 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -249,6 +249,9 @@ impl ServerOsApi for FakeInputOutput { fn clear_terminal_id(&self, _terminal_id: u32) -> Result<()> { unimplemented!() } + fn send_sigint(&self, pid: Pid) -> Result<()> { + unimplemented!() + } } fn create_new_screen(size: Size, advanced_mouse_actions: bool) -> Screen { @@ -402,6 +405,8 @@ impl MockScreen { initial_floating_panes_layout.clone(), tab_name, (vec![], vec![]), // swap layouts + None, // initial_panes + false, should_change_focus_to_new_tab, (self.main_client_id, false), None, @@ -416,6 +421,7 @@ impl MockScreen { true, (self.main_client_id, false), None, + None, )); self.last_opened_tab_index = Some(tab_index); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for the async render @@ -492,6 +498,8 @@ impl MockScreen { initial_floating_panes_layout.clone(), tab_name, (vec![], vec![]), // swap layouts + None, // initial_panes + false, should_change_focus_to_new_tab, (self.main_client_id, false), None, @@ -506,6 +514,7 @@ impl MockScreen { true, (self.main_client_id, false), None, + None, )); self.last_opened_tab_index = Some(tab_index); screen_thread @@ -528,6 +537,8 @@ impl MockScreen { vec![], // floating_panes_layout tab_name, (vec![], vec![]), // swap layouts + None, // initial_panes + false, should_change_focus_to_new_tab, (self.main_client_id, false), None, @@ -542,6 +553,7 @@ impl MockScreen { true, (self.main_client_id, false), None, + None, )); self.last_opened_tab_index = Some(tab_index); } @@ -756,6 +768,7 @@ fn new_tab(screen: &mut Screen, pid: u32, tab_index: usize) { tab_index, true, (client_id, false), + None, ) .expect("TEST"); } @@ -2638,6 +2651,8 @@ pub fn send_cli_new_pane_action_with_default_parameters() { pinned: None, stacked: false, blocking: false, + unblock_condition: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2684,6 +2699,8 @@ pub fn send_cli_new_pane_action_with_split_direction() { pinned: None, stacked: false, blocking: false, + unblock_condition: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2730,6 +2747,8 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { pinned: None, stacked: false, blocking: false, + unblock_condition: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2787,6 +2806,8 @@ pub fn send_cli_new_pane_action_with_floating_pane_and_coordinates() { pinned: None, stacked: false, blocking: false, + unblock_condition: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2826,6 +2847,7 @@ pub fn send_cli_edit_action_with_default_parameters() { width: None, height: None, pinned: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2865,6 +2887,7 @@ pub fn send_cli_edit_action_with_line_number() { width: None, height: None, pinned: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2904,6 +2927,7 @@ pub fn send_cli_edit_action_with_split_direction() { width: None, height: None, pinned: None, + near_current_pane: false, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -3089,6 +3113,13 @@ pub fn send_cli_new_tab_action_default_params() { layout: None, layout_dir: None, cwd: None, + initial_command: vec![], + initial_plugin: None, + close_on_exit: Default::default(), + start_suspended: Default::default(), + block_until_exit: false, + block_until_exit_success: false, + block_until_exit_failure: false, }; send_cli_action_to_server(&session_metadata, new_tab_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -3129,6 +3160,13 @@ pub fn send_cli_new_tab_action_with_name_and_layout() { ))), layout_dir: None, cwd: None, + initial_command: vec![], + initial_plugin: None, + close_on_exit: Default::default(), + start_suspended: Default::default(), + block_until_exit: false, + block_until_exit_success: false, + block_until_exit_failure: false, }; send_cli_action_to_server(&session_metadata, new_tab_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -3699,6 +3737,7 @@ pub fn screen_can_break_pane_to_a_new_tab() { true, (1, false), None, + None, )); std::thread::sleep(std::time::Duration::from_millis(100)); // move back to make sure the other pane is in the previous tab @@ -3806,6 +3845,7 @@ pub fn screen_can_break_floating_pane_to_a_new_tab() { true, (1, false), None, + None, )); std::thread::sleep(std::time::Duration::from_millis(200)); // move back to make sure the other pane is in the previous tab @@ -3880,6 +3920,7 @@ pub fn screen_can_break_plugin_pane_to_a_new_tab() { true, (1, false), None, + None, )); std::thread::sleep(std::time::Duration::from_millis(100)); // move back to make sure the other pane is in the previous tab @@ -3958,6 +3999,7 @@ pub fn screen_can_break_floating_plugin_pane_to_a_new_tab() { true, (1, false), None, + None, )); std::thread::sleep(std::time::Duration::from_millis(100)); // move back to make sure the other pane is in the previous tab diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap index e36f78b86..d322d6c19 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap index 73fec3930..b21357e74 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap index c09ce65b5..fc5e1af5b 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(Some(Down)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(Some(Down)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap index ca824efed..2428bce00 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap @@ -36,6 +36,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap index de7e1ed5e..fcb5c1354 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", new_pane_instruction)" --- -Some(SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Tiled(Some(Right)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false)) +Some(SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Tiled(Some(Right)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap index 75f460d5f..57aaa6500 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(None), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap index 4d5b11c81..3c3d85e75 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Floating(Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None })), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None, use_terminal_title: false })), None, Floating(Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None })), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap index 7ac623b8d..2bdd6975d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(Some(Right)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None }), false), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(Some(Right)), false, ClientId(10), Some(NotificationEnd { channel: None, exit_status: None, unblock_condition: None, affected_pane_id: None }), false), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap index 30640244c..0bdf3e1d8 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap @@ -59,6 +59,8 @@ Some( ), [], 0, + None, + false, true, ( 1, diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap index 1a0677e64..d61ae4d78 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap @@ -86,6 +86,8 @@ NewTab( ), [], 1, + None, + false, true, ( 10, @@ -95,6 +97,8 @@ NewTab( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap index ed7034530..5c1577625 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_query_tab_names_action.snap @@ -13,6 +13,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index 6030dcc7f..189f1f8f5 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -10,8 +10,8 @@ use zellij_utils::input::actions::Action; pub use zellij_utils::plugin_api; use zellij_utils::plugin_api::event::ProtobufPaneScrollbackResponse; use zellij_utils::plugin_api::plugin_command::{ - CreateTokenResponse, ListTokensResponse, ProtobufPluginCommand, RenameWebTokenResponse, - RevokeAllWebTokensResponse, RevokeTokenResponse, + CreateTokenResponse, ListTokensResponse, ProtobufGetPanePidResponse, ProtobufPluginCommand, + RenameWebTokenResponse, RevokeAllWebTokensResponse, RevokeTokenResponse, }; use zellij_utils::plugin_api::plugin_ids::{ProtobufPluginIds, ProtobufZellijVersion}; @@ -48,6 +48,17 @@ pub fn set_selectable(selectable: bool) { unsafe { host_run_plugin_command() }; } +/// Shows the cursor at specific coordinates or hides it +/// +/// # Arguments +/// * `cursor_position` - None to hide cursor, Some((x, y)) to show at coordinates +pub fn show_cursor(cursor_position: Option<(usize, usize)>) { + let plugin_command = PluginCommand::ShowCursor(cursor_position); + 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 request_permission(permissions: &[PermissionType]) { let plugin_command = PluginCommand::RequestPluginPermissions(permissions.into()); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); @@ -395,8 +406,9 @@ pub fn show_self(should_float_if_hidden: bool) { } /// Show the pane (unsuppress it if it is suppressed) with the specified [PaneId], focus it and switch to its tab -pub fn show_pane_with_id(pane_id: PaneId, should_float_if_hidden: bool) { - let plugin_command = PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden); +pub fn show_pane_with_id(pane_id: PaneId, should_float_if_hidden: bool, should_focus_pane: bool) { + let plugin_command = + PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden, should_focus_pane); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; @@ -561,6 +573,17 @@ pub fn write_chars(chars: &str) { unsafe { host_run_plugin_command() }; } +/// Copy arbitrary text to the user's clipboard +/// +/// Respects the user's configured clipboard destination (system clipboard or primary selection). +/// Requires the WriteToClipboard permission. +pub fn copy_to_clipboard(text: impl Into) { + let plugin_command = PluginCommand::CopyToClipboard(text.into()); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Focused the previously focused tab (regardless of the tab position) pub fn toggle_tab() { let plugin_command = PluginCommand::ToggleTab; @@ -774,16 +797,32 @@ pub fn close_plugin_pane(plugin_pane_id: u32) { } /// Changes the focus to the terminal pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled). -pub fn focus_terminal_pane(terminal_pane_id: u32, should_float_if_hidden: bool) { - let plugin_command = PluginCommand::FocusTerminalPane(terminal_pane_id, should_float_if_hidden); +pub fn focus_terminal_pane( + terminal_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { + let plugin_command = PluginCommand::FocusTerminalPane( + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; } /// Changes the focus to the plugin pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled). -pub fn focus_plugin_pane(plugin_pane_id: u32, should_float_if_hidden: bool) { - let plugin_command = PluginCommand::FocusPluginPane(plugin_pane_id, should_float_if_hidden); +pub fn focus_plugin_pane( + plugin_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { + let plugin_command = PluginCommand::FocusPluginPane( + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; @@ -1023,14 +1062,22 @@ pub fn resize_pane_with_id(resize_strategy: ResizeStrategy, pane_id: PaneId) { } /// Changes the focus to the pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled). -pub fn focus_pane_with_id(pane_id: PaneId, should_float_if_hidden: bool) { +pub fn focus_pane_with_id( + pane_id: PaneId, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { let plugin_command = match pane_id { - PaneId::Terminal(terminal_pane_id) => { - PluginCommand::FocusTerminalPane(terminal_pane_id, should_float_if_hidden) - }, - PaneId::Plugin(plugin_pane_id) => { - PluginCommand::FocusPluginPane(plugin_pane_id, should_float_if_hidden) - }, + PaneId::Terminal(terminal_pane_id) => PluginCommand::FocusTerminalPane( + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), + PaneId::Plugin(plugin_pane_id) => PluginCommand::FocusPluginPane( + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), }; let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); @@ -1102,6 +1149,48 @@ pub fn write_chars_to_pane_id(chars: &str, pane_id: PaneId) { unsafe { host_run_plugin_command() }; } +/// Send SIGINT to the process running inside a terminal pane identified by this PaneId +pub fn send_sigint_to_pane_id(pane_id: PaneId) { + let plugin_command = PluginCommand::SendSigintToPaneId(pane_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() }; +} + +/// Send SIGKILL to the process running inside a terminal pane identified by this PaneId +pub fn send_sigkill_to_pane_id(pane_id: PaneId) { + let plugin_command = PluginCommand::SendSigkillToPaneId(pane_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() }; +} + +/// Get the PID of the process running inside a terminal pane +pub fn get_pane_pid(pane_id: PaneId) -> Result { + let plugin_command = PluginCommand::GetPanePid { pane_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() }; + + // Read response from stdin + let response_bytes = + bytes_from_stdin().map_err(|e| format!("Failed to read response from stdin: {:?}", e))?; + + // Decode protobuf response + let protobuf_response = ProtobufGetPanePidResponse::decode(response_bytes.as_slice()) + .map_err(|e| format!("Failed to decode protobuf response: {}", e))?; + + // Convert to Rust type + let response = GetPanePidResponse::try_from(protobuf_response) + .map_err(|e| format!("Failed to convert protobuf response: {}", e))?; + + // Convert Result enum to actual Result type + match response { + GetPanePidResponse::Ok(pid) => Ok(pid), + GetPanePidResponse::Err(error_msg) => Err(error_msg), + } +} + /// Switch the position of the pane with this id with a different pane pub fn move_pane_with_pane_id(pane_id: PaneId) { let plugin_command = PluginCommand::MovePaneWithPaneId(pane_id); @@ -1504,9 +1593,16 @@ pub fn clear_key_presses_intercepts() { unsafe { host_run_plugin_command() }; } -pub fn replace_pane_with_existing_pane(pane_id_to_replace: PaneId, existing_pane_id: PaneId) { - let plugin_command = - PluginCommand::ReplacePaneWithExistingPane(pane_id_to_replace, existing_pane_id); +pub fn replace_pane_with_existing_pane( + pane_id_to_replace: PaneId, + existing_pane_id: PaneId, + suppress_replaced_pane: bool, +) { + let plugin_command = PluginCommand::ReplacePaneWithExistingPane( + pane_id_to_replace, + existing_pane_id, + suppress_replaced_pane, + ); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; @@ -1580,6 +1676,14 @@ pub fn post_message_to_plugin(plugin_message: PluginMessage) { unsafe { host_run_plugin_command() }; } +pub fn run_action(action: Action, context: BTreeMap) { + // TODO: also accept reference + let plugin_command = PluginCommand::RunAction(action, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + #[link(wasm_import_module = "zellij")] extern "C" { fn host_run_plugin_command(); diff --git a/zellij-tile/src/ui_components/nested_list.rs b/zellij-tile/src/ui_components/nested_list.rs index f9a31632b..0c0eb9a16 100644 --- a/zellij-tile/src/ui_components/nested_list.rs +++ b/zellij-tile/src/ui_components/nested_list.rs @@ -38,6 +38,58 @@ impl NestedListItem { self.content = self.content.color_range(index_level, indices); self } + pub fn error_color_indices(mut self, indices: Vec) -> Self { + self.content = self.content.error_color_indices(indices); + self + } + pub fn error_color_range>(mut self, indices: R) -> Self { + self.content = self.content.error_color_range(indices); + self + } + pub fn error_color_substring>(mut self, substr: S) -> Self { + self.content = self.content.error_color_substring(substr); + self + } + pub fn error_color_nth_substring>( + mut self, + substr: S, + occurrence_index: usize, + ) -> Self { + self.content = self + .content + .error_color_nth_substring(substr, occurrence_index); + self + } + pub fn error_color_all(mut self) -> Self { + self.content = self.content.error_color_all(); + self + } + pub fn success_color_indices(mut self, indices: Vec) -> Self { + self.content = self.content.success_color_indices(indices); + self + } + pub fn success_color_range>(mut self, indices: R) -> Self { + self.content = self.content.success_color_range(indices); + self + } + pub fn success_color_substring>(mut self, substr: S) -> Self { + self.content = self.content.success_color_substring(substr); + self + } + pub fn success_color_nth_substring>( + mut self, + substr: S, + occurrence_index: usize, + ) -> Self { + self.content = self + .content + .success_color_nth_substring(substr, occurrence_index); + self + } + pub fn success_color_all(mut self) -> Self { + self.content = self.content.success_color_all(); + self + } pub fn serialize(&self) -> String { let mut serialized = String::new(); for _ in 0..self.indentation_level { diff --git a/zellij-tile/src/ui_components/text.rs b/zellij-tile/src/ui_components/text.rs index 68e8c0a14..492e23526 100644 --- a/zellij-tile/src/ui_components/text.rs +++ b/zellij-tile/src/ui_components/text.rs @@ -29,6 +29,220 @@ impl Text { self.opaque = true; self } + pub fn dim_indices(mut self, mut indices: Vec) -> Self { + const DIM_LEVEL: usize = 4; + self.pad_indices(DIM_LEVEL); + self.indices + .get_mut(DIM_LEVEL) + .map(|i| i.append(&mut indices)); + self + } + pub fn dim_range>(mut self, indices: R) -> Self { + const DIM_LEVEL: usize = 4; + self.pad_indices(DIM_LEVEL); + let start = match indices.start_bound() { + Bound::Unbounded => 0, + Bound::Included(s) => *s, + Bound::Excluded(s) => *s, + }; + let end = match indices.end_bound() { + Bound::Unbounded => self.text.chars().count(), + Bound::Included(s) => *s + 1, + Bound::Excluded(s) => *s, + }; + let indices = (start..end).into_iter(); + self.indices + .get_mut(DIM_LEVEL) + .map(|i| i.append(&mut indices.into_iter().collect())); + self + } + pub fn dim_substring>(mut self, substr: S) -> Self { + let substr = substr.as_ref(); + let mut start = 0; + + while let Some(pos) = self.text[start..].find(substr) { + let abs_pos = start + pos; + self = self.dim_range(abs_pos..abs_pos + substr.chars().count()); + start = abs_pos + substr.len(); + } + + self + } + pub fn dim_all(self) -> Self { + const DIM_LEVEL: usize = 4; + self.color_range(DIM_LEVEL, ..) + } + pub fn unbold_indices(mut self, mut indices: Vec) -> Self { + const UNBOLD_LEVEL: usize = 5; + self.pad_indices(UNBOLD_LEVEL); + self.indices + .get_mut(UNBOLD_LEVEL) + .map(|i| i.append(&mut indices)); + self + } + pub fn unbold_range>(mut self, indices: R) -> Self { + const UNBOLD_LEVEL: usize = 5; + self.pad_indices(UNBOLD_LEVEL); + let start = match indices.start_bound() { + Bound::Unbounded => 0, + Bound::Included(s) => *s, + Bound::Excluded(s) => *s, + }; + let end = match indices.end_bound() { + Bound::Unbounded => self.text.chars().count(), + Bound::Included(s) => *s + 1, + Bound::Excluded(s) => *s, + }; + let indices = (start..end).into_iter(); + self.indices + .get_mut(UNBOLD_LEVEL) + .map(|i| i.append(&mut indices.into_iter().collect())); + self + } + pub fn unbold_substring>(mut self, substr: S) -> Self { + let substr = substr.as_ref(); + let mut start = 0; + + while let Some(pos) = self.text[start..].find(substr) { + let abs_pos = start + pos; + self = self.unbold_range(abs_pos..abs_pos + substr.chars().count()); + start = abs_pos + substr.len(); + } + + self + } + pub fn unbold_all(self) -> Self { + const UNBOLD_LEVEL: usize = 5; + self.color_range(UNBOLD_LEVEL, ..) + } + pub fn error_color_indices(mut self, mut indices: Vec) -> Self { + const ERROR_COLOR_LEVEL: usize = 6; + self.pad_indices(ERROR_COLOR_LEVEL); + self.indices + .get_mut(ERROR_COLOR_LEVEL) + .map(|i| i.append(&mut indices)); + self + } + pub fn error_color_range>(mut self, indices: R) -> Self { + const ERROR_COLOR_LEVEL: usize = 6; + self.pad_indices(ERROR_COLOR_LEVEL); + let start = match indices.start_bound() { + Bound::Unbounded => 0, + Bound::Included(s) => *s, + Bound::Excluded(s) => *s, + }; + let end = match indices.end_bound() { + Bound::Unbounded => self.text.chars().count(), + Bound::Included(s) => *s + 1, + Bound::Excluded(s) => *s, + }; + let indices = (start..end).into_iter(); + self.indices + .get_mut(ERROR_COLOR_LEVEL) + .map(|i| i.append(&mut indices.into_iter().collect())); + self + } + pub fn error_color_substring>(mut self, substr: S) -> Self { + let substr = substr.as_ref(); + let mut start = 0; + + while let Some(pos) = self.text[start..].find(substr) { + let abs_pos = start + pos; + self = self.error_color_range(abs_pos..abs_pos + substr.chars().count()); + start = abs_pos + substr.len(); + } + + self + } + pub fn error_color_nth_substring>( + self, + substr: S, + occurrence_index: usize, + ) -> Self { + const ERROR_COLOR_LEVEL: usize = 6; + let substr = substr.as_ref(); + let mut start = 0; + let mut count = 0; + + while let Some(pos) = self.text[start..].find(substr) { + if count == occurrence_index { + let abs_pos = start + pos; + return self.color_range(ERROR_COLOR_LEVEL, abs_pos..abs_pos + substr.len()); + } + count += 1; + start = start + pos + substr.len(); + } + + self + } + pub fn error_color_all(self) -> Self { + const ERROR_COLOR_LEVEL: usize = 6; + self.color_range(ERROR_COLOR_LEVEL, ..) + } + pub fn success_color_indices(mut self, mut indices: Vec) -> Self { + const SUCCESS_COLOR_LEVEL: usize = 7; + self.pad_indices(SUCCESS_COLOR_LEVEL); + self.indices + .get_mut(SUCCESS_COLOR_LEVEL) + .map(|i| i.append(&mut indices)); + self + } + pub fn success_color_range>(mut self, indices: R) -> Self { + const SUCCESS_COLOR_LEVEL: usize = 7; + self.pad_indices(SUCCESS_COLOR_LEVEL); + let start = match indices.start_bound() { + Bound::Unbounded => 0, + Bound::Included(s) => *s, + Bound::Excluded(s) => *s, + }; + let end = match indices.end_bound() { + Bound::Unbounded => self.text.chars().count(), + Bound::Included(s) => *s + 1, + Bound::Excluded(s) => *s, + }; + let indices = (start..end).into_iter(); + self.indices + .get_mut(SUCCESS_COLOR_LEVEL) + .map(|i| i.append(&mut indices.into_iter().collect())); + self + } + pub fn success_color_substring>(mut self, substr: S) -> Self { + let substr = substr.as_ref(); + let mut start = 0; + + while let Some(pos) = self.text[start..].find(substr) { + let abs_pos = start + pos; + self = self.success_color_range(abs_pos..abs_pos + substr.chars().count()); + start = abs_pos + substr.len(); + } + + self + } + pub fn success_color_nth_substring>( + self, + substr: S, + occurrence_index: usize, + ) -> Self { + const SUCCESS_COLOR_LEVEL: usize = 7; + let substr = substr.as_ref(); + let mut start = 0; + let mut count = 0; + + while let Some(pos) = self.text[start..].find(substr) { + if count == occurrence_index { + let abs_pos = start + pos; + return self.color_range(SUCCESS_COLOR_LEVEL, abs_pos..abs_pos + substr.len()); + } + count += 1; + start = start + pos + substr.len(); + } + + self + } + pub fn success_color_all(self) -> Self { + const SUCCESS_COLOR_LEVEL: usize = 7; + self.color_range(SUCCESS_COLOR_LEVEL, ..) + } pub fn color_indices(mut self, index_level: usize, mut indices: Vec) -> Self { self.pad_indices(index_level); self.indices @@ -54,16 +268,17 @@ impl Text { .map(|i| i.append(&mut indices.into_iter().collect())); self } + pub fn color_substring>(mut self, index_level: usize, substr: S) -> Self { let substr = substr.as_ref(); let mut start = 0; - while let Some(pos) = self.text[start..].find(substr) { let abs_pos = start + pos; - self = self.color_range(index_level, abs_pos..abs_pos + substr.chars().count()); + let char_start = self.text[..abs_pos].chars().count(); + let char_end = char_start + substr.chars().count(); + self = self.color_range(index_level, char_start..char_end); start = abs_pos + substr.len(); } - self } diff --git a/zellij-utils/assets/config/default.kdl b/zellij-utils/assets/config/default.kdl index 017e3407d..e06dbe5c9 100644 --- a/zellij-utils/assets/config/default.kdl +++ b/zellij-utils/assets/config/default.kdl @@ -150,6 +150,12 @@ keybinds { }; SwitchToMode "Normal" } + bind "q" { + LaunchPlugin "zellij:sequence" { + floating true + }; + SwitchToMode "Normal" + } } tmux { bind "[" { SwitchToMode "Scroll"; } @@ -235,6 +241,7 @@ plugins { configuration location="zellij:configuration" plugin-manager location="zellij:plugin-manager" about location="zellij:about" + sequence location="zellij:sequence" } // Plugins to load in the background when a new session starts diff --git a/zellij-utils/assets/plugins/about.wasm b/zellij-utils/assets/plugins/about.wasm index d5e4ee66a72c484ddc0fee5e9cda158ba72d02e8..ae99b4a11ee2de0c4d77d5d15de15300b72aaed5 100755 GIT binary patch literal 1390199 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%0DcX)AGBr#p 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

58>k#SS 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 g+l|K2_10kKG2Oopt2S*OSgG{-D~f4p7Uw~|Cy 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

q!TM0qO=?>l{rXa~-Yiz-3oCY>MF}IkP2)>Kbj3 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 z zou`(%Q0*(HHbK_ykY4A*{l|U{}4_8wmRW9KN4G*uNm`OAz)W z2>Td>eF?(82VtLs^!^E9zl5+)LfHQx?0XRQJLpt7b6?BO>{2=N{K9?>&OdeD_CHAJ zyi@+g^G+>$*mo!d-XPc%>?<*3o(|_*M;j(49PE*Tf-S^`U&i}7m zr>WD4*Wtgq4gGhX-{H68zdFw7Rymn*xq9dd_0m=9qkbBoft6GH{Qhm<<2JZ*uGG(` z;k%&2XO?fsJpaG#wfBwgi{Z1?BkB8flQ&iN`GU9(x0yFqcf|2snTG2!Z1d!}%Jv_V z??p&mzu~)(raAr$%~tqMiii2A!grKB&L=fr;d3(2@Hs8kQmxQS3g2P0hU>Im8}+8% zR`{-q@SP}IOo#852;YekzF%USarkba?cAYH^@VmSe6L0L?u&0t|DZkETRC%`_f^i5 z%vL2&GOvoLq{``J)ls7=c~Y0Hc@>`(sFFI)U%kEkzh$|<`n(>tL-_YsOt!SW+Nhm6 zRLPONgyC~GU3i&#=t_mp-CV`K8eqBb8JxkUuhsRs(Y%{DTH$sw#`sRt<1|r|!hFZM z-~8}BVhfX`&|SeofO1&DO(uRF7N!DK5~ndS2mk zm@k?izH4ncUovlv)@i-*8`^C8U2W9|`beMXbA6?6^u21>p1Uo-*YrLeQ1~2D@Q}i1 zk+Pj^+bfsyDts;}eC{;A=|U=^Vk)7MDt)roVLV9{RYlcQ)BICeSM}9UXR3+L(RsQ+ z;d5cF+1BzM*h!bFo5E+sy7LP4Rv-1(Kn>9_h0myl&qm!~dW3G$Xs0!ncWRs_DtzW_ zlKE3iKcJZkpDTKhbM%D2BXHAu%@L8@r%vUW(vJi`ed8Uuiai)(~_?*{?EU!wc zs_HsLr&_Ka8?bS;%-i$X#^Li|&3LZ)7qGS3n(m-WOn1>`>Y*!jmHH}tc5DC#X{fH# zaK{tZBwG6h2=z+jx%V>Pamy|5=64orTYHJ#YF&Ez?Sezs&G? z;qZC1wWeP)FMR%QBi~Z^Oyj%eZ&mml;0OFjpM=AzWq#J`Yvb>Xck?IxqF;>6<*)Ad$~;QNb&N`>j81S^c~v%jGHbFn>$1MW=i(X~pQUET=kfx!W;=FJCta#; z>aHssc9r^Rpu+umsQK4vxJK$`-Kw#=Q{yyIlXSo1oapxVfa#ffP;>N{<|%yU@hL9Q zvwB`HI?nQNUV6p&RlTk^^p<(=ax1rUhdwp^rM@x!y~1a@ck?IxqF;4Ti5i)o2h7e4 z<*AW*o6BdqppH~gy_nzoZ#8lxOPVgNvMQ$vs%(BWonrb_)m8ZXVEF7{_-@1c4r^rI zS!$~0I^VojYHPZ^I;yjAH-^s|b~k;ct~TzcYc$w+7;n%B-K5bPqdRoB!zXf*?$OOt@^&fD}z(IqD483;Pb!E!DKBmm;x70kP%PJ>Ty85xzb5}pUdfw_MRzJD=snt)fp1*p*>V>PHS^ezlMXR4% z{ley~=$CK%f4DjqfTqg!fou2D6i~e2jm(o!mTcTD zORklrnU-c{isA(YHSb#1?iU6dcNk;97~6nx*@eNb@MWUn1q4I^D}A?}bGBuEOS7_@ z|L4s5KL6j^?>W!=oacSt=Xr0kGqjV!lcJOPCnYBfPZpmnJz0KIdQx^$ezNAI;-vDV z>ZImm<4NtwmXmE+=lNMXPnu44p0u8{pX|y$(b>c5;q>r&1ZVBLdqh3?J(8Znp5mU; zp7I`PkE}=DQ`4j9QTC{MG(C+y+Mbr4wjO}~9AI3?|E>oxS6PAN_)PpQr_PBolmpK3WPIHfzAdscL+ z{Zz-lEXx@N8Z$zgO5R>do(!^s0L;y|%N= z@bkRz^ZfAhx#8yE6#ei}^HJ}-29MBH5473gC2aE%z zfzAQTfNj7r&^^c;6bw%Lk={vO)P^&7fjXIj9=c3^opG2U`Z)2K9r+ zLDOL8pk>fD=osuCVhwSIcte7r+@ZW7@lfGV@lfed`H*x-HY6Xa8Bz=>hg3tFp~fNY zP|Hx;kbcNGWE$!mvJBaV97Elgn3vd>xR>~sgqK8@@-Im)6<#X7RC=lWlJt`7lKfK5 zCB-G>CDkR(rN&FzOD&h$h84qg!^+|MVb!pDSTo!(+&J7ctQ~G1ZW(SJZX4DO>xT`) z#^Ls1({RUd=dgL$GHe~T4cmtu!(GGOml>CtmsywDmpPZYmwCgg%d8R2X#1#OwEZd{ zuDPS_*Xv8K*W0hxmjz^bKvo5$A|UGmQX7zMlvFFOt3lQUWE&+L4A&b#ngg;dAj<=? zDj>C#Y*t)v23bc*Oa67U;kqsVy47&qs=aQN2BhM;U3A^Sy57}!-H{iNg#lR>kg|Ye zT<3<24Gy~}XD3ygsxr5FQ6BXt*w_hnZRRky1uAQb_r4oGc47C@WMc8#;W z1+lA;M294LBrza~5lPyS#N?BT5W4`e3lX~rv5OJA1hGpIy9}|*5xWAhrHEaL*fPYH zBX%`n*C2K+Vk;244zZPpU60r*#8xA=2C*9uyAiRQ5L=7b&4>-%wIX&KV(SoFkJtvp zHX?RAVw(`V1F<_1+l<&2#I_=~1F^dhySulbw-B|ndaF=-8EP*_?Q+zv>MiOm?XBrm z^s0KBkjZvd-rIsYxMyp6^}V`YV{dz}`7G;{7PVKMEjU|<%uHlvBQqD7`N%9pW)U*y zBeMjV;Z`v+mm+gHGE0$JhRkwgu0du6GAof;h0GdcZbW7+GPfXe8#3#W*@(<0WbQ;} z3o_e~*@4X6$ihSxHnMP$g^w&kWDy}tKC(!Vr4U()k);$_%8^BiEHY$~BTEgkD3C>o zEGlHtAWI{%XpyA_S=x|Ak1R%HF(FGQvRIJChAa+b=|)y2va*qti>!QP6(Xw$S@V%q zf~ss|i^0ND$Xy$IQh zk-Y@jOOd@6*%ioMhwMsZuSa$jva69@gX}tF*CV?D*^S8Fj_f96??CoWx=wk+PW zW%0oix^27n?9Vx{HTyu$m4YjUSBkC_Z_7C16ckcFGR0FOkrK2hN=DNuL20p+7EAp^ z6&phd$`%((2}(<#ZX{5}gm_9&wyePG(4nkDS=2i#>&TI;BUxEda4Xs=(Ek5-t5fjb zw~HZgF@z8SjYg+M(_(0`v^ZKkErFIukBXp0M$jW8q9Y?>A|qlWBjO?>;v*vxA|nzb zBWO_o+^2y94LoSzLIWQfIMKk125vO)qk~^YWW?skh%J#3nUN7&BO|s&Mr@Ca*by0# z6&bNJGGbR`M0R9EPGrRH$cR0W5ql#eK8=jn7a6fXGU7mF#KFjjLy-}OBO{JPMjVZd zI2QR}E=!gy4ZNIM`FXQbr*rD`PMyK2GdgwcPMyiA>u~BiojSN>aq6s2oz1DUJ9Q4H zuFI+GcIp{UJ=3XYIrVI(p5xSWoqC>A&v)ttPQB2n&voiWPJNzJpYPO*oqCB=U*Oai zI`u_PeX&zt;?$Qq^<_?dxl>=^)JvUu_yJ7j)K@w6a;Lu9saN!Bk;&2PaOxYJ`X;Bo z*{O%0)H=>|_cELYrqjT78n{ja-)Rs!4I-x@-)WFI4TVlavC~lMG?Y6HQl~-YG{~KX z8mB?wG$@@0mD8Yc8XBDjt<%urG_*MldZ)qYG?<)*PN%`*G}xR5httsQG%}q=w$sRU z8u?D6&}kGojrmTa#Az&a8jGFAQm3)pX_PvRGN)1QG}btc3a3%&G&VbptxluSX;Khv z`QEM?x0&HKH@M9mZgaQWB6VB2Zfl;~TI;r2aZWeRRpDGM&ST-cGMuNy`L#ITgbNsW zt_&Ah@VrtyuM*EQXo zRwL0SBHBubHW{Il5V{gV*G@9Eq@alubdUlYDd;AJd{QVSg)%a?nG|zKv5+jTB8$~z zNd;L_LzXm>7@hi~@?@;m~WM^NJt zwt9pHkI?Lq=6j@CkAmS* zdaPQHE!Wc}^K|JvT_!K9(90Ei`8+Q_&&x0LmUeo}7~YC1Z)JzK(&Cjhc;$s&d9_zw z=an~lYee3f7H^HwTg&v;HF%XWud>FgF7v9TUUjp#slltQ@M>$k%_?tmo448EZMJ(` zD!oRP*JAQoy1iDF*J|_H*j`({*H-AYS-duf*Dm(ji@o+*uifT#d8SBQ8;h*yGm)rhBXn}xVc<~HZL%`I-T zh%7O<%~H3SiPtycRk{cmwMY;wO0X%xr38->d`bu@A)-VcCB&4FP@;emg_J0YjPU88 zmG4;bIL)QSp(jFP{0~@OSkOwXQPzrT#D52Vo ziuxP1lxs!(4>GvIu>-;iK9EUd1mr>$p;esQLfIf_ICwy_$U)0zMn=GHj*Niq3Yrc& zft?*00ZSR~R@FeUTm_=GiMj#pk@a10qaYtNp(QfHV^DymqMFKux^9~iv_c3AZ&AYy z85G@i=)+@#(ZTZ}3{pjfVTa~nUsA#tiI+-ni=Awh>^-oRPNUQ5(exO4EIp1MPfwsH zMn^@{qUq7m(J|4nFm5nvFlI1fFkUcPFjg>9FitQ^Fh(#!Fg`FkH*{v7u@*+?hP>iN zr4B{_@`vmpZAb=EfkYq;NCHxT1R#7;14mJ(m)VGOn(%xbVQlc$av@TjCnZ{xc&8ed z81XzC-dYaHL28f~qyJlcWmFfZ~N9m*#|ORtU4E~-o;Y8SPd>#lZ&Nwv07ZL zHWy1zZDf|o#p-miEH0MK#d5e<-7YrM#pbx!JlNwdcCL#pa|#q?>>?Mt z)WxoFv1KlHwToTjV%NIZ3KzT1#jba;)h>2}i{0pAH@Vna7rWWTZgH{OTx^|-t#`2v zZd*NGlt+ccE_AW&R2P&Eo~169BA~(t%#U2uVTk z&;>XPsUj$lBPAgQaDcm@z}?zF?$BCb5U3#8fdIf6f(-bu?gtFDK!J{`U94702T8>M zZGxxjA7?N^UB*9l7*)6n5|V|+p}Rnl8k|6;R4(@|5bgc0|Ks_OLXA1}4i4Z9-9fa0 z$)X~JM)Ijyqr!lsAUx>({%H)iKAQ5k3fs+3WkQj1gbwCzkOeday;KGKL4oxQ7I{EIBv8EH{(S{*!D6^Syf7C5o$3g- z0E~3MAny+pv;fNnBFu?7B1w-vA2m|7| zuYf;nWY`+u294aG6flAgg9A#*KVd^H7(lQ<$7L) zWM^jY%HEc4V&weQ9(5^#!5AQzQXFr^Cc-P@w{lc7n;pR`b zY}t~z1?uhEp1FDZ(H$8(_GazgwQJV_2xoWpp6%I3a_GItfv3GCI-hKP`?LTyQ z^C9rh$)E%c{@|no(Lf9k3&a8OKmw2mz?lz%@`N)V1m#PkoN1IdjdG_^{xqrrjjBPX zYS061Q#I&R4LVhWPSv1OHRx0gI#q*C)rh8QL{l}kXJq@NOrMnPlX87hzE3LjN%MVD ziBDSSlNS4=r9Nr7Pb&3EWj?9gC#~^G6+WrbCsp~R8lSY$C)N6-Ext;ouafPn`%DfLy#d{s(cmC9G8@l`eYs@KtsDHO?UQqTa=uS4^vOj&dA?6B@yQE)@?xL7)F&_Z$)!HI z%qN%o8ob@s=2;uzOOpZ zS6%3LhBYMHNE?yIixRV#eeN?*0gSFQ0?H}*E4tv<{5wSb$+SKaBWw)m=T zzG{cBy4zO+O_iVyv9CtptI74%boiP(eJw?2^O3j~i4{m(hr~)Gu18`O604C|gTxI; z+=#?YNUTNTW+ZMw;#MSXLt-5g>yg-i#6~1;M`9BacOY>m5}T3Og2YxNwjr?{i5*DX zg~Z)R!ax!xlCY43jU*f-;UWnSN%%-2KoTL6CaA|xqB zk`g2-MUpZkDMykDB#|OXC6dUH1Rm4Mk)#?)YLKKBNfby@ha^fQsYenOlBkhHgCq?| z(ugEYNTNlOW+Z7rl2#;X^XLVHtleW25Vk_M*?>z_xT+8@dx91=c`RkV1`)wrpE=+=75^F6A1 zLIj`MDm=9{xGk5cDkn@$q{!}Ni``v3oY#qqs)=F_p)Do_1*A;lso;5}Ri4f^ZhQdBQfYH{b>m%)ZgW0i%p*$8WP2ShVdIKwvWn>`6ndJPh*m3M5D=m+k4Qy`YspfT z+uDkA8*#pnsAG~wjYrt#(H4365?o}$3t70WnJDKH-CbmTleetJ+t}o_mV0etLdGLn zIz5g$+|o|)3J3v%D1!KvBv(il2}w;Z+1c)4wt4JoPjRc4q4ehG;(~HKSBV!nNVdSE zgqDSPw~5HN5v{GHu8Yh!Q9swoEO>{NU{sM}16c_3Sm|N%yn=SGtivl8cxx-%T_RH5 z>gBb2E6oI3;kNQ{b|v1{itDoc?M!Z0R>s3TWF(DTd zbq$13MHcYL@;cIC@hBx8rNS$#!}Gccc$`uoC;0_rQH7`6>aA3I_2ph`4N+ZAbc#Iu z2C})9G!&5{2Fa3oS}NQ&h9|EB7g%utAGfLrQ88&O!&|vTdo@wn?tu@{(tO-jjB^=y zIRjTz64G{@UrpvUk+NK}-cG8jNtKFJOT6+j($M9pDDr5{UWVDrc6gO-UZvez-{9?N z_p+Pm+eAp>+yn=^I8*l{!uWP{d^#rSg;5HCEF~K(wr4pjN zj;Jgo>bQidlQ6@y){)#+QlKRZ>d3l6QY9o+0#a2#s>(=pKB*RyjSRAhNwzUavyikf zNr%D1;ClEi9{6BWSnjDW@Tki?%}h_T#bYe?vlj4p>ysL#^ zR}fq=!4VMLT0+oHNH|166;W73l$H@yGD2QP*kpuFL^7($Y7Hqck-2STp`I+^ktH^= zLQYoHkTMx5YbWKoq?|!2^T;MWskf0P8ENnGtrdBji~MzpT!7?qx6<5(#!2v43|5v)LkjLBD+#`MSi8>O4F6b zD@=fOrSYA4b%b(Knc_XYCr=t z095NuKPKy(U1N+<>uC3=WvqToJ;oVhkMYL%WBFrwW8yKv zSjAZ3SmRjRm~l)$W*xI#Wn5*BbzLpGT0GWrm4B6YRd7{wm3viqwO~{@q8`zVsIQie zs7D2GVdlT53z}^J* zCa`P4u7$D|%33HlgHJP*L5{S*wH2IDiUg?fesQ@ANbr~cY&1$I>Zr>RJ_y(Ktur_SdUb+ z5I?L(Ah06u>);8i5_DLXe@kjSD4mkj_&_9q6-uo~s2ftVzl*AYp9={3%JTQ-~@cskKP8 z0=paHq{jKaguVQ?g_<)MTgncSnny~fBDk+pBTV_g-UT}~dN8k)q;jDo64(oH zr7To@uuB7yij!JRl!e-pf!zf*YR}zohuWu9oK(NiR-k1n&)mSCr%ox#PDK)^3%Y5P zbF~QC2MKG4L#=YSvZ);e?NDvEQ9e|!)QTGw1axZ0^G5|xrbZv`Q<+gR{GUd`p+>+f z{6B6mVc`%9C*Z;#(ZeYUJuY%Fm`k2{&BZ8lG0L3`_zJan<7dZRj1m{4)Ws-pF$!Ib zTo*&+V&u6P`7Vao#gKfo;o0Y&fAN)9KVE<>3m+B1b`!zj07nCLFu*>fjt1C>)ZqX- zkvbk2)G1K}m!c8HNZp8Xq<%yNyIcc#HjXp}PGdN0Ay+tU;CwK`44GhlI!DZ~X00%K zEErj8j;Iqr5E$(`$V3UKsEp<>T>Q!BUpUoVry8C#!m~$s0HSoURMgWR7Cg#;r$F$W z4IZJuV+web0Z&w<@CC$)x)aJ1%_r0+R8Cf-vxMd36*zf?PF|6dSL`gSb(V|#1qBU2 zBhUnBfo7luXa(8;9iRscfDvd1Oh5j}h`Q zLOw>w#|ZftAs-{;V}yK+kdG1aF+x5@$j1oz7$F}cBWzUnAsegnW&VuMzS!LcT`G z*9iFlKm#-YjX)Ei1)6~tpcQBX zbbuZ(07jr4FaaGvCtwCFfEBO-cEAC20o{H%w;WIb75{T>eZbcCfUbK$*FT^e{BoWJ z%Fq_i`uFwkG8fwV#}?54u|vE6vA3PnpXqc8_)Y=KUtM1ZD1mxF1*icH&;T?7O@J0? z23mktpbgLgdcXh}fp)+IbO4=z8L$9Wzy{a>2has{`>Rz9fC)ehD)wmWm}0aoY7uP_ zeNptHm_@OR;ugg(N?4Q#2WrWFI6My@+i_@r=H9)B4sU^Hgqb<}GIzR|HWyPA_?`s5 z9xulwdGL%JudnoIlx}N1QBg~B6u2-S@5;k@`9zrx7syEy%VTK7l{&n@LfA`)+)^UH z)XU5z^7w?Xm{c>#M)<@jAgm0s#E1(Gcv**+3&(T`QPmtc!Aszax4#uDoZxV#m*A~` zTj2TWeG4>oUm<1XfBT5!f8Q#lEO-}0+vYYq+-9@e!t~d2>fDZ6cb5%kuyCdoXGw8* zYF$+AudT4+T=;gY9_M!YYfGwJMHZZ^@z<7$a9%mit9RQVw`PAMzXlhuUBw`6xR8en zJ6$F4O9os#kB8?A@%&0W--zcs@ceFnZ9_B3)Zvm`TvFq&g|EIOT3n*X3wU@@HC|xG z3k7«{z7kA(#1$b#OUaG{)ICz;BFEirhEWD}=uPVo-g*be6R<`0bV!Wmuug%A+ zMR=_Nuhrvq&3;93J+3t1%1*qVhu7EPsye@-vca#AHQ}0Oyg`OHXmCvh-l%rTTJdH9 z-rVI^Xasm08*i(?+l+oiGhDiH9nV$G#Pzkfk%1fX{ff?d+{A{98aK7#CM|BV!rZxX|2$2`49z{Kr!E;wzJxn{qb zUx~w$7KhfQRN`Hgcy~VDU5-Z*|pI`RimQ1e;HA;qz}E!L<@R1Hr2&cx?n9 zo^im_85tpz6S;aqR6^tz`0JYUh&%@&vJ?3YgqTf8>iuKNAAQ-b79mk%C91iEqR6i-Y$58zL~RXGUqYx@gjz{xnuw+bzp_$EXk{*41<|bV zE9>B?eThpiCRz+cYYowA^DCQROxs0%rPfO5#eSv1P8hlgV?LqR5bb3|dlzA9Bur+a zgX>qq1C;i5!rVq!T3zi%!Uh9qD$1zpl6rr=u7fP;^4A++CV4ev1vJv70L*?BljG{PyBPw%ifsf8eicUw z7|AMlLRUjpi`-0}n^opl!NVkl*v(e@RTXN#s-fyS>gFi2yOJGYiJHjqXo+0O8*x_G2X>CR)4oqW>FA}w5ZUb|l{ zXz;6re0RRouNFy3ht;pn>ms{K$!^f#rwVn6(!;FvtIHZZOr2kuU*ndPdRPVzhwUy9 zc{p8olgY2H)&M5IQVg>#uJQ;to~~+lq1KaI=*bm%a^VYYqbFDIp`^njQv21-c2Az% zldtrMTReFn9Uh6slV9wS*b(h|+VHdeewH|4KN2>8i8$Ffq7I><}9$B5Is=*`Ida8Mz8il8p=`Oc; z6t#X0_$kXh%4&Co$)mKoifn#OU8`TCQoAd=+%mqW349C<9)s3nWO~|V9#f}ZV{h}< z)^a@X9IwOf>D2jamDL_wiNB$|2x#%LO1x~nms99(sA~0cWL|;UD=PPjD!f9wS7PxN zl=>Umtllz_TV3ic>-0C6I^7zzSH{LW4BjfGzY$hkqoC5=*y?WV@YdA&8w+yXO$L8s zQJJ^4(ccIMyRy#RZ1mPQdes`QhUL|Cx!c74#%7&Y&+r-@Zll<3Z1I{j{w8=lZ8ZCv zI9z{|KmWI*NF?tk6r(twDMvunmF&I4-qsL+Nc#NKa(GxLx5=KwP=qVUI6{DwN^mHsb z3X7&;(R3_28jFs>qGPe>I4n9Ii%!6z6S3$dEIJvBPQjv6vFJ1`IvtCN!eVGx3>}M! z#$sZym{=?(4vUG$ViK^JL@Xu=i%G^}Qm~j*EG7+$NylQNuvi)vOUGiPvDg?aHWrJG z!(!vH*aR##5sOX2Vw17h6f8Csi%r8~)3LZHERKf7(XqH_EG`C%i^byNu()_EE&+>6 z#Nv{$xMVCY1&d3?;?l6VbSyp!i>G1nbSyp^i;uzLW3l)+EIuBKPr%|6vG^n`J{gNo z!QxY~_%tj&9ZQJ95@=Wg9ZQJD5@N7~SS%q9ONhr360n3sEFlR?NX8OUu!K}BAq`7N z#}cEkL>iVz#}cEl#273w7E6r7663MN1S~NTOH9HNld;4UEHM>JOv4h>v7{(0iH0T7 zv7~4$DF#c5#ggK%q+ zvE(=`IUY++z>*WO zvD6eSH5E%u!&1|+v?wf%hNaQ5v}i0X21|>@(&DhRcq}aeOH0JklCZR7EG-2~OU2UC zu(Wh6Jqk;wVd-=%JsL}o!O~-~^f)X%9!pQa(i5@tBrH7{OHaYlQ?c|kEIr-$OwhOt z_`BLu;V(fPIygpa$uCU{&pv@tn6Xxs+4ehvf!5s}dL%%E|rKyLsZ1)^y5==;CJ zeE)BKfhq8Ukj6bu33yEesK1;31eBiyo&q+0xN_W|lY_>+1ooxC1mK_YlK&~k{ZDxt zlxIKSzX$Y%50v+UKIeh*KG2_epu8V+YK)dZNB{Ks1(YAG(+=h5fPe0rK!31}TqwW! zzTzMu290|jbUH8v_@_+8@?iOezsqn5yr?!Og4nbz=fILBfpxQKfB60# zfwi)EYj{@9-aY&GXKl{j8h$wI0GJPiXN2E(PT#XHC*#0@t@}1X8~^n87U+{6D1Qig z!~|kqq`4e96A2kzO7ph?%NM%LU?voPS%0&z>satJpS6YJ^NmHHGEO{k|m#Q z$=oMj^V$4=OA;*8wO|JE%@-YE7#(m5tdy_Proy1`fvN+IG;vrBx|)Pg997(g>2wG zee9K`+f*^lgB|bmvghcluas;lpZo5HXOoL2DypV`_14jES=YW8JN}Mr(o^lOkR8n* zZ62t|e7+3-WO`6|;@mZUCsT91<7Vo+hLB~(7iTm+_fFsH6-6KH)QB6TC)Q0#s{caQ z`Pr(4O(Vz0?p(YzH)hq=e{JklueMD&*LrfldF6eYk!5cHzOy zlOI&AJG}6@?BKy0s*$ULoSdIdVYenMy*}&ev)`vrd%P?6>x8)x%0J(p_GZWXgTdK< z?XKGN)|z){SAr+y{=4IyDdqZ2+tau+Sfbe~Mfb1!CO0n(v+Rs-8Gm`&+?CQzC-$wi zpiS>DTF{poQabI#g@@;^yA#`Io08*NGDoW&KjGmS&CkCuviMN$JDaDk6~^p&=(^qZ z{*>D%cTY5h2pfLTUp#-h=-+eAmzE#9Ip=ZfI`OinhOXXvt2k)S?>|m|?98=K#|<}p zerM0*u@C-OIOX!hZQf{`<~Q5hhDh-y_1xeq@H^yxtS;?UirJ2-~M}s!6%eOpyHRJo2ZmlW}>b?`^Nvl8I|HexD2Oo`n ztKM1|8orC2Jv#L1mKG-3PXlBT8CZTV{L2OsR4RIa}@yKlR8fH`~owWCw+d>SH- zn6A3uY0=F9_fI&}njqJFk8YmU!fss5uPZ_-sq~oGTsE zIlnEsds`>9#XOs_VtVthA&I}d9;=FNDrBC%q(5KK}f^2=#=YPTRko z@mpn=>YYT}SG>8GKYpy-J>}-qR@ThO8>zuTey;qy1&^D*|6L>R*s zTyn25uRFUW=>5v>L*XBXvJcHk*>v>f&HI~L?|s6U7F_K(GqCN>3vzRio_;QR-K;M& zbCOn{v>)H}^iSftkFSNE@5tSLHS5o_#L}-vRv!N{_*(AaeLa&GYp*PRRP27~-Ymv& z(MON$za?nS+xhC8?yb|dr6#|5G2+h9+NJMTEWhUqR@Oe8ydp_pSyyVi9Yoj8_7V^6 zxN;#eC`)6p+&)=qgK7G=>y0Cl8R%p(q#uw=?_J%A!m-S0#U+aY6-5;!ar+xC=mtVQr zvuZ^2isr|o`(G=VIHR}s$M~_MPoCxebovB++0rRjlfB(PpJ-^@W1U#tx$Vqcm&|(p zh5j|qJXgB+i$$wzXRzKZ-7DPJ7-s(Vxvl;K#wqfHg0RV)gTLf0e)S2G&z(2@liJVr z#T9OR>bZ)?Zq&rjyyl)+_R+7)W)5@GAN7B^XzJU(*R^e@#-X72M+fqx&j!8z?Q3ao z*KhA57Yw(*E*YHpnEt%{vUl~!yv}dGuG!ZxHDTdXZ>8P5dUWQZFS2Hy;03K8X$-D& zZH$zpM@^Q*eHwObicQ0uZM3R(-5weFWMSyy#?l*=u87U=3MDPq-?|Yr{ouc^|B^6C z?wRy>qRlfN0)O*3|!-sU&F7L~EY1+}e?^5n*-o0CR+i>KLqbpe4^5@`RugyL& z`$p%7^S5Nq9?8v2rbp|>Pxo&OHJLhKbFyXP6YIw}uP44OIQc?|^5Mjd(;xX6{^zuKGr{J``_>?_Yj^n~2IymEW~F5A;nYVRIDa^U56&n@_3 zqR-lw1Jq_zB!^yQWrPchGxJag$vZO_65XJgK@rX21&@?O8Cd;6Y= zIVsPy#Lv6?>5Jd0O3u$)zc;sk#k#vQPXFXM{_eMzzdUwZ@!G4+zfGBNb8)ZdrLKEl zo2%%59{pwB{;i%?CJ7+rhBhh!pT24D}2f`*VfRjf2{vjIB{qFFQJTNaz;wTnJul$ckjLF zEehVYb7Wz{(@#G(J$QN8^pv@?zkjCX#-jSAyFw1^{w$>Gi)m|Du5;_FkIfiEPqt|B_s~;@68$Oy_?)J>2%pS_|EhdFAf@ zoDfxM-nJLAo;~6FYRRn=H$Iy)=ex^ug;rLdEoSpa53MVkK4ZqUw;tadtNP>TcIWu! z??Tq!&OAC&C3v~yM}B$t?hyL>DrkUG+cPCHP zJoUtrvdHg#jW-@!{RcZX=*qVf8w!)7#Ouw^cNQo9d*+n4o(iAzQ2wjv?#*A5GrFfv ze&q?qtFonA$F7wwjyHyj#1$PU?VZLYUrQW+kqE6+f%QD7Z4Ykc) zg{&owuiRz*Bn=C_7xY4gQFhXL@U(a!{Ob)i+ALvM zeDUg@SLg8;vbG1yiZ;w%*3DQ%Y^iwlwTmOO-aP1jGx~hAE{d4!q7Lq-?ammlDCy&1VFe=AXxi|W!S${vdHjd363upI$4ddLMsi4U?FYJ#p$gq7UC5oA%wD{)Wo$r{^jgRdt^!TaSF9 zSA{$0PicI#v2N$a!Q%_dO?8!V)pOq)2xketyjni5`InWUMPJM~tYP#$w(awyZ$Eo# zHqrcqf-$tefD(Ft(2l4PCk0;{MkiMO*;NU+sqSHle#X(fArKI zhvL(-^Yf&=t6&p!8h z_U(?})S}QgTRVzJF0$rkKO4ERl>18XL0#^=pTesDY))wS>*fL75HQt9e(B0{_FKDM7oQtDckqOV8N$n}KjoWV(|#o~T`1R7&Dphg)uaEuHsks9n~x}_ z^K{dNw@2le@%nqaMDi6!t8a%KSpDOs8A4yyMc|`f@xf>cjVRg@+Fm!5XcP}p_ zd4}8a){gVDUYT4YxVL0*(vB%Pkw=#uTeN9L#aKll+dXmKf@eyiPjOC}6gTI} zjE)s4k+nx83E#ATQ(w6J+LYY3T@Bk7e)-|1XEGG5rgQV^y8mtYo=Xp1(Y~TxX4^A! zr8F-?I3R9XT2TM9bMyMC6Vc@`g=XaD+0l*{-eJ8SlqOs7iEQ7(FM@y0y{3P7V%Q^Z z&YAJ%9qwOG|N8RGkFqXLy;!?^%B2m}=j!h+p87do8?<74@ai?aTdpnnn6TWP&>Z&Z z_OSz#6|-k9*3JF>w>@h^zgqpq^P>!13-+(K7B9XX931oR(@o+SGW5v{A%-u$e`nUo zr$4><>V|pRoTny7(1oL+^7?$y*6B0t>z>!0NR ztk}7pGkO00pHE0pgbL&HbrAtO;K@^?;(d{M7lX{vRa||2TQYyr9(&S+M%o zGrpW{eAM%0>$#beV^4Q_2Unb*_VK`tdq37q9W5B#_{`)9OG9*H&qja53i^s%CEf9s zHe;3X`Ny~~>k zhrH1^bZYsbiL=HW<7%_tNWYrR|7O>4p)#~B^TOMX#~yt%x5oAFZ#C}(>z6o>oq6hs zhLn2=#A3B!)=w{aeow4RT$6RLcN7%pdxA_O16G<0dhWnYP}$SLkWbO}mql5I=tW=98WD=&QURo(s8IbNk2fJK~nC z=X_sSA39-6edv!gK!i#bT1bWy7)qWg%+||Ga$hmva2m z(S*$xc#b*Rv9m{>Ee!2(rGsauuMOSv;-|?O7c0-?@@NfDOqoA_M%&7rJ605q zH7$K-*@3y9_M^966|AWrYZYX^Hg3ZV{)UW*d)eQ3TR+HIbzXXWN`2{$r?<9lYINtn z5q9k3#q-#yKP>I+GFsW6*0yHoZq103=fdx5{QOefS40=N{>~JC#$nc!IS#i_cBTBa zpKs3laOI-d#^Yz%ineRl=)a0)hN{;768@K>io9ib`^4QnQ=8_5+%?i>Ew@BS_R31u z2Yp-G@zo8}Cn?vwHBKEY#8*3a4gi0Fr@!}=NHo4@EhnKkE&)fb=W z3Yy>Xq3mcmrkK1qs?(_H4P$;1`esIR=Zet}ZvT2>-tJJ@Td9vTpFMS@<@%lCSYko& z3(Z5X${t<1{>_-Ry!lIa&$0`@ITu>}=k=VggCAv`{V{Zl!nG%O#$Uz-SxND-m&L&Y zvcWG+>$mV8KNySk^h}#Q$u%juaH@A;u;7_aEn76>x8NhE zXn4VbUw*K?q1=9b{nxW!eDtHvWpfsZdWTH&R@I&t=`6@!d%uOF4&IJ-(U8d8^f z^o==v<3_|iEvd{WBImL$zL+z8Bznqg1MB3KL*X;})C(3IP5-%JtEPE*=%E!;j@K`# z6)$xh*rPgjSg_VPH*-}f@hUBILtf|aJ&%Q$W^}5XzCV}Wv3&2MvVmQbPEJ`@-xM-s z+JfM)*ZrQ5>9zB&d2deoCY3!lHT(9OQH2D z{-mMq!Pb(XYgd~ymFtqny*b@{Z_XF|u$iuBeWq*UFVu!?lIm%Rp{=Ibg2K1^_O3Wc zv@8_=7UX=tL~Uwug|*rCzB%#u^RqmMQ@AJBc|W_gIsfsc<+f1%-PlKV9_9CnO;0_R zd2Ms>rzh->1xZu~-GalHv$qb+S{QqFms-{Ni+89<>z|V}ZQe-8*fgYyf$Bd zA$aT1Lm8P{l=r3?^};va`F!@f-^f<1n(d`uix6LWY_xaUq~mXXy5AKpF@%pCdUWc` zA)miAnZ6Pj)wFf1Ni? z8}h)jRZ0!|pYqiIDN|pOJ@8saJt}|TC7>P~Kk(W)n zzZlo!kA6)(y8ruCJHlNT^ML=EmD_W^q8^j~{aRZ1f9$<=bQIa!u3b$-1dS6RB)A5G zL$Kfu!3R%(0D%}0T!J(BFfhOXgUtYgyAE!_Z3YbxtZ)eKpk^bJq9I zS*OX}*Hd?Gt6kF7)wPSzJ3o9&A3SOE0N=Ilwz*o!vs)MLcz;Vj{huawr_;XnZ_=BF zH;-fp_?q5-)BMW=YYmW}F^t!YX&DL^FFNsS`t4<{rMJFXZCf9~_bj8o-06GSwm!xO zj&SiSd9RQy{fZ%ZF6tjrOR4lpe_wqtX@+WVQY>?%wDTooVyt zZEAgtSsgm>Xx+TGmzwJ@SidyDI^@#Bxo6DvcYo@*Vk4Uzi3_V~roR;*vE`Qkz|-$t zjPyxY&RDzqM6|87EvJ!w+W4*`bFW|IQS|&NV|{EY`Y~@0--h#EjT>pKzp&TaSMK?} zbIvju;m)HRzbbu+BbOyQu0- zEbCt_n$vyQq3k}+!E5VJU0CB<-^_bIU+Z@+%-!j#_eO{5t+Hne96Hmj-VX1F$!Rfl zuD&YlP%ZjeWaK8N{2w15_i!m)X2Qv%ZsW(@bbC_i{;+w!eA)9j_>))f2VUM~^EW@8 zCwKbWpO;q+xm7B}sYX(qZ7w6K2dm;3MBdEk1zfsfZr3+pj1BF=SB_a_yjpUhfz<<F|hS(!Z1rB|K(eOGiDa$#(hBiAnMD3Npj zh0@t)_V<~zJWHjSlOjIks&x29;ax?4YTIC0t!r;b$rePc!~bT)f0% z#~;_G9yxbzcGu0@8@NtvoNLCohui-;Fls?3XSeK+FRXPQSS0-Z%1zzvH@nYqUUtIA z<6``K{4uThvrpb-*X-(|}&H9Faim|dZ3?Tqh! zb$2fv>N)*Yy+y+g4Qicfi=~6NUzKK8-<`-Gvoo^w0q2_ooC;;h=Tbp?+VJ6#qGj87 z&2mdSx$;8oq(86S8CY)L${T-qZ3!)AS1j$v%q1iD{ct>shtr*kTaJ{AEPgWR$nz4r zr}((}9$8YU*0}yjj+NHzh>FYWb!S^v2e*issf~`bE8>`=kKdG+_G4Csb&8yt>(ch{ z2a8?f(i$wyxg(+8#(Yf+?^!a@b82MD)cNxBoDs>&8o66W{pOY>>TJP_=}u^L%5E zbaLF`GX3h=&B;xg-?bKKTxs*fUOD@>sCzqT(I3}qmsl`v@tT^x6JBOHb#Qc{ERTj9 zm{DML1DB|@DV8_k&rcTU`09PMXNt%8RWC-w?}@5WGQRJ&3AumH_0P%*rIydSGye0v zx*I)SUUfe9%b2Ruclkd0w8%3wX#Gl)2Dl7d~niIb(eF~Q75Vf`^^0~b@6)tJas*e zJDpol(7}1+hca2N_xkhV)z32y*9&aup6|Uj#r?p~CtFkv+Scx`dEQ&*?j7)?-H^R4 zd*pZB_Ii=ilKp8Hdd1FNcYpYkoCV{Lxix;dD(k4m`%`Y+xIh0{j?Z2>JRjdX8}t6? zlZos1zb;bE$u;-Au*1juS9$QXQJM=Kn7dfE^1GbZM(dCE77lpyu%m0@v{A(`w9lMc@Oj+3KMIuf{5j$GtrMST zogKS+YQG#MYvfKzKHTE1heMYhC%jff?7HvbI(R^#&AE=f8D4#%+rh_+b6%X&rthsK zLtb@hmhAO<*+k!h{ujnZ=_lXKE#({dzJ7m~z~vL~JA_)^W*C-#NChAFoK>c;$(v={ zzD=X%2Xx5P^-8XApVhDJT;GSpjr{aOt)UJs)w_CbOm17@ZuTXWOU{@#!Q=Fx>o;}; zjQQ={#LShq*9yqBFYBY@Gpe{Q={8G0*s|d~=jW&Ie%YRd3*J@zx7_b&^>|uq!La4o zPpz5Qc=_$TWk>rYPRQ4+$kE^?7fUucHFIHUXP2nQi{n2|^FKNGYK@)shr72KzieVi z(B@uy+qZCe=zYVx{O0;?<7)Sw^Skn46$zPRO|8@Bw# zhhTj{%Kv)vEq^ao+uBw-2o86tJp?Q`s7me$ICA)}xdJ@68q4Cb^Ah9`nvA z@oGUgm#|xQQ477EPp>n#Xpsi98?PMFB!BIUPOIN~)J%-;u-os#)zE;}ncQY?o;STk z$cxp>j=O9hu)@wO{Z_3CJ?})%`Ds|&dmgRp``w6|Fmi9xyXoF*e+em3ZnA4z$ABfV zi?8pw+5WFP14qVsu5R@1c-BT2O8(mSQ76wOlX5pMIXL~^)4QFtLK}mg-OcIh_px32 zqTXE+_oj7m>~rH<&U*s`hc~RVb$Z(4t;g%M{l_=3@vx~)CvNEA@v6mwiEaLHsdA%J znY<+yyzp6HXk3X^O><^xTW;@)_jR9jo&UUWP}{t|J=^5jmbv4ke>!ED)oygZaxRut zMS5h5f7bBz{!cLl{@(9l$+>CInPw~JZ+Q9fc!?k5bA?Vh)Bl$9#Kp}946VMaT(a}~ z^#|QMTnL!h?LxhnhLqdsLRyYcP$WS`6{Ek*jD-g$87IPJ`!(Vd)6 zy4QT!>cGQto&MBD&$+wFJ$SB5V9|u|QJcJ8~rSq@7{LY1p_J7u;l|US{2+Dd>pv&Y2URmFZyo`Y~fbNYuupO^?Ns+o8?*S)W3SP z`^9fY<1SGdoNM&lTrO+*)VI4_cld2}sMXqeU*1|%Yh6lQ?YaEkont?*Xx;abYkaGw z=P%_x>U6sEyb1pljDLLOmDA{Yt{?v%*{{}<329UBy)We+?&TRYAz!N*%U3^+4;wJ7 z{cgY9-OK;7spF52=k=J>%p4zbG#Q2<_Hx<3I@RvO0icKBS z^@|oiN__ar+H@Jw|q&I;`Q4ts$!) z=3n+aclKOA&G(wRW_4VPRWAJ<+MXZp{3c^+Y43J9dbYhd<5+QrNA6|pX733tc|JHG zThQkU$HIM5t$X^<`#h?CmHM^6bp6fG`O?8PGp(P0Z{Mi>Kf6AT>FJ)mpZDO}RhpK% zzOLcwK|S|*AN?`y#EQFTu1{Fgbk(ZVZBCU}6;E>a8}my*`>q!+dfszuc(Fq2l^z8@ zZA%L}neB$Z_Y^(viTc{?`SBNOFYGn3l~d`3#nRhrUq(A+ZIfJcO@v#u@o#qbO{%)o zZEBxE=eR|9gdivd>(z?Hl42ljDb? zI~*sEsc3oR8S;GY<%X_LHx+K2wsh>i0)FTES(3A#aO*p#WShdTX7_g;`?qC~OM1JL z!*}*6U21r1&*cq9dR`p1Zf}`h7wsO?`FIA`iAM`$@x1-x zDerPsvy>lpAm`J{&$3^0J;;%cVxt!B)4LY=J zLqN)*_lJWYl+8JI;oQqxn)_91Sz+6|Y56kvwyJHZ@AC6T>x{hdbA#ICafz5|xpJZZ z!i<$3HLH1a<)0o0K8%=lVrFt3d!4(RJzC}3QKk8n1)b(kJQ#DTa=9s+obOM(d&YkA z=rx>O_oONokp?^J{am#5@k+S#8 z+TT7M*Kb~*qCr0HnakG5o8joyQ8{LevfJ#?)qCvTUac2(irDaD6_@;d>kM^TmbQO| z<7TVhs^cC}Cx4mec6L>~d*j6i3(gwWF*)h4176m~y(Y)p4H}U9bfuwZT6;TLyX=oW z{#yeNz2^9NwIBJr9enem@i4oTxeHpZIN)Beh*!T&B~yJJ&W{{-e@5B4G4Xy!&-ku# zxqD!JE9Yz4z5>f#Kh-YKw(a$@*Z*woR-;tO>7JE;d0PC5`~KE$ecJu>dB>LAcYWQf zY-%!R^W$3=2VE~)+O>1IccVOu(r+!hI@!x(|CgLwzNF5N_;JtGpISU$FgNatZ>a^V zGThqSw#eM`Z)z>F-{bP-aNAMsm#ls{V*INaKOT+FxocZM{!&@z#4cV@>cgYK4SoCl zJa5Zy%esvHBXgG_@spdnwAxmy``Dk}-fMcYUxzb+w>%=2w)%W8@%5s`Nv+~C?)o*C z<$kL#>mn-s5q>7&NZu`}&KdGPtm=DkT=wA^TMS%z`v;GaE4ok4zq!b{-^MI$`%A88 zK0iI|e5t&1`&y%1liytHo9JBrkA71|&kS_y?l~x-^{I32qnf&HxVxi@*U;Z)pM5x@ zo{!7=##2wfI#e=yxAgs`*JpKZbImW_8n<=l*~)w3hhJ;vzUuFL%|V0FMpL_iVW3?k=uP<~PI%#pS%dXzPUR}0#Kw*!g?dFx7 z*zdIGqNHph~j{&W$e%+_#8`b8wW?lsfmfkhbt*h&>gva?Fk6F@X&Dvp) z56lVjod46k;yrs#dON4XZ}-XuH^`k~r_+#yd$$G!zu)haC;5rXfd_7Llh=hen6~w0 zt0F;v<}8!{%DxY|_H;=2BXGsW@jv@6Y*To9uDG__d-d$xFt*$fm->-$_m=QWRZYvA zjwfpR>}KP|vlsn5qD;bY*IT(}cR!moHaxxdr@)2FOE%8tvU^u1rxVqxx2aq; zd3xmq(>zK9*t-qSe!AF%#)JB2K2kPU)ghxJb3}x7xDc~yLXS@iog2^nqh8Acm0ld5 z*ft=kvZIGzhN)hK%O*eF9lg3@=!A(rEyLdDnB!lyb%pTAd_&4ta9+OsZOc8qCKVks ztX^@SjAPtgmcK6iY-GvAf}PvF%~MDB&hq1&f&Z+p>UinOte|p_PCGSylzy>c?#WrE zoUQs}2HonOS5KdOEj)J0^E#7@jk;0W`=4if2CS%V_kK&GiXYc!>Em?l(KC;kr|WI~ zy|dk*-%gEj+oiAUIOu@a-6n6wdDgAD%&UCtqk+Y}1J|a#Z*{uQj}A_?8uysJ)&J9# z$cjY|9A25(t<{a;!|oQ|={)}MtN3kgvUwG~=yyH$%OV~{-#wq!V^xUXApLy9mlduw z@vc0}dvBlVu3o9*ebWww+)Q<>nrEF|e@{QpNBJY){_fST@uVUhlV{|1edaQ2iMRc_ zt!v-Tsq{IQ>!lSJhcv$FFz=7KiQ4!ocXCddnQh(zuPoN78GhDQG`i+HaOn7b)-*kA z&dmDwD9Pir?T|N1J|bRrTi0 zhtC%zKN|D$g!ACVRaQ)D_iOmmBRhKZ3=H=0K7Rb~XV0|s2LmI5M^riElh!%?&g+?> z)k{CFk$k2=SLapbt9OpyS@CqWo-IDqUc1A+ZN}5(LLSfGK}#T;h+wDD!vvEDs?y_hiS z-2k8PFF_%fKL6~bjmXyG_wsGKe%aNad(+R`+=6dT>(M0RlMh1!I(}YM<(^maB=695 zdH?<^dS1I~cgF-eeJGh{K*wT^krS+GlRGb~;`VNEkzdO6%VHmuF|t(ovyHsoT-i8y zZ_88l$7edSYt*6N{I2v0Y4XFXq=3Y3^V-B!KH%y!>i5v-Qa1;*7*gwT)6APZ14{&U z9heaA9~KuEHc)QR4G)X<59MC!k5<3Id^a&Iw@pOjge=cxZWPwwdrjcfvEgzza$>iH`0&11-NK{7V#A{o zqY}9npJZ_nVbKY;glaM&F_t@-)r6VZHkDX0BDzNaY8uv5yFq=nd+k$+Z=&q7FzO}Y zZFJ1jNoxkH*f9>_U(>$|+~RD!`^)|BF+Kd_!lHYAO~4wIyUmST&i!L! z*n+rKIw3A5(zub_++YfKObp}|AShM0hia>F(ET66n-nCcB%V~jR) z$GdGABrW%_8!1&2BclELCdMR$$M=Yg2}|(*zO)`P@FU#6a8Jg7u;ECL6)P!QQIW`) zXzs9PB#5jv?){F7=@~{!%IXz9z~AhUgt)MXNSWU)CW;&XzfRfqiulCnuk8wt?k@fG zE%U!`I}abwEj*kXu>ENwg@$w2eN1FxRJ1?ak!{l*Ki1s;eu56NeaY?qg^L^MgSb=O z%n{_jiTP}z+76X&Kg`VZquZ`(pQhWm1zvVS$@jIDqI*}``9_GIBmW7dh$2R?uY1vn8)BInf|7Cs_rez$5 zZGH}>WsHbz+Kp-1*Pwle&XZrj468<$m@n6&Z{x#kIU(*BrH9hcO(=y&be*8%P z|M?|bWd_a4_>W9%YxZo9j{mANGuuyA#mK%>QZr|D8JjU!MPI56DlF{*2TM zW)xhg7ON#`)Bd%V7i#OYz1kTqRZIKVoc~!J|EKx?XSMv_nre}g_qqX5yV4&!JysS%Pcyv=f9b3jkg_Dk~#_PjT^Rvaq^SHKiFeef@BNya~Y`%>BbVnZl z@^doniM;;hdo%5Wa{bHqWm?9{`Jq$JPMZ99I~mEix*mK+o8#Jga^4vyAL5*!aK`DM zV2t$iZ%{kPziUK7d~8@Z8NFp2OK?PPpLon=}+ zJNO7NUN*{vzm}BRqIJtwT^cv2*`;QUT8&z@s8Oqq;e4H9$XH@*Y)qUCyz9zq$xZs%D+1w@G`bl z&b?@}oO$E4ZdEs+;;|{_cs=PSY4c;Izx7l9I5{Uu=oQZ3zaBk|frQ<|62eHQO?5Vw zTYemV!T47hvnK1V2>f^c{=N80p-KoQpR`}{Nqrre=EO51VW81MV@zRecwAHj11lMa z$4O~Kcz4ap64@)xGFeerTyM+LSiNfOqN?MBvvtfyvUfCSV<5OZIW&@qY=%0B**t_TC4SuM7O zl2RD&8Qned>&bgWbS$Uz@}%sjaK72uPXA;JNQj_rIpa6CkU`;bG0`z!+hy!P@!{cp z{8?jc*+j;`Q>jDFzr*Mx^Ay*pH6bR(KQfH})_@fdlNiUo*EKPIVE6z=VYFLCDh+r;Q@9A$dO#4+5m zyJ1ynIwmg%`Bj?TW3Ef#H-f2x3U&D+c z%tmIu&oDARim%+#dFFN<7oLz97tLaEvA}G8|6c47aZh(_!8Fg++Ih5+c~HB3aMze3Kg(!*?fYh=}70S#-~Y zUfO8NEA(Cd(&U$8^SAsBVp>XeTW${Tw!8<)n~$_RIfhFa(r=R2)|OIStjPb}^a{Rc zm1CNx)kk#eBTJs(AC$R-cANZiJUh>_5dTsOF|1~|F zX*r(S<|i>NV}WhcGntk#?6&F2|C*kw(sv7smLre)n%OU$<4IVzzKI-$WbktMfHO0= z#fEa)xH%c^m2E_}hh$$TqkrZSm;P@00tBC4e8$NUk*fd+ zX6c&Nm;RCE&d7kEq@PRBPb|XMee~I$UFOd39~Mbpn7akv?2V?!`9Ff}wn$R_h}wrh7yWE>W<<7+aKoub7xV=J@O|)9GXEe8#y+D0$10x1Nvr z`9F^ET^rkvXothY1M7r7-LV5MaM)3Bu4j_k93;!pQUJ868U7m+RQOk zwvnDJQy>J!%XYk%J~m&{ljh4`)9(8R_DL|XKuBP6SrDlPuyCV=WX8`oVL~Hw5|2GCsQ;v&)U9ozNN2Wp0iPt^1{2<;FPUF zbnEzV37ApCcA}=rsm-oi(>PBH;WVv=d45*MI6afpwQc8N4dTDWUrkcfk#n#XoN_ed z6s#_v_~sedx2Q3vQ7z>xN>wOx>Kms}4b1b7266_a;@X@xwUX1OW{C-H<-EE*CrvHQ zGr77Php4cnI#Fsa=SX$bDUuZ0Dki3}oFKJOCrI4hGO*6q^CL+iPHlB|R7=i|!sBZj zr$_PRZNm9bW6t~HRZ}E`?6o!2*-&FnhNKEkg&N57Ld+AO*5AI8wElYavQA77+TW~4 z6XUF>L3D^Z>1ie>J*~e#-I1;5+x}LOji`dFlkr@R!uaKpoEyk_PnS63Sjkg0G_BWM zXH9M>wWXEM4f#x#mu$bHN|g2OJI2@Va(v`;=h+tK7nIq2=Hw-^AI1!(J-11RIV&@ zmM`Z??55v+x;o5r)+&;}2Wvc1K75Qqj71IdkLz!IY|0zCxfpBWj$ za^yQ)ZX~|kpe&NS{z{TJ50Z5t`SPIxh*K)#TtNC)d^w*HaoT2_dlZLqbduwlNc<8= zK7YlR;?=-25Tr8Ap=8{IPmCN;UX@guB zmuunT4}wEgJPe8?jhs7+B+Y0zM)_l*Nc?e7BcQNJ-;6v_554T|J@(ob*~lJa*$ zk@$O{Nc_D}B>q0QU-<{1Nc@BFkn#^hk@!cTNXkiu>B^TKF%z=j+d+FIZFYbnc{#$& zNZOnQisY3Qis%k48x+YaJIsNk94F|Fq+TD`5Xq|%?4tZo7=fe>y`f0z>H{N{9|dEO zyken9%IpjOQT_#(qWo)6BxPQQB5BVJcn3+|yHH2+x(Dwo{{a+9`iJm|@}I(INM331 zJ)#@6570>(%*z>yq8Q4iBy%knMvd;$bCKA6g6!E83;Y}odRTzx;(`xWmABo=pHb(quO?VTD-xP)* z{A@RGzB*dRKf;W-)BjG5-pEicKNh+QSr>Xd7xLn06;5rp= zfFl01Exc`4@n29Rk>ouEMf_;RTm_1xu4*t?`88lo<=2DtRon|>55r^?AA=`Ud=iQz{TV2dHe7@viFNow#V_GIB%ginp-8rq z4^Sk&?F)~TY2k~H6-hZ6p-B8pFst&jLnjrxz``mn3M;9&3KU7+s!$|lR)fLHuK{Z- zzb>q={D!cJid(}rD*gesM^a8FD3Ul7hN-wK?1rS?9xz7v{h>(G4}imvEcS^4T(063aHEPh!|f{m3yP$iUGSjt55r^?AA`qLd;*?ClKvlfLHXC< zbrq+=n<~BqZzD;s!)MBW4qvKRW?GP>$-rAyB+H&1I;q$N2C29*tb+K{s`3_$Bz+B7 z8}X;r<*hyvzaea_;wDhUpVpMOW=PVsf?+D|3cDfxv>v<-N0Md)6!E8xLZ z#lOP!D&7cps(2R^N&3C;u!@gC5r5ig-p(RPa}NHE_|q=%CX)CPZ#R&n(cv={zksh) zY++*wM3SZy6fsLH4a+FMEDTb9btsa3Eg05ClD8ggiX?9{*g^Rt;7ApZh9XHn7EVy{ zB)CMye?XC>Sq9gscs&$J`5WLybu-osENbsd2xlz$3dQL$Wn zFODRA01QNuz7!ORUm8|Wenlt}zY+{meq~ri`Bh;xr}h}ZdUO&xLd`0p-9Tv z4-ct08D3EFCFsNtfs#g^0O77;PuO0?onRLv%Nq)ZC_f2KRq-@92gx?P5WZIaJNQ|} z#*c~oz$a-ea5xtarQRec;!hjF+pkFcxo{pb%7pKfFF(RMBcsjG4N2SFp-6l`SW3mE zVHqT8%EI!>4~ETE+yb^l#xlZ4ilhx&;V$LxhKH1Y z7>cBvBQRO{N8x$p{|&Dw|0)#8F*XH?r2K18B;};S2g*-_?~(MI=E?UUBykp)O+=hs zJj5j}Ee8~d?*zS&l&BB598o^j5wP6p5c3wpM-{C=$Od6iGQhz|P7K zg(68421SylD-?;}4R%+4IE++&6pT}TJRG9@;ZP)bli-g?%A5x0sCXeSg?6q5Av zqkt7joDr5mlD8}riC+$i#4itnlwTQ&#IFKHlD;aeq5PUqBz`T}SotBaw~G6~cqC~O z;4tMU!4b+I2^T4UG5kaMOW`u*FNc3Be+3jt+g8HW%3lNTDqn{psrMcfN&5Tnf$|^1 z$I5>KMUwt06iNDL@VW9|z?aJZ1dH)wi=-(I%OJ^H7M4?fd00XDm0<(rH-Y0-JPqzp z@h*5o#b@9-BxRn5BB|?dn5z7nP$d2>cwhMs;A7=Kfg)qM;7jGdf+F!>!?((R2j46I z0~AU5a#Q0TB=KIDjwG-A*yPTSOyYY&UlseqIx4OYo2WPhwpDRED3ZJ#ph)6QP$Y2| zI8?<+aFdF+z`s%?_cvZ#M;0+{c zQsHCeKY`Db{{p^J{u}s7#h>99WE_9|IkqD{7PTxe8=?_zI?#fFeH5wUSUI*Z%`yStOrXglv4@vrk@HCQT zKLgW{v2Ew!ya!483{WKLt!P1$~vD8|G7f zekhXk1)xaEDF{X47lI=33qz6kMW9IhqA)=DC7?)_w-5!Te_WVAxQ_p>Ujv$HTcuwvBo40g}8A;mU$$-c?W}{%V+B$n@nug-J)^ zYeo26D`xur;7k?Ig6S&Oit}3)lJs}sLnM9s2tHN*Gx!|I_Vxn4RQ`LIjwHPnzG-J zWP>-jgd!=Y6fCFw^00#PE5a(uuL`RxzXtq8`E%f} zNXnlJ=OHO`K3sr|eufK`zX*O%{zoX1^q*k5@-vm9ok;SQf>TsH4en9#UU(Zx-ZYr2 zw3*%)=0@WC!)D44fnAgz3I{8H2pp#T;c%Vu*TX%^-wTf`{{%d({4=m$8MEI0a1fGu z2g7U1zYcFGKNWsaemWFMdbu%fPZP78y)Ydaep8OuznlIvco>O)24-Dq`q^L(B)$_Y zru<+St>PFMhh!baLy@FUfJ2o(3=UU*5}c2u|9^uEkmOwmpD8~LK3Dz=_*VJaGVZNG zQhr`I4oNxVp-B86;W6c(foD~G9*QLWKk%}OUqH)p)6W1!(jF_!q$euVD#w$Mo_D7O82_8`XL3jvB zIj7)d<)^~u%6|dBC_f#FB)#0UQvgZ51z`XZzXYs{9Et0}=1BY&uqARN?gEFXI0=qK zl4ca#p!|(cB>pD2S@~PwcIEGYJC*+z+@<{8@TBrj!^OqJOCU*85(X;26fCX$GO(=j%fa%>4~8|BUki$)oZ7IF@*6{u_)VZl>J5SIRNN5` zR`C!hlJrC2TIH{UBJtNlk(9FmZc_ecxJCI};Wp)Ohr5)&8}3p5UMP}s_Cb-9zaNUk zzX~6z_%VEfB+XO!TKR9FNPNpm_5~z)9btAAJ3|i@`@@1NE(}YkI1omtxHs&BWP6T< zca(n@iliTA62ZSa^2&DnI;xq zRRO!*Ss(|)nGFu%N_zxDgQJS ziJt~PDgQG}SHAowkU5al>jb@!r1ys@bJ&ouC(z^HOgplJq{%A4y$#U=Wh^UKs`}zXoit z{0=Z&`90unqaii%U=O(e^83*JG}hPzN#{(bmV`S0Op71Kj} z|FanF%mxdpxG)S-aTQoq#noXG6^Fo1Do%nQRIFJn6l<1gfg)*71}Ks~v4>?;%!Amq z>M9O~laQpJ45ui68l0#6g-|4E&cIJd%KQvPvOOndAUzU)Av~kvR49@(H{nMl>rt~> zw0ua?2f&6Z4uOd(?gs}UqkK4D`3v9y6(_@gRIFtr4KmsQ|5WihcwWVq;71k9f4o`< zN%}z8O~o;Akcx-E2`Zihr>l4doT=hjaFL3a!1XHL2)C=}Z*SHc3|p%> z6!uhc5*(xAad4fAH^3b#mj8$~x1+^4rujjUtRsIY|2eB1>nzZUqz^Mfk@%UQo$~Er z7UgG!Ih5}ND=5Dr3{rk&SWWrWp-9RPhIf>I7wXEt2P#YQcq5PF_6_RpR!%xcp4AYe_ zgU3rEqkLEg$*V35L6WyQY^VJ8a0HU{BjFe%X~x2IsD>nOdEyGnuL!Fm@vA|Rq^}Nxm0tsj#7}}_l|LSe zB<}<`S;bS~d=)Q%f2w#LysqLKP$Xrh!duF}4Ie5$4Zc^tJoLbVBz*>GMN)4jm{r9& zpp%MSVPO>)g@GzA4a=yw9IT|`%CHKO@~gt?$`6Jj@oT`^%C86OtGE$tqT&!JlD4&l zB8fY}ZYu5pBaxID3lmf<|B-hEBPXTA!y3x332Q6A4iriHx=%k7n?*v7X zrZW^tnl3O*`AKktiZ{Y-NYZSFBFVc0ip1XucPoDn+^hV3P$cR1!vo4c2#+ZL47{x3 zBpzI`9!dHQa5Iwfx51st{|oL?{%$Ce^n2i5SN%}&tnDPT*UFFMz zLrNe?QxaA{Qf5Uc62B4*QhsG95`Q6lq2hFC#{)>jcND5PD|A({JM>VoCoHGp3b3Mz zE5j;C+E5jWq|9niBz|>RQ~9-^Nc`HcuJS`*I~6a4%T&Aqo>%eT@FJ4DSKw6@r@$LX z>P>|rNpln4QNAV*S3#1-0_~8bv4;-IcZ8Xhp9Pjyei>L%`ITUh@+-q?%C8RVD!(2S zN%rZ&MfnO z&J8Q6xH7D!;$T=?#dV=b>S_o>RNMmoal!PL!z(Jj3PsWnDbVernZ_N8#P@(rmER1C z#1DbvmH#6Yi9Z4ESN;Jg68|7PuKZIl9U0fPE)icg>(#DsJVCM^E5INm%TgIeDnAM) zC_fR3Bz-?PO8KLqNc=HyqVng$1$efUVlPvBD(r@=2O z*6wpn0LgWpGw=eEGB3hf4@|!{Y>32f1Y;kYeqXo=$!oLliRoKlRV1%!FkSiDQ`(H= zl?I<9*~VVLbmeQ$h>^5MOXIr(k~D$vXB97mYgD`*?oshRcv{70;cFFZ&)H9rY`0lp z4kTqd!4gRNsw5N{b-@Vb_l7abkA#H~fHdk>d3`dez zd&zf!H)fmyAFDVGep0damTN&s(hr80Rh$YRsW=Uaj56PGofApy1na3d1h!LgC>*Ea zX>hfQ*TMBF*4|sRmLJS=LSdAOW8n}LC&BS5o(6ZRcn>_J;#2Udic{fz6{o>>D%L)7 zZh)lCGvF~5r@{BgIOb>>v>Qt^80$-0mO-nu)r^CoFAqeJ_2>^5oigKfF!hm2|Bf^~ z^h?snFE|ZdtwtOI*XA>0sa+(Weg1H`iZx4iHp}eB_AhtSeNNAz%5frgGUBB?m$Mi7 zLXaQg+nJU>!z_#ZeiOs5IBN}0rnnD)JM|olNS@VEmz3FzXLq=B*Ipg%G0$IdQgbuF z8K^CCpj~nl@Zk583_P<#p6Q#5ynG*EZ^_A&53wsUUvkW_$1Pz@avKpZt8p)&nM$4u zY;LnMhqH6uGw{!fauYjHs(8}#15rj*b|&VF%V&)--)h`bSkA~N&lr|@8A-!UqsGfz zX8FZRdS8}6N^~$H7o+bg8FQotDf!!rGcv>Rq2{dIt!PJzOvI8(mR`s$>V_}5G8=b5 zN}F@ggF<;_V2a-ZpggJAkx1rbL9(8uy&@@3UdA~VDKZ#OOcBS;=+~?g8tXu!>_**^ zHZzf(QKIDMbBAf^L0N-2ki4u$>Di2Wq&?=#lf06X^HdC>^o?wZ&PMNMBKE+O-jsUm zn3ioWWQYn`gG#(O6EiH)MU7&!jfXGy70VmHBq0lr7O* zVkc-vEoT3iy=#^%>&<+b%PjRsZ`#_)Ra;|i%ks$jH+#~y<;W7*8+FN2nY|;mn%jZY zX-9tB(n+sK+oZQ-{Yp*J_p(jMS~urOE6ui;<=3HrKHlqdR(#h6tkK~`(LMh+O zC2P!#OiC%X?a}NVS?kh2=2FU9Fk|U^+siCfmR7c8sYUwQEYV!c;>xl~nYOmuDC@^| z%r<+>ELU1-ZntJ0nYK6b+m^yCLEdGa*-CSLN-U8B@3KvpCD>||{Xk-KYcr3kQm1+R zHQOn@X>OC>yS5{VZBLf8=90;hOFhyy*(1#Ul2+NKrH1df1eyN!GM7U7N6NG_aD5BAnZC*;s{eYxi6#S`-RK|vqrt?8ZYv|P`b@1JVX zxk)YMGwBOZPQ3>fJ<(fp+>u?=`O@ISLvZxVcA6s>)b+=-mqE6AD@RR#5TNNBDd#0+ zyhXQ`Gxj~zl2Z7KX1T=ja3fVp6WYrIT6Aa1;HD_upZGqqqaW@BXpUUyvOnf*(bI}+ zDHmC8ewfxv-LyCcIcX`C?X~+qkZxQ?O5*0~%X-#1 zgK2botCpv^ot6^Fd@t07I`7bq7LHn49nwD!pl>O=9sWx4FmOrd=4^W&q%m>`<@ToU z?kv~zj}BVa4b0C&ogV|V``(mQkv;#szm`%IFT&L_GLH27y|olBr05LpJywYF891ZY z&tY-oM{%8jQ7Jn8QkG?^Vb$)xVcuiPUP=1L)Xx{i9Gj`*2z`)&ZHEEAI$u2X8xC5o z#?1c#-9-0j^J&V-KpPH{mYeHbx3gbxk;ai9U-XyEuVl|Uf+_S5Kd`41|5MZRk>@3K zauaL{Hv;G9D4PDb1Pih*Yq8f}W_{OxU~$?) zJDu_F`)YUIQqCu~UoIT$W9k2W^e+#`a;)uZapY!DM+R=CaAQIW4`oVeLmf{^|0F>3 zZ9?7Wa%zqY_Sfq?usHGqpKfJ7H`}Ii1oRxFdBXPP#&*Ax^>Y5c#lA`wO`lIW+{B@O z^wsRRu&5WM%%`l!8`N5Ao7n=+}9fH2a#qmXsZ=vrV+;9QzUv zU((~~V=dK^c^&QIL0~EMSPuScbH}pI7JGhx)eB~`=qdDjh*cXoGzZtTSw046r<~`k zngMSqJRDhfp-n|tjt`W_!>9CXzS^a5`sD%na?_9H*p8m~Y8`lhh3>-i?Er1$V9L7A zx{f06EAswLd#aF^ACL7_v^kk}K4LkF{i)e=qk`jJXN#pgZAhYD{-(d?lEy+=JaEcV z)~a3dVf#2oeOA0QwgF!$mwt<*JU1)%$a=DG65nN8DdTL>8MLhT_ttt=V%y`!7)KsF zkrF_j>6H77d^{vdzX{v2-4w&;rWc(DHS0W>D}@J<>2B0>oitxaQ-)*ENtU6ARr7s8 zzf|G)SC4c&;7TvgGI67i?#ujtSl(Lrb*o#ErD)1(K|9{i_WtB&fT@0u zxHNrrnKbXw1E#roKtIee{~rBtHkbCWGwYEb6?6uc>W#=>*{bE^;ca>k$}hmS$b+3y zxB=Lahrj4YeKijrf|qiJa(Gx-3OCN#SIMlU459AQw67rRf*T=HE>m`H=8s|-_zs@J zV8WE)d|Vb;?v`lT_; zl*alyP8x19(>t?W$FSZucx!jw(Y6)j=f*Le2chX%Q!SRer2WLU7ee00cswLce{ze@ zL|?6EMfQdHO!sBKZVwMp$B*elzNxzNu`g53* zcAcaQo%DC8uQ_%723_s6hbO7KHS=$>|951++{JNhJ81_j)f~BDE~O}GpDfp|Fc8Ob zg?h5F-xs4D7acU8G|EWfI>S~z8|-L1KOX2j*iTRO)vm9mkDgN>H(90pbKjz8r<`ZB zB@NADULn>c7fn-g@ww^FJZ?7EJ;?heK+DO)7A=+N-PXf%EtAC-buh}lLr&`kB+)Zd&l7*` zJ{NLzF8u2J7?RS8b@812tOI4-reCYkj!bN?+=!wl)3(ukmgb_2GB+(Q+vtN}(#>XB z`O!#Ep)K63l5(5Rx9YhpDcrF4fd7C%ze+n+u??T)SiYIh5FS2rEH8C8VjDd`9qmc; znBxvNMD=OJaf*iyrj)?zKwsu%-#Jg3U#au{a*hv>2Y~8PEYk@&Ph;7Gyfg;}KwC}{TgMQ_0=pD@rNws9Gq=sYO2Ma8$EP> z4AQw+@5sZ(QvS%K@?4<(_b59H+afXZKx>vtRN=b;Ju`vA?G!3BCZ%HW}xdVb28Lm9sz9(3u*KzZGhHb0;&er!(RCR6=y z%4e{MewX@clZP8iuQNC=r4(h1r_E3B>?nspBPlKMJUCxFMxN>{6A$Xq8H|;}wOaiy zefpSwdwR=qXASlBWjicF+OnkELfh`K9So(s&-51$KBOMLL*TcfPvwUU_3Fg=awp>( zs9Y5s$M@}W7IUV2tG=lXFy?n&_1mJxH(E(1 z*X0;tgPbVOk?T8b&s5!7;`?QSzcIQ2-aZQCAhM-)-lj|LMpqa+Jawx6LXk3BH#(b&6 zPAh0!AC;>Twkyi!brL42*`l%kN@&z4tud#hB>9al)JIa`i{9!php0 zcj-at7pYgSADQi!W&FO*oJ^Z*E)zXtZZ8>)>+fc3&80Q-NUO}W=5-s%X->N^CnL3G z;oWp3x4CpOB1rm6+GFcsbNi9LlK!)*cFGlPTW`n~VOzU$5@n0+g?)ox9!f>lXAUH)~t(4_H8Sb_L#kHw$^q%Ov=b;Y~SYc%Us#R%$JlU z{U)ho+c100T+iQPGi`RYU7AvVQF=+f`57_F(H_X`8uUnpb?yEyLV8&0jriTf8i({4=*hv#-o0 zHMb2Z(X83*W9hlf##U|~HO!^7miMwd9{kxb9qkZVNF_V$*>(bNE-sPS{ul1O-#pW?MOc- zuu)*+K<){$hWRbx$5eZ34Xq#z%4hAPm0^BH>m2K4e2cY#UlUlb%u4UZ~WepuA((AZ$e&S{k#pJ z#k$Au6#ksR!+}RAFQ2uaHk|bK)>y4Av{;+_wPt={YoZoUy>kLP1a>4{X39TAXXUdl zvfL(}Gwt%A{r1+DS}4<5ttlF}&aeWSY3G2wHAXARd<*^d3g6KhrY$kbcks(f`4;PT z>snT+#abp~OWI$@>hCuV-`?6)vy!fk)#^8jX$SgyG}HFh_S#^hJ^KRp(;i3KaRa}# zT_L*ytT#979%~Jw+@9KN(pjtvtdorLA8LC@m(|)$hAC05=9grobIoX_-h9?ZT50B6 ztOGTMdcywND5mRJv-?dk>aVXAWO`2E(!f{Lt64Kx)*0y|wIE};>S#NR=}LZ8N$5}eLKnXz+5Wz)ML_v@)36YZSZjq7> zLBz)Q`KKQArfeVt ze_?iitGc5HS$Lkq^LcrHBF%1-Y1Iv=7;x@gL;8 ziNemd+ppAD=E(1~{U zz?Y7EYwiOMoi{KSS`WlzhEB`4>F+IoBLi_E# z);0R?v*+9I(4R=1=MJ4d;Ji1=eqo(MFOL2fz;6`&`W(66-fyw>i8>_NUt^bOAGh^> zB_HEh75xa?_H6(|(0@UCk&I^-$M0~S8I@k2Kz~Pnx&1!&@pfgabBz4#4;+ARF@Gmw zA8Ho}$qAOQ`&kviq~NOHYU&+gZ^^yi@!!(Ag8GTnmr`Hl2G?&dvF~G_$zDzbhta4>%2m_Oy9gRB$7@#iDY_RtA-Fi;lzFwH;cbCLTa59o#h zudl=R(Z4n5r^hZUek(-;BT6uTl7d}=UGW=B{_i;cezh8cmi@PN6+dY?AHvZOVVs`8 zPPAhKAK=fT&S%gIx9j`=U>+sf#R8u?{2tal#Nk?pL7!b9P{iS93*-Qsvu?z&ZunSt z@747cO_FUUKDI(ML-KGyFRU?}q@ z6BrA>D}F-lURD4)-X0M%iaagWgC^J|1vdr1A#N)2X^Px$XY=2LAI5r@3ff2fGtN92 z7jxa|AN_%^7i~NyehIs#l?MOmIlsc_x6l6F`WJa5x(I74mSqoc~AkE#}oO`0@7K z=+)86f1SOS{v>c;(F=^XE5%f&PD#Pj!87u5FxGBhl|}Bi^M_nVp4J}jA4&WI_$dZ$+0lVm{Q8L7!-*dqhyz2Y z2aiy|Z)DW~ZSWN87VF(*M}Mb%l=*1cnVnnaOk6j*z>l{V$E2GBx?>@fKjy#?JG;*K4$afh!E#s$~O&{xgOZ05c z&+YKbM5T^O<6OTp__9EU*!8T^$Sv+iMmc%34YnhXRLqwq@Cz_Md6b;|E(R~bPqYgM zK1R=HR}0hx(=yLe5GT=IZSQsXy?vwbo1gVK3Vs6DPrbu0(H3#J4cDvjiK<0&&8T%a(2O{+MIm$$ZMTJw3Am?>aO){G{`rq;8ho(AN~XpE^E;j<@GTe@tHSc9)p0#P!?1T1CkxBjXvwE}ZrIr87=k z@3D)bu4{>t6xO<*efCe?nUKfZRjh&d<9^xK3%f+yA9&mGn`j-xeVM3;sFcjpq~JfnSJc-> z75X8!$?rS#{fx^g=nKqi{mq$hyRiRv>JdjiiNsB`y9K^L9?JcEdH9)#?}N_I{K!H4 zFwWQ4@#EusI!<1hSpUi+PYSLJt|wjyXf1@BN_+4-Ze2evnEy~QN@`0-8 z`|Y@p8_@A~cuWNS3FZ2pop_PDZo^NBpMhWt?q_1Ddnj~&Xv^Nr$ScpDfu#=i2`mT0 z?DoDMRl6lQR+4le?IOfPk{-Ho8EWo zqmHYcb#H)`2;WZ}3w@uRJ&?=syUtz*E(neajv>ET*0E{mg>&9Nqkl!2=h+-Ov)>0@ zfcg6X`*8b`{|a=t9qJDQZQ@=)FO+$A5`SUL!>s5fFfRuu zefT>A8OME4ddI$CNG{OF=aw&B5w!Ia82|kaPcH;J7*En*! zj#UWS$2u40)T2*eAbJ_Oj->+^aGgIz{*j!QwUM`G{cgZ|;=|t*#;pK#%nqOHao`yG z35@4{FpP1@0^i3xt>pL_9vq1uAMt}ueA~AUwC$VL3NVCm--DZQ{5=H2>^9bP_>r71 z-SLx=>r@l`WFoKhV40{YQPrILf^>mQj{hOSVfatvy!!|`-X0kV`3(NA>1eD z#7{VR9l?KIUBB?3Xcq}AL_dza$|4Wp{_8mM5Y|H;*CdZ-RvYxV53_E-k3{bt{0Q_8 zI{EdpsyKQLt!mJIyKL@w2lv@G@SBqBc@lI+t|tYci_)J#&=yz4`p{*f5~B1D?2Obc z546vIY86NBv+r6FV7T4aHwLshZ}&QO>+C`3wFo^OdWQ8VDR?e;-syMoz-RC+>N5n) z%lS4G{ZQ@$&ofUVscRH@hH(B214HdaxxYc4Xom%+I&qgde^W7pd`BWL%6VHKc_i1( z)6j{WufL!d!u?J-w2j^$$YWWD`-2gT<8sjAYFpCr_qtUAn(K1RE$W}i{*W_T{VEtJ z3Kr0L>-ha9uo>FV{ZWw+kAiyte*2Df3pw9g+Q&FA!ugy% z8M{oZHzm-EWjua@j^O_IrQ>f-$W!z~$*Z4ZcZc^y$?kRESmbGm6G@zm+~-!q-e+I5 zULm*nocA?yi|-Me!;fISc??~Y^RpfpLH|!U@@)Rp&ib%CW;OLsWSv`vewnCBQF<4< zh1Ue=L_1Yr1{g}-*TJH!8yT=a7kM~Rf6vFZA6WaKL-{22(if=z?Xpkw)bS`Pb6%=c*GrKC@a&LkHcR<=y-cm%wy~l$oCucLs=iUfIhpSRRwtj>)T?mOjL@fQ0mX; zNNWK4;mn6oEGvtFzSuEbv~pSy0t54SJ+FJoVV z`_{S8k&NeE{9D|2|4#mK^s``y^y^xOk@MoBKt}ip%)i!PEd5J>@8i5L?dbQjDq){! zrwB}jw)mX>gA*r<|0;39IFC|67v*z8B`}k{+x`hXzx}|c#{n&_Un!wOi2DH2qK@03 zeSCl368%IwBrpj&g3kx*p>58qK2E&Iz`Ks#5qqt3{tdI{Be$r>LHP0Z_?R2iJC=F- z0sQpL)3o%f0Qk^}nSLa#ORSbt~ALhlbC-rgAV2)%IVzo9d6 z9yY~qnBCdellY-_7XNPSqF5)^IDS{etU=$h8~B1;x(~a!H;Bpk3=t)&o|wmlY%XSt(Y%K zd@ni3nTHMikI5&|?iKjTv0vl6hn~f{UKqMeRMjZ`ore(CgTt^xsc&N^{@>O`Fe&&v z_$Pi6?V^EC9Qy{oX4r>w-rq()k@IvB{6srtU^*BI-^R{@-xb>8d#neJeii>+@`$%% zWAZxvJ#5cn+!t^?yx{nc3CwZ)pR*dEpJ?|Btb`8Z`r8-UZ3oBQzd4$b%NPCuRoeMx1cgfxW1uwTJmf!1wWe_21b07{@YB|GEUafqVGeqQ9x;!{3*VpM9)Q zqHkJDpcA+oYUS!%*YTI0d6tsA<2Zj~@fXHAF%!K+u9rvAiy;5A&^G7&b;tfyK!2OS zXXo%ol1C)@_Q1|!9$x{&`M&Wz^!(80phFmkn}|c0N3-BpiYOIPn$K-fT&ETxPf!0d z5Z~s$;Td{q8GpZ1$2Go3j-N!mCX9H|fqcaE+r>jlAP;4Iy$D@`>sKB0`28kO0XkIc zE&8Ec7m9+3c4%OVlW$$?7-|;xF%!^F3jQ4YopFfdd%n)-abIN}1(Je8f(vVrmE)d zGtr(2cb|@a9Z!Wf?ecMdrO$^>l#>hl`<;x^A(LO(tFajH&mBowx&M@z{<*t>+~;al zOP<7c_`+Swo(?|-0`K*Mk4L9RU=(e%Upy`S3zr-v!XBMln*rx~N!#vPk; zq}^ENpK?)N+-5r{zH22NNwoXRon!7^9NVc&I(p&G6;()?X&%Tnqto*c=74NfM^)K< zg4XzURK3|~s-PNazncD~$6EChCGTcGgQu8i`A_Rak%qfBB@1=ZJP@tp{1=2Erw&)xatJ{2#CyVpo@ctd$eZSnJN9OukXw7{Xr+^{Q12{J&D9h4Uk-CXT;-x(C@*<+|0y3ucW1e{Is-Lg zAHc6%x-*Nbf2XgasVb7zH{m)17*!u{ut zlzVmAKC@=kU*M8^F`=1$q)xfN9t|xglM^e^KNbLyLTyxhFc~wo6tvi?9E0vpb3TA~H z)%C0YyH%7o{d1-6@qhn!?gIY$IZ+1L{}Hr zr|gn@b#u{rF1aLbA31O$x$)c{yV2afyLS4&xNa8is2K~>PxmfDaWzx5hRI4ba@QO8 zT#yf0xZdT}Jyt!WCmX{ttA@*Q$Ip!_A8u`Q-%Sl45>GVb#qo`R#P5i}Js{nQoC z<>~)!TzOUP+^T9mDnGX_Zg1UBf^OdK2$;V8S3OLU{WF=mEO*zr?9KhH+aK4X`sI#| zJC4#aXQndLT#>#z*6Opk%24)hKXj~ptPA*YwGZ!`N@7!)e!pJMW<33VoHEq5@?f-7 zzWKuN4nMx!0}rt&LHjOGv$>=PbS-H8uKtoQT`J(GFMfR3^}}uo@?OYWv%#?lo2X~w z*B@qE+VAu>akXFa4PS`!J@0c+-!s+%d!nzuXQ1EJ3-IN>euwJLvx@p1{}b|BhI}mY zxSOnU=j4R z?=mlWRl!e2{B#0Kfw{pyvHuN!`WpzZ5igWH%iwQ6b*TN9W!>USu&&7G;AaZ@ZLup( z+;rIefdAC+hjL?<7yZoGy~(=*PJ;P)KJYMlE6~$^@0rBc?+P{e@i+;8hp^iNJ)gQA zz|U{wyB+`U<6ryQRxn;$(Yr7I_-ny9w8vj1{569=3I1#7mquUvcd8KIAH(Nr>=vWH z68#7CXS&7#+(;esVDH0T-=kj$^*i5Ne}vw8{N2P~G)T0Of^>-)+W7iBj z?HBR$yjp+!<;Jh}H{AixqVGq)3mfb*@yy;_?0R9R{o3{DcVG0gq1T3+_`T3E=rKXdTY z5xtV=orc~3eG$DX8VC5Fz}NnxdeHw6zbN^p0xOcoA^6!+P^Vb_1`p@MJm^oU%Od0_ zk)OohI{fK->W|2O59gRxrP1hhAy4faSOj1D05-BI^H=yY@u%N=*P>U1d9*2|ZB1n! zW@j_dQ~aI8->>-R(RF8^ZeIGO-}B2een;W|OvzfS^#3#boWRdL{A2@v z#Lq6`u0ei^x)p*>1w9JC_3_&etPbjX)lc!O@8t(EUQMu{Kpuzi_XmD*V)qaEl;UD~ zjlA!YPc`yMg{zTg6IBK(Nyh(qHr{^8M=GR@pm78 zIe9l>1Lor<=%1jck=G>V*B1QEpdU5BY+z0NT_&#?$fqH{L0;*x8;Adn#GMTG1Vf3l zjPY9!j;B9Y&`X7$ekZ!ZJoz4f^YEwr0VTAPuPZ7w>VE;W1ci)-Oq`>o)hX1y&k&{P%47n zHuU;npM?Dq@EoZ9MoH-HfPMn4-vzHwAMLXl$vj#C{|fwP|*q0z~2Kb*NABKHd{P)EFedKqLzW{$HpMK=Kkh-QvULE;svdzkJ_2Wgo#0o6--z?} z8Ry47{OYsyc;c=iuAYBMU>x=n=OuAQ!(R^nIdlyDJ5Ib9`la9H(xNwky!TOW?eCdQ z{CB8FWAG&LnlKMnqJL2L6Zn~kAMGRglRWgCLK)`cY5a!ZHwAUMLtgKqw;jEIkf-GQ zN(F9We6}HfkGf65-w5X89`v507et394}(`IS-$w5?@hFwGkvxwhY5--XKhC{0Aa1%3~J3&3xw<3j8QVi$v* zo>!Pj9o^?W_(q5LHHm+U_&)q;-|bQ4W%1h+zuIT}0KeKtafNz~#%}}s>N$ha(1Wr2 zocb34+kpBVav5>*Qr}qQ8_=JE{$2cKMXr6y$CyXjAMiGM8L874;-<^n3n2^yA_8hQE}!=ZRYt`#jkH0P{W zx#@@Y4PM}U{|Np;_N|8@DA7)yENca=+gK-fZuoUvz0u1g7d&0;D=yw z{OqD%X*kcTkbf8a6{3#X-}N>1vC%7q-YxRI$o#EIzp~S>rO?e;ue2}aIC@_~*N4_V ztWeh9#^~imZ$9}RAm940C?+Y-Az)VCz^UC4hX?^ERefN`!xUT4ws zW8VjUJ@}Ygo#B^4e-HWt!3N~}HS!tA z{JzOJ1<-4Zo}MqtNL|{Jcrp52kMX$Ac$CBLFm~CgdtK_T-{q&1S9<8`&~wOpD0zPj zjsvxSy&QhSi4#wp&(Z%HeLc7P9sCZ=_dMjcoq29E&vRh+7vo=-cz206hkW*s&$oPz z%7a|{bH}4e=!c)_m-b^E)RGcKRwX@5c`7oYm2|X z;D=JDL(Cuj3aI_T*TL`6`vpDi6F*OXwa=#nZi~Rm)KUA&PUC+A`TanC+HaGCI+vl}hv@ev?B-#Y62A|@CD=74 zuJ&u{BK!pXam3etmUf)y9YEbw-vac0>>1c~A|LJhn@>LR_&tW-mh^Wr{rwdAVC0Rk zyNCX8{Iwx|E%;IJQ!>x=w->b!|1^G=V|NL=%;?WTU;C)P$8T-y9?{S1$kS1WH?VJt zz4pO;Pk-kipNHRG$me6Pzs z-!l50j=ZXo*Kq7xVc!?54;DsW7q_9rUBfuHW?ZI{kM`>|q)vK{skr7P{1))fqW=~8 zW1&|-Hz)pE#IFiJ6a495N3a3;J|^Fa_$|u3+DjPyg0&zW*IfA3@tc;<)v1XyfI4Vj z;2Tb!tgqzt4E|)|+r%kFoX7ZiLS3GM&%=DqeyFvKzn(XGK%M6hw+C^*B%ib7bCCWm z$Il{gBB*`HJBVXL-{$<)^P)A07lD3x^uv&MM!pXJV~KMLzK^)+;g5iS8vYjMUnkD< z)STzl$!jq3uK25g|DVyDM84O-R-pE|4rQF{Fb+5AcTMbTQHLOQow3vY$G-TjLYx7_ zpNsxy=xcv}PR6kX{V7O){>J|g_`jy{WWI*TKX$kAlZo+s6M1Lk+Gl=-ypPD9^Rzbd zk;EyA|Bm?Yk9-mF8z6tlI-(!-o8hMtdi~Jb3%-y(dSU44x&A!V$N5`#^f!`x9usE@ zdf%X@{h90O=UdxBQA^y>l`hP)d5YxGC^Z+lTk zJ-<yVtSv zL6?C34f}tX2OaplbQHgxk(WV!n0m!ScZJs9g#8|Wzu@mMdF3GACd4U09KG+M5dB?% zzr*+&1TF&Gp+6n{jGU)67}pu-_d`D;@*2puvM$EczwGe;q(0m5`!n-o7IwR^YYx9O z`q~eBne)OA{S$gui8qjWqvweVlV2nF#nJl_yR`V#e*E*~r+wNRsGFWkeG{CDp9%Q? z6a6db7e>E5adLqT!7sowpr3q8lWzt3t-p(_ecscFbB?@Iz)uZUCQdK>)WOdg^p>Lc zoVdSG$0@{lgE&Qzr$PQ3^c?be2fYsH4I|E%#Ayaj0*|4$8od_KZ$oPz_m|XVH|S&j zT>)!@xUjZS=Njk@MQM#g?4fxr>7vw(; z|6B0C8N3UALciXCe+AqQRs*BK_we&8=hu8N3jgWo-!S?+ANeTct;lBz`Fsst2CE~# zjyw{&5_DJm&%u9B_+^%cEjMW zqd)hd`%~XU^5>CJ*P$eC+zt&%F3;fnPo6A4#3GU%55&>JfI2uzM4| zX6V%;&oSgV75&ZVXQf`Xsh8eYunW5&{`cUw47eZE^P(T%XEEnPN&2bh1;0iw4!^&V zS2yZXle`;(#lULJ`!rlcG?PERqfV_K>x8Cp34kPV5y+l5Ge)=SKzrb$=-%o!^)1O`7&tMMZw~^<>-z?U@ z+{9Uo-uvYJ598YaztQ+@Prnb-pG4>!(C5HqU@`o3!cPb2640B;?<4YKNchuX+^^#2 zbIvF253YdyRpj3xFO2**&i`W2X`yctzXSb#AAdXX*MPc=qb_gbw>5rmL1(1?=h5Gc zzV@w#;6E>Ri>X5gt+0X zD|__Ip`RH{1ogg?FY&MEVBe+AW2w(highBI^9cJf(BDD-#CTOfuIHyefu9Ncn%K{# zKD(*UPvn&u`Ymt+`OU)4N1Z2=&p6H(y+^5fV}A|%zsT<@`7H#; zgL)swHR`z;`}@@GYxFLoHyOLk*kz#}&(XU{ybQ#>LH=VIKa0Hd_q|&{|4h8iJ@_BE$n7tw~IWR!4Jp3p7&Uf-%sElgZ~!sHW2Ru_Pek@N?xn5%MXTu+W(({ zeud)iE_72cKjZfT{=2LTm+_O5Jjy~J)Om#e?fCx}zWxsRP5fsd&ezEI5Puc)55x<@ z&prH&LGNqiJ;8b41oVawPtTXNpf26W>uuKCRbYSCyWHgUFW0d}*bgO-Zut8Ee|k^T z8S1U)=erX>2mb2eF9rTOkeBx7FQ86c@bf0)97X-=lizjp(t(wcpG97h^ZI+{*AnbD zkgxW0XXO0MhI}4!mMUupdFgo%Kk=$!Kae<6$m1LGxK4h%>DM5zDfkBR)yRiHH;2~q zga`4X=b)>Rm-eH-kDn~af1_VFnKvDwqp@p>U1#Xx&^?Lw9(71d9Q{3bUmn&`^rykU z1%D~^7)?D^Ll34-UqX+B*1q{d$ah1}g?=CG3U*{&IZmBU5qCX#>G_OC|hw!tOKdhG3`XnaYrV40$&r z@8PV|`H>HX{v0|3m>@oSRneJ+= zevkfjrhgyd?;!p*(T`iq+qvYimplp+e+&9)h;x+s^oGs^>N$~q)OithC$VdWpE&$f z#;!khmx)sZyS?~J$$Ii3xRCnv!fux46ME0kyGDLH$*(eg`s3#@^l|8&_?v@2J)hQz zx}}DG0)HL&HvB))FND3GoA{ae5QW{}jAs+*5c01FT^RjY=yyZ^ZRST^>ahs}gKemNM|mBhJ9UcZ9{h^OcNLx}ehIzM!8^y{ME5Bpm9 zy$C-X{x{Hi2XhkiA?&}W9--7@Eph7*SI@g0AznB1ieabcSf(S-L)<3V`^oz!{9eL7 z0y-YOqs-H}*rnzCtcKno_~XG0Mvzt7=h5r!#aBvBj zjegdlpYK3#g`SF^-o#0XT?Onuf*uV$8f*uq2A>co2DG8yrGL-3&ngGTGN0>^?@#2b z=kli#uOxoE;`cOp7oqN_7>C^CT>$!P=FcelQJQgBiQZN8xRrthYlm3 zYxqfnpT)#K4c0)O7y0|hXHn;K(BD8$0=t1t=w}Dk3qAi9#{8SeI$Q+5Q;FA(c#ZJ$ z27Xo`?}5BB{0#6f(XXDYPxFxPM?M|@Q}Evgc~Rtg-tj}$!7j*WBd^IinO=Fr&p}<6 z5&s?Hcf(H_>QkROKcvojzsGs>2IH>@{%%s=cQxO95;Zsz=rs1i@!h6 zpT~Viarm#nFGe0Vd1QjF34IFsOXz**rKV0l66Y#$K1Y5Ed3pTjz<&Xjj-ScrH2e_q z{*LuIFYEIZ;#^@~^oIWt`i0PYLH}<-XGE_Z`xS2E?;v_#((f4J{f)oJ^lvtLpW%N3 z^cL!I5BvQ~8W1Y_?n(_Gi9Z&eoWr6(2L*?N3R%qdfxalwBCO)j{HB4=Dvn` z`8ND9*qtEnwd7qB`VM+Iz<0qOTrcR{DHrf`1=t3edrfMZwGqc5O+Rt zw`2c;Jfp#dQ;xkh2ZZN>p(bo zAIyrpHhx}%u11`S(62+M#qTuy>bbiZP|u6ML%(|vzZBPn8sz;0d2fTi4*ti~sUYV~ zKkRZ+?*rIHV)r`vd`$e`@qY>bdT#W0_}$1a2l;)4zpePwdyyLA=LmUzN}fLSZ<60k z{Qkjwj9|Sh&pbMazu)nf2D?Gjp)Pub@OzJV3HYsqeR}L4(T|+yT>(>p*_g-I$xF|T zPbSVd^ctf#3I9j%ujj#+QeVA~aSwW@;D5vX{*!oxi2DM&bJ*p8f06U51Nyni`*r+O z!_PJJ(xA7We7+)|%k;Ak^E?guJJ25szXSa5!7stA$mf!8B6NP}SJ)TB{ycu;(bxM$ zH!_~v;Xfk(y40sA@y}w{hWvhpp9lRCU>D?tz;@~{@eYyqSn_J5{?Y&SjOSA@fV?sB zg2elP^{*K9OT=zCd_B)R68~*kFZL66CGnar08?PUgn9*;k2{%K{45~iuA zU(P_Dr?FdtpF`k6a6a)55I-&FRaNHEYV5CJe~|j5p+4J@KSJIY{sQ=afrZgK2LB)U z0s6Ow{?&&+7I}L3)#0~e{v0H}-lunp{6{g*3Xx|7dgaku&Ae&}{~~#BCGVN!(}jEr z(Vx}mQ5tIu@lT-tFZyHQ_oA*x@c$S7_n`kF`ma%^w0sYr7e6WRGZ1V7>N(~n^m{7y zo3S549ab^F^qhA|`0Md=6F&*~$%-GnfB75o{RDat^akv1VV51O3!cI6M*I#&UK4q7 z{H5l4a0!3a@mHKWd`BIw;x`igjqtCNZ$9+@!LC32Pl%`YB+Ma>o~O>kb-;(81>i~K zx+$zcyuP5GJ8y(u1>#0w|1WqQ%#Ynt)d#!P*xBG`#J@nCugU9e{A?snA~+n>`}tz< zqxZrM0QH`)P1L<4cA3aOoN~rEr?>9_^UQY68KptC>zf1q}BY%beKcGXfD@}fT@jILR zhrsX5d`{1KzY_XA=mOZc!Tu8Z`>=lq9Yq~yfZxJjNB%dUx1;|F`i1cSFF20+eT@HK z@xPFIjlzB_`3*syNPZK@I}v#{?CW5EoBmZIj}ZKp#P4}96u#bgi^YFm^yXuK9lxVke;bnTc=FPF!2ZU6I`pfdUlzSQ==}m6i(K#1 z?n$0q@RNX_q42*z?+yBsiSI|#!+%b``{`E_{rUv?G31@`KMVUw@LR$k2>ls!Dg0-} zzus#!2JA(?<>~h&>U@kkF2LVd;^=)PJ)r4|wS_w9{jEXr$cLYn`00(`%J{8Dyg|g% z`;e;8k6HMeqyFQ61LLIkBB!S=RnZ%W-U$4+#{U55PobMok4N}T!tP7#m^M~3;$pkH+(EAv>Bg9(^UI*X8?g@o@91Un{SLdw#2G>Bl&5H~P)-mkNJFuv?5>4%VZ3%9DOor(YL{+nMpahhAUC zS?@*hQ>O&%tKp|3cJE>L1iiWBcZN7NbVKz2;C|;k^RocsJ`eq@%#UpN{e$yj4LA$` zf1zI({m$qYpbmOpd@cO{gZvuuhxm_DKamH?voP~&19iHNzf<%pGx9|2qwrIo{`~;| z2>frL??AtU-P`!xioXT;+kkum@>}FPfqeDe!D-a{1bOBp&u3sWa3_AB;`b1K{=m;N z@FLg_{&e`uz>DDL_^FAXPx1dI{%eun4e~nxy$o9KndyoDW9ZdGZzudk@K=%75&EOI ziVP#(m-su2zxL3tpbw$iHr1Be1^-ehJ2Qv*u^GL)=)I1- z0rCj?^#J^rI;^H2>5x}L{sQFB6p!I&RFUac&dHhTspQAqs`xf|3gWm!0zu>&vOg_`8b4BLc z8RpwF{6v#SS-v;9PJP}%?+$uLvCGYR+XneG^@sd(kbh0+VbFgNw;)J~tp?b=M1L0g zUm!mNe#W8k-kUl+a6_-{|XcZgdSepdLMpzlF1z~5o~)u$iL>Brm1dm!&mes!or8tkiJ zUnrJ!N%iD>s7&1T&>Wei-}_(3=?N{@8zl{a4@x@C*E|#_u-b zd`z6o=$*oD4LF?QbSD3B>edbY575ttUMPAm!3*Fn#%(j>ruSFfLvJDR1`@9V<8zAs zZ^O?_#&a0glZ@OSTrI@;f_?yhjq$gOb@dhb{z4wpssH!rFF^l0>hPF41c?77_4|r> zRGNA8g1G01tM@MciCt~C@{AI!4$K-W{y!3wfPs#fq{1kp#-ZJ8~ zC0+&M)n`8bLtS?eXD<8FTA^PU{T#BqQ7E&319zYS)>e|FWCx)sG=N9ZEh`Ki+l z;*}-dH}LPke-Hly@Sh3%m3fsNzrR8s2S3MuJM#P+ef`~;%8XwF^okXT#Jxv+AM>(=&Ijlm`2UDJ7E_NI#QPTdDj1183HuoAr-S!dk8^_8n1AuaO-LDE@n)R|!467j*=B8PGe3-V6LLVE&Xt|1jf}7X7N|XG4CL^I;_V zz0v2?u?7&|B5shlYw$M-f4jJ!+JgKc<5>s!W&G5{?|AILr%r8IS8gJIj$I6XKjnP= zobfvk9s-LIuM_-IjAtgsa{%TnD~FASA@E3XWqpy z?oG%iANdr4-vN8Qw{He^_wjoezm>4-hu!bU3t-ob{5mraS7P@jc60H+fOzMjmqQ;x z{x#!K3OXD*3j7T}Pw;mFEQ0=e>cxN7H`H$={=brc?DR)P?o+R6@Lz!|!G6SDNM22` zOTl@nzY{Qtx_pVh$@r_rdUc8ODu#NlhOfV8Pzn4LyW`juMlTY*8`Psc{)geW2!89~ z?>R}7N3RchdM|i2?7kx3G2}fNYy;lK{vh_8vi!Y9uH*1~!ygL21^iOjcf)=U^cRYQ z-?oh78T4Bb=Ol7{NGwF2>&O$Zy5grXdjB#m`RVry^!4{~O2W^N`XlU0P?s*$-#o~dAU}sZ3VI=SBkfUpW2x`^mhQ(pj4B* z3xfX=zc=yqKH@>h^G7odtjCyI6W}L;SHV&EZ;St9w0pbDw}h6SP+kQf{YN>3;~q4b1CF8$%q(i2Kg zC_SO%qdmS*bajyF;N&e7&2T!jP;>#07S@24-)bL579!=@+(?c8&n>>JQOWIqJ^U6N3>9MoJR}mK+C?jhjl^K zSK}cRtvp2wMa!>fp=jkLS}0m^>Vfjx*Tedt;=S%+15kDC=b>oHMGHl%f1-t&=hD~w z5Q>(bXrXB7i54~nm9OTDP_*(DEfmddq(cjvLCfzD4@JwbXrXBN6)kKIN`I(_qSar~ zLea7lEfg&~(ZUuUf0&1&#TPAX399~@$3oHShiIW_^+U8!w9Z4(Lec7%XrXA0k7!|Q zPI=`gX#Y4>((V9QT zUMPE^?1i#7wDK~wFvrrhQ+UzC-#t|S(t0*R(fnC;$A?hsj`&)4grdb4Ez~%QuW=NL7GJbb{S;q) z6p9vKv{2`l_&UFYqQw_2)HsT-u@#CIU$ju?SAJ0Emr&=EQ0J3S>zwMRbxx@MX$(~( zq52aCsy{;IXU1MRnq%>GKAQ0|$KuP6bcKdCdgAF==ao?BnNVY<@yJM13>|M}%qt>V zMiV{T<8Oxk&^w;*VUmZRdAP*G`u{C}SZ)Y+c z=^pav)5%b_{G~Lfk3!KILFw}m*r9WHbT&}6hy_DI(ZYBS%Xo63{FDOarS03A1)_c*yIFDc3!@?fc_b@J$bB88uL964T z=$5p49(~Tk-5#Fyus{T#A8A1kOL>^t!z>tU{~pq3G7MOSHoto=Ap<_anT7v|JNt4Loe>VJi>Y zdsq$JL>o*S;^8oGJ#7MQgNKrfoY?aZj~0q9;nBhx&~c#FhHlA@ zYjP|<-8~d7d(lGCvKK8BEkB}#qKkU8P}d8ce_CsF%`nG?ulRowXrbja+d=3nf<^(Za@{4JziqWXFcDdKkWr#aBNxFT^*;hHw0c zuj3}@2nTs6T6u~V>OM%Q`yfLrZ_z@@h4N>3Iu>935l^W5BiZZzNGMu%qJ^TBhtV;| z;_H6N@XfKYH+=cfvF^Ksy6-ZyWTJ(VD<9E9(WtFU@oDN~_{O*R z#(ylwqUFaNYyFiEt-V6gl8F{-T@h-nF|_nV3ne$Xif4`uU%48-jt$@VkbZJMb~1e( zOJ8xNCqL#`e0|>6xQcI%4d28S-^A6iiEECHzKJWoiK}D9GyZj~^IoWP-q7+XS}3{f zl$Uts*zlE$;p^D&jSuN3_hTp1*RjzzIhY)Ep39%kOQC4#h!%>LU(rI*@+Vrjj;7Cu z!c56%`7%6nEIswl@XfLK3CZ|6o=p>9D8Gi5FT*p(#;@VauhBQYueFTY0L_>vDD>+`krh2j}nz6{SC8^4AxzeeBqGJcbgNna?Qq2Cr;b`#f4G`jAHpMJtZ- zOZ1MFhdCBsxfoiqQeCycEMdMFA*%~zSQ9fqVnCJ#4zxYfgNJ^aqYogVJ?aIc5^ zJv`{)iDam}PJ6Ua^f`|fioWR4LeW<|S}1y{M?dxOXAhrw_}s&PJgoCBd&Bsm^zcmf zpmBVPFY!w9h2BqmS+(#pw>9O1)v4L+;o*Z?9gbgi;j=Vf{!D(8eXUb?hrm>}9!}#K zky)IleffOI7m1e!u~%~_`@G)fcUWwnC9$Utzr*qC=L^m#zGN$kZSGI`KCdJD)cHVq zY%<>+zrz~Qm3~fSuMs{EcjEUUzPRm+&%d!bPK+shz}?&w|9oM$moJ;o5HlUJyX54X zz#4|%4z#E5(U^Y-fs?RIpm8TYW+w*)%XX;9w2JrzpE4BHHm^iRW)wo%Kq@3Wr~y;u1EX%hYG#`hukTaA4maydks*qeCtZ6NZ~*qxZo z9$s=z;LF6JjOiolypK4q=vN_XwCY1@zJO~V^*K)a7~TCn`HqfwU5Pgg{aMTd{m8I@ zF^I*k?qHr%=S#`M*uNm(fz%^Ex=+Y8mT{{`y|d!y3)*+YJ;)r{!x*a{hw%3+eI85h ztBFyCT!&Ma+w|d&R&K4fb)>G;Yd!ov#98nr=P@x#&tXnd<2sCWwvQNx#`qwIjr4H~ z{2SOz!O!I;GLA{~Rbz3SoD)Vcx5#lEIllK9wWOcLuzQC*$1?YRp;c$h7Y<-8 zByL-3`#R&4jy`rGUjL@(Q-@L56edP?@_c}PA^JXpKGmd7S*gFqc?voO@tcfU!_#aK*PEea0w4?OnCU#YuGv4Ho3)_?A{Smr?=~|yrWR$Hmlen(jJA~8pCSMA=uM_Rxv}3!UKPo| z0r4B+e+K8}8T6{r*Ih07PL+8$44rGxh3MDe5&RZN%{$S0(B7xDVmx->^E>*IVG3&m z;~Y0WOKOtslE55s>RU`H?TK5k8 z=0Kav`1Yp8GilFhjTzgUwAti0nYxaoKRKvd%s}+1Tj3!bQ@h!tm}lf!msW??gw~4I zk@g;KCaoGZoJiY69W|#T-e4}!hR~-J%)Q4G8LLTdYt0-=N1f);eAKx-?F{Qj_Y-na zc9goW^J+Sl`O%)bsn(?5*y= zGe2*HST#PQezZ#|n6I?ww9T~pwA~)=@o;-Go{q&oNt3>Ci-(e(q6trXc*euC9-i~? zyoVP(R35Us?BNv;uX=dR!|NX2@bH$0w>`Y$;av~!d8mHL{{s(|$5xv1-APkCq5KGw zc&2F^?PCv@cvvDm&qL5kdRRLn`@m_!*0ilW6Sj>eT?@vtOq}$UlFWD8$ugN%Us4?FU-2Bbt469XDChg7IkS_OWVvvYLX)D$mnyx)hSi_FPdqGRh@eHseSc0~acAG!;@ErV&7Rox8gBGLpj<$@A`VVN2 zIF4fdi=$oSxF`6eEY}xWczf0ruN}uXz$T(=VA@$$X-Bj0Qfp>9PI|}Carip*EO&JYj0((zqGFK-iqdZH{e?64YY4) zx~HA<1<#*=C1QCFgXZHJ5Tp3C1L$ul$@4m0cn=En>$F?&7J$cS7ifRbCbG6yD9`+% z&E@zk4|W^?>#)8zplRI~j-hGoUr+mzwuW|%_ME1B`E*u6_bO}I8h7Uuau z@Neke;9IoYv}f>RxMu9*csZ?D1^Ns92JI8tNLoL5x(@fFr3~^+G59;zm%6m<72Rud zICvYqIn3z~Y1*K%5c#SJtg|)#yB0;m??h`(`<^wrE_Q!%Jek&v>$|S;{Y&!>ZZJU0 z)Q3FKNdUi~J)kY?%W+xWK?P>3#NH*YYhT6lj6K*0dIYGVhoGiw|H9(MnZzubl@tK2?Qhr;!a9 zNS~^bGi^V|QJUi9SZBL*>5~xFa>Nl2q zMOqy61g_Vo$MG46<9pyOnl=9aP<0pZQdQsk_%Gefy>vIyol1%bNJ)2hihxK-cb7DX zh$tP32m*p4A}SJ!g^H~xSlIvfzUMPP|KH&??Ad#-^{i*b-shaTGiRJb^za=jZ4!0$ zsy69l=UARq^h@^kT~W_YUcaZEFhy?r_+F0o56=`+9cTNxKS4ixyw^LlBegx$;$=Gf zy-xO+^NL3Fw1+yYtpVm)Tk7?E&kddj+E{m?^*rYJg=d{1 zzF(@%H(ky>cX<}^Jm&eOXE@hvt3Bs=-tz;`YD0ZDbr??CyBb@kWPb8Ym`U!Tq;Y+< zWk&d}r@3C9`@Ft5l8)D{W<}S`1GIxYpZ1*NnQ^xLO&iX|N_r0QoaK3y&L`R=bL>T4 z_tf_B95B}RsI(t>R=rpJv`4ErE{=B}*++ag)!3_^o1M3XbGLBb)^35APV^lj?Mcr( z3)Q`6`6=${k=l1-y?)X2N6(M+FD;7B^DfTxJz&ojOZe)UWvRVrwtFLJYb?Xj^Igx0 zp1&`5d|ZLgeBU!&X`M86KBgVF(05$DetDHVb`#^(>cVk0_cHtZ{mvmhuNzCd!o9q_ zUZoA^kKtL$^YBXdG}2aXrvJFSd!F+A$Mb@*3hR9TYMnY>@A%+(p*g=j2W;?qv-_!e zonnjcU~Tn%Q_rItoqM;ySNo4=icPK+Jrg`@d-}n}xTmvbPW+6R!&{tC{-3^3Cq9z> zuXT6PBpLleQ_}zSL+cJ!ajO&WPG$Wk34LohrVy7rPWXIRkS5`DUSIbuzGR8t(00x4 zRo=uqgNnCb-81d`XG?r$_)2(bHbYzrZOXV@KBrVENprvOp3*1gBKVZa1*V~-Gqg{&2FzxA}d3Xjz0C&CJEk+{b}A~Pq39+l$C zi*kmz&HhgvSM+}jrX_y_%BhC3+zP;gODP>cm%d{jXdTAJK@tMK5qKlQ^0k zs_zAR9mO`_g;&L}bHD3EEXVi6U&(PlD%v6PemNtqNL;~0zcRVwXpy+OiMT=AUA6r0 zJCAV+*CWIxJRHa<}!L?pQiNFl1J%q8<}^}xh8(-Y?-W`SX9{j|`tnGcWhiS`p{ zMr<aGEp0aZ@^ngmM867u zm(frORx@tsWl;C<;ZnaC}&7W{}kf?VFjN)C4+4*5%& z=#euJZ9bAI+=nEK8TU~0e=2bfkMLXd!TTt?;n%QJ#}!PJ$eoB*Tu$w#MngWMU*ArV z7|XC~q9}$8#CwKEupM3n|3l_Nm4&f1|G#I@3oMHJKRm*^NUxT|cr{ESq%aq;3j6}+ zFdrVtAqJ-5{|t%fVbs0N{2z9q@Q9)o`tE1q8GeO5Ge4p%hdAU+l*{x#ti%p0VKj$l zuv9#eNmwPR6ZO3y9XO@qRq!arH24$jhPjZ5{~l=)=RwSZD`3~68I*4j46Uo3RifZ5(;vV9f z&A%v0n*Z|%Q7dF5_#5m*@yx6O1FMkbz$CEDO)`1}f5Ic`XHD!yuOn{*o_pyScQ+{i zha;8ilc2&*N>v(S73C*Fiq0ZZkO@b!P>bpOAIo`&K|st2FBa|OiCzZn>~sRxz$#Qs zh)66d;V2qLgRKz#XnzY)4VuALD(fVQaj3VjszLH)?Gwd$mE}!n(WG)@4 z5bZD@X+=?v&LM);a3|luAgt@~2rD|;hk}n0>&Sk}|E;Eg6XG4kC)kSeA1nvnp&u$C ztnkoA(Fr*Uk0fyg|JR1*zq7NjQllJ&@#vM`hD?+RH4u)0(MpflY=j?i3lib%Bj5+5 z@Cdtg6z7oFFdvPF9W7cx;T$7WeUJ^K(fLGSuOdGq?5t3tSHZss!;Am-h%ymsHafQp zECX6BR)Jeo^AmoAZQKyZiML~ldH!VVXzENI2p zg}4OmkC?~2jUxJA%%X}7+95Y768F^*^R(=QN929t%fw!&zUUEYh8hZ-Q~fVvp$em1 zgw+?UhG&$a%!$#9dTIaPoN2o0{EO{kVI)K{I^sv?fx$+2MA!i}R7h-B3yh=cjjV^G zc(mptPm|*p?1uk?MDQZSHRemqR`4Z~iu{h|qdY|x!bmuJ$LcL`jLvjSc*N|vYrbCO zcUWVQd~8pRe2V51)e<#>kCDYtgV7@v|Lp9fOWafci$RbGl3~S#SHVW+#A*&c1n;7; zNGdRkR#?yr`#^|5SS{fUI;yTvb+L6Fi*z{dhS%vxhjkd$XT&qMe}pOsG9k7xZ==^S zkAhxwjPW9oSwM)+t0MMcG*orOByf##9Qv_JN|9I>(fMDDL0Ea=5goZ=@ef%FXGUQz z7Q=uaJPthnyHbc%PE^NX-v}5XdLgb+RR#R;2tGz$Cca4gFY+wx&{3U4Y(k9%M%far zhjkrACSns}9(fqs{lXp+9${CDW+Pj%Dvnk}kO+)Ip3)>%b2J}uh@uy*fDp5=Dg$0X zj%b#KFya-wk5xz{7p#VnfECqSl=pA=jnh{#q&!b0R8jEJ+Z-gKIkJeMD(@-0+oW$m12q8w%SQNpi zCZiY!zhiL-Z9t5wAzB0Of1fxKjRz)CwS+YjFr#BibnYD6Zz7+A^{9FRZtyY4Mr$^T zW5A3mCyH5+ie>`CFcz^3W3hgO9Xt)M0%kxDbrF#N|L1&BE`wa`ovh$-c&8#%(0|d2 z@)USPh|x^MEUJ=d_X}r8(KTx1L+osuVj_!(Z+IPLE6QNxUsTz#_(Z-0<{@sOK0_p; zCFN}t0 zM!R`bB~eVm(I;B}A(D}efc)RFBaHrMDRy-d;r=%sV;V(*LZVh^1Cv-3!%pzuOypOr zLZggCV?i%GA}?e9hp2~$hxbW>Z&8NANboHnhySB<41Xm_?8n&u7oX@z7Ib6lFXnfo zA2RZPSw=Ap?{`F!K`z3L;v2IZ5JMEh{uA*DQo&MaLzE+}@G9gyW+m8*DlkZf`U__< z5#w0J|2H4}{ZBWlpa?fw3E_2AAu)RaKPC}0W7dNGAQ|nKQ9NV5L{|Q92Etf0A9TVa z@+$FV;!Kp0D1JdASdDs-Ojr*=Ci48hIu0HO>9DF|QI1&(njxN1orKw__M#|88HfNxo`q8WKe-x*H5F~=F@Q8egPy<%1cEfxajdt;f zdC-WC`cXg3NBB`LBg82F5&vK(k_~G!icXAGU=(Qt9#IUVDvKBfgosh}-cy7V>m*D1%WvLvEryHOfZ73i6Tl$f8c- zNOWEvF^Jw92y(GUl$YpSDU3&+e16$)Q2KGl3YYwbu+P(N{>$Ia)47+dA0Wu;Gji?z ziHp1L=AEPe_IZ*FeqV=Xh(+znK3ke9McnQ`U2(bJX9@Ce`K;ZrqCT6H)V+DlS4)*V zZmsc#a2}(-j()0teKshQ`=J}pZhT*P`)YFcn`VD|7Qb6nk(~Z_aO?W=O=jco;5Dw0 zGl-h(@xuqrd~WYu{Kmq2-XCZS`rO+TdSAKk=g<7w#INgkl=q`w?XJ6L zH+#>r{~)}z{#^5o%>0JejEu?Smb252{h0;LC-FNZ?CsNjZG5xwI{1Fhza8GhyU70+ z*zL&fBJ-`x55=b(J|+DC-aG8Rt(`!=0-OzShO(QT-Ggwt;js4)WW=XYcSyk~B$NUh}8TPcz@l=N2cKYK}lHZf%tA+Tsg7Yez@8PV0vzpvq zH`-c?M=j&WwEeX$)K^FKwUhm4d?_tGxkc^4kTUQP$rzeA4M3P_MKp|`v*n&2~1@aoX3E_6_tcwYs(*6n%v)9IDh-iDLe{4Vu3nO-S+&++pm z#&v)Z7 z-SK6z`F!@XJh#L?K3Uut{#T8+Z{VF9??2ST0LPI7{A(>gJ@mtU&|hP(Fgu;u>!*F1 zd|&bv@wth2P2-J>?`7{Adq0`qY5qv!kxK=I0w-R~+}CymJ0!Y}+z z`D?~U8?S@kw|H&kM+<(Ww7zp$*Nx$(hTDf+dUAh=^ONFSpZ}Bje?Q*uSdYW>kI2_4 z`a|eX!gH~D8OcsT``A(AeT^@MQv=Qya5uosDlaeaI|aU*)Kebu`PY0J@(0;@1b%Y+ z*RSTgh|^U1rOelW{}(?$g0m9NH1Sv{9`})dOPzGreyz<5FOFZi@VJ>WW!yb@j>kKh z_;!`g{`|?p&QIbr(oL!!(=Vg{E&D6*ZE{_0v6qDYd^exmK`#kA>+B1slJXD#oa!pq zZNE*EATIbM$LDK!UGRH@y%xSuoB{8{@OqI?Lw*(g1N0Nfzo)+h{$T64J-L6$-Ouhx zc89>}D1WWA3EI*4<-_j+oKf_$;xmLFEA{K@KQ2y5o$uVMe^Xqa6Q}Cxx4k-iMV+=W z{)h4U_%=-N*DCfe(yOOUhW9OXKS+Iym;Wa6KU5rY;B)sa$1ZU!ipO#5WtI3=fzy*- zVS2BT8%?ePKbksjuEgsmUita+s`31IzeR4E{a^um#o?TSlOMmc;?x+w-RwOoUg38g zUNrwNe{16V2|MfcU()Z*?)M?D?0yVqDZ6#x&(XgheoOhzkLL~c7K>9|aXgsaxf44% z)Z;NYN!VM>&K>o7o!oqK%hbFI5wHw3=~{5ta^DZU-Ze~SNLc?!Qb-yH8uc#nbCOg$W+cb9xE zGykXgHS*A3T%LyeAl$>`vawqn?%VozrF9PS?>Wv>XR4pBj#s0^?;M`J#HEC|)Mfuwez(P^J3i;-p@8@#gR{?mdyo0o z%(uelFMPg+yA1Bb+Jf5f*~}sA-);T}^IhQ#fb%T<4D#}ZxRhq^3vr$<&i&1gGCz#{ z^6bB3zJmFi=I5CoCq4y3eDwbomyh7i6~E=$yR~=GOG|H-{M^UhDEnG8#E6%I=`J?{h`c>FFE-vf!!}o>8>i=WE-9zp@a%beDxOms(&!^^Z;8EQ^`aSto z`tNEV(>^BNGpwIC=nvsU=%i zS#TGyvlhRm;*?&zKb4os;#Iz|>kiiqz0Ke4d?ziO1Na?KU+KlQrg+v(@OwGz_EHDC z%(rJJ8Qc~2-TCsqhWOu><(skKK#n?PvSikpG@?xBu^gK_?B9e_ng|z>V7l1 z`^a^M_eCn7SHb^7^55z=k@te)u~a;+u~S`rl_dX``0f;+`?S08Ov&yJ>v#ycpXl|V z_bGb=@Xe|JjpIsH^_Gp@H}Dw`zlZsq_Q8JU|5aBl#c_u?e#uTFcE*awaPj((ok!U@ zr=Lf>=d;t4^Gr;{s3?gja(CtsQIpUJNejL$Uw61{Qs zuHZc>yLwg!r4y_(^UsT4F}%X}(V7@Q$@ufeUz3Lh>i0wOoQ%gU`0L@Hf;WNRMd_XA z&suE*`lI0HrT3=(X#I3}^u^;moMx_D{xJW9`2_7rIPv^{%0BU>xXgsJir(Gy!hN`V zsk8Ukn?dgH0^ZjU$9?4U*$n34YcdDC5)do|CD;`9`CwBzShZCRdu@r zUf1jPVDZ>b?pykkwUf0Q=>JOpckv%(U8KZsAG=-HPpK`he@(lI+#PZ+!utYVZG1n& z`(6HZvyKLm&qnTZI5qh-jr{xMpWn4G_Qm@|nsF@~W$^Kjd#J`S-|w zY<`vbhxq$}`gqm+0QGktyIa}aYdjA>lgraC@qCPYL-JkdAEaM}pU(t8)lWV0`OIGz z*9-hD!p;u-o=lxQ?gqaW(tj1sNb-mIkyoB_YX7hg{m$+Jc2jBB(i_CzEO1t-la1=+ zJ9^9MeFV3m`7!ifv2L@F->rW{TbKSD<_qa>#qUr23gN$-UrF#f4KIUy-GZ|aufFQP z8ofK@8`1lRpAU&!esP-!|4ND!akJU2Kt3P5vGC5pd5r&+^ylk0)K95@M%?>|d-dCL zl^}oYhTo|w$Id;eQpTMZ|5D_8tCKIBmmcO{cYM~7OHS^By8FX%Z4rMT=kFivPm$;M zwLP_;!=DbnzV`Ku@`mR;Jb#5hP#w+Gub{t-KW81cyW|Vsq99`*TF%Y{ay9w;viUCJ zw8;2s<9+Z*r~Mf2B=}v;m!aQKUc+~EALUdG2Hkyyo=+#f!+Jq?MVJj z%=P2^vHcJ60qtNG66=fDfU2YpbTbW8zUBQI$FG*`WVg=l!s|o4pM;x<-G2NC z-$`!8-#h%gOZ$$tC;1wVv%}%Ppq|E)55HGEmED%?R_FIgem9iYruNk&=2u#8TgWHH z?>&5{;hTzlZt}Uqc#7n475M+2@d@NVgZD7rQ}M1QK3mDPlaH&8uZPIzwhn5ubB3ML z;&NR*?ouyzoF9+EyE5LR$(_RQQMg6Lbs)J`;@6G+)a=yY|Ci#}UmiX*Karh0j(@Yn zp`!fEq*u;(UF{d-+tSZMe*xZI@F|W@5y#ye_UH<=-|DpWp%AW*&&r^RT*e}k0 zA@a|YuaM7rjdPsB^C|Y~7{6)!H~w^Yoju%mF5}hkIDto;{xf)=7WW$RbCY~OdD&t9 zUUuKaXDmM5_;pD;jeJ@9Yvk>SynR4!0=e&uuQZ+?&vAHe(7#W=9lV0#wpyGY6z7-3 zX)t?JkjcsV_m$dpTau%OB|kZ-uwi)2k?DC-g?tp$lfaLY2(9; zH^TcU9y{UoV{aw9_25>7(_CHthUZ4}f0ExuzNvUTAs!pa_aL7|dkJ1D@t7!nJ;bq| zwg%ii^jh-kIegZNYlnFGC;u<`UHE3icc6Z0I5X7UVs+PBJ4`!>->3Nf7(cS{BL)4h z;XSF}P<~&aUsQeksC_u>2Y603e*)fkcu$b4PcC1ulOk2ztN4$^|IGs7k|9~#OZ>ZT zU(QMIr12%<67H*zg#XXe&rJTPI9#XS4}KwaenCFpH$H=W-CJsmKQ$`2{=)Yucw6PC z7`ZFtK7l(2pJU?Q5AFi|o03nh{m%Hy=ntkpUmkx}pNHb2zyIeV_W}9K>^&sT z=g2=KE*tTfhj)Gb@96K*b~HYRy|3AOkRK6avetqHor5=AF|15s5sE-18eIS0b>2)Vp$?>Eb{g3FM5y!&nXSVrD=9luj2ftgv z{T-jZ=94%tD=d%4?T0nt4~PGtx_zD9EcDK>Q`LA6<2&KD!L#0NPsgLI_#T7XmfSz& zc52({?-Uh$M79Rm{VANbwGXS2MealWt* zZum}T2l2}V?{TRpO}vU}FKB;;*UrBE3;BM| ze>Q06&^wJsCUu`zyW75*h5tw7VHmvxcJku$Dn6C$B*6k z4a6_sZEKDnQ}pZWcc2#s=SA_&B*KN@ou_|;{$uoC6W0Ok&9J^2#EYG{UK7_|{2R)@ zd*DAS{~N{OtT^PNf13Uk_zU5mz-Ng5qx`Q7Mb7oC?4l+Tkq9t9^CoN||3XJ{wDFG9YN zxLvT`D&4Z5#XE1OzlHup^To`MU?;cu{i45K|EjoFmFGElEXQNB@utQ<7mrHfv5=jr z@VAKLPVEDi>=pbk3HO@zw7BG>SJZw}NIw4ZWvbcu?G=~8&f^Zk|3Ti;^Y@VV2ZpdS zmV6fc=G%v!r=LZCruo*^)zkcYhkh+QKErc4zkjy=-(+_ddsp0b_>+S_&p0mk(od_u8sC2So+#k&j^sasSJnIhdR^H) z$iE)+bMWH@@hQ!ZbJqD_`q}8uBUhDNO?ld@|26z-;*|=Isd#J?uU+CbOr8G2&NB9T zYU_&U=ho8!^GD6M=KoH0)d_w{aVo{``~0lV&z_EZ@!FfNTl=ZYijId>+5d>$BlJ(w ze@DJY!K(wml6AHY-p}y*YhThnjQ=?GSq0yZ`BT~Z9^rR@Ul8XT;@sJMaq}zS?{XaO zCY}SuGYuXu;jx;%di-lCKBpWP{?y;9--mp8e3J5KC;PqlAAWE7J978iCx4^AmA&2i z&!tWgHE!cS_*dXRum79* ziTHnx{}leugL9q!Z2Vr~-w<(bWxR{=vGQ@wI$Rj?qAp+5mUJFdIf?5lac#_>mX4Qq z%lk9(-5+lF-RQY^eTrAPTdteb$1Q&Bz<(+G+t_c*&Y$9#l0TcA*E}S?O zQ_UbpVyz6Y7JQ z&u|Lq=ZBwF{}ufU_zVqx!I>bR)A0BfkLU60h2IMKS`Y7YeokZmEBeFW?ZNLK{BAjK z=$>G|q8EPm{y<#x+2&Ww7s0P7|8B!sYkgd|J`V9`1iK%xJCWTl*;!)#KD@V(|IGYa z^V=Qgy2V>J#(y-v1K!u{^~O5`Ka;A9htx$L`mgAZ#q%*dd&=_>d0u0@A>8-a8OKfm z{d437!z~Lp4L%$B+Y4TLT_**(eb0rG>$_ZH9hj2}0igPkV!iE8$V zBI5Eo{Bi8~fK^-<`pL;1f%g!+7v$@Td`-iDLek`Md&zec$G-TEfb+KTa_qdXt)YDp zp8@!+qBnuw68+lx*R(UW55mm>wu(LucyRrj~`$MN%C^SAKI3imR+wc_~_{SvqM=J=Qn z?tc40S9;~>-OKMy{7y^$4f5}juc|*8{}TAsQXg^7zxt}DV{vL+z6QzH2JMsD+Wg7E zpW^ENfc5eZoJ0JX3TL!D56AysyleA!KfJ^E^}zoa*sRV&8^B!;cMJJTcz%pu8GauU zhi>>Zpm&7cT6~YVKKWMMSMl#9{S@l9BYp*~r@r(nIDXWT*Hoto z#~mbB&iTVC?IrT5@H_{<1G%;0I6-`y;(6Ko>izKM-ygt_kN7c0+@^@zb>n626RpV=Aa@Uc zzog&K{7Cb4*&VHp%F4qP@mi;C6yk^XNb!A;|M}%_FMDaomn2`Ad@b=@iGMczFT!!2 z-4E#fOYbnfDsVo8H(y)D_=fH3S>9H``2p{maKEx&H&-uzJFdLXuSf7&DZYEODM z>gWUd)9JT`e@?rW{!jFKiEnN3O{!fYKhN;57ymZdw|9v5Ed56M>&$;fF4JY}5wAt; zZsbok{a5u{YX8(eq<&I4Zgqx#0R94YtFkvhn_2q|oNV%%#C&J-_rUoX|5xPiNAKUC zP;Z0yyGFc|gm{Z@SMf@N$M^K-(Lanw3-SMjpQYelB!7_KZS=R%%K+~PoZiOY(mtYH z2xkqPwBj*KoN}n20`|c|`bWj5z$MqL{EgSXt6fL_3GyG(pGAKPehu;KDNoO;(_bAw z`Xso1V(*50w87&~a;^CFG{0WLryD*U=_fP(2i}V_W{n#TC$~CnjsNfF6ZpRs-){N% zr4F8#w|M&9eEwiD+&uVvgwH^B-qufs?|A&%vhystHt^1SKkRq$-=@x2kZ&&!W%NJN zegUr`xjp1l^XDY~m7Fge@OPB@?48832Odq}{u*yDwVpbM^Fw+$=*`BnJo|(Ak)0n^ z^*<#4C%q>fH~!%FmhAk-|7m!)jW03Zn4LM|G|zlx^AF?y5&lc%@d0+e#=E|Kqo#U! z(mL))e!X=)Tl*EgN#Z{T-`#lpsgBpMTMv&_{Ho8-z4&y(XOMcn4!_K8=all%fZR9i zAJz6DpHF*6KN-Cj#N!is^XR=Q?(yoqr}@<6y5Us}uXu4-tsY(z$EoB8(96o+WO}9O zeUEnwya%%TF}vI4HMx2|XZ%mcy*vEfWc&yHw&YrwPpw`T@nfTPaf#jX?5+`~YIr@x z-_-W2r}1cw$7u0L&fm`Bc|bf%7=M%8F8!O*TUvWr`yqc;@TUvBWbE|SFRot&pO4hvi{$$8FE9Kv+LCxYE-z!`?L&F{o?IWi z*V}()>5s8bH}`(h9d_6I+(s?>pR;p_+%5Y;Rrq(<86>V{#I>6BR@QnuR=|0)`uY>k z?c|SW`)WIgQ$BH;FYl}5{TKa-KKC*aep+?54(^MNC)tf3#3K*A3n4%7OT(Wh-rdE& z9{;`)k5+ge!Shu-CX-ulKMVJb%|ZUp?9Sb8Io5c;|3^6M*gqf-3D(7B{!cXDm)#%4 za}k{1;G|-IhB$T9KdIl9Tncgn#pxG*HP*i=ZV$lEhtGNItr$NZGhUip9ey>@|A_y| zyl-;Me1iTZ_NTD#&GoqF@SMudH1T_aKdbE%NsS*d{x*K?)yZo9Ulpghmz?t$zrx>f z{Cb&Q260)gE_SM)SL9;^J`2UYt30N}dyDJa^>}P!cS}C!f9fd@{g=h-6aG%o_Jh+T z#96zMzgvyhGrpAmAN+2G*BRG=XW@^6KTca%J6(Ji;_(FBH{iC`?$q|edzbY*9^Pnv z^`ZYe{W|<#seVgnr)r-dmz;mU*jIZe*w5`x4d~A@{w4h!tHN!yOD-8+ zk6ULK_ej$B>%PHBy~R33+@YW!|mxtIX@UB&z0kym)b7}(!U|k^X0jl`3n3Tc|~l+r81mj za3--|67M1Uzvx%y*MpA#h2Tzr8&7Yuc=sTemRw(U8{xlJp1b1xD81CyL2q`_v2z{% zT=<8Kx0RnEZS+#RptFr ze%0nz`b_cyX9T(2`0Qk_Eqfn`TQPO?nRwU3yPSAc60hgrkAn9$`HAGW9)@%RLfyYXG4|ARcuRT9|@$)wQmO)>;8ox)4&obUz+d=z^)Rl7ndJkS-;n9MhdHLCv{b$*K8(tcE z^Way7KV4k5i2r!&JDYvGHN8LRjWa&U_#^zS&EIb3-?yG;8{cJo9(ya+6=Gv>SpV}J#hd<4(d+&qZ^W^*Jcg80#y)Nv3<@{kT z+)Czevp<*pC-CWl&qQ%AD(++Xnclv#UH<|74%&a&d4ya|a=YPnf;$3kxG(oL>$jPG zz6Jlc%l{dCdpS)hwY=s;XH!xMgC-k9}oXy>$9=<-?#9q zIlo`i&n5p^#QzuioA6qoj;8bXJGd2Z*(2ip{SA-3>}_PXj<%-u<&5@K@@@Gsg1`Ov zJ0ET}xIbw(YJ1@GJU$iJxnf`XgZvo#Y!~*5!W}Q}9n?b;{C^bhJLD$fGeG>a>aQ|> z4_;aLpP&DY@cD^eUG`GiPe)qU$DQvD)jn^1pJn$Ub{EjEPXAAGTQa7OJFKmuZdStS z11A^xe_SU$&i;$+x51|%+z-@SxMycZ`I=7d0=!4y&4yPAUQ&FX(JqJ6%Y3}?6Xw&4 zb3bvOsScK?gVOT&z4$*0zbE{g;;q(54m-xudk#ig=+<6-^}weMe~ zR~}v$^>LB^W$;-`ev0wouCKepFQ_g*gZmiVT(Hq-x|enauTEiQ}oztVq={o>j)?1cNoFV^2| zUz?#m%D^qkkG%HN=ivSVw?6*Q!+VchwZKOno|oU&^cTt7GIHC=E#^mAew;SnU7qr? z_b~apZri65yg!8BEd1&lUu!%Mxl?d*!1+}kTaoKRt`PfKypLOt+~efVX^ZfCJHPkf zHy2J7IMu|XzVS)yPh@|#IQ=LO8TFT`)0F(4?D)}-{&6_%@%u!*uP2wn_2doxY51m8 zH{bB@qB?j~U38O|0`k&RKb?L8Ub*p#GyXFB+2}tZA0yc5$?j9y%i3)4_QG$by==c& zC=b=(mJ`=2>@#d#m&r|j9)-T47Qv5iqKU6=x_DB4> zy1rZ_Ze8J@(UybP*!f5^cGI)_Djr4g?#b?L$A{|ty3Wp9`l-ZW3AwH0_QLBAcMH3} zu=}w2vi6m5o6b)3*TPSRe`)wN;XkcS>pX9?I8+gbOWOI`LU{RM+7a5d_)Wua zJG?&ZUdFEwerc`KDc030{eQ({5&mD||1_L7*}acu{8i)2^Ps*TD87zz^%#875vQ1uWQyrA@d2ui2G%B7O=A)&IfST;B^bH!R*A-8z+ws+Q*9Pzf106 z{Ri})=f?^74dC7D?-jFs`FObf^8h@S9!9{=;cZ}2EP#o3Kl7r(>VM*c(cO~rRVygTC9%XwOIJiFm}j{L*qJK(<;|HAw} zCrsf_-vMeYf5lf_|~e2##Z z&++yx=d(TVz6Ey;+}7gRRUI7QPq@!@c6`p#`;+`Q>-QG_oAZALoNaJ^a=p`&{5(GMCJ+1@ z&%d?&*~*`X;hzZ18)G_Oxh3Go55Z=dKayyAbvUU_}t&+ z253|8yN&$(EzXnm>x=99eBQ_9??!d?6ucht`@H;a$Ey*X{^nmYzXVg@8-sTF}@If4Q&>@Ke8^S7%z$6EWFCW&k27N{3h&gQ3s>(?$6&<{OTw^ zrEd9KmFvC?aHpx4jK<%lcU`;M{3vuOx0+#BBh(2h>RgdHhZuzh}3edRn1>K|PH( ze?gvC)4PY>EOsigllqp=S~xD2!EYvhZ;Mwc`UAzkiud8~#_KFU`_s!vFT3_dJX?tS zuk?R`JAuD%;FrX@A4IRJe^&_8|{AIk$spCE3G)SCo<3G&#a0B*k ziOWiLzQO!Z@;S(7gu8=(&xzYG^AGapFZRc$6mR?7P4*g!TRrkW!aL5daR2{Zcs3)K zo}D+vp$NIXczt1fhVd-^>K{;UjE%puNpr-wce`SCY#_KnBA)Q+{2&y`SU10=F01X`aSe3!p#hKHy-Wb zG-LlsIL(abF+Live0bF+e=qsn>~>(cDx6=%BM!eE_UT;oPx7Y*|G!}`g*Z-BAGO4J zx%wz;{<8UGaKEB|#&~{sx$xbAZwYZZC@vL^&m%w9dTH(bz;^7%u|Js~_27USQ#t#(`492ytzmA=I z*?Cqx4~fI_z{~ot!p=fCOWuhCQt@{$+;_=Ohtr*3&+%(LoWJo| zEHBODoulHPAODjD{2j&n8+quRrdP^*YV+Ob9j13L{u{mTc3%50KgQx$h}=o@x!F&y zzlWXg@!y7DYIcunyU9a&_4ky18}pT~+v~DhpJ;}ARb9jP5quxQ>$H8Rkp64@eN#Nk zuv>|}mOf{d4ek|k>y4k0?+WDJB{vYyyYSo#zYF}U;$K95DvQhAcvWWqwm4-KueIv# zet6HqTMVx?emUU01m_-QmlvP2c+|5W^%3`*8J#!tYcoH;pjX?zHCMli{$Jws1V08? zx3`ickJ~D*=jC+=K0WXm#Qqre_wX~^Md~p7KdG;8@vCLu=mq~f_`ks02yYy_=lP#U zo6_gK6VGLM*5dz4JjRRv-^O?Fw=f>B(|=qZZj0A8^J^VnuQ;z5fX`Q< zE{&JRbG_qIlH1n5^S=}9cjxyc_Dj;=LT?$|?d-mT=S+AX(VGCLBmQsV)yChE}Wv7w%3-^+Lfc(4S zQdHiWh+7+R`%J%rem1=4;N3&rTw!M*o~ilwfOz~$?`izo;6IG~73=OU^A+T`x%QCb zdK=?MjTdMCYxaA%Zdt0|joq)r|0VhZ=^xT|*KQ}Dh24J&XuU6gNxz`}Fnqg;OF?$e zvil4_+VkVKc7wJnf49kB1GwkmPG`S`cowF=hrRE}ttNLjJ6~%jz#9wib-bpD+a`7T zgLSfr|4;G15czkEPvL)l$JZM0`#3JtApa*nw&BrSyHkFDupVAeXW_n`kH8%Rw+kL$ z;F0vE&zgwapY*5N_uiGaCh~brzlZ(;JbUAL7yF-DCn>dSw0q5GF@LwXAEN(^dPt5} zdVC&}k1Om{Cf8U0Tm9+y+=b6Ud@|U_SCIc+{d^B+G@MG>*5SBje82I^$TYp!~Pch#H-Vy8fIqUZm@w@+)>kj+;2joi1`wDXRkn2e9 zJiB%EzmmTs`XlwLYoFl%32|%VeEJFNp}BZH2yYj>)s8Ql#bqEr5At)R{zm;H{JkXZ zNyTv-KIQcrJI>dIw==|({0;K){2R`{w(_2!9`@2dLcg-{1;(fFE3@SYlAZPnj4^C{%(VfYu|Pjr8i z2erHPQ;B~Wc$dWS7WrZP%_bhl#p5A31L3U1vjd*rXt!v8@;>D}_5V5h3)r8DZytPa zn}6DTclv3>_Z9Oa%qQdj80&6&LGcua%5Xoh57xzZvi1Cf{s49NJe>A;{EhE4e4Ek# z8O}uY)5m()AWqx)-A4Vs1~;?%_*pxNA6NLZ4gY`mTZ{f6b=kqX>&?Ft?0hOOKPB;g zr}(vIFDJj^+1qbDB`1H-adq&f`G@cT_we)M? zdt6<7r7o86uRH(VBVSCNjmN(bepl&DrT3ElK>ZzfrWNO<>VdGr45sewUAh_)Rr`m-%&W`{hW<+WDa2!{IvmW;jPmdVzSq=QLH+dVavJ;f*l(o2#(7dYI8)j0Nk1L^ z3g$DJ|D0ZffQ!#8ajSOQXRgG%I=aQpNi}Py=`~Mi9>ivW&?38BrJcw%Q{S)IA zo#&k3Zz^&8NWT=h7x>YSACoT0gZzwTCqFx%l50V3LLq;Twr`ixKPygOu)mo7nz!ti z{4P)aD*Idc(=71iM|pniC)b7C)7I;Lc(3C*h+G;xd*hj)e;^}y_`~oVgikv0FRV@A z*ADiss?+O^Yi-rR%kYN6YeIgn_)WmO7~cOH-(mc!{xtne_&mo>C-t;ZJvCNGo9O?- z-g2KuSRtOR@g9nAJia5;%LIJ0;58Vp0`y;{pOyZn-d{MOtzexzZ@ecz(&4p09Fl7% z+232U{};RQw_O7z;Dmoc{M*9+3$K^p=7fK@{+IeG;p~P#z&d!#I%oj@G5gd>ID^e+ z$8(>!G$j9>{yF`D)P4EQX;Ya)A>`7w>1()hN5KOg?b z@aMogNq;c?Kgmy%-`3VuI{RfOap;R@;Y;d`UUK}_tB+d78yl}d|1uBKR)8$O!)cfC#ApNcuD*0 zL2?<$onmJIJ7vV>9&uS9uB9Bee!ypq_-ryBXJ22%zfI(7sGsHPCqJIa9ml(pOGR!h ze?I0Y38U1VQ&f!O8{@tY4N*tfY|2z9i8u%|e&Lq|D)|STi9e5QA z<6*uK-pT2Y6ZdKOcBg;S`##^}IX~2;{u|DxmT5z31kWApwPkMz|FY@dBEOjY zI(GhYUa$e*l#WMh@o&uD%f_pz>;2m7+Qs;9#(${w^|$r)I3DfsI4*w8#qT-s%ZyJ? zeA9^UY4*QU2lMEyqW8P;&Bp8C@x8pf4);FiE2ZdvBwr=PY2Hem2)4}-1>ZU6D*VX+p{JvEmBjClU z!)MIz7N06`euHyT`v_jg@M+4QW9;-7hbsKc%Fpxq59?RO^M?K=xM%p)9^}2)oZ1VVlJU_~>V#Z4we;khn_!Nfo z2Aq=Q4vAMS`*CIV_ml5Tei?gp%|D9I{rHx?<(yw$3W&=&dCGCy`$Y+2L9QUVTjDUp z_;B;Rt*;N&aV>F9!OmXu zq&Q~A>v?sM(fAQ~yNu`L-$*!l^lQlLQuglGKB28e{!{Yx`TGr=IogW+&H(>S>!}%> zU+L|0+_*>lx69imc^gA6AGtDk-oP`BI+-LNF7o3>yDmt^&k5oBJ)h6>(7R3kaq`dL zlYq}t?6%}jU-+5W{g8ZpILG-pmcQ57Da4-v^iR<5iSH47H;dQX)^&S0FUiL-{oKYs z)-MD1Ik-LGPGYY(d#m{IoBDo^|GoK9>$YP@g6}!1qetX%7&|%mGnrm-dR54M!Txr7 zsl<1pc-Il{vfA|8F8nPeZ@EMLT1P*VdxYFkZE@?qq45>=wM+Pxg@2J>ckyek_!Pi< zw|($AcHUucjJ7PfS@^eyn;UKla$_C8|K-m}{(PgYE{^&5^NKh%z#}Iff02LM`?>G3 zmpe^z-&H2Bu3uN*RkTCQcY;^id|B)IDf+F%qcyx2#O-h6lkB4%;1!0qIW9b$>*6y5 zpXBoJDt?a@wBM@hM=}}rzSnp5nR)7^Jijj4C)(umc@TQ_`SZ2$U6)-0igRUtY@+uJ zyAQJ42VOC89Yz0+zu)e`BRBu5ng5ty-Qhe3=QAbLUb~H419(-hd+(9{gZN%_{+Ju? zLb&tImvEfvfq!xQTf(^mXFQzK^zTuJH;uoF*HC^mlkfKOu^qqG_@xz}&GIr<{j`>s z>g?K(-XZSS-zYgkXEBqGlmx$xn z;`o@l_*DJvCpVN_ZuNe~{8{nK!G3=I*YpqQe{X-B#m-K4R*8FGerD&_F@9a;@5AD; zfc+}$kAwdf{DbQ0Mg6(tJCaYu-ZASo9?oI-&%y6WzlwN#CLW#O+{oztf8&#kr-r{z z`>S>X{~yr)rvJWnn*MRTlEIn9-pA}!)h-HtiO)CUGl;+0@t-TcE5vsc`M&(2GY0QZ`8QSnjPb$ZvYWk3*5@GOKk>V&erNVyl=ocxILc0T zcAg;LjC=yzkFD#w#Opor%EF&D_%tH7f&4r872rp0_P)S7Q^=S2+)Mr!@{8dAAm8g9 zC#rd$d3!#2;^#5rrR@(}>8GP#g5U3n&l&hx=$B=;miq3D=jV8)hyNV>$M78M?{*Iu zzh=BKp5OED2Y6%nRTlnS_*KQP9zPnuS!%uKz-NQw&|UI)NnGlaTSu-N{S^F6hW9dd z&%+%IuRK1V;8O&j7x`OQ|C0V4b|$gY5dH)3TghuSZUCHkI605udV;I_$8&E65b2yv#|c7;+b7LOuJ6Js)*OqH`QyrT;exIo(JRoGTz;< zyGDj{1@2?wl3aTf{zmp+R&Q<9$1!zM2)`TrdlF7pI0N9HfPcxUMqhlVk)K6=jrn%w z3z#1t@`~pK_}RqoZTatx=ML99W6Zx{eyH*6*7pp4PLq%R;&w|u=39R&*!xv~mFuCI zct3^rd^}papTS)KcO?0N_@~xCfM*uC zFBsoIt}$K(;JgjzA>(=3TS@+H@;%I_GCxMX(m1a?Egrq$79oF`{6zjYvybiMM>6&| z!fy(#)B_ zTTNS=+&|hhaQ3q^jC@YG-^h0($H#HvTO*z=ZEtN0<1aYAKgoV8@~8B_@cv*g{q*`t z*jXe$7vW5TlbSzy__Nsf8TLzvdji_8)j7 z>^~pqFNgo5epBZcAHpr+eCroDWAXn&+fMr+9{-a2xInm!bAJ&2wC2wqd21ogb>a8} zfO`mswmo@TEJd%5*LgntzNDDn@8%OB=XvpdLm5%XVYKcIgP-iyuG z61VoobCO%YpBL55DdWS8AJuPY-B09y3I0Dru0OdB=98Mg0jD*b^8CLq95?a1CZCh> z$!H&INj@w2`^DiW`UAvybXd3iN~O+* zeBtb_ax^x7PW^lg8gP{tmktt%sk*XT0;jC)DM$_%4M1 z1^nN9o~W-nn=B7?Cyf|FY zPlo@vOyc1@^*Q!?vOkZ%KdHC!@aDi9O|H0nK7wawaXPClW_%{xCUD1UYiLiByFqRO zy?4z2&dyeL?lONWd$kSeucx0+d|u&y0dY8}E+*mK-*NVCIA6%a zSU3gXY{KI;JQC#T5B>Jyxkmj=AXk{ZQvA3i{tucjB#)hpCo%q}@$vloRl7-h2+#9) z9)a5%&P8$$k?UyuQ+X_n*L1u-abENwdjs)m<+xeOd};OjiGDMDE75-+-h=XROdf9V zYaPGJ7WQ{t@!!X_CNjw&c zM^60Tr#FRu32kNkKIQ*r_LA_w5Bd7m=_ql`Esnd`J?J>_oH}SsKMOyy!yiH~wa){L zlaK52{)f13b-vgOei8Bc2HpsG?eL1j>lyYh(|?g%XZha8&(8dwjQ?Ex_mS&LZl(Fk z<_oZ!+HoU29*4;FCZ9o@QU5t@4tB2LpIM$($!~7$PHj8$|Cp}=_a3;Z;q0)F)Q5iy zui5s!CG?(U=YDod@uw_*?!E4shQBXccLn9AxHuP;@22P%6vr>&)V2TQE#!Su@$V>) z`^fzZcPHNK;MIgzUi`jMx0&%cf=54oALn;|{PyFw!Ti_aI}ZN6a9(GxB%Bx2;mCOY z$;)9llg0H*ajnko0PAfbx%Kwl$LW7azn`{=_E~n?;hk4Lo>gc6iu(+8G67yKctiO0 zsre@Oy_pf7IDU$6UvhgLZ#v>tT%9K~zT5bCajhjzY4O;P#}n-Q$xfqu{$9e5x9}*7 zZ+D-kSc2bQ^k?w*I{As>nwH(0?9~lOZn(I;O20h+OYncE@%P!U z#qQtqi?DZ*+)qB&)sb8eyuZPFIlb@nXVGg%Zy32Acx}Sxf_}}A$SN|j)`SH81t*d=r9EOYkNdEQa-%xF5?Xz%Gz)h;|vf}xZJh!o* zjW_-_y>{}l%6?u>f3|*6^ZUekkMYdb)BWcTst*$X-?Udf`#qKK?h}+wkr|uPT3Y!}&-5KK^dE?w)2hyYq-1mmEjLZJ2oF z6tA!7cVefD`O|pyrdN{vd&RLezn-PP&wkPLmRuNLiTAJStg`WTa5K?gVI9oFvl5=O z!?^kw>;1mb*4Z1zM;f0cPx!)XPggB!*e5^32=|YZKd80*niT9;|$kP8^oiw@l3{N;Fpo!MSp*+XMH~>Z)w@v ztWv|>jlo^@av0rIsCs8r%rI+#Cst-HRPj&cwN+f3vVtSRp@u} zIj!RSI%mIXBrYw*qZ&VU!9OBDpUKZR^p=bBP3>y!EA;!)Z?69vyrca2n?IH1tEB7X zG}^rU83(_jxc7uR1nvSnAHeefKhw(hTl%y0U&nhm-n;P5<@h+CpZD=|A3H7C`38PB z{*0BcH^t|;c$cxS?h}X3c;4aP6L>sCe^gjM@J`X&O7C^N@`%GCeD;&;My{v0z9z2a z*vY`oD0~~3KZ?&7eE!0Fg1G*`{z5o^8sBfcBztf3|6jQC@VUePE&5gAerdjncr6yM ze(ZfG4rSn{ga4uVIqcRmzKfl*_&0DqvC4c~^T+Y+&;LXEL-ez-|C;0ET>c#3&sFkW z?KeyL{|*1wSZ`a%4+-_+ICM%|z<5S>PT}z)yuRi)(*KTrJiBw*jmQ5uzR%+SvAC?! z9q)b;4FZ1mAxwD8u0&na>?;sZ9T7%=gsnb zN!&(@+faPZkV`3kui=xA{8{ps$!8VcRB*q|?s~%fOuUoa5`XJ!8UNOiKh91b`Y*zX zhuhM8a_2c&;qS@l{da9YcFN-UR@leLuM&^%3wZxW-Ct&JGJp5ePe*?~xi$Rmh-V-D z&%|j;X5YV358tbYe%cG#<#@H?Z)$NrVL$jw`5ZD6KpIKtHDw0^X`}$5R}~cnM6sX(DpD1s7pV#;D2R#$5TuEq0%EW4@4wfc zunwQ+e%|jn_x;XupR>>TJI0)I%+cnUbFIDhCi^7)`;gB=zKH%d?3+%+dl|j=5!Zvf z|8StU7V(@Rju^f-|2{`)I_Gpb^0%LSb!YsF>>>X>*WqCF&PQ)|^jt+xKJk4_e0A~X zHR^Xi^Cs11uYJqC2mgL(26=geym+GL6ZFI|??>j%X5P2Vn?{`7Xt%`vZt~rnd953; zr}1|u*OOz|YtQ^t^w*>A%8=g`1oGcfAKA3` z(td_|dXfCxji0};uU^JZCD!8v`o_~g5k2Fv{}TOW=nqBi5$^L|CXW}%V*~7c%lY0F zzZT-xBIZRf&z-!iAukQc)6<-v1Cd+G{ldi$*{kI5IpU2b-g@NiCuleH-p~7#50L9m zJ$aBnZ}Rs5cGr@xPsqny^0AV3E&SMzUv-Hu4}A^M7mS_;c;ma zh|?WEw%|uK)^8K?1^D|G{{DjeI^+k@-bi~D_N!z61^lnheMMRN2h!h!`5T#^jolQ^ zgAa(`oBnyw7sq&q3c0Y?L0P?ljPxrB(o}*rtQ7^rSw;u7jqrVjWi?QDm`(v@+4Evk#dnkU_N8jt{jiCKC zeHZoS?rs??bB7-hiHV=s$_wXIQ6x ztkYTi?1ug47>`2!GxCu^-iwiIf*)g$3q#+M-94Y~rqR^abbtN>x;+>B_FSCwMkdIK}T}6DS z$a6#D+DV;V!jH%BqY3imus;ud9np874A)!EnQ6@Hz`V`qsYhHh$(sjy!=P8_Uy9uY z+;2uAcMUxS=9*KyE(v0?>DX z@s8he-`IdP$L|IB|1;|{nRQtStpuVj%-eupdH9veyx;LN z3cr$B|6$bgIqY?$|6}?SnSX-##v|Vu`FEPI-aL1kgxwQ74|xQ8S>$y+^dPhrey(Oc z1F8SH_*5@?q zGl_kBk$oG3Tt(#i(Elp^(a3#EJP!Q4hM#vazKnfy9e?_BE$=&6Cd&9slw9zcF8pm!bmzQkTC^A~WQe8&9toLfcsc^E$zqNhK4 zW)q(`@qN#{#mr;boM0*3(p)^3b2rrJEr@fB+XT)ai*F4j6>j-JG{T+x92;-unf_SD zdVp*&62yVcAjd^_@SG+Oz6eBs0f5W4lOONmGogmpeCZRFKIsun0O}W2TRKIJPEqMF zx<IVrb#PTIyrxkY!jxfJkyZp$CVG7daWTRI|L zGRmXc%C-2{z!vb53+fZE@%>;o*ar51z2Hf(5xf8#6}S$7*1Qib1~D#rz(sqwXnYOU z61)Rm1FOJOF1iF-ttS0oG?)t3+xU~U*xUHKAA|wrFcLgchG#j@7+}`7C%o1q9wdN7 z(2V$#pvfQ=^ag!F8c1TS7bwgANT;oJae)5x4FrS0aN46lF6fEPd}u2D4VZH$D4<;o zO29p|^BEfh-x6NAT@N+@&P$%r>H;*E@S8a<|drN=I-_TNP< z1SRW>UQg&>LE}FB=XUthcRQLQD=_57+eW@CcME1reYfk9ycbYy_yK050kOwqRXP`Or{yX#2n5TMIP3x>s-Rn$Jz3WU<&C7;rTx(tow2#DVZby(| zAM}umDWai)mkX00l>arC1ciEyqP1ad7_#tYSvLY z)Hbyf7Aa#2cI9ja?Iq>}s8L#+p2*+j!Nl=~o>a-eKc)uVDIh z#u{GdtKqY4yv{Duuk+vV+AoIJeldKWjo0~U`U`CQXd7Q>?I>-OcyP3sVpq(HRWT|y#iTmC{Y(m>Ptd)OT zU<&vS`~j*B<^B^SfizGA_JPVQPypx&Inrw)Azz>XKA=|Nt0iYA;2BJZKFc7Q;GmE&t1}9nMi{LI6x(R3lyud?X zJ{ZH|PXe!iUEmvVf?_xeZh(+d?!m!MP)uPQ0zZSIiR2ChOrdtcgWz>gW-9MtK^@== zrhwVt+%%q*fg9jAP<=Yj?m-if2MWPB5Pu)>f$k4*F9kBd;wj!!g4JO8(>y;1r$NhSSbN|DI)ee=!XozDbL0fP z1h#{H;2rQD_!;~TYCKO}0e8>|^Z?0V4p;;h19wtUhfS(I5CI~A`ktas^l9h=;6bn+ z90YE)@gJ-NWx;B&29yKkK?SfDtOKus^XY|Z9#j`0eApU&=L560MH#ogE(*}#EiZJ4SxYYP#tH8Z@{ z%t8Ue=dR_%?ACnII z9Myr5Q9T%5bzykbhv664`g42T>Mv*OA7$$wZ0py#VD#wvVt8FU46kd6;dT8nyv|0$ z>l$i!U9Sw^Zp1CVifwM!(p&v^a3f>nOSvW)ehKHb;RoB~HzeQcKWB?&qD@cMK%2~% zTYQpD_-xuG^1Ju-^OQhFc`?0p2buUhs8M zKNt0P(Et|>bkQIe4Tfrtj%88lGde^Kq))u`X^&}NX)kI2nDbbBL-nXyRNbrA?dPxA zn`Td%y=eBJ*?VTsnZ0KAnAuxqPno@B_K?{-X3rS8&G;ePW}j#;NT<$lQMGSB8&&hF zb=A0PTQ#j(Rt>9mRkNy9)u?JyHK|%u4XXB3bE-Afm}*Nk^)WP%b5{3#*>jOcZvi?l zp{oMdaMi+7^ks0LWj~uQa^H6YxlUjqb*I`pN6o3$RAZ{G#_04V46U=M)>%~REE){7 zhFWJ)Zx>a~n6(u(&^n8kK2hltl|E7FlZ^C9m+~TAqOvC{IZ?@pN|&f~iAtBKbcsrj z^cmjh6*anJ;1P8`!z#4#ec88{8jfX~5Ma2{L)m%x|cGPnZ10$+ox z;2O9Nz6Iy0wTB5rG02AQp?(AMLw%Ynn@e2n8&KJooW=#oOHMhE-;z<>x-V0o+KN&6 zS>b9cPs)Sjj6KP#U+q;cs$6QmWW{St@oHSU6`y#;x(~>2wH2$zj4tU`pLA(lZSl(C z8dux&oAx34HDB!u!00pMSLoCFNtcoP8eZd~CI|9OKAV26mE`5CbeR6D@Fs@a=ic7d zT=}nl=};c=>40k8G>PB`+Ns7cXB-Jn~8PE|^>#ftOEj0P&_q?RM<_Mozlrvua;9w0}(9 z$`{$R_nVlFobn{z_-OWlz1B3Q{uh93NvGQCm;Z|MWgt81*IeaEdr0<_AI;Oa*;hIj z41Wk-KBz4j#b(B&M{$_8^vIrUt4~yYvSHR&dDJ}lsXoa_uW4({$Qn7xsL%Lmc#UiS zNT*^^y_vRjidPP_HsaMMIq{k+U%znir=doN#?)4g87dtn9_i5@TIK4q^NK_BZ{K6* z>68B&mmbrWE}fS;$23niP2FisZLOJjQx_%=qGqi%t~%5H5S1?3(!P^DwXXuB8`f=W zfpr}c)ip;{*E3OF&qQ@S6V>%hRM#_6UC%^yJrgz8GsCNGc%xf=M!$GtL%gvg-q;dv z?1?uv#T&cQ?FD2@yv7V~?1~z@;*DKyVce2H8ql*<(NNGEq`TUM(0rh4E+%e11I&dt zpDReG;bkWlNJkO(vb9j;!Sg0vJ7w){>5c-@Eh^oH>K;QjL}f!%_Z~cQa<&aGdxn=y z!xP#~UV3F;`b3o%M~Q8`m+qp{XXZ#wyzI!H@*$s0 zJn9!@Pc#`Q&sv`pFa{_u(ye?dM$HYi@j6@d-bd>v>g%F9Pt?{KCK}+Pfi9|ZOZ_^t zM5V{e#v8q&Mz?sQU%as)-q;auY>7Aa#2cI9ja}(BcExK<{)jhrMU7qY#;$l{SG=(+ z-q;my?20#brO((EZ|rJaRUcZn9_4vY1M*+CYD#BQFVL!t{w@?}C;fq|sFkv;9dr&< zXNiGoLA-R`-e>xY7*m}YT3ms32cr6ZljtZg8JPZD__ILY8PInHJ^&}cNpK2W0+&I1 z^h!qkqbpjN0JUQ>Z9AsYwqrbPJEqXKqm;HCFVePS8Erde(zas;Z9DFxZO8qz?U+Mb zc-VzUpuz(#JP8%%xv&Ci$E&pMSWnxIb+ql+MqAi^8$P6+3Jl!?Z^usBb{wN^pn2j& z*W3nucTL#u!a=B@K7GgSkPB}@g|}Qd3biAawxI98$xiEk!pnanW9Riq>Z=h(!4f6^F%dA)YC;ZPi@T+ zm3%uOc~QxWN?ug*qLLTw0ont}i)vg{~O7gamRMT4Q5C#wDsS6fu=P*+=2^F^gs)Ql@$wH0p| zkesN-MKvy}@o=De6_s64$%{&_XoQPuzS^2Es`(nzJWeycVVhp75R<)5g%hQv!wRC1z{6O|rO{iuPt~Z}qMEPktlFYRzvfE6bc$-OsL7Ge0r?{;J))W~`oBFs<>9}| zkG-Z;OXj{s{hBALyo#E<{*^v6&zuphk?#o%Z3nM;rp~2PZS~*I8yVR%yr_{EuQ{44 zUUEja(Pd=R7Oz?{yz0lqrFkY+jT_#`7(MF0oi}sUFBlo|sx#>mZs(1>sadse=cQXd zn>seRm#m#PbB#{bwQQO_VsfZ{!<)5|++Xq1W%}iVxp!5+xqtmetsM|NIuso&`PE8fUxo_sUszWR-?W=vEt_b3`~2c+N5Yp(j` zujvTJj&sp?7fpbgdr6J!KGNJzs;zrTb5E&uFIQVs?POP5v?7$!P1_Ew zpP;=jXr1hkZmo}M;IDYCt?9S(T6@!P=S`pX1|R>pX%CnhZw22PnEhh*h4z>BhW1xS zz&3S$zM;=Q^jU{KKhftV`n*J+lj!pieJ*0o5$!4MC+#ck%kCf)gaLiF76Bqb6o>}; zY%3P@06jq*&}Ui+AQ2=1eQuHrQa~!`4f=q-pdaWD1^}HW+Q&Lm_^8@>Mh%0efpm}o zGJykRf#F~T&}S_p!6=Xe^f_4`&}VQ3U^FNM=5v-3_%UEC7zawhc%XA|BA5gwgIOGo z_W_-==IqnC`z!bsECDZomw>+0vI3j~`filI$FUFSI}uBPz7wMFdo2em!78u@=sOEY8djS`fHL5J!@n6=N;ofo)xaI-Z#^u7z64g# zQI-qHTsGW1FdsYy7SneK94*UtPQgWFpMs`<7eLl3=0jfueL!C@?;dI!Is~i$nIIhu z1J3~cJL5&r;b10M308p|Q2sQ3Cxp)z^WZCphgO9CgxxXlV}WXVJhU?Xlc1BqRInT@ z1H5{Y&?R6gcoOW!{vNOwR7J)ae}{PfRcF(` zLoENwvsUq#I@5K;Tt9BVZv4MpGj6XXT^If;rFrH-Y)PR|nzW0%fryz0xOL8rM9{|4*F%S;-${V> z0sX+2;8k!0c!9s`gRw8$|IDtwS1sG~fb8`KL%}N03qRID^$b`B&!6?oRnMFC ztXj{D^~_bzb@hBy&u;b1R?ngJtXR*3^~_n%f%U9f&!hERT+hMvY+KK=^$c3ine{9= z4{QTVKt3>b_1stX{;sXt?Z}4oD+Z%S{@Q&term3KGjrt6U-@E>{lAL)uY9q`t5|Q( zvEu!!JpU_lY;yX~*79FrLwi}zyhVB3<=p?GdhRXi>!N!8t+t+li|RSJsGfz3>Up@R zo{5XL0lE+6F|d=@`)9+4+xQ3@ulIRICd$U^eV^%%vGK7sUhid%jGm_(KF-GL`MT-X z^Af}BeXrq@YpujlYaM(>dgujlfH*YkP9>p8vQ^}OEjdTwucJ-;`+p5u$xXNl6U z&l8m=*%eiuq(^f9x9;ziYsI0wiOMheAu1?Wg2v>V{FJPrl2uzVh}RlTAg-Q3&+W~# zd;P7azI=#r7^UXl_3CeYG$KLgW|J4_i?rRd_`HyZP*3r&Bp#&?^TFsG7HKW*duWI8 z0fhce(~5`rx9KE0n8m5bhZ&Efzjp@4(V@Q=(qk^qqWQ2ye@8}tqo5LF`uj&I$W1Hd z`7j@9RA%nfJnL^G=->AHqPGwmn^@%ddDc30pkM2xHIrV$%Xh=iCN9J4-!mFswhaH# zm|OfQY?%JO#3gou66_a(-su66N>1_?-eIHL6dPq;awHRH?)nQ^9$j$iFJ|>ys${YPFNor)`=i z&-A-(`cyC8?H5qat+CrF?DBg+&YdFhYM=rmo1irTf9s$BTEFyUeTLo=O|?LMZ1L+% zNY8Xi)O4##PoUF66j`f7ugOLWBJaVd+RAl#A}tFhI6nof4PVJQ&l}79H7B5#Kfcv) zyVq@x)#SewkZcT92C5)Chfm*9@u9X`6UOdDuhu6TuDbJcd~2OFF9@0XjA70Y5br-$;Az3J4f z)v5~0IcuOEoMtpcr@X01M(e;U*Ro_@<(S*lDO1h82yl{`t4UR7N& zC?35;%e&p>)GA&zsCAVUK`U-W&)-UO&b8vMfNo{kyfoLcAq`el$f6>v?8+4^FKIQe zCiv5ahSgV@4BdLE&+;;a`IViX+oa8wVXZ5oYiNwttwQHbwXKntz4+jvY=Ka(8Rg=<(<8jw~D%) zD{d>hnpFiG74hDxEWX`?E=!}bteRIQ^xs?iu8vcSGFpz>H2b2gTPt|Ywq{CqW%8pO zE3KDGT9x1=si-PIHD53JsB_I)Ys>fA z%&f>tNJ6tKy16@NYGtfhsziCGmd-@IWI^Ys_0nmf=q8&d#dL(wKTGfXaYh zGIQ#c*78ov(pR1HUt?8)@x?mBRipfxkyBbLD{ab>rL`8+szK|j!2p)*uS%|*nmU&M zvLLEetme!SzuRe_M87Ol<$v(G>!p~g^FM1vt$m|-D=|}9u~t#ClC)ly zW$Dlzhht!m&)ug|cQ=e5&>eV@Gd99dL{hDj}rTkcHRFM(OBjsC}Fe|0KWsO*NtuxKa zm(e3ykvvO>b(&Xn){@REGuNVu*gDS`V2*UFZTVx>iX|z1mZVi-RyAss6ut6m=9o;; zx{ZL93c&)oK|Z=wP|0)1d5~qjtm@NUyF9eKlbrgk6GHK-vaS0o`J?~o zB`eaexHMOi)`&)}j9Hu|Yt@p~V_8>DR7EB$8qe z4kTgLMb^#!uwpXWBrQqn1h(!5Xgbey%R{v+Yr2;)x~)1;#MZ90EJ#vzByZ`ma;>&i z1J)H#YiFv&^4gkVytH*?{?u>on>5q9Ly_-- z6`S>6)t7Wx{kQbVmw$}fM1RW@L~Jk1JJVs-(egvRvU}?+uI;p{UJH^i*2P=>)_<*> znRCSQTlHZ@Y|YdRvo7MT+*)_S(qgrB&68)Acak^Ot@kJ9x^DH#uJtb1lC%6X^R0L+ zO-7@9F+I2PXXdH04wb3lc8cG#3*l`=Xgz*^miD^F{B}BhuX0O&lJ+!y7tOCBzd6Y7 zsx>EN6PNL9kb@<81^%4jcL$lfkvFQvymkD;gU{5L^Eb-NlyN&#mfu}N$2R12{4M*G z-}fVkR)1iN`O7%KpG4nu9%B4Tdpok@dE?aR2)|34&u^k)ClbCRJ|u!p`1K?DccJeJ zHlEvoPsne(ggN}>L>B?9` z{FnxPftdD@*SU@O-9zRUk;^RReQ=52?R$^k+H~fY^x(t0=n01Ir0*DfW$cAQ1Na@f zz36I*?*XIu{Y!Mm5?^h6e}nP&-Fdc$?3egZgZYE;c{;j7;s3y91?Kg~{zV={?8mk{ zbAo7ZM(0=b^+Hb-@DBVA)_o)XPL&S)$b+sV?@u!4V;+H2BfhtZ{~EGy!tWry9O@#I zJhbKE-frf4!M~23IONK*u3hN+`aHiwh@a)L+X}xLpzkna@iiG+$@iOyr!4CehHMAM z4luTp{-&(mBJ6io5PqM#S z;bUX?E%-YST}ScfIdm-mQ-IGs{QfY0eoFs%#y6=ZvGWLH?#!J;zNVAUP3(^d@>zyl z6y*~)azU)cVf+lF?>b}Mv9q53vg9!8OMXw7SYz?Y6LiJbs^~wf{X%~^<|V=xvCgsN zD(EhL2NPR|srR+WtwG;)e0m4JdozBPymn?@YcMOHGmjXb$IlVe`)xmDCR;~z5jQ{u`1{;b2j z*uR(lOUUd(HVS+1;adrPU!5)E_5?Bff=xecjm@XNiT`vQUi94x1Q zAN~Z9-}U6BFLT<_x0=|-;L92OFJycvd?EAKqx(nZZ$dr;dj;tK3ER>5aGw3~KIf7* zYr7Ah?;sz6jrg5W(d5u`_B>!E}JC(8F$X_9b_t3Eg+6>#*JMeoC==0({@ngIde)+Jszre>g z(A}55k<|ARXeoO35WjvGcScQW2)XI_)C(VbQWsM^s59mSvzPq9KytW~J<V*HD@UbWMWALpry51sA{Wfqb#@3SS-uT{`b-0M`JBhgpbN#574&?hH`K<~4 zfjMtsw==PIMpr5_C(u=wT>cUnd!vU9bMgs$qk$DlOuofF^2IM z(N_=uqH0nz`TTw?p^*LC-||{uH?w)^YqYbRD4v>ED50y^&du&c4W0;J0$y zVP`D%)}eC`x+)@Dfk%9Kbp0D2)jPy z^eM*fqg@UgW4WfRC*SqS>+{%n2VeIP*9*k;Bz3Wkdz}gRd4PHxL4Lnr-OnKthcAJ| z)&-m+Z`ZMZ7FvMb_1H~E_e}J4W9|%mevSMNgMS5`i8af(rQzpQa`-WQ74at+`2hTW z4PQDU(-nImv}2LIj6b2+)4%KV!$t>WUuE7DY;_{G=JoNBL_U?jDCof_6+mF7j$on^fq9+?2%ZTyXa{kRHI#%K9A!2!ozW&I5h2Kx1vmbJ8 zn70wRJBjOC{O!#8*G6YHv_Lkfrv%ozHuDxSe=9i;qsH6OHxIfEnNgqvYZid5`;Z?F zmcsweTGeOXjC|ywZL!e?TEO~kAnxt>6ir@6W9x2oq~VVrIzJ%SU6J)C?_T&fkTE}K zEIOmeRR(fX;j6Q6{E1@|dS1k@#o$l!wGEkIP=HK#ax@frl680s9Wmt558L7R(Sh33 z?;WpWygBPK3_qV`zJ3e&8*)$wJ8zJiIA~|qw=H8~__b8Aa0c|n_xJE|KkHGM{$2R_ z966eX&G*q+1-VJ@@jL0{W-f8viw%FSKQ+7$BfTuO)E)ji#)7yGKS2JISf6i@nTGDg%;TYj z+i~{7z4*P6_GfYeNQ5<-;Qrj z|5S2*lK6WP(+Fg)E#v#^$^r9zcu%sD@kRI(&v^{q!k?8$_ z`-qk3xQwrj$$c<>Y{54_YUTv7dC@It9)JEMe+?Pa?}H!4 z=4!454>Ml15!ZU+=}1lQM$ZCt3?=4D^bde90iQap#)q;BWras@m*GY^`K&KyeH?me0kr_k#ApSMN&sg$z4STPV_ip&Q zk(@<9J?ML%wJW5qs-fct{5XUB6l$QD`O)Mh9N)dDqcY^7C%#R<&t}B(74p%3%)^hT z(fbQ?_tMvb`kuwLC>i;8XqQ8F`*P;c@1^xce|@l=ejmntnIDF|kMaFZ)_XL4&*RrA zWQQQL65m=t%Mi;D#=GE?1DWB(xJiD3Aan#$OE-w+0_e_o;WDn_I!_h|a6vyRiCo5;iC_`e(38MIro4?o7AyRmZ|dYK%i z5#yb-&$HHBShtxqd0$69w$pbETNSW-KfYfkhWGHP4SC&1|62UqivG^T9E0uzYOyEt zHzB(RxtHs9=H0(6zfryIzZp}uxfhu*~MOFk+guirw~-y^v|`xE@w!uV?D zcctH*JbcN#pNYR8dOoB-7uo|FkFSgIrz$!wF?Sd_e}eW9=H18mcJzFNZ{Lk9|=|OBuk^hQV8sp1ZY}G*D zX?$+RnQ)Qz{n&n#96j2I_a^8`V7wx_jw1gtG1Vi_-N}6`{7ONl7xmJgIcdm!&HL$z z*c-QuYrhwN8-n<}k!!`=F4(<6oHeP_KIHsC^7aY#&fr&DWP-?#8#Nb6EM>{@>#S=y zu~cMyD|~hIA4jexzW5-Uirt>LiMFsw`i@6~;S3 zi;x`-eG>l*nd{BH?O|e@2LB;>9)aI;;kRS|ch<{|-26xkeemIa=IzFx#~7bLoDukY zmOB20@%CT|wekY~hap>+u`GPd!QKhxwPoG~=-rI1Wxusxd?)$b4NjpW06&syaxaYE zuOs&!G58YS-K_K7=nh}W^_KpV)WdoFjb*+Md7VjL3c9~SM>M=Q@*c=Wvk#6iuLEN( z$lKlE9ekOFObd_>zpD!S0-xis)tY_w3~RX?{a1;*1~Ol>MqcPzNld$-cj5c1pb?nH zS}&u&EcRC5$2R24p|1k%T~)bnMb|ELMWMSkV~ep9f?P}Nl;?c-5Z_8UyDAfhJH9c>Id1S;lQ4HMN5^yVild z$Nb@76tX4gjbR;rCYA#B#1Q5_g`NrYm$HTx8gXxoY!CeCu$*<^{-`JVj$t>7Se_%+ z6Zjg8{C50lMZ47wVsNtHN^ZC^K+1kVC-G? z;Yo7x1#`xNk66ng(B7=qpTzh!b30KVWsv=XGrtV`_bK#t#m_R>?o5me;h$s9(_jdD z{~>51{&!LRLcbv=?LjngB!GF$uY*i?^nQacQ^|ubeoeur&#=D=y^|S_Wc?mvod(d} z4h^I21^)xOlAza+-%O6WV`mt4zNb#Qu?FMF-yg_cK=-?>VKQ=_tYb%V?nzxwLHBpa zz5w;chilBa!M)1s*!TncU0I*9jd(A^_#fop8)RQ%Yyl{b-K*%0WUK}@qd_`3s)GJb z%zK@DY+_w%9pU~K*{#UMK;y~ho9O<4Tt~7tcd-`54f^J{x;RrH~(A5n6 zdy(}eA0@Q6Vlx5S4n19w%|W)4az?C&kvWH*=g}ENZUe|qTja{&$2-Ka3jM+O{gtlG z#CZpP&SrjlFRn%S=8etv_%ZoC;($NO8JI-8H_&|&KRl6*W4s)BdyTc+NDZD{&OI@H z1mV-y)Y=i~m(*JX)K}MV{M`h<7vJ6_-U#}F@hh11oJDQ3shxk%>m}x{$G2#79>dmE zWc=~(K6DR8M|Jo~>@x?xttE~ww68GdQSv*0{9Pc&b&0zRKGq?&0Q7iKBN60gGroo} z?#;LtW8b2?3N#MC>O;fGPZV<98Q)KAd*Hty?iJX685=j~3&q|x*5NR|>?fBesEO9} zc`#=jdj2Fwe%$}P%~&w!?M3FTVgCE9!v=B|Lfj8<|8$1+3BYC`b9bW48-G7Q*GJgw zhQCc2dxLg)>T))EMMk<&u*7eKx}O zZx!Q5r3;*4?_*6R4--B4XQX_@L5JPQzN&fec zzgOr>WnM6~6ojrT_!L54O?+R)TE9(9``8cDR`7lU-j{2@g;m%?cOWrWK!0C!2FM?L ztx5X26M)v&z<=1;d&fRY!}J%1MJaI)@B52vIyS;xStAT ztRuem!Iwbh#^LK)=8l5@j{JI%gR{_1*!r0{yXo)Fywk)u13kXXjbY9P=IpD=dk^y3 znb_jdyOmspAmffdpE9=({^@UBwMOS-$h0Sxh0Oa9|A!(o6WI;KTEN^tsMl=TyOH%H z-ydMFGiXdqZJ4)<8p>f#AN={2T$RWFC9HujarVbn7`}L*H;BBCt^*+&ok(4Kz~#6SC;+@{(4F}?$b5~hr}48K zKKtWa5A?l>Z^8JI&$-x*wf%^>ui!&H#v5Sg3UgAh5s7ap_|%!&s1Hr0Z!7WdByWe1 znMV5r=f}&)^(3B)==mQ1Uc_#5&WZN;_6feVB_AEhYdo@LkUNOY_mF)QxeLqLN5Gpi z@H+m?C*QxLFCLkm*y>77>m%2dc2jH~C1>q`KQhgk_ac5bWqc4QC2upB|2cV!Ucr40 z{#9hpy-&QesI9*El1|?f$gC$<{?tiB=1ronEdE9jXT%Y5>p{(~eS8(lG!T4cf z>D!3fW^DqQpNz~M__~33xDj!C86VHlcLUjF=t#zH1u&idLfZb=4kwt%=;DnKG^TX_*V2?LVgtEqwuc-zK6i?Ku;#^S;#~}1K4}l&{Y%uDdvB|_`TSC z37Z|L@g=nPgCzQrsiSk~`J9-313j2ip4?@S%h}|q407>cej`4!Lzg%Hb;pm>^fjf% z%2JP?!)F0MWDeu&SL8gMb*{u(G(gu?e7wxu+Q?7FhnKMtNFH;U^9^;@2DyQZ_h79* zqW*P5uphMBUoH@^cXMs0!=QZNlHL^X~+kL@cbU(`c zGUVrNYW#ENJ-dT_gdbsy-%Gncdfc(I5WmXcdl2#ii17*L<`Kh7_|uejFX%CJtbvBm z?t|Pq#*YwlH21G=^tIsZFH4Pvv36hJZxi~8kkj9}d<`Fc@$WEt%c8>Z=a2Tb2_)zAd9BF0p2b$S-FP1QX+Qa+AlL5Y~AfzPHBaICKxDuOo5+*jP)Q z)F7rc#B`kbVd(xH+L0PRkKT!lcOt(r|;NC!+nV# zxyhyP%T+uNAou>{XC<+9!`~{{?uM=hnL7v{j3gq+EcMTQT0Hc4l%Z#v6kc@1pTd{J*a`7pq`#wmpGyb(T&?u?(4`k=nTwD z>^WCMGC~(R(~625g~i$VdG1+h**T8P5ceWSPL^kO(a?+$X@x`6^GotF(+W%5WM__R z`*&sY{YNm_ARx3}-A<@~#-Rr#`GAo;metCsWc zp(ew(1%L8_nAcP@KAj$o4;&nFbIx(vl;h2IMRHA*b#oiowc0*#+u8p8zptKy^(eV?T#I@D3O1Ztw*jX(VMcKw4-io_p!By zG2Y46*5B<^u8r+E>?d#9%Jm&n-G0OLII!iHxAbqdZprOOF2vSeN88`l-c7rUt^EV- zR8J1r-Be45Utfkhc39J!968~{VpiiVaHWsi4wdJgt<9v?+R$7UCgXw!_kY}WQ4 z^s^Q>+w#ZW9znaAZCt0XdlSmYQw zy2MdfIy4OrvkKFO=Q{F=+q8A3);Lq$~!u z_KHZ1kLcAqF*UMZY)WcWXz#exC_IWuOiAs{kj84Yq*o0JE z?GqXon;4rSE3qjNvB`0XiAnKMv2l^{aj^+K@hv5GKx8}$V`CDN5<=r6Qxg;85)+~m z@FKBq0t8)=sZf`t1Wisz4C@`0l8_h?*(V_}G9i`!^otBnNQ?{b$$wCskQg5s&wo;) z6B2OEF*8N@{p$lGA#=RlM%`85t#og^o;5_mtA2Vn?pCV%;b`<586lOTwOY&~c=%C$` zU*IToo(b+_^Gk9v-P1YHM|p~L8ndCru`lA~}8^P-dk$2e{&tem(MTm8=UM4Q7ihRdUSb`iNJ zmD~nuwPIP?;_R$!hjNsgFKw}$ZNt-Y+|x^o9o#i?0FonH&g?4?n^(+fSyG^yy6IPJ z-WZPf%$p&2#&%3}9jYnh!{Kxy!&+L|BUtxL5|F|Am3pR9f4OOS+#)%~IC6>llK){?tpt;FGeE6!UQoZ|5;Cr6@9K>5l`%XM|B))O4XWAh6~DLa|@ zWAp5*nr5v%>2S}pq;5*v6M5693KFji9C@nMBIou~d8Lq6;3P8J7>?7;xy_~nyDBHw$NF}mTt>3k=o9j+m07aym=le z9@m`MytD%LegU^9s8_|}cyS^5xOp_)TpTL}PXDbf?AhlZOHgs7lL!i$^il?yX~k(K z&Ezk?gbEp(M>%BbT)lN3$vY0G-0WhVmSKhYqbQ?-Z2R(9cPIa_S~uglwTNR2DQl-i zcM8P>$%#>tQ*7G_$(&Ih`FWhv&VqAQtJ%Os4#%jQLAwq{`_?GV&Lun!D9=>KxME9% z^MDO6%r7ePaHUC`)-!Tku_I5{k`VXsw1Tws?40c4Z1zcZUJ?5uJ0qK8$TPCAFfU)X zMtWWAX3-YiE!y9r-5<5+1N$sG@+T*qI@2@Mjn~mS8BRL$qlHfDc;_8a_o0i+hCwfl zi3t>4x}Z@mwEKlcUQ3~K?|oy(aj0Lb??+V+cbj@9uykK&xZC27XZ7_P6Yh2}VR-JI zRpD-3<_$aF@AL5P4{scI&#Uz#lCGXTe!fx9i1{DJS3GiUYQzscK0i>_V`IdIXFn+o zA9p!oUfDJs+CAhR>0i!g^LJ}fBg@YG1Ut#?N@{pjK^XS~0Qy!`Ou z;Qn3PMzvU5`GKo*hDP0)S7GDEEssSldMm2gxn&2V%1!+E@-s*Oh?*XMpfD}WH~O4= z>5-r7jEKHFyKnfGJD-bQx1>S4_uoAheNT@?-`zjGQp`((_FZqA(Iw`KhK&M$8C)2X zw)o5&`=);NQpJg}gBEXC-+Jb{ z*rJ0=7JFZ~5c_Dz+m$B|xx2^HnUmkFad)pCyMI45=2+US9$u3kuNS>-TaT`Jr*d*O zTH^2>$;dame_bk;j*ZqK^$=LdAne4}UIVb5NVpY(Ij+%4tv zmYnPu7ja|n`SV|9#MNJWUVQYg!8Nx3zBIn!_=E4Yef^{O=bsFTDqej@Lgw@5R~>vPETPMRQ^&V?j!mc@ z{P@G!zpPGpIsDX*(;A;mn781AlBF*+NZhzJw(di5af!9-)%fc8tJ4x2JXQPU!*_2= z9QfylM|Ul~lK9lFS!Xv#Hcgt+vGs|T3wtLG{qixJywxjbPrpOe8n`7NxbC_0 zk-PnpgJ0Q}Ti7f+`9S}+RcelUKKY)Hw>rLD`hIeYgf_cgc&Kv9nzV0UdH9vCDb*+S z{rXOiqLjozYc37`>E)D+^&h8~{BSDe-hu;zt8A;2+A=P9<3l5&Q$3%*f9We>lTs(` zThMY%>}#omzWX`vu9Fv2i$-sG@ZQH7_r4UhzQK(Xy?QUbYuL%F$@les``&Tyulizp z?{0P5XC5lJ-n+)f{$2h!+_F!dgc*msbRXE~P_1Lnx2im^&mRl+M|<^nvrm_hE&X>a z`lU}+i@ICBU*gqw>eqL+DtbG!@0m-_Uak52Q+*#^xA*(DU61y?I@q^pLwxyuqx{|G zHcboe_hy*eciCI>`)zMKHR$a7FZ65Yw|M`j2S4uT9~v{R_OCVi?`h+4#9D&1^r&EB4*T7yG0Qns_2~d(4!_2MtWFbGgy!w+EFL^*mN^ z$Zc@nq|YkG|KT?{_x$5AXS$3W{KhMTJyvHe9$eCBV^H6z9}KROcD7>f;wnQ{O^k05 zQNH_-<0poB^sZ1m<5pH&F=R^LFB;)E3$F~m z>xG9W4{g0Zf!#-3TPj(Y6Tf()PG&qR$||6;};-NX9zIrB-z^CQ~+=-;7M=Kj4mio*jV zGRLj=O0E}Kn%U>fj;#JqyqXzMJ>blbub;~de>D8#k~McZ>J_CXy#H~6)8PmDW<5G>==ncK&dK_D?e=d@ zr|-=QdUoXHg}?rgbzek<3zN2W82&+z=C3~TUE1*3_k1-W|;JiPAM z%6;E|pv;Jm7QEe|@)iFPcZB>N__kxzh?s~!(w}RxWW<0EU;lO1@DE3<>#=71@I6(t zUrkuO`plN@*#pu)`sl7NinFhWymQBC_m$blBNmT%DD_Ns^*#r~UdgUE^3hS_-)}fG zc4Se-{xR+sri`roVxWiL)%7E*&Y2Zd=E|j!ao3jJx2I*3QC@x8eD~zolu_G9`FKz1 z{lKV|6{r0E*~p!v+GXYsIaKz>DE}_i0w(Wkoin}qBl`w#7@YIofuN_i&7GgK|L6VP zzw|qh6S(E4xy{S|p3}VOnUFqBeR8iPhP}0FMON;`bMv=1NL`d$@NOsnM>f2dTYc|? zd)GCsnD=O*hwr^BJLNq!{I}D|Jx1qEnfB|#FBZL&cRKBtNlnY2$m=j^$2SYk*2*8V zXjHq9yCd@#%&54ra{BoEE_GUrj-0eM|8Rrccb-^uK7Y!fgHw0xYglk3c+%0{jgkt& zA6OJ|#eHT$>dJlfTeaO<@Z|!(XYz}#7SulFwx{Lt=A--63-#_ezu)Ll{pbC@ZPO#8 z&wVuhGe4hwqfgFh*kJD;KaNhh{`@nAe|Qvr@I&~LO1shvXMeX~_FH)i3s-sna%Dn~ zcM7Wwomey{p={ARV+J1eIvY?lEw!-x>rdwt9W6f4Y}1(~Mdg!ASDov3yy(7VeV=H2 zwOVn#gFl=aT@qS+*ZAVz?;a~De(uTlE>DYIRh;qXUY~W6mcv zn+wBdkJ+9!e&p#ryT;U?^zhR5pWGNTU{S}1#vExgwqVAu9;xMqj&0@h`l5R2kBwbB z`Kx_Tg&Z6^=(#Way2t)8_UFB|njZYxXWW(>scl163?KKB*UI$|JofCk;X`^9_)k1G zuFMaE4u{=csdTz;@szq}JC}MdUfwb8j>6I|2j_Qse(ti;`0-<_9`HL^TCn=Ttlt*b z9{+G(kExxiM2*j16Ey6>hbD}7$%4Yq8i%Q%c=zKnKa=FLcR`xuVJNfLu?mZG$E}i^o;nBwDQa_qJ z_tEm_?{0U;lx?3(&+8QuHl^*{=5Jp(IA)4(@#@Y^Caj*a_~4aUHx7S3h5IPys|^3u zO;%D)$?)vF*vz5=Co?oVlaO<=M-DB>&dko^elIO&XvWygj2zwUF*?9G+K0#A+!t~q zFCtxf@y5XQ&Xdnk>eh1pKG~Bz59Q++H}lpHah}ELEt{i&_X6CvXLizq3HOL>Tu3Xu zo?H;S_R`k+C$|JX}KqGhR5Kc$E$Q$_3YU(X9i!)I~B9C@!UL;rjieoOPnYXiqsER|r4Jm7&FGUiCo{ez#AEjLR%824 zoZ#i<+S2~>+9?1>+c)j8|WM48|>%h=k4d?=j-R^=kFKb7w8w{7wqrl z@9pp7@9Xd9@9!VrALt+C9~|Hn;2q!-;2Yo<;2#hW5Eu{?5FF?g=pE=2=o{!4=pPsm z7#J877#!pk5QEK|!GSAg@{+&D5J7_++aujCe|OPoc+ za{=Bl@qUn}8jj48Jjb{KT<5I`50>4B7v`4~xMRbp9+Or`gr+r?x0ufNNg?j;ZEj9% z`;N=z8K|DMUV*AM&9tIol-zXN`Sy-N)Z4e-sZkz5Sk}|n%sx(ADcR$SOQU!I6_#Bb z=g1pgJR-v3blH)~yV=6xXt@}fm+7RbBeDyNOH;?@Bb=0$mz@!lpFb)#FDsun_|E4> zJhK{Fk~cOxFOzq68IGZO`9sswGDZ~_@?gO&93Sfewu`KnwHgo&A=B6-ipWB~y7(Rr9LGXjY5HJ)(&=(2P;WJ$QdQ;DP zRoCBKwQTD7zx8+!UGVZl$OQJbm>N|dW9=snr^g=K^wq;j_hUJ+RVc1>Vnc0zHA2aOCX5|rQd#3NqG}F`FcK7V= zAP@;knWzL5DlS+>1<`1zXb}?)Wl;j=Ar%5E5=8M;Aqfzq%&I7*Se4KBoO^EH>FL|u zkbnGxuKL!!=bqpBopaCQch5P$-}!aY%W;1#m;-sBwE8KXFb@h~h_bu>7IxEcRG=q^ z7piG!*n}&vV`sJo`sjOv>HU%IDTZ^_?@KvuBkbt0JAuUf6g<|$___4zSL!>_uylzoEZQjjAM$e1@O?pe{q~X6=%y>T zj%*s-cm$2EI?(SIFUUtPcJL-tyDFGsXw*Mfx)hrUl8vqm|INc_o`+Ep(eOPec7e{!H(Rom)O5KxPwVkbt(EPf7p;79`CO0A=mPj$a?&;D4xsOT2luiYIF;)@ z@Xdh!I_{qi?p0p>>aS}e&t3~?Pa3^W=3qt z5#WBheI8`o1S^%3K1r%0tI#O>)rE2a$%6nevIr66KB@V|usx3@vt!`n>@xm~KEJXq z{PsxryTmKpd7xUk;VXx}^3ivG=nJ=ZpMCW_I);s!m=Jf{%SqE`3Oy@~?7y66YI7GJ zdpB$jLI?R4)vujdr|UGOQG#^fU>+4}uw?t8)Fu`9gYT>p~zbGR<&goROReM$<- zf#LBh9ltxNDe+rQ?`Kg}&HA~S*=lOT25Yty1kX;L@6!KGkluwK2*T}u3#}baNMGOs zNqO#jC28zS9N!`Op8C=9avF1npkNzQn!mU-yJO$2Ql2`8nq}3(n`J9i8*u4##*^$q zKL5hEL2}K-A3>yK@$#}Xsx!Tit4As>!spkWadltJXD7<4dD&Q{&SKWEfLeI{hOqg< zviyp&@M&yN7V(g-$gtSB!SV>xy%wYk>%GOC#l5@!J4I`XcDp&rPUJSmf?Yec*@`zpYfsNO^}Ux35nDV|tg`urXx@ z$c9w(J=QKyVp7(p3Cq0ph#PACDPX>w~mzoa_IT)wf;v1j70j z{sg%o87muY<#pJq6=v=(JFykTJ4m*sk_Q(WD2r!=*jz0+WK;lM9zV z88m9|0c;jCtmw)+{5+qUJ^s#eewQ`A>CaUBx~Bt~0t>Nzf0N>bF~6#!j1-o{z+;46 z2dyMWW$H6rsG5SBq6Y;U%+0V0D^?ugc7Mj*UgejIwYk!i$}Gbs1WM9s<> zyI#x%E8eWwqL^bT3o&y!EheogU`;uv$=@_&5U@y`L2X_|PaC1C%wvYslq#^L@Ke`O zSfdCmV1Z}?;zc{TZ*UG-BiZ7@Paw}V|8VX6SA-=8UHBowrw|^)w(=^jzXq2^!mEPs zfxZ#-zrNIvu}M|YjgeK#ZWu|0Z6^}UReqlIQY5^LD_x4Sx`>rxVPYy@toSZq?8Mkn zvPyEcgJ??_6lP?|Fi|Z|Oc$qQq%k42c?N~`>;xmAlv#u)Tb%Rs9yx8grFxnY`=_n9}76B@9vK z`KTC9V{8gd&5jqh>49Y%&o4?m+Nx}pSbT?ymg4Y;a+|WK(a>=BnJW<*1#kcwUxfXQ?&C zCi;OH1a@?}fl;im4P7k6m&xU@DJah%W*V(>6V3lGKg+@9JznfDR;ya!$Ms=HH(qQ~ z5u>sKHC5WIx@uI-U-UBMK#jH;$EB3bxsDfSX7YAi3}J~_Y0;A`x%%c1rn(r9#MY3d zlvvv1k1ZCa7$EV)@ttA2&&;6EL{LI76nt`85{~oX$cn1=8k@2G&yJKGi})f26&1;< z$;%Ju6WKy+#lN#kxSiS^mb~9t$QE}PQ#n13FJC-6YKY3;UL0xCRo_z_FG_MZZ6y&o zx!sh|yna)P_|hs9lC~sJ1=%)vlNph$K_$OQW;+%NgMO8n%$sQ-Ek*dmPR+%?v{`zz zpxKtoX7j!ws(rttP43J}K zHE!FXyF$k(f?nT5cGccrg2PBmqf0j8C#cr=I$WM6p4KSdSdjZ#3)sFHPi$q1>@rca zs4Oi=Ex+c3W>Abrd9t7#&c<_&j3UFi1-X^mOEQRE4+Jtktm^ne1Y9$d{b*a~OtZxH zjgZ8Qz4$&9(rGluleH?;7-=@IU{QepV7#U54PK8Nsr0(bZ#Hrz?@B>CQLoLI*X)Zu^v8^VM3-*wIX+* zSYTU-BOh4M+r1@r2o?$zEE{xOBO7c`vAr77X-kK>fE7MlgT0hNS)Q962D1ioTPzbY zSqO<65HyM-uj$;(f<34c5{$4)&t)nR9wlr4qw?szp^QY97YY-K87R(k%!BE#EpLQ^ zV@isdD3;wujOb0Rhi%=wQZWBve=^&mWTF$o9AK1bfkRorD0sQep%UfwWyJC zjwO`qiKdFBMQu1v<#VOUBKsO{CK_L!0VNqPrkK?RNm^uVk55FhkQRRd`=S=#R*ie-4%o8oIHnt}u^iyft3XsbU&Q)HRn zyB_ZPx9mi;N9w|lbFcm8_%a7mglM0SCq`@qGAcMW)1nG@`I9?jvskINM;|cP_}~DL z<_s+|h$Ps&j}6?G3B=k=T?5M6wmXs>)kifYis5X09cW{&{Q^4b_DUCdogL;I(c<-O z>Boy^^P0~ipQ7<1rk-=H>P@>@Gn}=}nzK+X-o+Mw zSB7nE9rY@-_agMLF`f7xb#H7|MPW9rQlT-^d`G80k=-mC zIUC%fOzKRmA!v&ozRm;(^g3tE%+=1?^tsuI(UYA4Iyt?(^9Jz^spGqJgtIN{vb-%{ zx~DlT-A?}Prm(|J@7Fj*e5vc`mz2CjouX+L+kw4V*T;i-!t!dX6=FGcd;ub~Ci95g z{duRITL(H$%}(7UCOCCXKTO%_P~!~dwS|*n{}&BFYN6ByQI;h_GqSvvl6>o@=9*C% z{dsFL=^LA}v71lLNM>0}mKzh89T`)n+7g@(HEz*~-aM1Mi5y12H5PWyiRWtfh7&>e zUAzsQ{&1wd2B&uh%y9NwX&JhvWrV- z_{f+T6)={vA_Hhqj8Ta)+LriqY-GP(7Zs?`C+7S`w*=x=Q^(r0UMJ;6;MDEhN^@zB zx$~ai!)8hEUj|weIzC$Ak6AYX^w*#^I5iz;_A*x8s=lo1o?))0nQ_+Nw|tBRv{G>E zST&2)flx_XoUH03f2Lf{aO_sLoQ{Syqo2<GK$I6Bgd^YzDw4jhexIF)n3(V?$Jm0rFhs_1bmCF2#O1iJtsI+?n4R~*gWDIvXf03sHhJLtkSM>%3%VYSy zP&y~o+smPR2&Lh+7B+UZEqk*yt+Ri-{8-K|dEKUV`f0{al>*>0UqgOms85dc14EZg3mOf{z3J zzJ7C$w}<FzYbg@>o7(BHfJeaN;2H4ntv%lJT>lrm z4vxO7$6E!?1_NLOTm>e<9M}VH0=I&@z~{g}fQP{o;CtXD@H#m3?jG+runL?B)`5$` zTlM)?ef}=@PdC;z26ZoJ>?y2qrZIUuaN}6_g2t%gL@W6#n<$-u(RW<58tak^;-_b# z6~t4rTH`|JQ1nbRk`>~sajtvOx$&<&N`KzteGuFZJ_EiCz5$*AFM?M==WRXSiC_&l z7Yu?c!7SJV{uF!(ya2r0d%WKRtHD}uAs7OG1m?gZxCPt=?gbBle+AEhgW!-)^msj> z7pw!9g3E#4#mPY33vbouo3BsQ1?IaexvxIu`k}%u?vQ{+eM-+=zY)FS6xMfHaSr;H z>$$FaroQU#^*vWQJ$KJ^ul$sU(z$!3Q=FrZ-bbG~I>$$G;-&sCUXE7z>AA|TdzZiH z^i1j9Gj|oe(krZd?tdcb{Vn(k_!{^}Z~#09ehgj!FN1^NRq$KT@nn+!F-`J+(MkO3 zC%s;90eC0q1DAq9a2Xf_yTCPI8e9vC;Qe4PxE_2Ed>H&0xE<^V_ksJtm%&5eQSeRh zZ{R8LEcgL<9=r%%0lxyTgTw*OH-Tfo31AI43!D!w1bv_%Yyl%+47?XigCeMcec%Rg z6SxK33hn@(0vA$ml2ej*~M6}@;Vt?0#5 zkepK*wUy#TqjgX!xK|m(!^vdv7M-rY4@9r4@)KXtil54R2VVu^@fg?V zz{}w9r<2|(;1aMCWWkN#ZXnt(a{W5^A$S!W{qOWE@NQ5Bw}4NBFMuC_#4}0nB(ND= z3EmHG03QRN0gr-jgO|WBf$})yJEQ?;g7rY-)YY}xUt?F{Kj1v?#b7fS2k!&Z;B?~J zSrbVvh>w$fk_C;{K59onbZSSz^~)6Z`i84aYY#H^!A39)t_JhqX0RVT2%ZA^X{{4o z11TJZX!L7`E}BmF?$=IQ(Ke&2=jG_5dDcH`H;qddtp}I3t!uR4POz)9xDSmQO&vxJ zr-p9x_eR*dzSGXt%?+dT9rXsu6DKEB#5a<^Ud!>7jEm!~{_5nM`m1D_=8}?k8Y_~M zl3`A!uI66yN^(!*sTb(?yIMAtD+*KCy7KB-lt%aNr~7C>9J5YFy@n1YJ$tgpo)h%~ zjhS|M%5vsWVMkGZ{k-iw!E;`9QKu!Ax+C>s+~$$Sx>Pj!L$;Hw9RR*1!x%Q)2z;q8;C^ zduuf+x!ow1vHD=oEaDI~+>n(2J#U#WJ<>OD+UHr*2ufl0$;_!EcEdvdsj5>>nJi+W z;+G>;7y9s9N^G2)dQyGWc?|V}^I6(JWYgY@_$c&3Kc8VmFY}aG7ejD~Pe^Zgi8D~o z=+aC(%CDd&ADA)$3LRgDRps2JdYhczRO4aYI0eNMqBj)Nx7N$NO-9-t!y@DT)?4DtGd$GoXH^VmKp-Eq5r3iH za?i2eRy;j&2C2eHCY=cJQF*|_7_zW69Srq|gI?IH^{od^Z?K7LTyGo0b%_(#8r!{% zTwT_pB~wCorb{1(yUwN{wUF!Lja(R;Ar!bu4adULJnEdudM+IC$FX#<1tT+XFB^>u zoX@Hq8vBps&x4kE)OF8PDs(XNpiDE=q-6tF%8^(p1_B4m>Qv6%EShr+yuB+Hiq#Av zbISK|Z{uylooH^Bb0~oiAs!9Hx%cGju+XucfA{>4t_QnLOx)W2O2-LZKlA>gGtqfb z_m>iXk{Ibcx9e2z>F#^^x9n3pA5HwQ^DzClbRyevFyVKv>-bp5lO1PwZtZ%$`<{;1 zx=!vstownEE#1d=?DKYXtnWP7`Jdi5I&bKD-23a!#qKp7g~WX4X0KT&%V18106$&Uv_(&zW<#A-jPS?3$}Un3iFQu{|9|1 B{JQ`E literal 1231744 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