aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-10-31 20:15:32 +0100
committerGitHub <noreply@github.com>2025-10-31 20:15:32 +0100
commit82f30e2cde5207e5b51301633686b2c7feac54f3 (patch)
tree2bdc9a39be42b9e781619730fc6558afe0783838 /zellij-utils
parentFeature: watcher clients (#4487) (diff)
downloadsl0ppij-82f30e2cde5207e5b51301633686b2c7feac54f3.tar.gz
sl0ppij-82f30e2cde5207e5b51301633686b2c7feac54f3.tar.xz
sl0ppij-82f30e2cde5207e5b51301633686b2c7feac54f3.zip
Improve CLI interface (add detach, switch session, blocking zellij run and more) (#4492)
* initial implementation * fix tests * move more ations * screen adjustments (does not compile) * plugin/pty adjustments (does not compile) * more progress, tests not compiling * fix tests * more progress, does not compile * more progress, compiles, tests failing * tests passing * rely on Drop for NotificationEnd * atomicify some more actions * fmt * move unblock input to route * don't pass hard-coded action names * refactor: consolidate completion channel logic * comment * track last active client * track cli clients explicitly * use the last active client for cli commands when possible * fix focus-next-pane for multiple clients * various fixes for multi-client actions from the cli * add detach action * fix tests * add switch session cli action * fix switch session deadlock * add and layout to switch-session cli action * blocking zellij run: add NewBlockingPane variant * blocking zellij run: wait forever mechanism * blocking zellij run: thread NotificationEnd as needed until TerminalPane (tests not compiling) * blocking zellij run: update cli * blocking zellij run: add command * blocking zellij run: finish implementation * fix tests * e2e test and close_on_exit fixes * fmt * fix e2e tests * fix plugin tests
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/assets/prost/api.action.rs3
-rw-r--r--zellij-utils/assets/prost_ipc/client_server_contract.rs68
-rw-r--r--zellij-utils/src/cli.rs27
-rw-r--r--zellij-utils/src/client_server_contract/client_to_server.proto1
-rw-r--r--zellij-utils/src/client_server_contract/common_types.proto34
-rw-r--r--zellij-utils/src/data.rs76
-rw-r--r--zellij-utils/src/input/actions.rs118
-rw-r--r--zellij-utils/src/ipc.rs3
-rw-r--r--zellij-utils/src/ipc/protobuf_conversion.rs181
-rw-r--r--zellij-utils/src/ipc/tests/roundtrip_tests.rs155
-rw-r--r--zellij-utils/src/kdl/mod.rs73
-rw-r--r--zellij-utils/src/plugin_api/action.proto1
-rw-r--r--zellij-utils/src/plugin_api/action.rs4
13 files changed, 719 insertions, 25 deletions
diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs
index b835236b..8f381ee0 100644
--- a/zellij-utils/assets/prost/api.action.rs
+++ b/zellij-utils/assets/prost/api.action.rs
@@ -476,6 +476,7 @@ pub enum ActionName {
TogglePaneInGroup = 87,
ToggleGroupMarking = 88,
NewStackedPane = 89,
+ SwitchSession = 90,
}
impl ActionName {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -571,6 +572,7 @@ impl ActionName {
ActionName::TogglePaneInGroup => "TogglePaneInGroup",
ActionName::ToggleGroupMarking => "ToggleGroupMarking",
ActionName::NewStackedPane => "NewStackedPane",
+ ActionName::SwitchSession => "SwitchSession",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -663,6 +665,7 @@ impl ActionName {
"TogglePaneInGroup" => Some(Self::TogglePaneInGroup),
"ToggleGroupMarking" => Some(Self::ToggleGroupMarking),
"NewStackedPane" => Some(Self::NewStackedPane),
+ "SwitchSession" => Some(Self::SwitchSession),
_ => None,
}
}
diff --git a/zellij-utils/assets/prost_ipc/client_server_contract.rs b/zellij-utils/assets/prost_ipc/client_server_contract.rs
index 26b5a155..c977170c 100644
--- a/zellij-utils/assets/prost_ipc/client_server_contract.rs
+++ b/zellij-utils/assets/prost_ipc/client_server_contract.rs
@@ -119,7 +119,7 @@ pub struct RgbColor {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Action {
- #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91")]
+ #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93")]
pub action_type: ::core::option::Option<action::ActionType>,
}
/// Nested message and enum types in `Action`.
@@ -309,9 +309,13 @@ pub mod action {
TogglePaneInGroup(super::TogglePaneInGroupAction),
#[prost(message, tag="91")]
ToggleGroupMarking(super::ToggleGroupMarkingAction),
+ #[prost(message, tag="92")]
+ SwitchSession(super::SwitchSessionAction),
+ #[prost(message, tag="93")]
+ NewBlockingPane(super::NewBlockingPaneAction),
}
}
-// Action message definitions (all 91 variants)
+// Action message definitions (all 92 variants)
/// Simple action types (no data)
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -629,6 +633,16 @@ pub struct NewStackedPaneAction {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct NewBlockingPaneAction {
+ #[prost(message, optional, tag="1")]
+ pub placement: ::core::option::Option<NewPanePlacement>,
+ #[prost(string, optional, tag="2")]
+ pub pane_name: ::core::option::Option<::prost::alloc::string::String>,
+ #[prost(message, optional, tag="3")]
+ pub command: ::core::option::Option<RunCommandAction>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PaneNameInputAction {
#[prost(uint32, repeated, tag="1")]
pub input: ::prost::alloc::vec::Vec<u32>,
@@ -984,6 +998,51 @@ pub struct ConnectToSession {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct SwitchSessionAction {
+ #[prost(string, tag="1")]
+ pub name: ::prost::alloc::string::String,
+ #[prost(uint32, optional, tag="2")]
+ pub tab_position: ::core::option::Option<u32>,
+ #[prost(message, optional, tag="3")]
+ pub pane_id: ::core::option::Option<PaneIdWithPlugin>,
+ #[prost(message, optional, tag="4")]
+ pub layout: ::core::option::Option<LayoutInfo>,
+ #[prost(string, optional, tag="5")]
+ pub cwd: ::core::option::Option<::prost::alloc::string::String>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct NewPanePlacement {
+ #[prost(oneof="new_pane_placement::PlacementType", tags="1, 2, 3, 4, 5")]
+ pub placement_type: ::core::option::Option<new_pane_placement::PlacementType>,
+}
+/// Nested message and enum types in `NewPanePlacement`.
+pub mod new_pane_placement {
+ #[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Oneof)]
+ pub enum PlacementType {
+ #[prost(bool, tag="1")]
+ NoPreference(bool),
+ #[prost(enumeration="super::Direction", tag="2")]
+ Tiled(i32),
+ #[prost(message, tag="3")]
+ Floating(super::FloatingPaneCoordinates),
+ #[prost(message, tag="4")]
+ InPlace(super::NewPanePlacementInPlace),
+ #[prost(message, tag="5")]
+ Stacked(super::PaneId),
+ }
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct NewPanePlacementInPlace {
+ #[prost(message, optional, tag="1")]
+ pub pane_id_to_replace: ::core::option::Option<PaneId>,
+ #[prost(bool, tag="2")]
+ pub close_replaced_pane: bool,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PaneIdWithPlugin {
#[prost(uint32, tag="1")]
pub pane_id: u32,
@@ -1813,6 +1872,7 @@ pub enum ExitReason {
Disconnect = 5,
WebClientsForbidden = 6,
Error = 7,
+ CustomExitStatus = 8,
}
impl ExitReason {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -1829,6 +1889,7 @@ impl ExitReason {
ExitReason::Disconnect => "EXIT_REASON_DISCONNECT",
ExitReason::WebClientsForbidden => "EXIT_REASON_WEB_CLIENTS_FORBIDDEN",
ExitReason::Error => "EXIT_REASON_ERROR",
+ ExitReason::CustomExitStatus => "EXIT_REASON_CUSTOM_EXIT_STATUS",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -1842,6 +1903,7 @@ impl ExitReason {
"EXIT_REASON_DISCONNECT" => Some(Self::Disconnect),
"EXIT_REASON_WEB_CLIENTS_FORBIDDEN" => Some(Self::WebClientsForbidden),
"EXIT_REASON_ERROR" => Some(Self::Error),
+ "EXIT_REASON_CUSTOM_EXIT_STATUS" => Some(Self::CustomExitStatus),
_ => None,
}
}
@@ -2396,6 +2458,8 @@ pub struct ActionMsg {
pub terminal_id: ::core::option::Option<u32>,
#[prost(uint32, optional, tag="3")]
pub client_id: ::core::option::Option<u32>,
+ #[prost(bool, tag="4")]
+ pub is_cli_client: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index da1f777a..0fd52473 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -388,6 +388,9 @@ pub enum Sessions {
takes_value(false)
)]
stacked: bool,
+ /// Whether to block until this command has finished
+ #[clap(long, value_parser, default_value("false"), takes_value(false))]
+ blocking: bool,
},
/// Load a plugin
#[clap(visible_alias = "p")]
@@ -686,6 +689,8 @@ pub enum CliAction {
takes_value(false)
)]
stacked: bool,
+ #[clap(short, long)]
+ blocking: bool,
},
/// Open the specified file in a new zellij pane with your default EDITOR
Edit {
@@ -940,4 +945,26 @@ tail -f /tmp/my-live-logfile | zellij action pipe --name logs --plugin https://e
#[clap(long)]
pinned: Option<bool>,
},
+ /// Detach from the current session
+ Detach,
+ /// Switch to a different session
+ SwitchSession {
+ /// Name of the session to switch to
+ name: String,
+ /// Optional tab position to focus
+ #[clap(long)]
+ tab_position: Option<usize>,
+ /// Optional pane ID to focus (eg. "terminal_1" for terminal pane with id 1, or "plugin_2" for plugin pane with id 2)
+ #[clap(long)]
+ pane_id: Option<String>,
+ /// Layout to apply when switching to the session (relative paths start at layout-dir)
+ #[clap(short, long, value_parser)]
+ layout: Option<PathBuf>,
+ /// Default folder to look for layouts
+ #[clap(long, value_parser, requires("layout"))]
+ layout_dir: Option<PathBuf>,
+ /// Change the working directory when switching
+ #[clap(short, long, value_parser)]
+ cwd: Option<PathBuf>,
+ },
}
diff --git a/zellij-utils/src/client_server_contract/client_to_server.proto b/zellij-utils/src/client_server_contract/client_to_server.proto
index 9ec0a49f..cae8b6d3 100644
--- a/zellij-utils/src/client_server_contract/client_to_server.proto
+++ b/zellij-utils/src/client_server_contract/client_to_server.proto
@@ -68,6 +68,7 @@ message ActionMsg {
Action action = 1;
optional uint32 terminal_id = 2;
optional uint32 client_id = 3;
+ bool is_cli_client = 4;
}
message KeyMsg {
diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto
index be86e0d1..254a2a75 100644
--- a/zellij-utils/src/client_server_contract/common_types.proto
+++ b/zellij-utils/src/client_server_contract/common_types.proto
@@ -227,10 +227,12 @@ message Action {
ChangeFloatingPaneCoordinatesAction change_floating_pane_coordinates = 89;
TogglePaneInGroupAction toggle_pane_in_group = 90;
ToggleGroupMarkingAction toggle_group_marking = 91;
+ SwitchSessionAction switch_session = 92;
+ NewBlockingPaneAction new_blocking_pane = 93;
}
}
-// Action message definitions (all 91 variants)
+// Action message definitions (all 92 variants)
// Simple action types (no data)
message QuitAction {}
@@ -364,6 +366,12 @@ message NewStackedPaneAction {
optional string pane_name = 2;
}
+message NewBlockingPaneAction {
+ NewPanePlacement placement = 1;
+ optional string pane_name = 2;
+ optional RunCommandAction command = 3;
+}
+
message PaneNameInputAction {
repeated uint32 input = 1;
}
@@ -605,6 +613,29 @@ message ConnectToSession {
optional string cwd = 5;
}
+message SwitchSessionAction {
+ string name = 1;
+ optional uint32 tab_position = 2;
+ optional PaneIdWithPlugin pane_id = 3;
+ optional LayoutInfo layout = 4;
+ optional string cwd = 5;
+}
+
+message NewPanePlacement {
+ oneof placement_type {
+ bool no_preference = 1;
+ Direction tiled = 2;
+ FloatingPaneCoordinates floating = 3;
+ NewPanePlacementInPlace in_place = 4;
+ PaneId stacked = 5;
+ }
+}
+
+message NewPanePlacementInPlace {
+ optional PaneId pane_id_to_replace = 1;
+ bool close_replaced_pane = 2;
+}
+
message PaneIdWithPlugin {
uint32 pane_id = 1;
bool is_plugin = 2;
@@ -619,6 +650,7 @@ enum ExitReason {
EXIT_REASON_DISCONNECT = 5;
EXIT_REASON_WEB_CLIENTS_FORBIDDEN = 6;
EXIT_REASON_ERROR = 7;
+ EXIT_REASON_CUSTOM_EXIT_STATUS = 8;
}
// Additional supporting types for Action messages
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 53425e0b..7f700d4d 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -2582,6 +2582,82 @@ impl FromStr for WebSharing {
}
}
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
+pub enum NewPanePlacement {
+ NoPreference,
+ Tiled(Option<Direction>),
+ Floating(Option<FloatingPaneCoordinates>),
+ InPlace {
+ pane_id_to_replace: Option<PaneId>,
+ close_replaced_pane: bool,
+ },
+ Stacked(Option<PaneId>),
+}
+
+impl Default for NewPanePlacement {
+ fn default() -> Self {
+ NewPanePlacement::NoPreference
+ }
+}
+
+impl NewPanePlacement {
+ pub fn with_floating_pane_coordinates(
+ floating_pane_coordinates: Option<FloatingPaneCoordinates>,
+ ) -> Self {
+ NewPanePlacement::Floating(floating_pane_coordinates)
+ }
+ pub fn with_should_be_in_place(
+ self,
+ should_be_in_place: bool,
+ close_replaced_pane: bool,
+ ) -> Self {
+ if should_be_in_place {
+ NewPanePlacement::InPlace {
+ pane_id_to_replace: None,
+ close_replaced_pane,
+ }
+ } else {
+ self
+ }
+ }
+ pub fn with_pane_id_to_replace(
+ pane_id_to_replace: Option<PaneId>,
+ close_replaced_pane: bool,
+ ) -> Self {
+ NewPanePlacement::InPlace {
+ pane_id_to_replace,
+ close_replaced_pane,
+ }
+ }
+ pub fn should_float(&self) -> Option<bool> {
+ match self {
+ NewPanePlacement::Floating(_) => Some(true),
+ NewPanePlacement::Tiled(_) => Some(false),
+ _ => None,
+ }
+ }
+ pub fn floating_pane_coordinates(&self) -> Option<FloatingPaneCoordinates> {
+ match self {
+ NewPanePlacement::Floating(floating_pane_coordinates) => {
+ floating_pane_coordinates.clone()
+ },
+ _ => None,
+ }
+ }
+ pub fn should_stack(&self) -> bool {
+ match self {
+ NewPanePlacement::Stacked(_) => true,
+ _ => false,
+ }
+ }
+ pub fn id_of_stack_root(&self) -> Option<PaneId> {
+ match self {
+ NewPanePlacement::Stacked(id) => *id,
+ _ => None,
+ }
+ }
+}
+
type Context = BTreeMap<String, String>;
#[derive(Debug, Clone, EnumDiscriminants, ToString)]
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index fa5374f0..d623197b 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -6,7 +6,7 @@ use super::layout::{
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
};
use crate::cli::CliAction;
-use crate::data::{Direction, KeyWithModifier, PaneId, Resize};
+use crate::data::{Direction, KeyWithModifier, LayoutInfo, NewPanePlacement, PaneId, Resize};
use crate::data::{FloatingPaneCoordinates, InputMode};
use crate::home::{find_default_config_dir, get_layout_dir};
use crate::input::config::{Config, ConfigError, KdlError};
@@ -99,7 +99,7 @@ impl FromStr for SearchOption {
// They might need to be adjusted in the default config
// as well `../../assets/config/default.yaml`
/// Actions that can be bound to keys.
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, strum_macros::Display)]
pub enum Action {
/// Quit Zellij.
Quit,
@@ -190,6 +190,11 @@ pub enum Action {
pane_name: Option<String>,
start_suppressed: bool,
},
+ NewBlockingPane {
+ placement: NewPanePlacement,
+ pane_name: Option<String>,
+ command: Option<RunCommandAction>,
+ },
/// Open the file in a new pane using the default editor
EditFile {
payload: OpenFilePayload,
@@ -269,6 +274,14 @@ pub enum Action {
},
/// Detach session and exit
Detach,
+ /// Switch to a different session
+ SwitchSession {
+ name: String,
+ tab_position: Option<usize>,
+ pane_id: Option<(u32, bool)>, // (id, is_plugin)
+ layout: Option<LayoutInfo>,
+ cwd: Option<PathBuf>,
+ },
LaunchOrFocusPlugin {
plugin: RunPluginOrAlias,
should_float: bool,
@@ -478,6 +491,7 @@ impl Action {
height,
pinned,
stacked,
+ blocking,
} => {
let current_dir = get_current_dir();
// cwd should only be specified in a plugin alias if it was explicitly given to us,
@@ -486,7 +500,51 @@ impl Action {
let cwd = cwd
.map(|cwd| current_dir.join(cwd))
.or_else(|| Some(current_dir.clone()));
- if let Some(plugin) = plugin {
+ if blocking {
+ // For blocking panes, we don't support plugins
+ if plugin.is_some() {
+ return Err("Blocking panes do not support plugin variants".to_string());
+ }
+
+ let command = if !command.is_empty() {
+ let mut command = command.clone();
+ let (command, args) = (PathBuf::from(command.remove(0)), command);
+ let hold_on_start = start_suspended;
+ let hold_on_close = !close_on_exit;
+ Some(RunCommandAction {
+ command,
+ args,
+ cwd,
+ direction,
+ hold_on_close,
+ hold_on_start,
+ ..Default::default()
+ })
+ } else {
+ None
+ };
+
+ let placement = if floating {
+ NewPanePlacement::Floating(FloatingPaneCoordinates::new(
+ x, y, width, height, pinned,
+ ))
+ } else if in_place {
+ NewPanePlacement::InPlace {
+ pane_id_to_replace: None,
+ close_replaced_pane: false,
+ }
+ } else if stacked {
+ NewPanePlacement::Stacked(None)
+ } else {
+ NewPanePlacement::Tiled(direction)
+ };
+
+ Ok(vec![Action::NewBlockingPane {
+ placement,
+ pane_name: name,
+ command,
+ }])
+ } else if let Some(plugin) = plugin {
let plugin = match RunPluginLocation::parse(&plugin, cwd.clone()) {
Ok(location) => {
let user_configuration = configuration.unwrap_or_default();
@@ -633,9 +691,7 @@ impl Action {
coordinates: FloatingPaneCoordinates::new(x, y, width, height, pinned),
}])
},
- CliAction::SwitchMode { input_mode } => {
- Ok(vec![Action::SwitchModeForAllClients { input_mode }])
- },
+ CliAction::SwitchMode { input_mode } => Ok(vec![Action::SwitchToMode { input_mode }]),
CliAction::TogglePaneEmbedOrFloating => Ok(vec![Action::TogglePaneEmbedOrFloating]),
CliAction::ToggleFloatingPanes => Ok(vec![Action::ToggleFloatingPanes]),
CliAction::ClosePane => Ok(vec![Action::CloseFocus]),
@@ -939,6 +995,56 @@ impl Action {
}
}
},
+ CliAction::Detach => Ok(vec![Action::Detach]),
+ CliAction::SwitchSession {
+ name,
+ tab_position,
+ pane_id,
+ layout,
+ layout_dir,
+ cwd,
+ } => {
+ let pane_id = match pane_id {
+ Some(stringified_pane_id) => match PaneId::from_str(&stringified_pane_id) {
+ Ok(PaneId::Terminal(id)) => Some((id, false)),
+ Ok(PaneId::Plugin(id)) => Some((id, true)),
+ Err(_e) => {
+ return Err(format!(
+ "Malformed pane id: {}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)",
+ stringified_pane_id
+ ));
+ },
+ },
+ None => None,
+ };
+
+ let cwd = cwd.map(|cwd| {
+ let current_dir = get_current_dir();
+ current_dir.join(cwd)
+ });
+
+ let layout_dir = layout_dir.map(|layout_dir| {
+ let current_dir = get_current_dir();
+ current_dir.join(layout_dir)
+ });
+
+ let layout_info = if let Some(layout_path) = layout {
+ let layout_dir = layout_dir
+ .or_else(|| config.and_then(|c| c.options.layout_dir.clone()))
+ .or_else(|| get_layout_dir(find_default_config_dir()));
+ LayoutInfo::from_config(&layout_dir, &Some(layout_path))
+ } else {
+ None
+ };
+
+ Ok(vec![Action::SwitchSession {
+ name: name.clone(),
+ tab_position: tab_position.clone(),
+ pane_id,
+ layout: layout_info,
+ cwd,
+ }])
+ },
}
}
pub fn launches_plugin(&self, plugin_url: &str) -> bool {
diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs
index 1f37b2e7..53dd4d9f 100644
--- a/zellij-utils/src/ipc.rs
+++ b/zellij-utils/src/ipc.rs
@@ -121,6 +121,7 @@ pub enum ClientToServerMsg {
action: Action,
terminal_id: Option<u32>,
client_id: Option<ClientId>,
+ is_cli_client: bool,
},
Key {
key: KeyWithModifier,
@@ -181,6 +182,7 @@ pub enum ExitReason {
CannotAttach,
Disconnect,
WebClientsForbidden,
+ CustomExitStatus(i32),
Error(String),
}
@@ -225,6 +227,7 @@ There are a few things you can try now:
"
)
},
+ Self::CustomExitStatus(exit_status) => write!(f, "Exit {}", exit_status),
Self::Error(e) => write!(f, "Error occurred in server:\n{}", e),
}
}
diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs
index 658c10f3..ab06faae 100644
--- a/zellij-utils/src/ipc/protobuf_conversion.rs
+++ b/zellij-utils/src/ipc/protobuf_conversion.rs
@@ -78,10 +78,12 @@ impl From<ClientToServerMsg> for ProtoClientToServerMsg {
action,
terminal_id,
client_id,
+ is_cli_client,
} => client_to_server_msg::Message::Action(ActionMsg {
action: Some(action.into()),
terminal_id,
client_id: client_id.map(|id| id as u32),
+ is_cli_client,
}),
ClientToServerMsg::Key {
key,
@@ -198,6 +200,7 @@ impl TryFrom<ProtoClientToServerMsg> for ClientToServerMsg {
.try_into()?,
terminal_id: action.terminal_id,
client_id: action.client_id.map(|id| id as u16),
+ is_cli_client: action.is_cli_client,
}),
Some(client_to_server_msg::Message::Key(key)) => Ok(ClientToServerMsg::Key {
key: key.key.ok_or_else(|| anyhow!("Missing key"))?.try_into()?,
@@ -239,6 +242,9 @@ impl From<ServerToClientMsg> for ProtoServerToClientMsg {
ServerToClientMsg::Exit { exit_reason } => {
let (proto_exit_reason, payload) = match exit_reason {
ExitReason::Error(ref msg) => (ProtoExitReason::Error, Some(msg.clone())),
+ ExitReason::CustomExitStatus(status) => {
+ (ProtoExitReason::CustomExitStatus, Some(status.to_string()))
+ },
other => (ProtoExitReason::from(other), None),
};
server_to_client_msg::Message::Exit(ExitMsg {
@@ -310,6 +316,13 @@ impl TryFrom<ProtoServerToClientMsg> for ServerToClientMsg {
exit.payload.unwrap_or_else(|| "Protobuf error".to_string());
ExitReason::Error(error_msg)
},
+ ProtoExitReason::CustomExitStatus => {
+ let status_str = exit.payload.unwrap_or_else(|| "0".to_string());
+ let status = status_str
+ .parse::<i32>()
+ .map_err(|_| anyhow!("Invalid custom exit status: {}", status_str))?;
+ ExitReason::CustomExitStatus(status)
+ },
other => other.try_into()?,
};
@@ -704,21 +717,22 @@ impl From<crate::input::actions::Action>
HalfPageScrollDownAction, HalfPageScrollUpAction, KeybindPipeAction,
LaunchOrFocusPluginAction, LaunchPluginAction, ListClientsAction, MouseEventAction,
MoveFocusAction, MoveFocusOrTabAction, MovePaneAction, MovePaneBackwardsAction,
- MoveTabAction, NewFloatingPaneAction, NewFloatingPluginPaneAction,
- NewInPlacePaneAction, NewInPlacePluginPaneAction, NewPaneAction, NewStackedPaneAction,
- NewTabAction, NewTiledPaneAction, NewTiledPluginPaneAction, NextSwapLayoutAction,
- NoOpAction, PageScrollDownAction, PageScrollUpAction, PaneNameInputAction,
- PreviousSwapLayoutAction, QueryTabNamesAction, QuitAction, RenamePluginPaneAction,
- RenameSessionAction, RenameTabAction, RenameTerminalPaneAction, ResizeAction,
- RunAction, ScrollDownAction, ScrollDownAtAction, ScrollToBottomAction,
- ScrollToTopAction, ScrollUpAction, ScrollUpAtAction, SearchAction, SearchInputAction,
- SearchToggleOptionAction, SkipConfirmAction, StackPanesAction,
- StartOrReloadPluginAction, SwitchFocusAction, SwitchModeForAllClientsAction,
- SwitchToModeAction, TabNameInputAction, ToggleActiveSyncTabAction,
- ToggleFloatingPanesAction, ToggleFocusFullscreenAction, ToggleGroupMarkingAction,
- ToggleMouseModeAction, TogglePaneEmbedOrFloatingAction, TogglePaneFramesAction,
- TogglePaneInGroupAction, TogglePanePinnedAction, ToggleTabAction, UndoRenamePaneAction,
- UndoRenameTabAction, WriteAction, WriteCharsAction,
+ MoveTabAction, NewBlockingPaneAction, NewFloatingPaneAction,
+ NewFloatingPluginPaneAction, NewInPlacePaneAction, NewInPlacePluginPaneAction,
+ NewPaneAction, NewStackedPaneAction, NewTabAction, NewTiledPaneAction,
+ NewTiledPluginPaneAction, NextSwapLayoutAction, NoOpAction, PageScrollDownAction,
+ PageScrollUpAction, PaneIdWithPlugin, PaneNameInputAction, PreviousSwapLayoutAction,
+ QueryTabNamesAction, QuitAction, RenamePluginPaneAction, RenameSessionAction,
+ RenameTabAction, RenameTerminalPaneAction, ResizeAction, RunAction, ScrollDownAction,
+ ScrollDownAtAction, ScrollToBottomAction, ScrollToTopAction, ScrollUpAction,
+ ScrollUpAtAction, SearchAction, SearchInputAction, SearchToggleOptionAction,
+ SkipConfirmAction, StackPanesAction, StartOrReloadPluginAction, SwitchFocusAction,
+ SwitchModeForAllClientsAction, SwitchSessionAction, SwitchToModeAction,
+ TabNameInputAction, ToggleActiveSyncTabAction, ToggleFloatingPanesAction,
+ ToggleFocusFullscreenAction, ToggleGroupMarkingAction, ToggleMouseModeAction,
+ TogglePaneEmbedOrFloatingAction, TogglePaneFramesAction, TogglePaneInGroupAction,
+ TogglePanePinnedAction, ToggleTabAction, UndoRenamePaneAction, UndoRenameTabAction,
+ WriteAction, WriteCharsAction,
};
use std::collections::HashMap;
@@ -890,6 +904,15 @@ impl From<crate::input::actions::Action>
pane_name,
})
},
+ crate::input::actions::Action::NewBlockingPane {
+ placement,
+ pane_name,
+ command,
+ } => ActionType::NewBlockingPane(NewBlockingPaneAction {
+ placement: Some(placement.into()),
+ pane_name,
+ command: command.map(|c| c.into()),
+ }),
crate::input::actions::Action::TogglePaneEmbedOrFloating => {
ActionType::TogglePaneEmbedOrFloating(TogglePaneEmbedOrFloatingAction {})
},
@@ -960,6 +983,22 @@ impl From<crate::input::actions::Action>
command: Some(command.into()),
}),
crate::input::actions::Action::Detach => ActionType::Detach(DetachAction {}),
+ crate::input::actions::Action::SwitchSession {
+ name,
+ tab_position,
+ pane_id,
+ layout,
+ cwd,
+ } => ActionType::SwitchSession(SwitchSessionAction {
+ name: name.clone(),
+ tab_position: tab_position.map(|p| p as u32),
+ pane_id: pane_id.map(|(id, is_plugin)| PaneIdWithPlugin {
+ pane_id: id,
+ is_plugin: is_plugin,
+ }),
+ layout: layout.as_ref().map(|l| l.clone().into()),
+ cwd: cwd.as_ref().map(|p| p.to_string_lossy().to_string()),
+ }),
crate::input::actions::Action::LaunchOrFocusPlugin {
plugin,
should_float,
@@ -1383,6 +1422,19 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action>
pane_name: new_stacked_action.pane_name,
})
},
+ ActionType::NewBlockingPane(new_blocking_action) => {
+ Ok(crate::input::actions::Action::NewBlockingPane {
+ placement: new_blocking_action
+ .placement
+ .ok_or_else(|| anyhow!("NewBlockingPane missing placement"))?
+ .try_into()?,
+ pane_name: new_blocking_action.pane_name,
+ command: new_blocking_action
+ .command
+ .map(|c| c.try_into())
+ .transpose()?,
+ })
+ },
ActionType::TogglePaneEmbedOrFloating(_) => {
Ok(crate::input::actions::Action::TogglePaneEmbedOrFloating)
},
@@ -1466,6 +1518,21 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action>
.try_into()?,
}),
ActionType::Detach(_) => Ok(crate::input::actions::Action::Detach),
+ ActionType::SwitchSession(switch_session_action) => {
+ Ok(crate::input::actions::Action::SwitchSession {
+ name: switch_session_action.name.clone(),
+ tab_position: switch_session_action.tab_position.map(|p| p as usize),
+ pane_id: switch_session_action
+ .pane_id
+ .as_ref()
+ .map(|p| (p.pane_id, p.is_plugin)),
+ layout: switch_session_action
+ .layout
+ .map(|l| l.try_into())
+ .transpose()?,
+ cwd: switch_session_action.cwd.map(PathBuf::from),
+ })
+ },
ActionType::LaunchOrFocusPlugin(launch_plugin_action) => {
Ok(crate::input::actions::Action::LaunchOrFocusPlugin {
plugin: launch_plugin_action
@@ -1870,6 +1937,7 @@ impl From<ExitReason> for ProtoExitReason {
ExitReason::Disconnect => ProtoExitReason::Disconnect,
ExitReason::WebClientsForbidden => ProtoExitReason::WebClientsForbidden,
ExitReason::Error(_msg) => ProtoExitReason::Error,
+ ExitReason::CustomExitStatus(_status) => ProtoExitReason::CustomExitStatus,
}
}
}
@@ -1885,6 +1953,7 @@ impl TryFrom<ProtoExitReason> for ExitReason {
ProtoExitReason::Disconnect => Ok(ExitReason::Disconnect),
ProtoExitReason::WebClientsForbidden => Ok(ExitReason::WebClientsForbidden),
ProtoExitReason::Error => Ok(ExitReason::Error("Protobuf error".to_string())),
+ ProtoExitReason::CustomExitStatus => Ok(ExitReason::CustomExitStatus(0)),
ProtoExitReason::Unspecified => Err(anyhow!("Unspecified exit reason")),
}
}
@@ -2197,6 +2266,88 @@ impl TryFrom<crate::client_server_contract::client_server_contract::FloatingPane
}
}
+// NewPanePlacement conversion
+impl From<crate::data::NewPanePlacement>
+ for crate::client_server_contract::client_server_contract::NewPanePlacement
+{
+ fn from(placement: crate::data::NewPanePlacement) -> Self {
+ use crate::client_server_contract::client_server_contract::new_pane_placement::PlacementType;
+ let placement_type = match placement {
+ crate::data::NewPanePlacement::NoPreference => PlacementType::NoPreference(true),
+ crate::data::NewPanePlacement::Tiled(direction) => {
+ PlacementType::Tiled(direction.map(direction_to_proto_i32).unwrap_or(0))
+ },
+ crate::data::NewPanePlacement::Floating(coords) => {
+ PlacementType::Floating(coords.map(|c| c.into()).unwrap_or_default())
+ },
+ crate::data::NewPanePlacement::InPlace {
+ pane_id_to_replace,
+ close_replaced_pane,
+ } => PlacementType::InPlace(
+ crate::client_server_contract::client_server_contract::NewPanePlacementInPlace {
+ pane_id_to_replace: pane_id_to_replace.map(|id| id.into()),
+ close_replaced_pane,
+ },
+ ),
+ crate::data::NewPanePlacement::Stacked(pane_id) => {
+ PlacementType::Stacked(pane_id.map(|id| id.into()).unwrap_or_default())
+ },
+ };
+ Self {
+ placement_type: Some(placement_type),
+ }
+ }
+}
+
+// Reverse NewPanePlacement conversion
+impl TryFrom<crate::client_server_contract::client_server_contract::NewPanePlacement>
+ for crate::data::NewPanePlacement
+{
+ type Error = anyhow::Error;
+ fn try_from(
+ placement: crate::client_server_contract::client_server_contract::NewPanePlacement,
+ ) -> Result<Self> {
+ use crate::client_server_contract::client_server_contract::new_pane_placement::PlacementType;
+ match placement
+ .placement_type
+ .ok_or_else(|| anyhow!("NewPanePlacement missing placement_type"))?
+ {
+ PlacementType::NoPreference(_) => Ok(crate::data::NewPanePlacement::NoPreference),
+ PlacementType::Tiled(direction) => {
+ let direction = if direction == 0 {
+ None
+ } else {
+ Some(proto_i32_to_direction(direction)?)
+ };
+ Ok(crate::data::NewPanePlacement::Tiled(direction))
+ },
+ PlacementType::Floating(coords) => {
+ let coords = if coords == Default::default() {
+ None
+ } else {
+ Some(coords.try_into()?)
+ };
+ Ok(crate::data::NewPanePlacement::Floating(coords))
+ },
+ PlacementType::InPlace(in_place) => Ok(crate::data::NewPanePlacement::InPlace {
+ pane_id_to_replace: in_place
+ .pane_id_to_replace
+ .map(|id| id.try_into())
+ .transpose()?,
+ close_replaced_pane: in_place.close_replaced_pane,
+ }),
+ PlacementType::Stacked(pane_id) => {
+ let pane_id = if pane_id == Default::default() {
+ None
+ } else {
+ Some(pane_id.try_into()?)
+ };
+ Ok(crate::data::NewPanePlacement::Stacked(pane_id))
+ },
+ }
+ }
+}
+
// MouseEvent conversion
impl From<crate::input::mouse::MouseEvent>
for crate::client_server_contract::client_server_contract::MouseEvent
diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
index a2585181..2ec513da 100644
--- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs
+++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
@@ -696,11 +696,13 @@ fn test_client_messages() {
action: Action::Quit,
terminal_id: None,
client_id: None,
+ is_cli_client: false,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Quit,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Write {
@@ -710,6 +712,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Write {
@@ -720,6 +723,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::WriteChars {
@@ -727,6 +731,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SwitchToMode {
@@ -735,6 +740,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SwitchModeForAllClients {
@@ -743,6 +749,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -751,6 +758,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -759,6 +767,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -767,6 +776,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -775,6 +785,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -783,6 +794,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Resize {
@@ -791,21 +803,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusNextPane,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusPreviousPane,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SwitchFocus,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MoveFocus {
@@ -814,6 +830,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MoveFocusOrTab {
@@ -821,11 +838,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MovePane { direction: None },
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MovePane {
@@ -833,16 +852,19 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MovePaneBackwards,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ClearScreen,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpScreen {
@@ -851,6 +873,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpScreen {
@@ -859,21 +882,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpLayout,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditScrollback,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollUp,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollUpAt {
@@ -881,6 +908,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollUpAt {
@@ -888,11 +916,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollDown,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollDownAt {
@@ -900,51 +930,61 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollToBottom,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ScrollToTop,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::PageScrollUp,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::PageScrollDown,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::HalfPageScrollUp,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::HalfPageScrollDown,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleFocusFullscreen,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::TogglePaneFrames,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleActiveSyncTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewPane {
@@ -954,6 +994,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewPane {
@@ -963,6 +1004,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -980,6 +1022,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1001,6 +1044,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1022,6 +1066,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1043,6 +1088,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1070,6 +1116,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1097,6 +1144,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1124,6 +1172,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::EditFile {
@@ -1145,6 +1194,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewFloatingPane {
@@ -1154,6 +1204,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewFloatingPane {
@@ -1178,6 +1229,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewFloatingPane {
@@ -1206,6 +1258,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTiledPane {
@@ -1215,6 +1268,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTiledPane {
@@ -1237,6 +1291,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewInPlacePane {
@@ -1258,6 +1313,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewInPlacePane {
@@ -1266,6 +1322,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewStackedPane {
@@ -1287,6 +1344,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewStackedPane {
@@ -1295,21 +1353,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::TogglePaneEmbedOrFloating,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleFloatingPanes,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::CloseFocus,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::PaneNameInput {
@@ -1317,11 +1379,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::UndoRenamePane,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1335,6 +1399,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1348,6 +1413,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1364,6 +1430,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1380,6 +1447,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1397,6 +1465,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1426,6 +1495,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1442,6 +1512,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1458,6 +1529,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1476,6 +1548,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1495,6 +1568,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1514,6 +1588,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1533,6 +1608,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1552,6 +1628,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1571,6 +1648,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1590,6 +1668,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1609,6 +1688,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1628,6 +1708,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1644,6 +1725,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1666,6 +1748,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1690,6 +1773,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1718,6 +1802,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1734,6 +1819,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1754,6 +1840,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1770,6 +1857,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1806,6 +1894,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1827,6 +1916,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1840,6 +1930,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTab {
@@ -1853,31 +1944,37 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NoOp,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::GoToNextTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::GoToPreviousTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::CloseTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::GoToTab { index: 0 },
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::GoToTabName {
@@ -1886,6 +1983,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::GoToTabName {
@@ -1894,11 +1992,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::TabNameInput {
@@ -1906,11 +2006,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::UndoRenameTab,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MoveTab {
@@ -1918,6 +2020,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Run {
@@ -1935,11 +2038,13 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Detach,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::LaunchOrFocusPlugin {
@@ -1952,6 +2057,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::LaunchOrFocusPlugin {
@@ -1964,6 +2070,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::LaunchPlugin {
@@ -1976,6 +2083,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::LaunchPlugin {
@@ -1988,6 +2096,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MouseEvent {
@@ -2006,6 +2115,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MouseEvent {
@@ -2024,6 +2134,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::MouseEvent {
@@ -2042,21 +2153,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Copy,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Confirm,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Deny,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SkipConfirm {
@@ -2064,6 +2179,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SearchInput {
@@ -2071,6 +2187,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Search {
@@ -2078,6 +2195,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::Search {
@@ -2085,6 +2203,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SearchToggleOption {
@@ -2092,6 +2211,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SearchToggleOption {
@@ -2099,6 +2219,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::SearchToggleOption {
@@ -2106,26 +2227,31 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleMouseMode,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::PreviousSwapLayout,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NextSwapLayout,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::QueryTabNames,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewTiledPluginPane {
@@ -2136,6 +2262,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewFloatingPluginPane {
@@ -2147,6 +2274,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewFloatingPluginPane {
@@ -2164,6 +2292,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::NewInPlacePluginPane {
@@ -2173,6 +2302,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::StartOrReloadPlugin {
@@ -2180,16 +2310,19 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::CloseTerminalPane { pane_id: 11 },
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ClosePluginPane { pane_id: 12 },
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusTerminalPaneWithId {
@@ -2198,6 +2331,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusTerminalPaneWithId {
@@ -2206,6 +2340,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusPluginPaneWithId {
@@ -2214,6 +2349,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::FocusPluginPaneWithId {
@@ -2222,6 +2358,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::RenameTerminalPane {
@@ -2230,6 +2367,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::RenamePluginPane {
@@ -2238,6 +2376,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::RenameTab {
@@ -2246,21 +2385,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::BreakPane,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::BreakPaneRight,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::BreakPaneLeft,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::RenameSession {
@@ -2268,6 +2411,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::CliPipe {
@@ -2286,6 +2430,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::CliPipe {
@@ -2304,6 +2449,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::KeybindPipe {
@@ -2322,6 +2468,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::KeybindPipe {
@@ -2340,21 +2487,25 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ListClients,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::TogglePanePinned,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::StackPanes { pane_ids: vec![] },
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::StackPanes {
@@ -2367,6 +2518,7 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ChangeFloatingPaneCoordinates {
@@ -2382,16 +2534,19 @@ fn test_client_messages() {
},
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::TogglePaneInGroup,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::ToggleGroupMarking,
terminal_id: Some(1),
client_id: Some(100),
+ is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Key {
key: KeyWithModifier {
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index ad541a48..789c3d96 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -1022,6 +1022,35 @@ impl Action {
},
},
Action::Detach => Some(KdlNode::new("Detach")),
+ Action::SwitchSession {
+ name,
+ tab_position,
+ pane_id,
+ layout,
+ cwd,
+ } => {
+ let mut node = KdlNode::new("SwitchSession");
+ node.push(KdlEntry::new_prop("name", name.clone()));
+ if let Some(pos) = tab_position {
+ node.push(KdlEntry::new_prop("tab_position", *pos as i64));
+ }
+ if let Some((id, is_plugin)) = pane_id {
+ node.push(KdlEntry::new_prop("pane_id", *id as i64));
+ if *is_plugin {
+ node.push(KdlEntry::new_prop("is_plugin", true));
+ }
+ }
+ if let Some(layout_info) = layout {
+ node.push(KdlEntry::new_prop("layout", layout_info.name()));
+ }
+ if let Some(cwd_path) = cwd {
+ node.push(KdlEntry::new_prop(
+ "cwd",
+ cwd_path.to_string_lossy().to_string(),
+ ));
+ }
+ Some(node)
+ },
Action::LaunchOrFocusPlugin {
plugin: run_plugin_or_alias,
should_float,
@@ -1466,6 +1495,50 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
},
"Detach" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "SwitchSession" => {
+ let name = kdl_get_string_property_or_child_value!(kdl_action, "name")
+ .map(|s| s.to_string())
+ .ok_or(ConfigError::new_kdl_error(
+ "SwitchSession action requires a 'name' property".into(),
+ kdl_action.span().offset(),
+ kdl_action.span().len(),
+ ))?;
+ let tab_position =
+ crate::kdl_get_int_property_or_child_value!(kdl_action, "tab_position")
+ .map(|i| i as usize);
+ let pane_id = crate::kdl_get_int_property_or_child_value!(kdl_action, "pane_id")
+ .map(|i| i as u32);
+ let is_plugin =
+ crate::kdl_get_bool_property_or_child_value!(kdl_action, "is_plugin")
+ .unwrap_or(false);
+ let pane_id_tuple = pane_id.map(|id| (id, is_plugin));
+
+ // Parse layout
+ let layout = if let Some(layout_str) =
+ kdl_get_string_property_or_child_value!(kdl_action, "layout")
+ {
+ let layout_path = PathBuf::from(layout_str);
+ let layout_dir = config_options
+ .layout_dir
+ .clone()
+ .or_else(|| get_layout_dir(find_default_config_dir()));
+ LayoutInfo::from_config(&layout_dir, &Some(layout_path))
+ } else {
+ None
+ };
+
+ // Parse cwd
+ let cwd =
+ kdl_get_string_property_or_child_value!(kdl_action, "cwd").map(PathBuf::from);
+
+ Ok(Action::SwitchSession {
+ name,
+ tab_position,
+ pane_id: pane_id_tuple,
+ layout,
+ cwd,
+ })
+ },
"Copy" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Clear" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Confirm" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto
index 5bdd34e9..2772e725 100644
--- a/zellij-utils/src/plugin_api/action.proto
+++ b/zellij-utils/src/plugin_api/action.proto
@@ -244,6 +244,7 @@ enum ActionName {
TogglePaneInGroup = 87;
ToggleGroupMarking = 88;
NewStackedPane = 89;
+ SwitchSession = 90;
}
message Position {
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index 2b48ffe1..c442144a 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -1388,7 +1388,9 @@ impl TryFrom<Action> for ProtobufAction {
pane_id: _,
coordinates: _,
}
- | Action::SkipConfirm { action: _ } => Err("Unsupported action"),
+ | Action::SkipConfirm { action: _ }
+ | Action::NewBlockingPane { .. }
+ | Action::SwitchSession { .. } => Err("Unsupported action"),
}
}
}