From 510feb30402d1d0766765d0cdee20f7ba098c95b Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Sat, 6 Nov 2021 06:59:45 +0900 Subject: [PATCH] fix(main): Refactor src/main.rs by splitting one massive main function into commands.rs (#829) * fix(main): Remove unnecessary pub visibility from the main function in `src/main.rs` * fix(main): Avoid unnecessary if-evaluations in the main function of `src/main.rs` * fix(commands): Simplify kill_all_sessions --- Cargo.lock | 36 +++++++- Cargo.toml | 1 + src/commands.rs | 234 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 238 +++--------------------------------------------- 4 files changed, 282 insertions(+), 227 deletions(-) create mode 100644 src/commands.rs diff --git a/Cargo.lock b/Cargo.lock index d61a653e..859c316e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,6 +400,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "console" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "cranelift-bforest" version = "0.68.0" @@ -653,6 +668,18 @@ dependencies = [ "syn", ] +[[package]] +name = "dialoguer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61579ada4ec0c6031cfac3f86fdba0d195a7ebeb5e36693bd53cb5999a25beeb" +dependencies = [ + "console 0.15.0", + "lazy_static", + "tempfile", + "zeroize", +] + [[package]] name = "directories-next" version = "2.0.0" @@ -1048,7 +1075,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15226a375927344c78d39dc6b49e2d5562a5b0705e26a589093c6792e52eed8e" dependencies = [ "backtrace", - "console", + "console 0.14.1", "lazy_static", "serde", "serde_json", @@ -2835,6 +2862,7 @@ name = "zellij" version = "0.20.0" dependencies = [ "anyhow", + "dialoguer", "insta", "log", "names", @@ -2933,3 +2961,9 @@ dependencies = [ "vte", "zellij-tile", ] + +[[package]] +name = "zeroize" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" diff --git a/Cargo.toml b/Cargo.toml index 1c33bae7..c964af41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ zellij-client = { path = "zellij-client/", version = "0.20.0" } zellij-server = { path = "zellij-server/", version = "0.20.0" } zellij-utils = { path = "zellij-utils/", version = "0.20.0" } log = "0.4.14" +dialoguer = "0.9.0" [dev-dependencies] insta = { version = "1.6.0", features = ["backtrace"] } diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 00000000..23105ec0 --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,234 @@ +use crate::install::populate_data_dir; +use crate::sessions::kill_session as kill_session_impl; +use crate::sessions::{ + assert_session, assert_session_ne, get_active_session, get_sessions, + get_sessions_sorted_by_creation_date, print_sessions, print_sessions_with_index, + session_exists, ActiveSession, +}; +use dialoguer::Confirm; +use std::path::PathBuf; +use std::process; +use zellij_client::start_client as start_client_impl; +use zellij_client::{os_input_output::get_client_os_input, ClientInfo}; +use zellij_server::os_input_output::get_server_os_input; +use zellij_server::start_server as start_server_impl; +use zellij_utils::input::options::Options; +use zellij_utils::nix; +use zellij_utils::{ + cli::{CliArgs, Command, SessionCommand, Sessions}, + setup::{get_default_data_dir, Setup}, +}; + +pub(crate) use crate::sessions::list_sessions; + +pub(crate) fn kill_all_sessions(yes: bool) { + match get_sessions() { + Ok(sessions) => { + if sessions.is_empty() { + println!("No active zellij sessions found."); + process::exit(1); + } else { + if !yes { + println!("WARNING: this action will kill all sessions."); + if !Confirm::new() + .with_prompt("Do you want to continue?") + .interact() + .unwrap() + { + println!("Abort."); + process::exit(1); + } + } + for session in sessions.iter() { + kill_session_impl(session); + } + process::exit(0); + } + } + Err(e) => { + eprintln!("Error occurred: {:?}", e); + process::exit(1); + } + } +} + +pub(crate) fn kill_session(target_session: &Option) { + match target_session { + Some(target_session) => { + assert_session(target_session); + kill_session_impl(target_session); + process::exit(0); + } + None => { + println!("Please specify the session name to kill."); + process::exit(1); + } + } +} + +fn get_os_input( + fn_get_os_input: fn() -> Result, +) -> OsInputOutput { + match fn_get_os_input() { + Ok(os_input) => os_input, + Err(e) => { + eprintln!("failed to open terminal:\n{}", e); + process::exit(1); + } + } +} + +pub(crate) fn start_server(path: PathBuf) { + let os_input = get_os_input(get_server_os_input); + start_server_impl(Box::new(os_input), path); +} + +fn create_new_client() -> ClientInfo { + ClientInfo::New(names::Generator::default().next().unwrap()) +} + +fn find_indexed_session( + sessions: Vec, + config_options: Options, + index: usize, + create: bool, +) -> ClientInfo { + match sessions.get(index) { + Some(session) => ClientInfo::Attach(session.clone(), config_options), + None => { + if create { + create_new_client() + } else { + println!( + "No session indexed by {} found. The following sessions are active:", + index + ); + print_sessions_with_index(sessions); + process::exit(1); + } + } + } +} + +fn attach_with_session_index(config_options: Options, index: usize, create: bool) -> ClientInfo { + // Ignore the session_name when `--index` is provided + match get_sessions_sorted_by_creation_date() { + Ok(sessions) => { + if sessions.is_empty() { + if create { + create_new_client() + } else { + println!("No active zellij sessions found."); + process::exit(1); + } + } else { + find_indexed_session(sessions, config_options, index, create) + } + } + Err(e) => { + eprintln!("Error occurred: {:?}", e); + process::exit(1); + } + } +} + +fn attach_with_session_name( + session_name: Option, + config_options: Options, + create: bool, +) -> ClientInfo { + match session_name.as_ref() { + Some(session) => { + if create { + if !session_exists(session).unwrap() { + ClientInfo::New(session_name.unwrap()) + } else { + ClientInfo::Attach(session_name.unwrap(), config_options) + } + } else { + assert_session(session); + ClientInfo::Attach(session_name.unwrap(), config_options) + } + } + None => match get_active_session() { + ActiveSession::None => { + if create { + create_new_client() + } else { + println!("No active zellij sessions found."); + process::exit(1); + } + } + ActiveSession::One(session_name) => ClientInfo::Attach(session_name, config_options), + ActiveSession::Many => { + println!("Please specify the session name to attach to. The following sessions are active:"); + print_sessions(get_sessions().unwrap()); + process::exit(1); + } + }, + } +} + +pub(crate) fn start_client(opts: CliArgs) { + let (config, layout, config_options) = match Setup::from_options(&opts) { + Ok(results) => results, + Err(e) => { + eprintln!("{}", e); + process::exit(1); + } + }; + let os_input = get_os_input(get_client_os_input); + + if let Some(Command::Sessions(Sessions::Attach { + session_name, + create, + index, + options, + })) = opts.command.clone() + { + let config_options = match options { + Some(SessionCommand::Options(o)) => config_options.merge(o), + None => config_options, + }; + + let client = if let Some(idx) = index { + attach_with_session_index(config_options.clone(), idx, create) + } else { + attach_with_session_name(session_name, config_options.clone(), create) + }; + + let attach_layout = match client { + ClientInfo::Attach(_, _) => None, + ClientInfo::New(_) => layout, + }; + + start_client_impl( + Box::new(os_input), + opts, + config, + config_options, + client, + attach_layout, + ); + } else { + let session_name = opts + .session + .clone() + .unwrap_or_else(|| names::Generator::default().next().unwrap()); + assert_session_ne(&session_name); + + // 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); + + start_client_impl( + Box::new(os_input), + opts, + config, + config_options, + ClientInfo::New(session_name), + layout, + ); + } +} diff --git a/src/main.rs b/src/main.rs index f12eb010..f4b8aa05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,244 +1,30 @@ +mod commands; mod install; mod sessions; #[cfg(test)] mod tests; -use crate::install::populate_data_dir; -use sessions::{ - assert_session, assert_session_ne, get_active_session, get_sessions, - get_sessions_sorted_by_creation_date, kill_session, list_sessions, print_sessions, - print_sessions_with_index, session_exists, ActiveSession, -}; -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, Command, SessionCommand, Sessions}, + cli::{CliArgs, Command, Sessions}, logging::*, - setup::{get_default_data_dir, Setup}, structopt::StructOpt, }; -pub fn main() { +fn main() { configure_logger(); let opts = CliArgs::from_args(); if let Some(Command::Sessions(Sessions::ListSessions)) = opts.command { - 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 occurred: {:?}", e); - process::exit(1); - } - } - } - - if let Some(Command::Sessions(Sessions::KillSession { target_session })) = opts.command.clone() + commands::list_sessions(); + } else if let Some(Command::Sessions(Sessions::KillAllSessions { yes })) = opts.command { + commands::kill_all_sessions(yes); + } else if let Some(Command::Sessions(Sessions::KillSession { ref target_session })) = + opts.command { - 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); - } - } - } - - if let Some(path) = opts.server { - let os_input = match get_server_os_input() { - Ok(server_os_input) => server_os_input, - Err(e) => { - eprintln!("failed to open terminal:\n{}", e); - process::exit(1); - } - }; - start_server(Box::new(os_input), path); + commands::kill_session(target_session); + } else if let Some(path) = opts.server { + commands::start_server(path); } else { - let (config, layout, config_options) = match Setup::from_options(&opts) { - Ok(results) => results, - Err(e) => { - eprintln!("{}", e); - process::exit(1); - } - }; - - let os_input = match get_client_os_input() { - Ok(os_input) => os_input, - Err(e) => { - eprintln!("failed to open terminal:\n{}", e); - process::exit(1); - } - }; - if let Some(Command::Sessions(Sessions::Attach { - session_name, - create, - index, - options, - })) = opts.command.clone() - { - let config_options = match options { - Some(SessionCommand::Options(o)) => config_options.merge(o), - None => config_options, - }; - - let (client, attach_layout) = if let Some(idx) = index { - // Ignore session_name when `--index` is provided - match get_sessions_sorted_by_creation_date() { - Ok(sessions) => { - if sessions.is_empty() { - if create { - ( - ClientInfo::New(names::Generator::default().next().unwrap()), - layout, - ) - } else { - println!("No active zellij sessions found."); - process::exit(1); - } - } else { - match sessions.get(idx) { - Some(session) => ( - ClientInfo::Attach(session.clone(), config_options.clone()), - None, - ), - None => { - if create { - ( - ClientInfo::New( - names::Generator::default().next().unwrap(), - ), - layout, - ) - } else { - println!("No session indexed by {} found. The following sessions are active:", idx); - print_sessions_with_index(sessions); - process::exit(1); - } - } - } - } - } - Err(e) => { - eprintln!("Error occurred: {:?}", e); - process::exit(1); - } - } - } else { - match session_name.as_ref() { - Some(session) => { - if create { - if !session_exists(session).unwrap() { - (ClientInfo::New(session_name.unwrap()), layout) - } else { - ( - ClientInfo::Attach( - session_name.unwrap(), - config_options.clone(), - ), - None, - ) - } - } else { - assert_session(session); - ( - ClientInfo::Attach(session_name.unwrap(), config_options.clone()), - None, - ) - } - } - None => match get_active_session() { - ActiveSession::None => { - if create { - ( - ClientInfo::New(names::Generator::default().next().unwrap()), - layout, - ) - } else { - println!("No active zellij sessions found."); - process::exit(1); - } - } - ActiveSession::One(session_name) => ( - ClientInfo::Attach(session_name, config_options.clone()), - None, - ), - ActiveSession::Many => { - println!("Please specify the session name to attach to. The following sessions are active:"); - print_sessions(get_sessions().unwrap()); - process::exit(1); - } - }, - } - }; - - start_client( - Box::new(os_input), - opts, - config, - config_options, - client, - attach_layout, - ); - } else { - let session_name = opts - .session - .clone() - .unwrap_or_else(|| names::Generator::default().next().unwrap()); - assert_session_ne(&session_name); - - // 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); - - start_client( - Box::new(os_input), - opts, - config, - config_options, - ClientInfo::New(session_name), - layout, - ); - } + commands::start_client(opts); } }