Skip to content

Commit

Permalink
feat(cli): add kill-session command (#745)
Browse files Browse the repository at this point in the history
* 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 <aram@poor.dev>
  • Loading branch information
jaeheonji and imsnif authored Oct 11, 2021
1 parent 8415004 commit 0ca5c18
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 2 deletions.
61 changes: 59 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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<std::string::String>| {
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 {
Expand Down
13 changes: 13 additions & 0 deletions src/sessions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
10 changes: 10 additions & 0 deletions zellij-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub(crate) enum ServerInstruction {
ClientExit(ClientId),
RemoveClient(ClientId),
Error(String),
KillSession,
DetachSession(ClientId),
AttachClient(ClientAttributes, Options, ClientId),
}
Expand All @@ -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,
}
Expand Down Expand Up @@ -400,6 +402,14 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, 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);
Expand Down
3 changes: 3 additions & 0 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
}
15 changes: 15 additions & 0 deletions zellij-utils/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,19 @@ pub enum Sessions {
#[structopt(subcommand, name = "options")]
options: Option<SessionCommand>,
},

/// Kill the specific session
#[structopt(alias = "k")]
KillSession {
/// Name of target session
target_session: Option<String>,
},

/// Kill all sessions
#[structopt(alias = "ka")]
KillAllSessions {
/// Automatic yes to prompts
#[structopt(short, long)]
yes: bool,
},
}
1 change: 1 addition & 0 deletions zellij-utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ pub enum ServerContext {
ClientExit,
RemoveClient,
Error,
KillSession,
DetachSession,
AttachClient,
}
1 change: 1 addition & 0 deletions zellij-utils/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub enum ClientToServerMsg {
AttachClient(ClientAttributes, Options),
Action(Action),
ClientExited,
KillSession,
}

// Types of messages sent from the server to the client
Expand Down

0 comments on commit 0ca5c18

Please sign in to comment.