diff options
| author | Kunal Mohan <44079328+kunalmohan@users.noreply.github.com> | 2021-05-25 17:30:40 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-25 17:30:40 +0530 |
| commit | 2bca7e007aad9a74e6c48191b8a7a3edf85808d4 (patch) | |
| tree | 61366b1e29601ad003fc53a715f4b925d8ef5871 /src | |
| parent | hotfix(build): Fix cargo make install (diff) | |
| parent | check for residual socket files and clean them (diff) | |
| download | sl0ppij-2bca7e007aad9a74e6c48191b8a7a3edf85808d4.tar.gz sl0ppij-2bca7e007aad9a74e6c48191b8a7a3edf85808d4.tar.xz sl0ppij-2bca7e007aad9a74e6c48191b8a7a3edf85808d4.zip | |
Merge pull request #531 from zellij-org/detach-sessions
Feature: Detachable/Persistent sessions
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 45 | ||||
| -rw-r--r-- | src/sessions.rs | 109 | ||||
| -rw-r--r-- | src/tests/fakes.rs | 2 | ||||
| -rw-r--r-- | src/tests/mod.rs | 4 |
4 files changed, 150 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs index a970ce44..67b83398 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,14 @@ +mod sessions; #[cfg(test)] mod tests; +use sessions::{assert_session, assert_session_ne, list_sessions}; use std::convert::TryFrom; -use zellij_client::{os_input_output::get_client_os_input, start_client}; +use std::process; +use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo}; use zellij_server::{os_input_output::get_server_os_input, start_server}; use zellij_utils::{ - cli::{CliArgs, ConfigCli}, + cli::{CliArgs, Command, Sessions}, consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR}, input::config::Config, logging::*, @@ -16,15 +19,17 @@ use zellij_utils::{ pub fn main() { let opts = CliArgs::from_args(); - if let Some(ConfigCli::Setup(setup)) = opts.option.clone() { - Setup::from_cli(&setup, &opts).expect("Failed to print to stdout"); + if let Some(Command::Sessions(Sessions::ListSessions)) = opts.command { + list_sessions(); + } else if let Some(Command::Setup(ref setup)) = opts.command { + Setup::from_cli(setup, &opts).expect("Failed to print to stdout"); } let config = match Config::try_from(&opts) { Ok(config) => config, Err(e) => { eprintln!("There was an error in the config file:\n{}", e); - std::process::exit(1); + process::exit(1); } }; atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap(); @@ -34,7 +39,7 @@ pub fn main() { Ok(server_os_input) => server_os_input, Err(e) => { eprintln!("failed to open terminal:\n{}", e); - std::process::exit(1); + process::exit(1); } }; start_server(Box::new(os_input), path); @@ -43,9 +48,33 @@ pub fn main() { Ok(os_input) => os_input, Err(e) => { eprintln!("failed to open terminal:\n{}", e); - std::process::exit(1); + process::exit(1); } }; - start_client(Box::new(os_input), opts, config); + if let Some(Command::Sessions(Sessions::Attach { + session_name, + force, + })) = opts.command.clone() + { + assert_session(&session_name); + start_client( + Box::new(os_input), + opts, + config, + ClientInfo::Attach(session_name, force), + ); + } else { + let session_name = opts + .session + .clone() + .unwrap_or_else(|| names::Generator::default().next().unwrap()); + assert_session_ne(&session_name); + start_client( + Box::new(os_input), + opts, + config, + ClientInfo::New(session_name), + ); + } } } diff --git a/src/sessions.rs b/src/sessions.rs new file mode 100644 index 00000000..fd834e40 --- /dev/null +++ b/src/sessions.rs @@ -0,0 +1,109 @@ +use std::os::unix::fs::FileTypeExt; +use std::{fs, io, process}; +use zellij_utils::{ + consts::ZELLIJ_SOCK_DIR, + interprocess::local_socket::LocalSocketStream, + ipc::{ClientToServerMsg, IpcSenderWithContext}, +}; + +fn get_sessions() -> Result<Vec<String>, io::ErrorKind> { + match fs::read_dir(&*ZELLIJ_SOCK_DIR) { + Ok(files) => { + let mut sessions = Vec::new(); + files.for_each(|file| { + let file = file.unwrap(); + let file_name = file.file_name().into_string().unwrap(); + if file.file_type().unwrap().is_socket() && assert_socket(&file_name) { + sessions.push(file_name); + } + }); + Ok(sessions) + } + Err(err) => { + if let io::ErrorKind::NotFound = err.kind() { + Ok(Vec::with_capacity(0)) + } else { + Err(err.kind()) + } + } + } +} + +pub(crate) fn list_sessions() { + let exit_code = match get_sessions() { + Ok(sessions) => { + if sessions.is_empty() { + println!("No active zellij sessions found."); + } else { + let curr_session = + std::env::var("ZELLIJ_SESSION_NAME").unwrap_or_else(|_| "".into()); + sessions.iter().for_each(|session| { + let suffix = if curr_session == *session { + " (current)" + } else { + "" + }; + println!("{}{}", session, suffix); + }) + } + 0 + } + Err(e) => { + eprintln!("Error occured: {:?}", e); + 1 + } + }; + process::exit(exit_code); +} + +pub(crate) fn assert_session(name: &str) { + let exit_code = match get_sessions() { + Ok(sessions) => { + if sessions.iter().any(|s| s == name) { + return; + } + println!("No session named {:?} found.", name); + 0 + } + Err(e) => { + eprintln!("Error occured: {:?}", e); + 1 + } + }; + process::exit(exit_code); +} + +pub(crate) fn assert_session_ne(name: &str) { + let exit_code = match get_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); + 0 + } + Err(e) => { + eprintln!("Error occured: {:?}", e); + 1 + } + }; + process::exit(exit_code); +} + +fn assert_socket(name: &str) -> bool { + let path = &*ZELLIJ_SOCK_DIR.join(name); + match LocalSocketStream::connect(path) { + Ok(stream) => { + IpcSenderWithContext::new(stream).send(ClientToServerMsg::ClientExited); + true + } + Err(e) => { + if e.kind() == io::ErrorKind::ConnectionRefused { + drop(fs::remove_file(path)); + false + } else { + true + } + } + } +} diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs index a2f338ba..23f9f182 100644 --- a/src/tests/fakes.rs +++ b/src/tests/fakes.rs @@ -333,6 +333,8 @@ impl ServerOsApi for FakeInputOutput { self.send_instructions_to_client.send(msg).unwrap(); } fn add_client_sender(&self) {} + fn remove_client_sender(&self) {} + fn send_to_temp_client(&self, _msg: ServerToClientMsg) {} fn update_receiver(&mut self, _stream: LocalSocketStream) {} fn load_palette(&self) -> Palette { default_palette() diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 3e548db7..e075ed49 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -5,7 +5,7 @@ pub mod tty_inputs; pub mod utils; use std::path::PathBuf; -use zellij_client::{os_input_output::ClientOsApi, start_client}; +use zellij_client::{os_input_output::ClientOsApi, start_client, ClientInfo}; use zellij_server::{os_input_output::ServerOsApi, start_server}; use zellij_utils::{cli::CliArgs, input::config::Config}; @@ -21,6 +21,6 @@ pub fn start( start_server(server_os_input, PathBuf::from("")); }) .unwrap(); - start_client(client_os_input, opts, config); + start_client(client_os_input, opts, config, ClientInfo::New("".into())); let _ = server_thread.join(); } |
