Add option to specify default-shell

* Adds an option to specify a default shell
  either by specifying `default_shell: [PATH]`
  in the config, or running zellij with
  `zellij options --default-shell [PATH]`
This commit is contained in:
a-kenji 2021-07-01 20:02:08 +02:00
parent 71f980a01d
commit 6f1c103e02
4 changed files with 60 additions and 16 deletions

View file

@ -29,7 +29,12 @@ use zellij_utils::{
channels::{self, ChannelWithContext, SenderWithContext}, channels::{self, ChannelWithContext, SenderWithContext},
cli::CliArgs, cli::CliArgs,
errors::{ContextType, ErrorInstruction, ServerContext}, errors::{ContextType, ErrorInstruction, ServerContext},
input::{get_mode_info, layout::Layout, options::Options}, input::{
command::{RunCommand, TerminalAction},
get_mode_info,
layout::Layout,
options::Options,
},
ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg}, ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg},
setup::get_default_data_dir, setup::get_default_data_dir,
}; };
@ -84,6 +89,7 @@ pub(crate) struct SessionMetaData {
pub senders: ThreadSenders, pub senders: ThreadSenders,
pub capabilities: PluginCapabilities, pub capabilities: PluginCapabilities,
pub palette: Palette, pub palette: Palette,
pub default_shell: Option<TerminalAction>,
screen_thread: Option<thread::JoinHandle<()>>, screen_thread: Option<thread::JoinHandle<()>>,
pty_thread: Option<thread::JoinHandle<()>>, pty_thread: Option<thread::JoinHandle<()>>,
wasm_thread: Option<thread::JoinHandle<()>>, wasm_thread: Option<thread::JoinHandle<()>>,
@ -219,13 +225,21 @@ pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
); );
*session_data.write().unwrap() = Some(session); *session_data.write().unwrap() = Some(session);
*session_state.write().unwrap() = SessionState::Attached; *session_state.write().unwrap() = SessionState::Attached;
let default_shell = session_data
.read()
.unwrap()
.as_ref()
.map(|session| session.default_shell.clone())
.flatten();
session_data session_data
.read() .read()
.unwrap() .unwrap()
.as_ref() .as_ref()
.unwrap() .unwrap()
.senders .senders
.send_to_pty(PtyInstruction::NewTab) .send_to_pty(PtyInstruction::NewTab(default_shell.clone()))
.unwrap(); .unwrap();
} }
ServerInstruction::AttachClient(attrs, _, options) => { ServerInstruction::AttachClient(attrs, _, options) => {
@ -324,6 +338,13 @@ fn init_session(
arrow_fonts: config_options.simplified_ui, arrow_fonts: config_options.simplified_ui,
}; };
let default_shell = config_options.default_shell.clone().map(|command| {
TerminalAction::RunCommand(RunCommand {
command,
..Default::default()
})
});
let pty_thread = thread::Builder::new() let pty_thread = thread::Builder::new()
.name("pty".to_string()) .name("pty".to_string())
.spawn({ .spawn({
@ -393,6 +414,7 @@ fn init_session(
should_silently_fail: false, should_silently_fail: false,
}, },
capabilities, capabilities,
default_shell,
palette: client_attributes.palette, palette: client_attributes.palette,
screen_thread: Some(screen_thread), screen_thread: Some(screen_thread),
pty_thread: Some(pty_thread), pty_thread: Some(pty_thread),

View file

@ -28,7 +28,7 @@ pub(crate) enum PtyInstruction {
SpawnTerminal(Option<TerminalAction>), SpawnTerminal(Option<TerminalAction>),
SpawnTerminalVertically(Option<TerminalAction>), SpawnTerminalVertically(Option<TerminalAction>),
SpawnTerminalHorizontally(Option<TerminalAction>), SpawnTerminalHorizontally(Option<TerminalAction>),
NewTab, NewTab(Option<TerminalAction>),
ClosePane(PaneId), ClosePane(PaneId),
CloseTab(Vec<PaneId>), CloseTab(Vec<PaneId>),
Exit, Exit,
@ -42,7 +42,7 @@ impl From<&PtyInstruction> for PtyContext {
PtyInstruction::SpawnTerminalHorizontally(_) => PtyContext::SpawnTerminalHorizontally, PtyInstruction::SpawnTerminalHorizontally(_) => PtyContext::SpawnTerminalHorizontally,
PtyInstruction::ClosePane(_) => PtyContext::ClosePane, PtyInstruction::ClosePane(_) => PtyContext::ClosePane,
PtyInstruction::CloseTab(_) => PtyContext::CloseTab, PtyInstruction::CloseTab(_) => PtyContext::CloseTab,
PtyInstruction::NewTab => PtyContext::NewTab, PtyInstruction::NewTab(_) => PtyContext::NewTab,
PtyInstruction::Exit => PtyContext::Exit, PtyInstruction::Exit => PtyContext::Exit,
} }
} }
@ -81,11 +81,11 @@ pub(crate) fn pty_thread_main(mut pty: Pty, maybe_layout: Option<Layout>) {
.send_to_screen(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid))) .send_to_screen(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)))
.unwrap(); .unwrap();
} }
PtyInstruction::NewTab => { PtyInstruction::NewTab(terminal_action) => {
if let Some(layout) = maybe_layout.clone() { if let Some(layout) = maybe_layout.clone() {
pty.spawn_terminals_for_layout(layout); pty.spawn_terminals_for_layout(layout, terminal_action);
} else { } else {
let pid = pty.spawn_terminal(None); let pid = pty.spawn_terminal(terminal_action);
pty.bus pty.bus
.senders .senders
.send_to_screen(ScreenInstruction::NewTab(pid)) .send_to_screen(ScreenInstruction::NewTab(pid))
@ -234,12 +234,20 @@ impl Pty {
self.id_to_child_pid.insert(pid_primary, pid_secondary); self.id_to_child_pid.insert(pid_primary, pid_secondary);
pid_primary pid_primary
} }
pub fn spawn_terminals_for_layout(&mut self, layout: Layout) { pub fn spawn_terminals_for_layout(
&mut self,
layout: Layout,
terminal_action: Option<TerminalAction>,
) {
let total_panes = layout.total_terminal_panes(); let total_panes = layout.total_terminal_panes();
let mut new_pane_pids = vec![]; let mut new_pane_pids = vec![];
for _ in 0..total_panes { for _ in 0..total_panes {
let (pid_primary, pid_secondary): (RawFd, Pid) = let (pid_primary, pid_secondary): (RawFd, Pid) = self
self.bus.os_input.as_mut().unwrap().spawn_terminal(None); .bus
.os_input
.as_mut()
.unwrap()
.spawn_terminal(terminal_action.clone());
self.id_to_child_pid.insert(pid_primary, pid_secondary); self.id_to_child_pid.insert(pid_primary, pid_secondary);
new_pane_pids.push(pid_primary); new_pane_pids.push(pid_primary);
} }

View file

@ -133,13 +133,14 @@ fn route_action(
.unwrap(); .unwrap();
} }
Action::NewPane(direction) => { Action::NewPane(direction) => {
let shell = session.default_shell.clone();
let pty_instr = match direction { let pty_instr = match direction {
Some(Direction::Left) => PtyInstruction::SpawnTerminalVertically(None), Some(Direction::Left) => PtyInstruction::SpawnTerminalVertically(shell),
Some(Direction::Right) => PtyInstruction::SpawnTerminalVertically(None), Some(Direction::Right) => PtyInstruction::SpawnTerminalVertically(shell),
Some(Direction::Up) => PtyInstruction::SpawnTerminalHorizontally(None), Some(Direction::Up) => PtyInstruction::SpawnTerminalHorizontally(shell),
Some(Direction::Down) => PtyInstruction::SpawnTerminalHorizontally(None), Some(Direction::Down) => PtyInstruction::SpawnTerminalHorizontally(shell),
// No direction specified - try to put it in the biggest available spot // No direction specified - try to put it in the biggest available spot
None => PtyInstruction::SpawnTerminal(None), None => PtyInstruction::SpawnTerminal(shell),
}; };
session.senders.send_to_pty(pty_instr).unwrap(); session.senders.send_to_pty(pty_instr).unwrap();
} }
@ -150,7 +151,11 @@ fn route_action(
.unwrap(); .unwrap();
} }
Action::NewTab => { Action::NewTab => {
session.senders.send_to_pty(PtyInstruction::NewTab).unwrap(); let shell = session.default_shell.clone();
session
.senders
.send_to_pty(PtyInstruction::NewTab(shell))
.unwrap();
} }
Action::GoToNextTab => { Action::GoToNextTab => {
session session

View file

@ -20,6 +20,9 @@ pub struct Options {
/// Set the default mode /// Set the default mode
#[structopt(long)] #[structopt(long)]
pub default_mode: Option<InputMode>, pub default_mode: Option<InputMode>,
/// Set the default shell
#[structopt(long, parse(from_os_str))]
pub default_shell: Option<PathBuf>,
/// Set the layout_dir, defaults to /// Set the layout_dir, defaults to
/// subdirectory of config dir /// subdirectory of config dir
#[structopt(long, parse(from_os_str))] #[structopt(long, parse(from_os_str))]
@ -50,6 +53,11 @@ impl Options {
other => other, other => other,
}; };
let default_shell = match other.default_shell {
None => self.default_shell.clone(),
other => other,
};
let layout_dir = match other.layout_dir { let layout_dir = match other.layout_dir {
None => self.layout_dir.clone(), None => self.layout_dir.clone(),
other => other, other => other,
@ -64,6 +72,7 @@ impl Options {
simplified_ui, simplified_ui,
theme, theme,
default_mode, default_mode,
default_shell,
layout_dir, layout_dir,
} }
} }