diff --git a/Cargo.lock b/Cargo.lock index 2294d655..41959027 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,15 +26,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -338,17 +329,41 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375" dependencies = [ - "ansi_term 0.11.0", "atty", "bitflags", - "strsim 0.8.0", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_complete" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d044e9db8cd0f68191becdeb5246b7462e4cf0c069b19ae00d1bf3fa9889498d" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -603,7 +618,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] @@ -980,6 +995,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1259,9 +1280,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" @@ -1438,6 +1459,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "parking" version = "2.0.0" @@ -2030,7 +2060,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "status-bar" version = "0.1.0" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "colored", "lazy_static", "rand 0.8.4", @@ -2059,42 +2089,12 @@ dependencies = [ "vte", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "strum" version = "0.20.0" @@ -2107,7 +2107,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -2152,7 +2152,7 @@ dependencies = [ name = "tab-bar" version = "0.1.0" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "colored", "unicode-width", "zellij-tile", @@ -2179,6 +2179,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -2216,12 +2225,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.11.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" [[package]] name = "thiserror" @@ -2435,12 +2441,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.3" @@ -2816,6 +2816,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2864,7 +2873,7 @@ dependencies = [ name = "zellij-server" version = "0.25.0" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "async-trait", "base64", "byteorder", @@ -2890,6 +2899,7 @@ dependencies = [ name = "zellij-tile" version = "0.25.0" dependencies = [ + "clap", "serde", "serde_json", "strum", @@ -2900,7 +2910,7 @@ dependencies = [ name = "zellij-tile-utils" version = "0.25.0" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", ] [[package]] @@ -2911,6 +2921,8 @@ dependencies = [ "async-std", "backtrace", "bincode", + "clap", + "clap_complete", "colored", "colorsys", "crossbeam", @@ -2927,7 +2939,6 @@ dependencies = [ "serde_yaml", "signal-hook", "strip-ansi-escapes", - "structopt", "strum", "tempfile", "termion", diff --git a/src/main.rs b/src/main.rs index f4b8aa05..98b27581 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,14 @@ mod sessions; mod tests; use zellij_utils::{ + clap::Parser, cli::{CliArgs, Command, Sessions}, logging::*, - structopt::StructOpt, }; fn main() { configure_logger(); - let opts = CliArgs::from_args(); + let opts = CliArgs::parse(); if let Some(Command::Sessions(Sessions::ListSessions)) = opts.command { commands::list_sessions(); diff --git a/zellij-tile/Cargo.toml b/zellij-tile/Cargo.toml index 583a7d17..b42e2124 100644 --- a/zellij-tile/Cargo.toml +++ b/zellij-tile/Cargo.toml @@ -7,6 +7,7 @@ description = "A small client-side library for writing Zellij plugins" license = "MIT" [dependencies] +clap = { version = "3.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" strum = "0.20.0" diff --git a/zellij-tile/src/data.rs b/zellij-tile/src/data.rs index e120748a..dae7cd09 100644 --- a/zellij-tile/src/data.rs +++ b/zellij-tile/src/data.rs @@ -1,3 +1,4 @@ +use clap::ArgEnum; use serde::{Deserialize, Serialize}; use std::fmt; use std::str::FromStr; @@ -82,7 +83,7 @@ pub enum Event { } /// Describes the different input modes, which change the way that keystrokes will be interpreted. -#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, EnumIter, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, EnumIter, Serialize, Deserialize, ArgEnum)] pub enum InputMode { /// In `Normal` mode, input is always written to the terminal, except for the shortcuts leading /// to other modes diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml index efd07f54..3aefa684 100644 --- a/zellij-utils/Cargo.toml +++ b/zellij-utils/Cargo.toml @@ -12,6 +12,8 @@ license = "MIT" anyhow = "1.0.45" backtrace = "0.3.55" bincode = "1.3.1" +clap = { version = "3.0", features = ["derive", "env"] } +clap_complete = "3.0" colored = "2.0.0" colorsys = "0.6.5" crossbeam = "0.8.0" @@ -26,7 +28,6 @@ serde_yaml = "0.8" serde_json = "1.0" signal-hook = "0.3" strip-ansi-escapes = "0.1.0" -structopt = "0.3" strum = "0.20.0" termion = "1.5.0" thiserror = "1.0.30" diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 2c1aeba3..03bf8db4 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -3,111 +3,111 @@ use crate::{ consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV}, input::options::CliOptions, }; +use clap::{Parser, Subcommand}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use structopt::StructOpt; -#[derive(StructOpt, Default, Debug, Clone, Serialize, Deserialize)] -#[structopt(name = "zellij")] +#[derive(Parser, Default, Debug, Clone, Serialize, Deserialize)] +#[clap(version, name = "zellij")] pub struct CliArgs { /// Maximum panes on screen, caution: opening more panes will close old ones - #[structopt(long)] + #[clap(long)] pub max_panes: Option, /// Change where zellij looks for layouts and plugins - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] pub data_dir: Option, /// Run server listening at the specified socket path - #[structopt(long, parse(from_os_str), hidden = true)] + #[clap(long, parse(from_os_str), hide = true)] pub server: Option, /// Specify name of a new session - #[structopt(long, short)] + #[clap(long, short)] pub session: Option, /// Name of a layout file in the layout directory - #[structopt(short, long, parse(from_os_str))] + #[clap(short, long, parse(from_os_str))] pub layout: Option, /// Path to a layout yaml file - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] pub layout_path: Option, /// Change where zellij looks for the configuration file - #[structopt(short, long, env=ZELLIJ_CONFIG_FILE_ENV, parse(from_os_str))] + #[clap(short, long, env = ZELLIJ_CONFIG_FILE_ENV, parse(from_os_str))] pub config: Option, /// Change where zellij looks for the configuration directory - #[structopt(long, env=ZELLIJ_CONFIG_DIR_ENV, parse(from_os_str))] + #[clap(long, env = ZELLIJ_CONFIG_DIR_ENV, parse(from_os_str))] pub config_dir: Option, - #[structopt(subcommand)] + #[clap(subcommand)] pub command: Option, - #[structopt(short, long)] + #[clap(short, long)] pub debug: bool, } -#[derive(Debug, StructOpt, Clone, Serialize, Deserialize)] +#[derive(Debug, Subcommand, Clone, Serialize, Deserialize)] pub enum Command { /// Change the behaviour of zellij - #[structopt(name = "options")] + #[clap(name = "options")] Options(CliOptions), /// Setup zellij and check its configuration - #[structopt(name = "setup")] + #[clap(name = "setup")] Setup(Setup), /// Explore existing zellij sessions - #[structopt(flatten)] + #[clap(flatten)] Sessions(Sessions), } -#[derive(Debug, StructOpt, Clone, Serialize, Deserialize)] +#[derive(Debug, Subcommand, Clone, Serialize, Deserialize)] pub enum SessionCommand { /// Change the behaviour of zellij - #[structopt(name = "options")] + #[clap(name = "options")] Options(CliOptions), } -#[derive(Debug, StructOpt, Clone, Serialize, Deserialize)] +#[derive(Debug, Subcommand, Clone, Serialize, Deserialize)] pub enum Sessions { /// List active sessions - #[structopt(alias = "ls")] + #[clap(alias = "ls")] ListSessions, /// Attach to session - #[structopt(alias = "a")] + #[clap(alias = "a")] Attach { /// Name of the session to attach to. session_name: Option, /// Create a session if one does not exist. - #[structopt(short, long)] + #[clap(short, long)] create: bool, /// Number of the session index in the active sessions ordered creation date. - #[structopt(long)] + #[clap(long)] index: Option, /// Change the behaviour of zellij - #[structopt(subcommand, name = "options")] + #[clap(subcommand, name = "options")] options: Option, }, /// Kill the specific session - #[structopt(alias = "k")] + #[clap(alias = "k")] KillSession { /// Name of target session target_session: Option, }, /// Kill all sessions - #[structopt(alias = "ka")] + #[clap(alias = "ka")] KillAllSessions { /// Automatic yes to prompts - #[structopt(short, long)] + #[clap(short, long)] yes: bool, }, } diff --git a/zellij-utils/src/input/options.rs b/zellij-utils/src/input/options.rs index d8bef694..41f241f6 100644 --- a/zellij-utils/src/input/options.rs +++ b/zellij-utils/src/input/options.rs @@ -1,12 +1,12 @@ //! Handles cli and configuration options use crate::cli::Command; +use clap::{ArgEnum, Args}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use std::str::FromStr; -use structopt::StructOpt; use zellij_tile::data::InputMode; -#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize, ArgEnum)] pub enum OnForceClose { #[serde(alias = "quit")] Quit, @@ -32,7 +32,7 @@ impl FromStr for OnForceClose { } } -#[derive(Clone, Default, Debug, PartialEq, Deserialize, Serialize, StructOpt)] +#[derive(Clone, Default, Debug, PartialEq, Deserialize, Serialize, Args)] /// Options that can be set either through the config file, /// or cli flags - cli flags should take precedence over the config file /// TODO: In order to correctly parse boolean flags, this is currently split @@ -40,43 +40,43 @@ impl FromStr for OnForceClose { pub struct Options { /// Allow plugins to use a more simplified layout /// that is compatible with more fonts (true or false) - #[structopt(long)] + #[clap(long)] #[serde(default)] pub simplified_ui: Option, /// Set the default theme - #[structopt(long)] + #[clap(long)] pub theme: Option, /// Set the default mode - #[structopt(long)] + #[clap(long, arg_enum, hide_possible_values = true)] pub default_mode: Option, /// Set the default shell - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] pub default_shell: Option, /// Set the layout_dir, defaults to /// subdirectory of config dir - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] pub layout_dir: Option, - #[structopt(long)] + #[clap(long)] #[serde(default)] /// Set the handling of mouse events (true or false) /// Can be temporarily bypassed by the [SHIFT] key pub mouse_mode: Option, - #[structopt(long)] + #[clap(long)] #[serde(default)] /// Set display of the pane frames (true or false) pub pane_frames: Option, - #[structopt(long)] + #[clap(long)] #[serde(default)] /// Mirror session when multiple users are connected (true or false) pub mirror_session: Option, /// Set behaviour on force close (quit or detach) - #[structopt(long)] + #[clap(long, arg_enum, hide_possible_values = true)] pub on_force_close: Option, - #[structopt(long)] + #[clap(long)] pub scroll_buffer_size: Option, /// Switch to using a user supplied command for clipboard instead of OSC52 - #[structopt(long)] + #[clap(long)] #[serde(default)] pub copy_command: Option, } @@ -173,17 +173,17 @@ impl Options { } } -#[derive(Clone, Default, Debug, PartialEq, StructOpt, Serialize, Deserialize)] +#[derive(Clone, Default, Debug, PartialEq, Args, Serialize, Deserialize)] /// Options that can be set through cli flags /// boolean flags end up toggling boolean options in `Options` pub struct CliOptions { /// Disable handling of mouse events - #[structopt(long, conflicts_with("mouse-mode"))] + #[clap(long, conflicts_with("mouse-mode"))] pub disable_mouse_mode: bool, /// Disable display of pane frames - #[structopt(long, conflicts_with("pane-frames"))] + #[clap(long, conflicts_with("pane-frames"))] pub no_pane_frames: bool, - #[structopt(flatten)] + #[clap(flatten)] options: Options, } diff --git a/zellij-utils/src/lib.rs b/zellij-utils/src/lib.rs index 4ccb25f5..7115c1b4 100644 --- a/zellij-utils/src/lib.rs +++ b/zellij-utils/src/lib.rs @@ -12,13 +12,13 @@ pub mod setup; pub mod shared; pub use async_std; +pub use clap; pub use interprocess; pub use libc; pub use nix; pub use serde; pub use serde_yaml; pub use signal_hook; -pub use structopt; pub use termion; pub use vte; pub use zellij_tile; diff --git a/zellij-utils/src/setup.rs b/zellij-utils/src/setup.rs index 0de85724..565e72c9 100644 --- a/zellij-utils/src/setup.rs +++ b/zellij-utils/src/setup.rs @@ -10,12 +10,13 @@ use crate::{ options::Options, }, }; +use clap::{Args, IntoApp}; +use clap_complete::Shell; use directories_next::BaseDirs; use serde::{Deserialize, Serialize}; use std::{ convert::TryFrom, fmt::Write as FmtWrite, io::Write, path::Path, path::PathBuf, process, }; -use structopt::StructOpt; const CONFIG_LOCATION: &str = ".config/zellij"; const CONFIG_NAME: &str = "config.yaml"; @@ -124,25 +125,25 @@ pub fn dump_specified_layout(layout: &str) -> std::io::Result<()> { } } -#[derive(Debug, Default, Clone, StructOpt, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Args, Serialize, Deserialize)] pub struct Setup { /// Dump the default configuration file to stdout - #[structopt(long)] + #[clap(long)] pub dump_config: bool, /// Disables loading of configuration file at default location, /// loads the defaults that zellij ships with - #[structopt(long)] + #[clap(long)] pub clean: bool, /// Checks the configuration of zellij and displays /// currently used directories - #[structopt(long)] + #[clap(long)] pub check: bool, /// Dump the specified layout file to stdout - #[structopt(long)] + #[clap(long)] pub dump_layout: Option, /// Generates completion for the specified shell - #[structopt(long)] + #[clap(long, value_name = "SHELL")] pub generate_completion: Option, } @@ -231,7 +232,7 @@ impl Setup { } if let Some(shell) = &self.generate_completion { - Self::generate_completion(shell.into()); + Self::generate_completion(shell); std::process::exit(0); } @@ -376,8 +377,8 @@ impl Setup { Ok(()) } - fn generate_completion(shell: String) { - let shell = match shell.parse() { + fn generate_completion(shell: &str) { + let shell: Shell = match shell.to_lowercase().parse() { Ok(shell) => shell, _ => { eprintln!("Unsupported shell: {}", shell); @@ -385,7 +386,7 @@ impl Setup { } }; let mut out = std::io::stdout(); - CliArgs::clap().gen_completions_to("zellij", shell, &mut out); + clap_complete::generate(shell, &mut CliArgs::into_app(), "zellij", &mut out); } }