diff --git a/Cargo.lock b/Cargo.lock index 982e1f406..b766abae8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,15 +43,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "anyhow" version = "1.0.57" @@ -534,17 +525,41 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" dependencies = [ - "ansi_term", "atty", "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -1645,12 +1660,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -1743,6 +1755,16 @@ dependencies = [ "tiff", ] +[[package]] +name = "indexmap" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +dependencies = [ + "autocfg", + "hashbrown 0.11.2", +] + [[package]] name = "inflate" version = "0.4.5" @@ -2324,7 +2346,7 @@ dependencies = [ "terminfo", "termwiz", "termwiz-funcs", - "textwrap 0.15.0", + "textwrap", "thiserror", "unicode-segmentation", "url", @@ -2724,6 +2746,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "parking" version = "2.0.0" @@ -3925,46 +3953,16 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "strip-ansi-escapes" version = "0.1.0" dependencies = [ - "structopt", + "clap", "termwiz", ] -[[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.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -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 = "svg_fmt" version = "0.4.1" @@ -4123,15 +4121,6 @@ dependencies = [ "wezterm-dynamic", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "textwrap" version = "0.15.0" @@ -4392,12 +4381,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.4" @@ -4646,6 +4629,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "clap", "codec", "config", "env-bootstrap", @@ -4660,12 +4644,11 @@ dependencies = [ "serde_json", "shell-words", "smol", - "structopt", "tabout", "tempfile", "termios 0.3.3", "termwiz", - "textwrap 0.15.0", + "textwrap", "umask", "url", "wezterm-client", @@ -4708,7 +4691,7 @@ dependencies = [ "ratelim", "smol", "termwiz", - "textwrap 0.15.0", + "textwrap", "thiserror", "uds_windows", "umask", @@ -4734,7 +4717,7 @@ dependencies = [ "log", "maplit", "ordered-float", - "strsim 0.10.0", + "strsim", "thiserror", "wezterm-dynamic-derive", ] @@ -4792,6 +4775,7 @@ dependencies = [ "bitflags", "cc", "chrono", + "clap", "codec", "colorgrad", "config", @@ -4829,12 +4813,11 @@ dependencies = [ "serial", "shared_library", "smol", - "structopt", "tabout", "terminfo", "termwiz", "termwiz-funcs", - "textwrap 0.15.0", + "textwrap", "thiserror", "tiny-skia", "uds_windows", @@ -4863,8 +4846,8 @@ name = "wezterm-gui-subcommands" version = "0.1.0" dependencies = [ "anyhow", + "clap", "config", - "structopt", ] [[package]] @@ -4884,6 +4867,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async_ossl", + "clap", "config", "env-bootstrap", "libc", @@ -4892,7 +4876,6 @@ dependencies = [ "openssl", "portable-pty", "promise", - "structopt", "umask", "wezterm-gui-subcommands", "wezterm-mux-server-impl", @@ -4934,6 +4917,7 @@ dependencies = [ "base64", "bitflags", "camino", + "clap", "dirs-next", "env_logger", "filedescriptor", @@ -4952,7 +4936,6 @@ dependencies = [ "smol-potat", "socket2", "ssh2", - "structopt", "termwiz", "thiserror", "whoami", diff --git a/strip-ansi-escapes/Cargo.toml b/strip-ansi-escapes/Cargo.toml index ce105bf8f..1d154287b 100644 --- a/strip-ansi-escapes/Cargo.toml +++ b/strip-ansi-escapes/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -structopt = "0.3" +clap = {version="3.1", features=["derive"]} termwiz = { path = "../termwiz" } diff --git a/strip-ansi-escapes/src/main.rs b/strip-ansi-escapes/src/main.rs index d4c44a2d3..7a4b8c1ac 100644 --- a/strip-ansi-escapes/src/main.rs +++ b/strip-ansi-escapes/src/main.rs @@ -1,12 +1,9 @@ +use clap::Parser; use std::io::{Read, Result}; -use structopt::StructOpt; -use termwiz::escape::parser::Parser; +use termwiz::escape::parser::Parser as TWParser; use termwiz::escape::{Action, ControlCode}; -#[derive(Debug, StructOpt)] -#[structopt( - global_setting = structopt::clap::AppSettings::ColoredHelp, -)] +#[derive(Debug, Parser)] /// This is a little utility that strips escape sequences from /// stdin and prints the result on stdout. /// It preserves only printable characters and CR, LF and HT. @@ -17,10 +14,10 @@ use termwiz::escape::{Action, ControlCode}; struct Opt {} fn main() -> Result<()> { - let _ = Opt::from_args(); + let _ = Opt::parse(); let mut buf = [0u8; 4096]; - let mut parser = Parser::new(); + let mut parser = TWParser::new(); loop { let len = std::io::stdin().read(&mut buf)?; diff --git a/wezterm-gui-subcommands/Cargo.toml b/wezterm-gui-subcommands/Cargo.toml index fe9fa39ec..0c34661f8 100644 --- a/wezterm-gui-subcommands/Cargo.toml +++ b/wezterm-gui-subcommands/Cargo.toml @@ -7,6 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -structopt = "0.3" +clap = {version="3.1", features=["derive"]} config = { path = "../config" } anyhow = "1.0" diff --git a/wezterm-gui-subcommands/src/lib.rs b/wezterm-gui-subcommands/src/lib.rs index 36b0f9a8d..0c6dd070c 100644 --- a/wezterm-gui-subcommands/src/lib.rs +++ b/wezterm-gui-subcommands/src/lib.rs @@ -1,7 +1,7 @@ +use clap::Parser; use config::{Dimension, GeometryOrigin, SshParameters}; use std::ffi::OsString; use std::str::FromStr; -use structopt::StructOpt; pub const DEFAULT_WINDOW_CLASS: &str = "org.wezfurlong.wezterm"; @@ -142,23 +142,23 @@ mod test { } } -#[derive(Debug, StructOpt, Default, Clone)] +#[derive(Debug, Parser, Default, Clone)] pub struct StartCommand { /// If true, do not connect to domains marked as connect_automatically /// in your wezterm configuration file. - #[structopt(long = "no-auto-connect")] + #[clap(long = "no-auto-connect")] pub no_auto_connect: bool, /// If enabled, don't try to ask an existing wezterm GUI instance /// to start the command. Instead, always start the GUI in this /// invocation of wezterm so that you can wait for the command /// to complete by waiting for this wezterm process to finish. - #[structopt(long = "always-new-process")] + #[clap(long = "always-new-process")] pub always_new_process: bool, /// Specify the current working directory for the initially /// spawned program - #[structopt(long = "cwd", parse(from_os_str))] + #[clap(long = "cwd", parse(from_os_str))] pub cwd: Option, /// Override the default windowing system class. @@ -168,12 +168,12 @@ pub struct StartCommand { /// This changes the class for all windows spawned by this /// instance of wezterm, including error, update and ssh /// authentication dialogs. - #[structopt(long = "class")] + #[clap(long = "class")] pub class: Option, /// Override the default workspace with the provided name. /// The default is "default". - #[structopt(long = "workspace")] + #[clap(long = "workspace")] pub workspace: Option, /// Override the position for the initial window launched by this process. @@ -183,17 +183,17 @@ pub struct StartCommand { /// --position main:10,20 to set x=10, y=20 relative to the main monitor /// --position active:10,20 to set x=10, y=20 relative to the active monitor /// --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor named HDMI-1 - #[structopt(long, verbatim_doc_comment)] + #[clap(long, verbatim_doc_comment)] pub position: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm start -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub prog: Vec, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct SshCommand { /// Specifies the remote system using the form: /// `[username@]host[:port]`. @@ -212,9 +212,9 @@ pub struct SshCommand { /// For example: /// /// `wezterm ssh -oIdentityFile=/secret/id_ed25519 some-host` - #[structopt( + #[clap( long = "ssh-option", - short = "o", + short = 'o', name = "name=value", parse(try_from_str = name_equals_value), number_of_values = 1)] @@ -223,7 +223,7 @@ pub struct SshCommand { /// Enable verbose ssh protocol tracing. /// The trace information is printed to the stderr stream of /// the process. - #[structopt(short = "v")] + #[clap(short = 'v')] pub verbose: bool, /// Override the default windowing system class. @@ -233,7 +233,7 @@ pub struct SshCommand { /// This changes the class for all windows spawned by this /// instance of wezterm, including error, update and ssh /// authentication dialogs. - #[structopt(long = "class")] + #[clap(long = "class")] pub class: Option, /// Override the position for the initial window launched by this process. /// @@ -242,20 +242,20 @@ pub struct SshCommand { /// --position main:10,20 to set x=10, y=20 relative to the main monitor /// --position active:10,20 to set x=10, y=20 relative to the active monitor /// --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor named HDMI-1 - #[structopt(long, verbatim_doc_comment)] + #[clap(long, verbatim_doc_comment)] pub position: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm ssh user@host -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub prog: Vec, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct SerialCommand { /// Set the baud rate. The default is 9600 baud. - #[structopt(long = "baud")] + #[clap(long = "baud")] pub baud: Option, /// Override the default windowing system class. @@ -265,7 +265,7 @@ pub struct SerialCommand { /// This changes the class for all windows spawned by this /// instance of wezterm, including error, update and ssh /// authentication dialogs. - #[structopt(long = "class")] + #[clap(long = "class")] pub class: Option, /// Override the position for the initial window launched by this process. /// @@ -274,17 +274,17 @@ pub struct SerialCommand { /// --position main:10,20 to set x=10, y=20 relative to the main monitor /// --position active:10,20 to set x=10, y=20 relative to the active monitor /// --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor named HDMI-1 - #[structopt(long, verbatim_doc_comment)] + #[clap(long, verbatim_doc_comment)] pub position: Option, /// Specifies the serial device name. /// On Windows systems this can be a name like `COM0`. /// On posix systems this will be something like `/dev/ttyUSB0` - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub port: OsString, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct ConnectCommand { /// Name of the multiplexer domain section from the configuration /// to which you'd like to connect @@ -297,12 +297,12 @@ pub struct ConnectCommand { /// This changes the class for all windows spawned by this /// instance of wezterm, including error, update and ssh /// authentication dialogs. - #[structopt(long = "class")] + #[clap(long = "class")] pub class: Option, /// Override the default workspace with the provided name. /// The default is "default". - #[structopt(long = "workspace")] + #[clap(long = "workspace")] pub workspace: Option, /// Override the position for the initial window launched by this process. /// @@ -311,23 +311,23 @@ pub struct ConnectCommand { /// --position main:10,20 to set x=10, y=20 relative to the main monitor /// --position active:10,20 to set x=10, y=20 relative to the active monitor /// --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor named HDMI-1 - #[structopt(long, verbatim_doc_comment)] + #[clap(long, verbatim_doc_comment)] pub position: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm start -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub prog: Vec, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct LsFontsCommand { /// Whether to list all fonts available to the system - #[structopt(long = "list-system")] + #[clap(long = "list-system")] pub list_system: bool, /// Explain which fonts are used to render the supplied text string - #[structopt(long = "text", conflicts_with = "list-system")] + #[clap(long = "text", conflicts_with = "list-system")] pub text: Option, } diff --git a/wezterm-gui/Cargo.toml b/wezterm-gui/Cargo.toml index cb28d8eb8..d92bb2e0f 100644 --- a/wezterm-gui/Cargo.toml +++ b/wezterm-gui/Cargo.toml @@ -23,6 +23,7 @@ cc = "1.0" anyhow = "1.0" bitflags = "1.3" chrono = {version="0.4", features=["unstable-locales"]} +clap = {version="3.1", features=["derive"]} codec = { path = "../codec" } colorgrad = "0.5" config = { path = "../config" } @@ -56,7 +57,6 @@ serde = {version="1.0", features = ["rc", "derive"]} serde_json = "1.0" serial = "0.4" smol = "1.2" -structopt = "0.3" tabout = { path = "../tabout" } terminfo = "0.7" termwiz = { path = "../termwiz" } diff --git a/wezterm-gui/src/main.rs b/wezterm-gui/src/main.rs index 95e806b80..aff90208a 100644 --- a/wezterm-gui/src/main.rs +++ b/wezterm-gui/src/main.rs @@ -3,6 +3,7 @@ use ::window::*; use anyhow::{anyhow, Context}; +use clap::Parser; use config::{ConfigHandle, SshDomain, SshMultiplexing}; use mux::activity::Activity; use mux::domain::{Domain, LocalDomain}; @@ -15,7 +16,6 @@ use std::ffi::OsString; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; -use structopt::StructOpt; use termwiz::cell::{CellAttributes, UnicodeVersion}; use termwiz::surface::{Line, SEQ_ZERO}; use wezterm_bidi::Direction; @@ -49,20 +49,19 @@ mod utilsprites; pub use selection::SelectionMode; pub use termwindow::{set_window_class, set_window_position, TermWindow, ICON_DATA}; -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( about = "Wez's Terminal Emulator\nhttp://github.com/wez/wezterm", - global_setting = structopt::clap::AppSettings::ColoredHelp, version = config::wezterm_version() )] struct Opt { /// Skip loading wezterm.lua - #[structopt(name = "skip-config", short = "n")] + #[clap(name = "skip-config", short = 'n')] skip_config: bool, /// Specify the configuration file to use, overrides the normal /// configuration file resolution - #[structopt( + #[clap( long = "config-file", parse(from_os_str), conflicts_with = "skip-config" @@ -70,7 +69,7 @@ struct Opt { config_file: Option, /// Override specific configuration values - #[structopt( + #[clap( long = "config", name = "name=value", parse(try_from_str = name_equals_value), @@ -79,32 +78,32 @@ struct Opt { /// On Windows, whether to attempt to attach to the parent /// process console to display logging output - #[structopt(long = "attach-parent-console")] + #[clap(long = "attach-parent-console")] #[allow(dead_code)] attach_parent_console: bool, - #[structopt(subcommand)] + #[clap(subcommand)] cmd: Option, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] enum SubCommand { - #[structopt( + #[clap( name = "start", about = "Start the GUI, optionally running an alternative program" )] Start(StartCommand), - #[structopt(name = "ssh", about = "Establish an ssh session")] + #[clap(name = "ssh", about = "Establish an ssh session")] Ssh(SshCommand), - #[structopt(name = "serial", about = "Open a serial port")] + #[clap(name = "serial", about = "Open a serial port")] Serial(SerialCommand), - #[structopt(name = "connect", about = "Connect to wezterm multiplexer")] + #[clap(name = "connect", about = "Connect to wezterm multiplexer")] Connect(ConnectCommand), - #[structopt(name = "ls-fonts", about = "Display information about fonts")] + #[clap(name = "ls-fonts", about = "Display information about fonts")] LsFonts(LsFontsCommand), } @@ -913,7 +912,7 @@ fn run() -> anyhow::Result<()> { } } - let opts = Opt::from_args(); + let opts = Opt::parse(); // This is a bit gross. // In order to not to automatically open a standard windows console when @@ -953,7 +952,7 @@ fn run() -> anyhow::Result<()> { for a in &config.default_gui_startup_args { argv.push(a.clone()); } - SubCommand::from_iter_safe(&argv).with_context(|| { + SubCommand::try_parse_from(&argv).with_context(|| { format!( "parsing the default_gui_startup_args config: {:?}", config.default_gui_startup_args diff --git a/wezterm-mux-server/Cargo.toml b/wezterm-mux-server/Cargo.toml index 967dcfea8..f2568326a 100644 --- a/wezterm-mux-server/Cargo.toml +++ b/wezterm-mux-server/Cargo.toml @@ -10,6 +10,7 @@ resolver = "2" [dependencies] anyhow = "1.0" async_ossl = { path = "../async_ossl" } +clap = {version="3.1", features=["derive"]} config = { path = "../config" } env-bootstrap = { path = "../env-bootstrap" } libc = "0.2" @@ -18,7 +19,6 @@ mux = { path = "../mux" } openssl = "0.10" portable-pty = { path = "../pty", features = ["serde_support"]} promise = { path = "../promise" } -structopt = "0.3" umask = { path = "../umask" } wezterm-mux-server-impl = { path = "../wezterm-mux-server-impl" } wezterm-gui-subcommands = { path = "../wezterm-gui-subcommands" } diff --git a/wezterm-mux-server/src/main.rs b/wezterm-mux-server/src/main.rs index ff4ab12df..dcefb0c27 100644 --- a/wezterm-mux-server/src/main.rs +++ b/wezterm-mux-server/src/main.rs @@ -1,3 +1,4 @@ +use clap::*; use config::configuration; use mux::activity::Activity; use mux::domain::{Domain, LocalDomain}; @@ -8,25 +9,23 @@ use std::process::Command; use std::rc::Rc; use std::sync::Arc; use std::thread; -use structopt::*; use wezterm_gui_subcommands::*; mod daemonize; -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( about = "Wez's Terminal Emulator\nhttp://github.com/wez/wezterm", - global_setting = structopt::clap::AppSettings::ColoredHelp, version = config::wezterm_version() )] struct Opt { /// Skip loading wezterm.lua - #[structopt(name = "skip-config", short = "n")] + #[clap(name = "skip-config", short = 'n')] skip_config: bool, /// Specify the configuration file to use, overrides the normal /// configuration file resolution - #[structopt( + #[clap( long = "config-file", parse(from_os_str), conflicts_with = "skip-config" @@ -34,7 +33,7 @@ struct Opt { config_file: Option, /// Override specific configuration values - #[structopt( + #[clap( long = "config", name = "name=value", parse(try_from_str = name_equals_value), @@ -42,18 +41,18 @@ struct Opt { config_override: Vec<(String, String)>, /// Detach from the foreground and become a background process - #[structopt(long = "daemonize")] + #[clap(long = "daemonize")] daemonize: bool, /// Specify the current working directory for the initially /// spawned program - #[structopt(long = "cwd", parse(from_os_str))] + #[clap(long = "cwd", parse(from_os_str))] cwd: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm start -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] prog: Vec, } @@ -71,7 +70,7 @@ fn run() -> anyhow::Result<()> { config::designate_this_as_the_main_thread(); let _saver = umask::UmaskSaver::new(); - let opts = Opt::from_args(); + let opts = Opt::parse(); config::common_init( opts.config_file.as_ref(), &opts.config_override, diff --git a/wezterm-ssh/Cargo.toml b/wezterm-ssh/Cargo.toml index a189407bc..4e4263684 100644 --- a/wezterm-ssh/Cargo.toml +++ b/wezterm-ssh/Cargo.toml @@ -40,6 +40,7 @@ async_ossl = { path = "../async_ossl" } [dev-dependencies] assert_fs = "1.0.4" +clap = {version="3.1", features=["derive"]} k9 = "0.11.0" once_cell = "1.8" predicates = "2.0" @@ -47,6 +48,5 @@ env_logger = "0.9" rstest = "0.13" shell-words = "1.1" smol-potat = "1.1.2" -structopt = "0.3" termwiz = { version = "0.16", path = "../termwiz" } whoami = "1.1" diff --git a/wezterm-ssh/examples/ssh.rs b/wezterm-ssh/examples/ssh.rs index 17d6d9f41..9df6e156a 100644 --- a/wezterm-ssh/examples/ssh.rs +++ b/wezterm-ssh/examples/ssh.rs @@ -2,9 +2,9 @@ //! to test the guts of the ssh handling, rather than //! to be a full fledged replacement for ssh. use anyhow::Context; +use clap::Parser; use portable_pty::{Child, MasterPty, PtySize}; use std::io::{Read, Write}; -use structopt::StructOpt; use termwiz::cell::unicode_column_width; use termwiz::lineedit::*; use wezterm_ssh::{Config, Session, SessionEvent}; @@ -39,9 +39,9 @@ impl LineEditorHost for PasswordPromptHost { } } -#[derive(Debug, StructOpt, Default, Clone)] +#[derive(Debug, Parser, Default, Clone)] struct Opt { - #[structopt(long = "user", short = "l")] + #[clap(long = "user", short = 'l')] pub user: Option, pub destination: String, pub cmd: Vec, diff --git a/wezterm/Cargo.toml b/wezterm/Cargo.toml index 8b8c7f2ed..e4477606f 100644 --- a/wezterm/Cargo.toml +++ b/wezterm/Cargo.toml @@ -26,7 +26,7 @@ serde = {version="1.0", features = ["derive"]} serde_json = "1.0" shell-words = "1.1" smol = "1.2" -structopt = "0.3" +clap = {version="3.1", features=["derive"]} tabout = { path = "../tabout" } tempfile = "3.3" termwiz = { path = "../termwiz" } diff --git a/wezterm/src/asciicast.rs b/wezterm/src/asciicast.rs index ae11a2f92..233b5493f 100644 --- a/wezterm/src/asciicast.rs +++ b/wezterm/src/asciicast.rs @@ -1,6 +1,7 @@ use anyhow::Context; use chrono::serde::ts_seconds_option; use chrono::{DateTime, Utc}; +use clap::Parser; use config::ConfigHandle; use filedescriptor::FileDescriptor; use portable_pty::{native_pty_system, PtySize}; @@ -11,8 +12,7 @@ use std::io::{BufRead, BufReader, BufWriter, Read, Write}; use std::path::PathBuf; use std::sync::mpsc::channel; use std::time::{Duration, Instant}; -use structopt::StructOpt; -use termwiz::escape::parser::Parser; +use termwiz::escape::parser::Parser as TWParser; use termwiz::escape::Action; #[cfg(unix)] use unix::UnixTty as Tty; @@ -335,9 +335,9 @@ enum Message { Terminated(portable_pty::ExitStatus), } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct RecordCommand { - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] prog: Vec, } @@ -474,10 +474,10 @@ impl RecordCommand { } } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] pub struct PlayCommand { /// Explain what is being sent/received - #[structopt(long)] + #[clap(long)] explain: bool, cast_file: PathBuf, @@ -532,7 +532,7 @@ impl PlayCommand { let start = Instant::now(); - let mut sent_parser = Parser::new(); + let mut sent_parser = TWParser::new(); let mut sent_actions = vec![]; for line in cast_file.lines() { @@ -590,7 +590,7 @@ impl PlayCommand { if self.explain { println!("< RECV"); } - let mut parser = Parser::new(); + let mut parser = TWParser::new(); while let Ok(msg) = rx.try_recv() { match msg { Message::Stdin(data) => { diff --git a/wezterm/src/main.rs b/wezterm/src/main.rs index 44a78f4d2..f06ee43cc 100644 --- a/wezterm/src/main.rs +++ b/wezterm/src/main.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Context}; use chrono::{DateTime, Utc}; +use clap::Parser; use config::keyassignment::SpawnTabDomain; use config::wezterm_version; use mux::activity::Activity; @@ -12,7 +13,6 @@ use serde::Serializer as _; use std::ffi::OsString; use std::io::{Read, Write}; use std::rc::Rc; -use structopt::StructOpt; use tabout::{tabulate_output, Alignment, Column}; use umask::UmaskSaver; use wezterm_client::client::{unix_connect_with_retry, Client}; @@ -22,20 +22,19 @@ mod asciicast; // let message = "; ❤ 😍🤢\n\x1b[91;mw00t\n\x1b[37;104;m bleet\x1b[0;m."; -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( about = "Wez's Terminal Emulator\nhttp://github.com/wez/wezterm", - global_setting = structopt::clap::AppSettings::ColoredHelp, version = wezterm_version() )] struct Opt { /// Skip loading wezterm.lua - #[structopt(name = "skip-config", short = "n")] + #[clap(name = "skip-config", short = 'n')] skip_config: bool, /// Specify the configuration file to use, overrides the normal /// configuration file resolution - #[structopt( + #[clap( long = "config-file", parse(from_os_str), conflicts_with = "skip-config" @@ -43,85 +42,85 @@ struct Opt { config_file: Option, /// Override specific configuration values - #[structopt( + #[clap( long = "config", name = "name=value", parse(try_from_str = name_equals_value), number_of_values = 1)] config_override: Vec<(String, String)>, - #[structopt(subcommand)] + #[clap(subcommand)] cmd: Option, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] enum SubCommand { - #[structopt( + #[clap( name = "start", about = "Start the GUI, optionally running an alternative program" )] Start(StartCommand), - #[structopt(name = "ssh", about = "Establish an ssh session")] + #[clap(name = "ssh", about = "Establish an ssh session")] Ssh(SshCommand), - #[structopt(name = "serial", about = "Open a serial port")] + #[clap(name = "serial", about = "Open a serial port")] Serial(SerialCommand), - #[structopt(name = "connect", about = "Connect to wezterm multiplexer")] + #[clap(name = "connect", about = "Connect to wezterm multiplexer")] Connect(ConnectCommand), - #[structopt(name = "ls-fonts", about = "Display information about fonts")] + #[clap(name = "ls-fonts", about = "Display information about fonts")] LsFonts(LsFontsCommand), - #[structopt(name = "cli", about = "Interact with experimental mux server")] + #[clap(name = "cli", about = "Interact with experimental mux server")] Cli(CliCommand), - #[structopt(name = "imgcat", about = "Output an image to the terminal")] + #[clap(name = "imgcat", about = "Output an image to the terminal")] ImageCat(ImgCatCommand), - #[structopt( + #[clap( name = "set-working-directory", about = "Advise the terminal of the current working directory by \ emitting an OSC 7 escape sequence" )] SetCwd(SetCwdCommand), - #[structopt(name = "record", about = "Record a terminal session as an asciicast")] + #[clap(name = "record", about = "Record a terminal session as an asciicast")] Record(asciicast::RecordCommand), - #[structopt(name = "replay", about = "Replay an asciicast terminal session")] + #[clap(name = "replay", about = "Replay an asciicast terminal session")] Replay(asciicast::PlayCommand), } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] struct CliCommand { /// Don't automatically start the server - #[structopt(long = "no-auto-start")] + #[clap(long = "no-auto-start")] no_auto_start: bool, /// Prefer connecting to a background mux server. /// The default is to prefer connecting to a running /// wezterm gui instance - #[structopt(long = "prefer-mux")] + #[clap(long = "prefer-mux")] prefer_mux: bool, /// When connecting to a gui instance, if you started the /// gui with `--class SOMETHING`, you should also pass /// that same value here in order for the client to find /// the correct gui instance. - #[structopt(long = "class")] + #[clap(long = "class")] class: Option, - #[structopt(subcommand)] + #[clap(subcommand)] sub: CliSubCommand, } -#[derive(Debug, StructOpt, Clone, Copy)] +#[derive(Debug, Parser, Clone, Copy)] enum CliOutputFormatKind { - #[structopt(name = "table", about = "multi line space separated table")] + #[clap(name = "table", about = "multi line space separated table")] Table, - #[structopt(name = "json", about = "JSON format")] + #[clap(name = "json", about = "JSON format")] Json, } @@ -136,29 +135,29 @@ impl std::str::FromStr for CliOutputFormatKind { } } -#[derive(Debug, StructOpt, Clone, Copy)] +#[derive(Debug, Parser, Clone, Copy)] struct CliOutputFormat { /// Controls the output format. /// "table" and "json" are possible formats. - #[structopt(long = "format", default_value = "table")] + #[clap(long = "format", default_value = "table")] format: CliOutputFormatKind, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] enum CliSubCommand { - #[structopt(name = "list", about = "list windows, tabs and panes")] + #[clap(name = "list", about = "list windows, tabs and panes")] List(CliOutputFormat), - #[structopt(name = "list-clients", about = "list clients")] + #[clap(name = "list-clients", about = "list clients")] ListClients(CliOutputFormat), - #[structopt(name = "proxy", about = "start rpc proxy pipe")] + #[clap(name = "proxy", about = "start rpc proxy pipe")] Proxy, - #[structopt(name = "tlscreds", about = "obtain tls credentials")] + #[clap(name = "tlscreds", about = "obtain tls credentials")] TlsCreds, - #[structopt( + #[clap( name = "move-pane-to-new-tab", rename_all = "kebab", about = "Move a pane into a new tab" @@ -167,28 +166,28 @@ enum CliSubCommand { /// Specify the pane that should be moved. /// The default is to use the current pane based on the /// environment variable WEZTERM_PANE. - #[structopt(long)] + #[clap(long)] pane_id: Option, /// Specify the window into which the new tab will be /// created. /// If omitted, the window associated with the current /// pane is used. - #[structopt(long)] + #[clap(long)] window_id: Option, /// Create tab in a new window, rather than the window /// currently containing the pane. - #[structopt(long, conflicts_with = "window_id")] + #[clap(long, conflicts_with = "window-id")] new_window: bool, /// If creating a new window, override the default workspace name /// with the provided name. The default name is "default". - #[structopt(long)] + #[clap(long)] workspace: Option, }, - #[structopt( + #[clap( name = "split-pane", rename_all = "kebab", about = "split the current pane. @@ -198,63 +197,63 @@ Outputs the pane-id for the newly created pane on success" /// Specify the pane that should be split. /// The default is to use the current pane based on the /// environment variable WEZTERM_PANE. - #[structopt(long)] + #[clap(long)] pane_id: Option, /// Equivalent to `--right`. If neither this nor any other direction /// is specified, the default is equivalent to `--bottom`. - #[structopt(long, conflicts_with_all=&["left", "right", "top", "bottom"])] + #[clap(long, conflicts_with_all=&["left", "right", "top", "bottom"])] horizontal: bool, /// Split horizontally, with the new pane on the left - #[structopt(long, conflicts_with_all=&["right", "top", "bottom"])] + #[clap(long, conflicts_with_all=&["right", "top", "bottom"])] left: bool, /// Split horizontally, with the new pane on the right - #[structopt(long, conflicts_with_all=&["left", "top", "bottom"])] + #[clap(long, conflicts_with_all=&["left", "top", "bottom"])] right: bool, /// Split vertically, with the new pane on the top - #[structopt(long, conflicts_with_all=&["left", "right", "bottom"])] + #[clap(long, conflicts_with_all=&["left", "right", "bottom"])] top: bool, /// Split vertically, with the new pane on the bottom - #[structopt(long, conflicts_with_all=&["left", "right", "top"])] + #[clap(long, conflicts_with_all=&["left", "right", "top"])] bottom: bool, /// Rather than splitting the active pane, split the entire /// window. - #[structopt(long)] + #[clap(long)] top_level: bool, /// The number of cells that the new split should have. /// If omitted, 50% of the available space is used. - #[structopt(long)] + #[clap(long)] cells: Option, /// Specify the number of cells that the new split should /// have, expressed as a percentage of the available space. - #[structopt(long, conflicts_with = "cells")] + #[clap(long, conflicts_with = "cells")] percent: Option, /// Specify the current working directory for the initially /// spawned program - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] cwd: Option, /// Instead of spawning a new command, move the specified /// pane into the newly created split. - #[structopt(long, conflicts_with_all=&["cwd", "prog"])] + #[clap(long, conflicts_with_all=&["cwd", "prog"])] move_pane_id: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm cli split-pane -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] prog: Vec, }, - #[structopt( + #[clap( name = "spawn", about = "Spawn a command into a new window or tab Outputs the pane-id for the newly created pane on success" @@ -265,52 +264,52 @@ Outputs the pane-id for the newly created pane on success" /// environment variable WEZTERM_PANE. /// The pane is used to determine the current domain /// and window. - #[structopt(long = "pane-id")] + #[clap(long = "pane-id")] pane_id: Option, - #[structopt(long = "domain-name")] + #[clap(long = "domain-name")] domain_name: Option, /// Specify the window into which to spawn a tab. /// If omitted, the window associated with the current /// pane is used. - #[structopt(long = "window-id")] + #[clap(long = "window-id")] window_id: Option, /// Spawn into a new window, rather than a new tab - #[structopt(long = "new-window", conflicts_with = "window_id")] + #[clap(long = "new-window", conflicts_with = "window-id")] new_window: bool, /// Specify the current working directory for the initially /// spawned program - #[structopt(long = "cwd", parse(from_os_str))] + #[clap(long = "cwd", parse(from_os_str))] cwd: Option, /// When creating a new window, override the default workspace name /// with the provided name. The default name is "default". - #[structopt(long = "workspace")] + #[clap(long = "workspace")] workspace: Option, /// Instead of executing your shell, run PROG. /// For example: `wezterm cli spawn -- bash -l` will spawn bash /// as if it were a login shell. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] prog: Vec, }, /// Send text to a pane as though it were pasted. /// If bracketed paste mode is enabled in the pane, then the /// text will be sent as a bracketed paste. - #[structopt(name = "send-text", rename_all = "kebab")] + #[clap(name = "send-text", rename_all = "kebab")] SendText { /// Specify the target pane. /// The default is to use the current pane based on the /// environment variable WEZTERM_PANE. - #[structopt(long)] + #[clap(long)] pane_id: Option, /// Send the text directly, rather than as a bracketed paste. - #[structopt(long)] + #[clap(long)] no_paste: bool, /// The text to send. If omitted, will read the text from stdin. @@ -322,27 +321,27 @@ use termwiz::escape::osc::{ ITermDimension, ITermFileData, ITermProprietary, OperatingSystemCommand, }; -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] struct ImgCatCommand { /// Specify the display width; defaults to "auto" which automatically selects /// an appropriate size. You may also use an integer value `N` to specify the /// number of cells, or `Npx` to specify the number of pixels, or `N%` to /// size relative to the terminal width. - #[structopt(long = "width")] + #[clap(long = "width")] width: Option, /// Specify the display height; defaults to "auto" which automatically selects /// an appropriate size. You may also use an integer value `N` to specify the /// number of cells, or `Npx` to specify the number of pixels, or `N%` to /// size relative to the terminal height. - #[structopt(long = "height")] + #[clap(long = "height")] height: Option, /// Do not respect the aspect ratio. The default is to respect the aspect /// ratio - #[structopt(long = "no-preserve-aspect-ratio")] + #[clap(long = "no-preserve-aspect-ratio")] no_preserve_aspect_ratio: bool, /// The name of the image file to be displayed. /// If omitted, will attempt to read it from stdin. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] file_name: Option, } @@ -376,16 +375,16 @@ impl ImgCatCommand { } } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Parser, Clone)] struct SetCwdCommand { /// The directory to specify. /// If omitted, will use the current directory of the process itself. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] cwd: Option, /// The hostname to use in the constructed file:// URL. /// If omitted, the system hostname will be used. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] host: Option, } @@ -446,7 +445,7 @@ fn run() -> anyhow::Result<()> { let saver = UmaskSaver::new(); - let opts = Opt::from_args(); + let opts = Opt::parse(); config::common_init( opts.config_file.as_ref(), &opts.config_override,