diff --git a/src/main.rs b/src/main.rs index b3706eadda..bcb019469d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod sessions; mod tests; use crate::install::populate_data_dir; -use sessions::{assert_session, assert_session_ne, get_active_session, list_sessions}; +use sessions::{assert_session_ne, get_sessions, print_sessions, print_sessions_and_exit}; use std::convert::TryFrom; use std::process; use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo}; @@ -18,11 +18,37 @@ use zellij_utils::{ structopt::StructOpt, }; +fn start_new_session_name(opts: &CliArgs) -> String { + let session_name = opts + .session + .clone() + .unwrap_or_else(|| names::Generator::default().next().unwrap()); + assert_session_ne(&session_name); + return session_name; +} + +fn start_new_session_layout(opts: &CliArgs, config_options: &Options) -> Option { + // Determine and initialize the data directory + let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir); + #[cfg(not(disable_automatic_asset_installation))] + populate_data_dir(&data_dir); + + let layout_dir = config_options + .layout_dir + .clone() + .or_else(|| get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir))); + + let layout = + Layout::from_path_or_default(opts.layout.as_ref(), opts.layout_path.as_ref(), layout_dir); + + return layout; +} + pub fn main() { - let opts = CliArgs::from_args(); + let mut opts = CliArgs::from_args(); if let Some(Command::Sessions(Sessions::ListSessions)) = opts.command { - list_sessions(); + print_sessions_and_exit(); } let config = match Config::try_from(&opts) { @@ -59,49 +85,83 @@ pub fn main() { }; if let Some(Command::Sessions(Sessions::Attach { mut session_name, + create, force, })) = opts.command.clone() { - if let Some(session) = session_name.as_ref() { - assert_session(session); - } else { - session_name = Some(get_active_session()); - } - start_client( - Box::new(os_input), - opts, - config, - ClientInfo::Attach(session_name.unwrap(), force, config_options), - None, - ); - } else { - let session_name = opts - .session - .clone() - .unwrap_or_else(|| names::Generator::default().next().unwrap()); - assert_session_ne(&session_name); + let mut sessions = get_sessions(); + let mut start_new_session = false; - // Determine and initialize the data directory - let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir); - #[cfg(not(disable_automatic_asset_installation))] - populate_data_dir(&data_dir); + if session_name.is_none() { + if sessions.len() == 1 { + // If a session name was omitted but there is only one session, attach it + session_name = sessions.pop(); + println!("Attaching session {:?}", session_name); + } else if create { + // If a session name was omitted, but --create was used, attach to new session + // with random name + start_new_session = true; + println!("Creating a new session to attach"); + } else if sessions.is_empty() { + // If a session name was omitted and there are no sessions, exit with error + eprintln!("ERROR: No active Zellij sessions found"); + process::exit(1); + } else { + // If session name was omitted but there are some sessions, list them before + // exiting with error + eprintln!("ERROR: Please specify the session name to attach to. The following sessions are active:"); + print_sessions(sessions); + process::exit(1); + } - let layout_dir = config_options.layout_dir.or_else(|| { - get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir)) - }); - let layout = Layout::from_path_or_default( - opts.layout.as_ref(), - opts.layout_path.as_ref(), - layout_dir, - ); + } else { + if sessions + .iter() + .any(|s| s.to_string() == session_name.as_deref().unwrap()) + { + // If a session name was given, and it exists, attach to it + } else if create { + // If a session name was given, but does not exist while --create was used, + // attach a new session using that name + start_new_session = true; + println!( + "Creating new session {:?} to attach", + session_name.clone().unwrap() + ); + opts.session = session_name.clone(); + } else { + // If a session name was given, but does not exist and will not be created, + // just list sessions and exit + eprintln!("ERROR: No session named {:?} found", session_name.unwrap()); + process::exit(1); + } + } + if start_new_session { + start_client( + Box::new(os_input), + opts.clone(), + config, + ClientInfo::New(start_new_session_name(&opts)), + start_new_session_layout(&opts, &config_options), + ); + } else { + start_client( + Box::new(os_input), + opts, + config, + ClientInfo::Attach(session_name.unwrap(), force, config_options), + None, + ); + } + } else { start_client( Box::new(os_input), - opts, + opts.clone(), config, - ClientInfo::New(session_name), - layout, + ClientInfo::New(start_new_session_name(&opts)), + start_new_session_layout(&opts, &config_options), ); } } diff --git a/src/sessions.rs b/src/sessions.rs index fb1a963525..cadf032891 100644 --- a/src/sessions.rs +++ b/src/sessions.rs @@ -6,7 +6,7 @@ use zellij_utils::{ ipc::{ClientToServerMsg, IpcSenderWithContext}, }; -fn get_sessions() -> Result, io::ErrorKind> { +fn read_sessions() -> Result, io::ErrorKind> { match fs::read_dir(&*ZELLIJ_SOCK_DIR) { Ok(files) => { let mut sessions = Vec::new(); @@ -47,7 +47,17 @@ fn assert_socket(name: &str) -> bool { } } -fn print_sessions(sessions: Vec) { +pub(crate) fn get_sessions() -> Vec { + match read_sessions() { + Ok(sessions) => { + return sessions; + } + Err(e) => eprintln!("Error occured: {:?}", e), + } + process::exit(1); +} + +pub(crate) fn print_sessions(sessions: Vec) { let curr_session = std::env::var("ZELLIJ_SESSION_NAME").unwrap_or_else(|_| "".into()); sessions.iter().for_each(|session| { let suffix = if curr_session == *session { @@ -59,26 +69,8 @@ fn print_sessions(sessions: Vec) { }) } -pub(crate) fn get_active_session() -> String { - match get_sessions() { - Ok(mut sessions) => { - if sessions.len() == 1 { - return sessions.pop().unwrap(); - } - if sessions.is_empty() { - println!("No active zellij sessions found."); - } else { - println!("Please specify the session name to attach to. The following sessions are active:"); - print_sessions(sessions); - } - } - Err(e) => eprintln!("Error occured: {:?}", e), - } - process::exit(1); -} - -pub(crate) fn list_sessions() { - let exit_code = match get_sessions() { +pub(crate) fn print_sessions_and_exit() { + let exit_code = match read_sessions() { Ok(sessions) => { if sessions.is_empty() { println!("No active zellij sessions found."); @@ -95,26 +87,13 @@ pub(crate) fn list_sessions() { process::exit(exit_code); } -pub(crate) fn assert_session(name: &str) { - match get_sessions() { - Ok(sessions) => { - if sessions.iter().any(|s| s == name) { - return; - } - println!("No session named {:?} found.", name); - } - Err(e) => eprintln!("Error occured: {:?}", e), - }; - process::exit(1); -} - pub(crate) fn assert_session_ne(name: &str) { - match get_sessions() { + match read_sessions() { Ok(sessions) => { if sessions.iter().all(|s| s != name) { return; } - println!("Session with name {:?} aleady exists. Use attach command to connect to it or specify a different name.", name); + println!("Session with name {:?} already exists. Use attach command to connect to it or specify a different name.", name); } Err(e) => eprintln!("Error occured: {:?}", e), }; diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 2ac0e986ba..bea424c895 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -74,8 +74,12 @@ pub enum Sessions { /// Name of the session to attach to. session_name: Option, - /// Force attach- session will detach from the other - /// zellij client (if any) and attach to this. + /// If session does not exist, create it to ensure that the + /// attach command will always succeed. + #[structopt(long, short)] + create: bool, + + /// Detach session from other Zellij client (if any) and attach to this. #[structopt(long, short)] force: bool, },