aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-07-08 11:06:03 +0200
committerGitHub <noreply@github.com>2025-07-08 11:06:03 +0200
commit358caa180ce7c60b8923caa98cf339f897d14feb (patch)
treebb14df05b46d907a7af55ae98095abd8e9f4e7b4 /zellij-utils
parentfix(plugins): use the terminal title when spawning terminals (#4272) (diff)
downloadsl0ppij-358caa180ce7c60b8923caa98cf339f897d14feb.tar.gz
sl0ppij-358caa180ce7c60b8923caa98cf339f897d14feb.tar.xz
sl0ppij-358caa180ce7c60b8923caa98cf339f897d14feb.zip
fix(tabs): allow setting cwd without a layout (#4273)
* working for cli and keybinding * working for plugin API * style(fmt): rustfmt * docs(changelog): add PR
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs12
-rw-r--r--zellij-utils/src/cli.rs2
-rw-r--r--zellij-utils/src/data.rs5
-rw-r--r--zellij-utils/src/input/actions.rs6
-rw-r--r--zellij-utils/src/kdl/mod.rs18
-rw-r--r--zellij-utils/src/plugin_api/action.rs2
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto6
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs23
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap2
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap2
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap2
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap2
12 files changed, 64 insertions, 18 deletions
diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs
index e3c63626..0c290fc3 100644
--- a/zellij-utils/assets/prost/api.plugin_command.rs
+++ b/zellij-utils/assets/prost/api.plugin_command.rs
@@ -3,7 +3,7 @@
pub struct PluginCommand {
#[prost(enumeration="CommandName", tag="1")]
pub name: i32,
- #[prost(oneof="plugin_command::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111")]
+ #[prost(oneof="plugin_command::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112")]
pub payload: ::core::option::Option<plugin_command::Payload>,
}
/// Nested message and enum types in `PluginCommand`.
@@ -213,10 +213,20 @@ pub mod plugin_command {
RenameWebLoginTokenPayload(super::RenameWebLoginTokenPayload),
#[prost(message, tag="111")]
ReplacePaneWithExistingPanePayload(super::ReplacePaneWithExistingPanePayload),
+ #[prost(message, tag="112")]
+ NewTabPayload(super::NewTabPayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct NewTabPayload {
+ #[prost(string, optional, tag="1")]
+ pub name: ::core::option::Option<::prost::alloc::string::String>,
+ #[prost(string, optional, tag="2")]
+ pub cwd: ::core::option::Option<::prost::alloc::string::String>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ReplacePaneWithExistingPanePayload {
#[prost(message, optional, tag="1")]
pub pane_id_to_replace: ::core::option::Option<PaneId>,
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index 164f5999..b85d975f 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -722,7 +722,7 @@ pub enum CliAction {
name: Option<String>,
/// Change the working directory of the new tab
- #[clap(short, long, value_parser, requires("layout"))]
+ #[clap(short, long, value_parser)]
cwd: Option<PathBuf>,
},
/// Move the focused tab in the specified direction. [right|left]
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 0520e15d..190011f9 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -2344,7 +2344,10 @@ pub enum PluginCommand {
ShowSelf(bool), // bool - should float if hidden
SwitchToMode(InputMode),
NewTabsWithLayout(String), // raw kdl layout
- NewTab,
+ NewTab {
+ name: Option<String>,
+ cwd: Option<String>,
+ },
GoToNextTab,
GoToPreviousTab,
Resize(Resize),
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index 38c46833..5f2b2af0 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -198,7 +198,8 @@ pub enum Action {
Option<Vec<SwapTiledLayout>>,
Option<Vec<SwapFloatingLayout>>,
Option<String>,
- bool, // should_change_focus_to_new_tab
+ bool, // should_change_focus_to_new_tab
+ Option<PathBuf>, // cwd
), // the String is the tab name
/// Do nothing.
NoOp,
@@ -621,6 +622,7 @@ impl Action {
swap_floating_layouts.clone(),
name,
should_change_focus_to_new_tab,
+ None, // the cwd is done through the layout
));
}
Ok(new_tab_actions)
@@ -636,6 +638,7 @@ impl Action {
swap_floating_layouts,
name,
should_change_focus_to_new_tab,
+ None, // the cwd is done through the layout
)])
}
} else {
@@ -647,6 +650,7 @@ impl Action {
None,
name,
should_change_focus_to_new_tab,
+ cwd,
)])
}
},
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 724f52be..ec6abf72 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -696,11 +696,10 @@ impl Action {
Some(node)
},
Action::UndoRenamePane => Some(KdlNode::new("UndoRenamePane")),
- Action::NewTab(_, _, _, _, name, should_change_focus_to_new_tab) => {
- log::warn!("Converting new tab action without arguments, original action saved to .bak.kdl file");
+ Action::NewTab(_, _, _, _, name, should_change_focus_to_new_tab, cwd) => {
let mut node = KdlNode::new("NewTab");
+ let mut children = KdlDocument::new();
if let Some(name) = name {
- let mut children = KdlDocument::new();
let mut name_node = KdlNode::new("name");
if !should_change_focus_to_new_tab {
let mut should_change_focus_to_new_tab_node =
@@ -712,6 +711,13 @@ impl Action {
}
name_node.push(name.clone());
children.nodes_mut().push(name_node);
+ }
+ if let Some(cwd) = cwd {
+ let mut cwd_node = KdlNode::new("cwd");
+ cwd_node.push(cwd.display().to_string());
+ children.nodes_mut().push(cwd_node);
+ }
+ if name.is_some() || cwd.is_some() {
node.set_children(children);
}
Some(node)
@@ -1472,7 +1478,7 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
"NewTab" => {
let command_metadata = action_children.iter().next();
if command_metadata.is_none() {
- return Ok(Action::NewTab(None, vec![], None, None, None, true));
+ return Ok(Action::NewTab(None, vec![], None, None, None, true, None));
}
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
@@ -1508,7 +1514,7 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
&raw_layout,
path_to_raw_layout,
swap_layouts.as_ref().map(|(f, p)| (f.as_str(), p.as_str())),
- cwd,
+ cwd.clone(),
)
.map_err(|e| {
ConfigError::new_kdl_error(
@@ -1540,6 +1546,7 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
swap_floating_layouts,
name,
should_change_focus_to_new_tab,
+ cwd,
))
} else {
let (layout, floating_panes_layout) = layout.new_tab();
@@ -1552,6 +1559,7 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
swap_floating_layouts,
name,
should_change_focus_to_new_tab,
+ cwd,
))
}
},
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index d018ea1b..3aaa6ee1 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -315,7 +315,7 @@ impl TryFrom<ProtobufAction> for Action {
Some(_) => Err("NewTab should not have a payload"),
None => {
// we do not serialize the layouts of this action
- Ok(Action::NewTab(None, vec![], None, None, None, true))
+ Ok(Action::NewTab(None, vec![], None, None, None, true, None))
},
}
},
diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto
index b1797214..d46ba1e3 100644
--- a/zellij-utils/src/plugin_api/plugin_command.proto
+++ b/zellij-utils/src/plugin_api/plugin_command.proto
@@ -265,9 +265,15 @@ message PluginCommand {
RevokeWebLoginTokenPayload revoke_web_login_token_payload = 109;
RenameWebLoginTokenPayload rename_web_login_token_payload = 110;
ReplacePaneWithExistingPanePayload replace_pane_with_existing_pane_payload = 111;
+ NewTabPayload new_tab_payload = 112;
}
}
+message NewTabPayload {
+ optional string name = 1;
+ optional string cwd = 2;
+}
+
message ReplacePaneWithExistingPanePayload {
PaneId pane_id_to_replace = 1;
PaneId existing_pane_id = 2;
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index 296a8a74..073284bc 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -16,7 +16,7 @@ pub use super::generated_api::api::{
HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload,
ListTokensResponse, LoadNewPluginPayload, MessageToPluginPayload,
MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload,
- NewPluginArgs as ProtobufNewPluginArgs, NewTabsWithLayoutInfoPayload,
+ NewPluginArgs as ProtobufNewPluginArgs, NewTabPayload, NewTabsWithLayoutInfoPayload,
OpenCommandPaneFloatingNearPluginPayload, OpenCommandPaneInPlaceOfPluginPayload,
OpenCommandPaneNearPluginPayload, OpenCommandPanePayload,
OpenFileFloatingNearPluginPayload, OpenFileInPlaceOfPluginPayload,
@@ -474,11 +474,18 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for NewTabsWithLayout"),
},
- Some(CommandName::NewTab) => {
- if protobuf_plugin_command.payload.is_some() {
- return Err("NewTab should not have a payload");
- }
- Ok(PluginCommand::NewTab)
+ Some(CommandName::NewTab) => match protobuf_plugin_command.payload {
+ Some(Payload::NewTabPayload(protobuf_new_tab_payload)) => {
+ Ok(PluginCommand::NewTab {
+ name: protobuf_new_tab_payload.name,
+ cwd: protobuf_new_tab_payload.cwd,
+ })
+ },
+ None => Ok(PluginCommand::NewTab {
+ name: None,
+ cwd: None,
+ }),
+ _ => Err("Mismatched payload for NewTab"),
},
Some(CommandName::GoToNextTab) => {
if protobuf_plugin_command.payload.is_some() {
@@ -1886,9 +1893,9 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
name: CommandName::NewTabsWithLayout as i32,
payload: Some(Payload::NewTabsWithLayoutPayload(raw_layout)),
}),
- PluginCommand::NewTab => Ok(ProtobufPluginCommand {
+ PluginCommand::NewTab { name, cwd } => Ok(ProtobufPluginCommand {
name: CommandName::NewTab as i32,
- payload: None,
+ payload: Some(Payload::NewTabPayload(NewTabPayload { name, cwd })),
}),
PluginCommand::GoToNextTab => Ok(ProtobufPluginCommand {
name: CommandName::GoToNextTab as i32,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
index 3dc47894..1bceb902 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
@@ -1852,6 +1852,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
@@ -5582,6 +5583,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
index f1f79aa4..2281e405 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
@@ -1852,6 +1852,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
@@ -5582,6 +5583,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
index 92fa7f7f..45f351b0 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap
@@ -1852,6 +1852,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
@@ -5582,6 +5583,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
index 391cbea5..2e4e0dff 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap
@@ -1852,6 +1852,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,
@@ -5582,6 +5583,7 @@ Config {
None,
None,
true,
+ None,
),
SwitchToMode(
Normal,