feat(command-panes): optionally allow panes to be closed on exit (#1869)
* feat(cli): allow option to close command pane on exit * feat(layouts): allow option to close command panes on exit * style(fmt): rustfmt
This commit is contained in:
parent
eed9541a74
commit
c97b972383
10 changed files with 342 additions and 22 deletions
|
|
@ -25,6 +25,7 @@ fn main() {
|
||||||
cwd,
|
cwd,
|
||||||
floating,
|
floating,
|
||||||
name,
|
name,
|
||||||
|
close_on_exit,
|
||||||
})) = opts.command
|
})) = opts.command
|
||||||
{
|
{
|
||||||
let command_cli_action = CliAction::NewPane {
|
let command_cli_action = CliAction::NewPane {
|
||||||
|
|
@ -33,6 +34,7 @@ fn main() {
|
||||||
cwd,
|
cwd,
|
||||||
floating,
|
floating,
|
||||||
name,
|
name,
|
||||||
|
close_on_exit,
|
||||||
};
|
};
|
||||||
commands::send_action_to_session(command_cli_action, opts.session);
|
commands::send_action_to_session(command_cli_action, opts.session);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
|
|
|
||||||
|
|
@ -1821,6 +1821,7 @@ pub fn send_cli_new_pane_action_with_default_parameters() {
|
||||||
cwd: None,
|
cwd: None,
|
||||||
floating: false,
|
floating: false,
|
||||||
name: None,
|
name: None,
|
||||||
|
close_on_exit: false,
|
||||||
};
|
};
|
||||||
send_cli_action_to_server(
|
send_cli_action_to_server(
|
||||||
&session_metadata,
|
&session_metadata,
|
||||||
|
|
@ -1859,6 +1860,7 @@ pub fn send_cli_new_pane_action_with_split_direction() {
|
||||||
cwd: None,
|
cwd: None,
|
||||||
floating: false,
|
floating: false,
|
||||||
name: None,
|
name: None,
|
||||||
|
close_on_exit: false,
|
||||||
};
|
};
|
||||||
send_cli_action_to_server(
|
send_cli_action_to_server(
|
||||||
&session_metadata,
|
&session_metadata,
|
||||||
|
|
@ -1897,6 +1899,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() {
|
||||||
cwd: Some("/some/folder".into()),
|
cwd: Some("/some/folder".into()),
|
||||||
floating: false,
|
floating: false,
|
||||||
name: None,
|
name: None,
|
||||||
|
close_on_exit: false,
|
||||||
};
|
};
|
||||||
send_cli_action_to_server(
|
send_cli_action_to_server(
|
||||||
&session_metadata,
|
&session_metadata,
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,10 @@ pub enum Sessions {
|
||||||
/// Name of the new pane
|
/// Name of the new pane
|
||||||
#[clap(short, long, value_parser)]
|
#[clap(short, long, value_parser)]
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
|
||||||
|
/// Close the pane immediately when its command exits
|
||||||
|
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
|
||||||
|
close_on_exit: bool,
|
||||||
},
|
},
|
||||||
/// Edit file with default $EDITOR / $VISUAL
|
/// Edit file with default $EDITOR / $VISUAL
|
||||||
#[clap(visible_alias = "e")]
|
#[clap(visible_alias = "e")]
|
||||||
|
|
@ -246,6 +250,17 @@ pub enum CliAction {
|
||||||
/// Name of the new pane
|
/// Name of the new pane
|
||||||
#[clap(short, long, value_parser)]
|
#[clap(short, long, value_parser)]
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
|
||||||
|
/// Close the pane immediately when its command exits
|
||||||
|
#[clap(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
value_parser,
|
||||||
|
default_value("false"),
|
||||||
|
takes_value(false),
|
||||||
|
requires("command")
|
||||||
|
)]
|
||||||
|
close_on_exit: bool,
|
||||||
},
|
},
|
||||||
/// Open the specified file in a new zellij pane with your default EDITOR
|
/// Open the specified file in a new zellij pane with your default EDITOR
|
||||||
Edit {
|
Edit {
|
||||||
|
|
|
||||||
|
|
@ -258,17 +258,19 @@ impl Action {
|
||||||
cwd,
|
cwd,
|
||||||
floating,
|
floating,
|
||||||
name,
|
name,
|
||||||
|
close_on_exit,
|
||||||
} => {
|
} => {
|
||||||
if !command.is_empty() {
|
if !command.is_empty() {
|
||||||
let mut command = command.clone();
|
let mut command = command.clone();
|
||||||
let (command, args) = (PathBuf::from(command.remove(0)), command);
|
let (command, args) = (PathBuf::from(command.remove(0)), command);
|
||||||
let cwd = cwd.or_else(|| std::env::current_dir().ok());
|
let cwd = cwd.or_else(|| std::env::current_dir().ok());
|
||||||
|
let hold_on_close = !close_on_exit;
|
||||||
let run_command_action = RunCommandAction {
|
let run_command_action = RunCommandAction {
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
cwd,
|
cwd,
|
||||||
direction,
|
direction,
|
||||||
hold_on_close: true,
|
hold_on_close,
|
||||||
};
|
};
|
||||||
if floating {
|
if floating {
|
||||||
Ok(vec![Action::NewFloatingPane(
|
Ok(vec![Action::NewFloatingPane(
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,26 @@ impl Run {
|
||||||
_ => {}, // plugins aren't yet supported
|
_ => {}, // plugins aren't yet supported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn add_args(&mut self, args: Option<Vec<String>>) {
|
||||||
|
// overrides the args of a Run::Command if they are Some
|
||||||
|
// and not empty
|
||||||
|
if let Some(args) = args {
|
||||||
|
if let Run::Command(run_command) = self {
|
||||||
|
if !args.is_empty() {
|
||||||
|
run_command.args = args.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn add_close_on_exit(&mut self, close_on_exit: Option<bool>) {
|
||||||
|
// overrides the args of a Run::Command if they are Some
|
||||||
|
// and not empty
|
||||||
|
if let Some(close_on_exit) = close_on_exit {
|
||||||
|
if let Run::Command(run_command) = self {
|
||||||
|
run_command.hold_on_close = !close_on_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,19 @@ fn layout_with_command_panes_and_cwd_and_args() {
|
||||||
assert_eq!(layout, expected_layout);
|
assert_eq!(layout, expected_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn layout_with_command_panes_and_close_on_exit() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
pane command="htop" {
|
||||||
|
close_on_exit true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn layout_with_plugin_panes() {
|
fn layout_with_plugin_panes() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
|
|
@ -1033,6 +1046,24 @@ fn args_override_args_in_template() {
|
||||||
assert_snapshot!(format!("{:#?}", layout));
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn close_on_exit_overrides_close_on_exit_in_template() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
pane_template name="tail" {
|
||||||
|
command "tail"
|
||||||
|
close_on_exit false
|
||||||
|
}
|
||||||
|
tail
|
||||||
|
tail {
|
||||||
|
close_on_exit true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn args_added_to_args_in_template() {
|
fn args_added_to_args_in_template() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
|
|
@ -1050,6 +1081,23 @@ fn args_added_to_args_in_template() {
|
||||||
assert_snapshot!(format!("{:#?}", layout));
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn close_on_exit_added_to_close_on_exit_in_template() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
pane_template name="tail" {
|
||||||
|
command "tail"
|
||||||
|
}
|
||||||
|
tail
|
||||||
|
tail {
|
||||||
|
close_on_exit true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cwd_override_cwd_in_template() {
|
fn cwd_override_cwd_in_template() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
|
|
@ -1125,6 +1173,19 @@ fn error_on_bare_args_without_command() {
|
||||||
assert!(layout.is_err(), "error provided");
|
assert!(layout.is_err(), "error provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_on_bare_close_on_exit_without_command() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
pane {
|
||||||
|
close_on_exit true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
|
||||||
|
assert!(layout.is_err(), "error provided");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_on_bare_args_in_template_without_command() {
|
fn error_on_bare_args_in_template_without_command() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
|
|
@ -1139,6 +1200,20 @@ fn error_on_bare_args_in_template_without_command() {
|
||||||
assert!(layout.is_err(), "error provided");
|
assert!(layout.is_err(), "error provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn error_on_bare_close_on_exit_in_template_without_command() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
pane_template name="my_template"
|
||||||
|
my_template {
|
||||||
|
close_on_exit true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
|
||||||
|
assert!(layout.is_err(), "error provided");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd() {
|
fn pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1098
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1064
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 281
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "htop",
|
||||||
|
args: [],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -53,6 +53,7 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
|| word == "children"
|
|| word == "children"
|
||||||
|| word == "tab"
|
|| word == "tab"
|
||||||
|| word == "args"
|
|| word == "args"
|
||||||
|
|| word == "close_on_exit"
|
||||||
|| word == "borderless"
|
|| word == "borderless"
|
||||||
|| word == "focus"
|
|| word == "focus"
|
||||||
|| word == "name"
|
|| word == "name"
|
||||||
|
|
@ -70,6 +71,7 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
|| property_name == "edit"
|
|| property_name == "edit"
|
||||||
|| property_name == "cwd"
|
|| property_name == "cwd"
|
||||||
|| property_name == "args"
|
|| property_name == "args"
|
||||||
|
|| property_name == "close_on_exit"
|
||||||
|| property_name == "split_direction"
|
|| property_name == "split_direction"
|
||||||
|| property_name == "pane"
|
|| property_name == "pane"
|
||||||
|| property_name == "children"
|
|| property_name == "children"
|
||||||
|
|
@ -237,22 +239,28 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
.map(|c| PathBuf::from(c));
|
.map(|c| PathBuf::from(c));
|
||||||
let cwd = self.parse_cwd(pane_node)?;
|
let cwd = self.parse_cwd(pane_node)?;
|
||||||
let args = self.parse_args(pane_node)?;
|
let args = self.parse_args(pane_node)?;
|
||||||
match (command, edit, cwd, args, is_template) {
|
let close_on_exit =
|
||||||
(None, None, Some(cwd), _, _) => Ok(Some(Run::Cwd(cwd))),
|
kdl_get_bool_property_or_child_value_with_error!(pane_node, "close_on_exit");
|
||||||
(None, _, _, Some(_args), false) => Err(ConfigError::new_layout_kdl_error(
|
if !is_template {
|
||||||
"args can only be set if a command was specified".into(),
|
self.assert_no_bare_attributes_in_pane_node(
|
||||||
pane_node.span().offset(),
|
&command,
|
||||||
pane_node.span().len(),
|
&args,
|
||||||
)),
|
&close_on_exit,
|
||||||
(Some(command), None, cwd, args, _) => Ok(Some(Run::Command(RunCommand {
|
pane_node,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let hold_on_close = close_on_exit.map(|c| !c).unwrap_or(true);
|
||||||
|
match (command, edit, cwd) {
|
||||||
|
(None, None, Some(cwd)) => Ok(Some(Run::Cwd(cwd))),
|
||||||
|
(Some(command), None, cwd) => Ok(Some(Run::Command(RunCommand {
|
||||||
command,
|
command,
|
||||||
args: args.unwrap_or_else(|| vec![]),
|
args: args.unwrap_or_else(|| vec![]),
|
||||||
cwd,
|
cwd,
|
||||||
hold_on_close: true,
|
hold_on_close,
|
||||||
}))),
|
}))),
|
||||||
(None, Some(edit), Some(cwd), _, _) => Ok(Some(Run::EditFile(cwd.join(edit), None))),
|
(None, Some(edit), Some(cwd)) => Ok(Some(Run::EditFile(cwd.join(edit), None))),
|
||||||
(None, Some(edit), None, _, _) => Ok(Some(Run::EditFile(edit, None))),
|
(None, Some(edit), None) => Ok(Some(Run::EditFile(edit, None))),
|
||||||
(Some(_command), Some(_edit), _, _, _) => Err(ConfigError::new_layout_kdl_error(
|
(Some(_command), Some(_edit), _) => Err(ConfigError::new_layout_kdl_error(
|
||||||
"cannot have both a command and an edit instruction for the same pane".into(),
|
"cannot have both a command and an edit instruction for the same pane".into(),
|
||||||
pane_node.span().offset(),
|
pane_node.span().offset(),
|
||||||
pane_node.span().len(),
|
pane_node.span().len(),
|
||||||
|
|
@ -370,12 +378,15 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
let name = kdl_get_string_property_or_child_value_with_error!(kdl_node, "name")
|
let name = kdl_get_string_property_or_child_value_with_error!(kdl_node, "name")
|
||||||
.map(|name| name.to_string());
|
.map(|name| name.to_string());
|
||||||
let args = self.parse_args(kdl_node)?;
|
let args = self.parse_args(kdl_node)?;
|
||||||
|
let close_on_exit =
|
||||||
|
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "close_on_exit");
|
||||||
let split_size = self.parse_split_size(kdl_node)?;
|
let split_size = self.parse_split_size(kdl_node)?;
|
||||||
let run = self.parse_command_plugin_or_edit_block_for_template(kdl_node)?;
|
let run = self.parse_command_plugin_or_edit_block_for_template(kdl_node)?;
|
||||||
self.assert_no_bare_args_in_pane_node_with_template(
|
self.assert_no_bare_attributes_in_pane_node_with_template(
|
||||||
&run,
|
&run,
|
||||||
&pane_template.run,
|
&pane_template.run,
|
||||||
&args,
|
&args,
|
||||||
|
&close_on_exit,
|
||||||
kdl_node,
|
kdl_node,
|
||||||
)?;
|
)?;
|
||||||
self.insert_children_to_pane_template(
|
self.insert_children_to_pane_template(
|
||||||
|
|
@ -384,13 +395,12 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
pane_template_kdl_node,
|
pane_template_kdl_node,
|
||||||
)?;
|
)?;
|
||||||
pane_template.run = Run::merge(&pane_template.run, &run);
|
pane_template.run = Run::merge(&pane_template.run, &run);
|
||||||
if let (Some(Run::Command(pane_template_run_command)), Some(args)) =
|
if let Some(pane_template_run_command) = pane_template.run.as_mut() {
|
||||||
(pane_template.run.as_mut(), args)
|
// we need to do this because panes consuming a pane_templates
|
||||||
{
|
// can have bare args without a command
|
||||||
if !args.is_empty() {
|
pane_template_run_command.add_args(args);
|
||||||
pane_template_run_command.args = args.clone();
|
pane_template_run_command.add_close_on_exit(close_on_exit);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
if let Some(borderless) = borderless {
|
if let Some(borderless) = borderless {
|
||||||
pane_template.borderless = borderless;
|
pane_template.borderless = borderless;
|
||||||
}
|
}
|
||||||
|
|
@ -584,11 +594,12 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn assert_no_bare_args_in_pane_node_with_template(
|
fn assert_no_bare_attributes_in_pane_node_with_template(
|
||||||
&self,
|
&self,
|
||||||
pane_run: &Option<Run>,
|
pane_run: &Option<Run>,
|
||||||
pane_template_run: &Option<Run>,
|
pane_template_run: &Option<Run>,
|
||||||
args: &Option<Vec<String>>,
|
args: &Option<Vec<String>>,
|
||||||
|
close_on_exit: &Option<bool>,
|
||||||
pane_node: &KdlNode,
|
pane_node: &KdlNode,
|
||||||
) -> Result<(), ConfigError> {
|
) -> Result<(), ConfigError> {
|
||||||
if let (None, None, true) = (pane_run, pane_template_run, args.is_some()) {
|
if let (None, None, true) = (pane_run, pane_template_run, args.is_some()) {
|
||||||
|
|
@ -597,6 +608,37 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
pane_node
|
pane_node
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let (None, None, true) = (pane_run, pane_template_run, close_on_exit.is_some()) {
|
||||||
|
return Err(kdl_parsing_error!(
|
||||||
|
format!("close_on_exit can only be specified if a command was specified either in the pane_template or in the pane"),
|
||||||
|
pane_node
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn assert_no_bare_attributes_in_pane_node(
|
||||||
|
&self,
|
||||||
|
command: &Option<PathBuf>,
|
||||||
|
args: &Option<Vec<String>>,
|
||||||
|
close_on_exit: &Option<bool>,
|
||||||
|
pane_node: &KdlNode,
|
||||||
|
) -> Result<(), ConfigError> {
|
||||||
|
if command.is_none() {
|
||||||
|
if close_on_exit.is_some() {
|
||||||
|
return Err(ConfigError::new_layout_kdl_error(
|
||||||
|
"close_on_exit can only be set if a command was specified".into(),
|
||||||
|
pane_node.span().offset(),
|
||||||
|
pane_node.span().len(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if args.is_some() {
|
||||||
|
return Err(ConfigError::new_layout_kdl_error(
|
||||||
|
"args can only be set if a command was specified".into(),
|
||||||
|
pane_node.span().offset(),
|
||||||
|
pane_node.span().len(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn assert_one_children_block(
|
fn assert_one_children_block(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue