summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKunal Mohan <44079328+kunalmohan@users.noreply.github.com>2021-05-25 17:30:40 +0530
committerGitHub <noreply@github.com>2021-05-25 17:30:40 +0530
commit2bca7e007aad9a74e6c48191b8a7a3edf85808d4 (patch)
tree61366b1e29601ad003fc53a715f4b925d8ef5871 /src
parent6755b6a88defe30c63fa3bc6d25aa89e545180c9 (diff)
parentdf6d6cb3a70cbea9d088c7af47f3540896b98089 (diff)
Merge pull request #531 from zellij-org/detach-sessions
Feature: Detachable/Persistent sessions
Diffstat (limited to 'src')
-rw-r--r--src/main.rs45
-rw-r--r--src/sessions.rs109
-rw-r--r--src/tests/fakes.rs2
-rw-r--r--src/tests/mod.rs4
4 files changed, 150 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index a970ce446..67b833988 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 000000000..fd834e408
--- /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 a2f338ba6..23f9f1824 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 3e548db7c..e075ed49a 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();
}