Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(layouts): global cwd #1798

Merged
merged 4 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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