Skip to content

Commit

Permalink
feat(layouts): global cwd (#1798)
Browse files Browse the repository at this point in the history
* feat(layouts): allow defining a global cwd

* feat(layouts): allow passing global cwd from cli

* style(fmt): rustfmt

* fix(layouts): error on mixed cwd and pane children
  • Loading branch information
imsnif authored Oct 14, 2022
1 parent 5c43a59 commit d074bb1
Show file tree
Hide file tree
Showing 22 changed files with 1,048 additions and 138 deletions.
8 changes: 7 additions & 1 deletion zellij-server/src/os_input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ fn handle_openpty(
let cmd = cmd.clone();
let command = &mut Command::new(cmd.command);
if let Some(current_dir) = cmd.cwd {
if current_dir.exists() {
if current_dir.exists() && current_dir.is_dir() {
command.current_dir(current_dir);
} else {
// TODO: propagate this to the user
log::error!(
"Failed to set CWD for new pane. {} does not exist or is not a folder",
current_dir.display()
);
}
}
command
Expand Down
33 changes: 28 additions & 5 deletions zellij-server/src/pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,11 @@ impl Pty {
default_editor,
}
}
pub fn get_default_terminal(&self) -> TerminalAction {
pub fn get_default_terminal(&self, cwd: Option<PathBuf>) -> TerminalAction {
TerminalAction::RunCommand(RunCommand {
args: vec![],
command: PathBuf::from(env::var("SHELL").expect("Could not find the SHELL variable")),
cwd: None, // this should be filled by the calling function, eg. spawn_terminal
cwd, // note: this might also be filled by the calling function, eg. spawn_terminal
hold_on_close: false,
})
}
Expand Down Expand Up @@ -400,12 +400,12 @@ impl Pty {
let terminal_action = match client_or_tab_index {
ClientOrTabIndex::ClientId(client_id) => {
let mut terminal_action =
terminal_action.unwrap_or_else(|| self.get_default_terminal());
terminal_action.unwrap_or_else(|| self.get_default_terminal(None));
self.fill_cwd(&mut terminal_action, client_id);
terminal_action
},
ClientOrTabIndex::TabIndex(_) => {
terminal_action.unwrap_or_else(|| self.get_default_terminal())
terminal_action.unwrap_or_else(|| self.get_default_terminal(None))
},
};
let hold_on_close = match &terminal_action {
Expand Down Expand Up @@ -454,7 +454,7 @@ impl Pty {
default_shell: Option<TerminalAction>,
client_id: ClientId,
) {
let mut default_shell = default_shell.unwrap_or_else(|| self.get_default_terminal());
let mut default_shell = default_shell.unwrap_or_else(|| self.get_default_terminal(None));
self.fill_cwd(&mut default_shell, client_id);
let extracted_run_instructions = layout.extract_run_instructions();
let mut new_pane_pids: Vec<(u32, Option<RunCommand>, Result<RawFd, SpawnTerminalError>)> =
Expand Down Expand Up @@ -513,6 +513,29 @@ impl Pty {
},
}
},
Some(Run::Cwd(cwd)) => {
let shell = self.get_default_terminal(Some(cwd));
match self.bus.os_input.as_mut().unwrap().spawn_terminal(
shell,
quit_cb,
self.default_editor.clone(),
) {
Ok((terminal_id, pid_primary, child_fd)) => {
self.id_to_child_pid.insert(terminal_id, child_fd);
new_pane_pids.push((terminal_id, None, Ok(pid_primary)));
},
Err(SpawnTerminalError::CommandNotFound(terminal_id)) => {
new_pane_pids.push((
terminal_id,
None,
Err(SpawnTerminalError::CommandNotFound(terminal_id)),
));
},
Err(e) => {
log::error!("Failed to spawn terminal: {}", e);
},
}
},
None => {
match self.bus.os_input.as_mut().unwrap().spawn_terminal(
default_shell.clone(),
Expand Down
2 changes: 1 addition & 1 deletion zellij-server/src/tab/unit/tab_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str)
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let layout = Layout::from_str(layout, "layout_file_name".into()).unwrap();
let layout = Layout::from_str(layout, "layout_file_name".into(), None).unwrap();
let tab_layout = layout.new_tab();
let mut tab = Tab::new(
index,
Expand Down
2 changes: 2 additions & 0 deletions zellij-server/src/unit/screen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2207,6 +2207,7 @@ pub fn send_cli_new_tab_action_default_params() {
let new_tab_action = CliAction::NewTab {
name: None,
layout: None,
cwd: None,
};
send_cli_action_to_server(
&session_metadata,
Expand Down Expand Up @@ -2242,6 +2243,7 @@ pub fn send_cli_new_tab_action_with_name_and_layout() {
"{}/src/unit/fixtures/layout-with-three-panes.kdl",
env!("CARGO_MANIFEST_DIR")
))),
cwd: None,
};
send_cli_action_to_server(
&session_metadata,
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,7 @@ pub enum CliAction {
layout: Option<PathBuf>,
#[clap(short, long, value_parser)]
name: Option<String>,
#[clap(short, long, value_parser, requires("layout"))]
cwd: Option<PathBuf>,
},
}
4 changes: 2 additions & 2 deletions zellij-utils/src/input/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,12 @@ impl Action {
Action::TabNameInput(name.as_bytes().to_vec()),
]),
CliAction::UndoRenameTab => Ok(vec![Action::UndoRenameTab]),
CliAction::NewTab { name, layout } => {
CliAction::NewTab { name, layout, cwd } => {
if let Some(layout_path) = layout {
let (path_to_raw_layout, raw_layout) =
Layout::stringified_from_path_or_default(Some(&layout_path), None)
.map_err(|e| format!("Failed to load layout: {}", e))?;
let layout = Layout::from_str(&raw_layout, path_to_raw_layout).map_err(|e| {
let layout = Layout::from_str(&raw_layout, path_to_raw_layout, cwd).map_err(|e| {
let stringified_error = match e {
ConfigError::KdlError(kdl_error) => {
let error = kdl_error.add_src(layout_path.as_path().as_os_str().to_string_lossy().to_string(), String::from(raw_layout));
Expand Down
45 changes: 42 additions & 3 deletions zellij-utils/src/input/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,41 @@ pub enum Run {
Plugin(RunPlugin),
#[serde(rename = "command")]
Command(RunCommand),
Cwd(PathBuf),
}

impl Run {
pub fn merge(base: &Option<Run>, other: &Option<Run>) -> Option<Run> {
// TODO: handle Plugin variants once there's a need
match (base, other) {
(Some(Run::Command(base_run_command)), Some(Run::Command(other_run_command))) => {
let mut merged = other_run_command.clone();
if merged.cwd.is_none() && base_run_command.cwd.is_some() {
merged.cwd = base_run_command.cwd.clone();
}
if merged.args.is_empty() && !base_run_command.args.is_empty() {
merged.args = base_run_command.args.clone();
}
Some(Run::Command(merged))
},
(Some(Run::Command(base_run_command)), Some(Run::Cwd(other_cwd))) => {
let mut merged = base_run_command.clone();
merged.cwd = Some(other_cwd.clone());
Some(Run::Command(merged))
},
(Some(Run::Cwd(base_cwd)), Some(Run::Command(other_command))) => {
let mut merged = other_command.clone();
if merged.cwd.is_none() {
merged.cwd = Some(base_cwd.clone());
}
Some(Run::Command(merged))
},
(Some(_base), Some(other)) => Some(other.clone()),
(Some(base), _) => Some(base.clone()),
(None, Some(other)) => Some(other.clone()),
(None, None) => None,
}
}
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -252,12 +287,16 @@ impl Layout {
) -> Result<(Layout, Config), ConfigError> {
let (path_to_raw_layout, raw_layout) =
Layout::stringified_from_path_or_default(layout_path, layout_dir)?;
let layout = Layout::from_kdl(&raw_layout, path_to_raw_layout)?;
let layout = Layout::from_kdl(&raw_layout, path_to_raw_layout, None)?;
let config = Config::from_kdl(&raw_layout, Some(config))?; // this merges the two config, with
Ok((layout, config))
}
pub fn from_str(raw: &str, path_to_raw_layout: String) -> Result<Layout, ConfigError> {
Layout::from_kdl(raw, path_to_raw_layout)
pub fn from_str(
raw: &str,
path_to_raw_layout: String,
cwd: Option<PathBuf>,
) -> Result<Layout, ConfigError> {
Layout::from_kdl(raw, path_to_raw_layout, cwd)
}
pub fn stringified_from_dir(
layout: &PathBuf,
Expand Down
Loading

0 comments on commit d074bb1

Please sign in to comment.