From 0ca5c187295a157d9e6d24676146681da4fa0188 Mon Sep 17 00:00:00 2001 From: Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:57:56 +0900 Subject: [PATCH] feat(cli): add `kill-session` command (#745) * feat: add kill-session command * style: apply formatting rules * feat: add new instruction for kill-session * feat: update feedback of kill-session * separation of command `kill-session` and `kill-all-sessions` function. * Add information to various situations * Add a question (yes or no) when executing the `kill-all-sessions` command. * chore: adjust clippy warning * fix warning wording * make rustfmt happy Co-authored-by: Aram Drevekenin --- src/main.rs | 61 ++++++++++++++++++++++++++++++++++++-- src/sessions.rs | 13 ++++++++ zellij-server/src/lib.rs | 10 +++++++ zellij-server/src/route.rs | 3 ++ zellij-utils/src/cli.rs | 15 ++++++++++ zellij-utils/src/errors.rs | 1 + zellij-utils/src/ipc.rs | 1 + 7 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 90eeb96b..70734ae4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,8 @@ mod tests; use crate::install::populate_data_dir; use sessions::{ - assert_session, assert_session_ne, get_active_session, get_sessions, list_sessions, - print_sessions, session_exists, ActiveSession, + assert_session, assert_session_ne, get_active_session, get_sessions, kill_session, + list_sessions, print_sessions, session_exists, ActiveSession, }; use std::process; use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo}; @@ -27,6 +27,63 @@ pub fn main() { list_sessions(); } + if let Some(Command::Sessions(Sessions::KillAllSessions { yes })) = opts.command { + match get_sessions() { + Ok(sessions) => { + if sessions.is_empty() { + println!("No active zellij sessions found."); + process::exit(1); + } else { + let kill_all_sessions = |sessions: Vec| { + for session in sessions.iter() { + kill_session(session); + } + process::exit(0) + }; + + if yes { + kill_all_sessions(sessions); + } else { + use std::io::{stdin, stdout, Write}; + + let mut answer = String::new(); + println!("WARNING: this action will kill all sessions."); + print!("Do you want to continue? [y/N] "); + let _ = stdout().flush(); + stdin().read_line(&mut answer).unwrap(); + + match answer.as_str().trim() { + "y" | "Y" | "yes" | "Yes" => kill_all_sessions(sessions), + _ => { + println!("Abort."); + process::exit(1); + } + } + } + } + } + Err(e) => { + eprintln!("Error occured: {:?}", e); + process::exit(1); + } + } + } + + if let Some(Command::Sessions(Sessions::KillSession { target_session })) = opts.command.clone() + { + match target_session.as_ref() { + Some(target_session) => { + assert_session(target_session); + kill_session(target_session); + process::exit(0); + } + None => { + println!("Please specify the session name to kill."); + process::exit(1); + } + } + } + atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap(); atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap(); if let Some(path) = opts.server { diff --git a/src/sessions.rs b/src/sessions.rs index 9f1e20f0..c2d8afea 100644 --- a/src/sessions.rs +++ b/src/sessions.rs @@ -84,6 +84,19 @@ pub(crate) fn get_active_session() -> ActiveSession { } } +pub(crate) fn kill_session(name: &str) { + let path = &*ZELLIJ_SOCK_DIR.join(name); + match LocalSocketStream::connect(path) { + Ok(stream) => { + IpcSenderWithContext::new(stream).send(ClientToServerMsg::KillSession); + } + Err(e) => { + eprintln!("Error occured: {:?}", e); + process::exit(1); + } + }; +} + pub(crate) fn list_sessions() { let exit_code = match get_sessions() { Ok(sessions) => { diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 5ba04909..2e1b901d 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -65,6 +65,7 @@ pub(crate) enum ServerInstruction { ClientExit(ClientId), RemoveClient(ClientId), Error(String), + KillSession, DetachSession(ClientId), AttachClient(ClientAttributes, Options, ClientId), } @@ -78,6 +79,7 @@ impl From<&ServerInstruction> for ServerContext { ServerInstruction::ClientExit(..) => ServerContext::ClientExit, ServerInstruction::RemoveClient(..) => ServerContext::RemoveClient, ServerInstruction::Error(_) => ServerContext::Error, + ServerInstruction::KillSession => ServerContext::KillSession, ServerInstruction::DetachSession(..) => ServerContext::DetachSession, ServerInstruction::AttachClient(..) => ServerContext::AttachClient, } @@ -400,6 +402,14 @@ pub fn start_server(mut os_input: Box, socket_path: PathBuf) { .unwrap(); } } + ServerInstruction::KillSession => { + let client_ids = session_state.read().unwrap().client_ids(); + for client_id in client_ids { + os_input.send_to_client(client_id, ServerToClientMsg::Exit(ExitReason::Normal)); + remove_client!(client_id, os_input, session_state); + } + break; + } ServerInstruction::DetachSession(client_id) => { os_input.send_to_client(client_id, ServerToClientMsg::Exit(ExitReason::Normal)); remove_client!(client_id, os_input, session_state); diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 4a22b5c5..fa659faa 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -358,6 +358,9 @@ pub(crate) fn route_thread_main( let _ = to_server.send(ServerInstruction::RemoveClient(client_id)); break; } + ClientToServerMsg::KillSession => { + to_server.send(ServerInstruction::KillSession).unwrap(); + } } } } diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 452033b8..7ac9e958 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -89,4 +89,19 @@ pub enum Sessions { #[structopt(subcommand, name = "options")] options: Option, }, + + /// Kill the specific session + #[structopt(alias = "k")] + KillSession { + /// Name of target session + target_session: Option, + }, + + /// Kill all sessions + #[structopt(alias = "ka")] + KillAllSessions { + /// Automatic yes to prompts + #[structopt(short, long)] + yes: bool, + }, } diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 348e6013..1859a904 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -304,6 +304,7 @@ pub enum ServerContext { ClientExit, RemoveClient, Error, + KillSession, DetachSession, AttachClient, } diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs index 5c327022..995b89fb 100644 --- a/zellij-utils/src/ipc.rs +++ b/zellij-utils/src/ipc.rs @@ -68,6 +68,7 @@ pub enum ClientToServerMsg { AttachClient(ClientAttributes, Options), Action(Action), ClientExited, + KillSession, } // Types of messages sent from the server to the client