diff --git a/Cargo.toml b/Cargo.toml index 0268d36c..9ae3d943 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ serde_ignored = "0.1.7" serde_json = "1.0.91" siphasher = "0.3.10" strsim = "0.10.0" -structopt = "0.3.26" +clap = { version = "4.2.5", features = ["derive"] } toml = "0.5.11" ureq = { version = "2.6.2", features = ["json"] } walkdir = "2.3.2" diff --git a/src/command/build.rs b/src/command/build.rs index c5572123..ad50e081 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -19,7 +19,7 @@ use std::fmt; use std::path::PathBuf; use std::str::FromStr; use std::time::Instant; -use structopt::clap::AppSettings; +use clap::{Args}; /// Everything required to configure and run the `wasm-pack build` command. #[allow(missing_docs)] @@ -109,74 +109,67 @@ pub enum BuildProfile { } /// Everything required to configure and run the `wasm-pack build` command. -#[derive(Debug, StructOpt)] -#[structopt( - // Allows unknown `--option`s to be parsed as positional arguments, so we can forward it to `cargo`. - setting = AppSettings::AllowLeadingHyphen, - - // Allows `--` to be parsed as an argument, so we can forward it to `cargo`. - setting = AppSettings::TrailingVarArg, -)] +#[derive(Debug, Args)] +#[command(allow_hyphen_values = true, trailing_var_arg = true)] pub struct BuildOptions { /// The path to the Rust crate. If not set, searches up the path from the current directory. - #[structopt(parse(from_os_str))] + #[clap()] pub path: Option, /// The npm scope to use in package.json, if any. - #[structopt(long = "scope", short = "s")] + #[clap(long = "scope", short = 's')] pub scope: Option, - #[structopt(long = "mode", short = "m", default_value = "normal")] + #[clap(long = "mode", short = 'm', default_value = "normal")] /// Sets steps to be run. [possible values: no-install, normal, force] pub mode: InstallMode, - #[structopt(long = "no-typescript")] + #[clap(long = "no-typescript")] /// By default a *.d.ts file is generated for the generated JS file, but /// this flag will disable generating this TypeScript file. pub disable_dts: bool, - #[structopt(long = "weak-refs")] + #[clap(long = "weak-refs")] /// Enable usage of the JS weak references proposal. pub weak_refs: bool, - #[structopt(long = "reference-types")] + #[clap(long = "reference-types")] /// Enable usage of WebAssembly reference types. pub reference_types: bool, - #[structopt(long = "target", short = "t", default_value = "bundler")] + #[clap(long = "target", short = 't', default_value = "bundler")] /// Sets the target environment. [possible values: bundler, nodejs, web, no-modules] pub target: Target, - #[structopt(long = "debug")] + #[clap(long = "debug")] /// Deprecated. Renamed to `--dev`. pub debug: bool, - #[structopt(long = "dev")] + #[clap(long = "dev")] /// Create a development build. Enable debug info, and disable /// optimizations. pub dev: bool, - #[structopt(long = "release")] + #[clap(long = "release")] /// Create a release build. Enable optimizations and disable debug info. pub release: bool, - #[structopt(long = "profiling")] + #[clap(long = "profiling")] /// Create a profiling build. Enable optimizations and debug info. pub profiling: bool, - #[structopt(long = "out-dir", short = "d", default_value = "pkg")] + #[clap(long = "out-dir", short = 'd', default_value = "pkg")] /// Sets the output directory with a relative path. pub out_dir: String, - #[structopt(long = "out-name")] + #[clap(long = "out-name")] /// Sets the output file names. Defaults to package name. pub out_name: Option, - #[structopt(long = "no-pack", alias = "no-package")] + #[clap(long = "no-pack", alias = "no-package")] /// Option to not generate a package.json pub no_pack: bool, - #[structopt(allow_hyphen_values = true)] /// List of extra options to pass to `cargo build` pub extra_options: Vec, } @@ -225,7 +218,7 @@ impl Build { (false, false, false) | (false, true, false) => BuildProfile::Release, (true, false, false) => BuildProfile::Dev, (false, false, true) => BuildProfile::Profiling, - // Unfortunately, `structopt` doesn't expose clap's `conflicts_with` + // Unfortunately, `clap` doesn't expose clap's `conflicts_with` // functionality yet, so we have to implement it ourselves. _ => bail!("Can only supply one of the --dev, --release, or --profiling flags"), }; diff --git a/src/command/mod.rs b/src/command/mod.rs index 631eca71..dad39f40 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -20,64 +20,64 @@ use crate::install::InstallMode; use anyhow::Result; use log::info; use std::path::PathBuf; - +use clap::Subcommand; +use clap::builder::ValueParser; /// The various kinds of commands that `wasm-pack` can execute. -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum Command { /// 🏗️ build your npm package! - #[structopt(name = "build", alias = "init")] + #[clap(name = "build", alias = "init")] Build(BuildOptions), - #[structopt(name = "pack")] + #[clap(name = "pack")] /// 🍱 create a tar of your npm package but don't publish! Pack { /// The path to the Rust crate. If not set, searches up the path from the current directory. - #[structopt(parse(from_os_str))] + #[clap(value_parser = ValueParser::os_string())] path: Option, }, - #[structopt(name = "new")] + #[clap(name = "new")] /// 🐑 create a new project with a template Generate { /// The name of the project name: String, /// The URL to the template - #[structopt( + #[clap( long = "template", - short = "temp", default_value = "https://github.com/rustwasm/wasm-pack-template" )] template: String, - #[structopt(long = "mode", short = "m", default_value = "normal")] + #[clap(long = "mode", short = 'm', default_value = "normal")] /// Should we install or check the presence of binary tools. [possible values: no-install, normal, force] mode: InstallMode, }, - #[structopt(name = "publish")] + #[clap(name = "publish")] /// 🎆 pack up your npm package and publish! Publish { - #[structopt(long = "target", short = "t", default_value = "bundler")] + #[clap(long = "target", short = 't', default_value = "bundler")] /// Sets the target environment. [possible values: bundler, nodejs, web, no-modules] target: String, /// The access level for the package to be published - #[structopt(long = "access", short = "a")] + #[clap(long = "access", short = 'a')] access: Option, /// The distribution tag being used for publishing. /// See https://docs.npmjs.com/cli/dist-tag - #[structopt(long = "tag")] + #[clap(long = "tag")] tag: Option, /// The path to the Rust crate. If not set, searches up the path from the current directory. - #[structopt(parse(from_os_str))] + #[clap(value_parser = ValueParser::os_string())] path: Option, }, - #[structopt(name = "login", alias = "adduser", alias = "add-user")] + #[clap(name = "login", alias = "adduser", alias = "add-user")] /// 👤 Add an npm registry user account! (aliases: adduser, add-user) Login { - #[structopt(long = "registry", short = "r")] + #[clap(long = "registry", short = 'r')] /// Default: 'https://registry.npmjs.org/'. /// The base URL of the npm package registry. If scope is also /// specified, this registry will only be used for packages with that @@ -85,13 +85,13 @@ pub enum Command { /// currently in, if any. registry: Option, - #[structopt(long = "scope", short = "s")] + #[clap(long = "scope", short = 's')] /// Default: none. /// If specified, the user and login credentials given will be /// associated with the specified scope. scope: Option, - #[structopt(long = "auth-type", short = "t")] + #[clap(long = "auth-type", short = 't')] /// Default: 'legacy'. /// Type: 'legacy', 'sso', 'saml', 'oauth'. /// What authentication strategy to use with adduser/login. Some npm @@ -100,7 +100,7 @@ pub enum Command { auth_type: Option, }, - #[structopt(name = "test")] + #[clap(name = "test")] /// 👩‍🔬 test your wasm! Test(TestOptions), } diff --git a/src/command/publish/access.rs b/src/command/publish/access.rs index 6b374b4c..1cbfea6e 100644 --- a/src/command/publish/access.rs +++ b/src/command/publish/access.rs @@ -3,7 +3,7 @@ use std::fmt; use std::str::FromStr; /// Represents access level for the to-be publish package. Passed to `wasm-pack publish` as a flag, e.g. `--access=public`. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum Access { /// Access is granted to all. All unscoped packages *must* be public. Public, diff --git a/src/command/test.rs b/src/command/test.rs index d7b66424..c0939746 100644 --- a/src/command/test.rs +++ b/src/command/test.rs @@ -14,68 +14,63 @@ use log::info; use std::path::PathBuf; use std::str::FromStr; use std::time::Instant; -use structopt::clap::AppSettings; +use clap::Args; +use clap::builder::ValueParser; -#[derive(Debug, Default, StructOpt)] -#[structopt( - // Allows unknown `--option`s to be parsed as positional arguments, so we can forward it to `cargo`. - setting = AppSettings::AllowLeadingHyphen, - - // Allows `--` to be parsed as an argument, so we can forward it to `cargo`. - setting = AppSettings::TrailingVarArg, -)] +#[derive(Debug, Default, Args)] +#[command(allow_hyphen_values = true, trailing_var_arg = true)] /// Everything required to configure the `wasm-pack test` command. pub struct TestOptions { - #[structopt(long = "node")] + #[clap(long = "node")] /// Run the tests in Node.js. pub node: bool, - #[structopt(long = "firefox")] + #[clap(long = "firefox")] /// Run the tests in Firefox. This machine must have a Firefox installation. /// If the `geckodriver` WebDriver client is not on the `$PATH`, and not /// specified with `--geckodriver`, then `wasm-pack` will download a local /// copy. pub firefox: bool, - #[structopt(long = "geckodriver", parse(from_os_str))] + #[clap(long = "geckodriver", value_parser = ValueParser::os_string())] /// The path to the `geckodriver` WebDriver client for testing in /// Firefox. Implies `--firefox`. pub geckodriver: Option, - #[structopt(long = "chrome")] + #[clap(long = "chrome")] /// Run the tests in Chrome. This machine must have a Chrome installation. /// If the `chromedriver` WebDriver client is not on the `$PATH`, and not /// specified with `--chromedriver`, then `wasm-pack` will download a local /// copy. pub chrome: bool, - #[structopt(long = "chromedriver", parse(from_os_str))] + #[clap(long = "chromedriver", value_parser = ValueParser::os_string())] /// The path to the `chromedriver` WebDriver client for testing in /// Chrome. Implies `--chrome`. pub chromedriver: Option, - #[structopt(long = "safari")] + #[clap(long = "safari")] /// Run the tests in Safari. This machine must have a Safari installation, /// and the `safaridriver` WebDriver client must either be on the `$PATH` or /// specified explicitly with the `--safaridriver` flag. `wasm-pack` cannot /// download the `safaridriver` WebDriver client for you. pub safari: bool, - #[structopt(long = "safaridriver", parse(from_os_str))] + #[clap(long = "safaridriver", value_parser = ValueParser::os_string())] /// The path to the `safaridriver` WebDriver client for testing in /// Safari. Implies `--safari`. pub safaridriver: Option, - #[structopt(long = "headless")] + #[clap(long = "headless")] /// When running browser tests, run the browser in headless mode without any /// UI or windows. pub headless: bool, - #[structopt(long = "mode", short = "m", default_value = "normal")] + #[clap(long = "mode", short = 'm', default_value = "normal")] /// Sets steps to be run. [possible values: no-install, normal] pub mode: InstallMode, - #[structopt(long = "release", short = "r")] + #[clap(long = "release", short = 'r')] /// Build with the release profile. pub release: bool, @@ -85,7 +80,6 @@ pub struct TestOptions { /// /// This is a workaround to allow wasm pack to provide the same command line interface as `cargo`. /// See for more information. - #[structopt(allow_hyphen_values = true)] pub path_and_extra_options: Vec, } diff --git a/src/lib.rs b/src/lib.rs index 1f5c5085..af66554d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,8 +15,6 @@ extern crate which; extern crate serde_derive; extern crate serde_ignored; extern crate serde_json; -#[macro_use] -extern crate structopt; extern crate binary_install; extern crate chrono; extern crate dialoguer; @@ -43,27 +41,29 @@ pub mod target; pub mod test; pub mod wasm_opt; +use clap::Parser; +use clap::builder::ArgAction; use crate::progressbar::{LogLevel, ProgressOutput}; /// The global progress bar and user-facing message output. pub static PBAR: ProgressOutput = ProgressOutput::new(); /// 📦 ✨ pack and publish your wasm! -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct Cli { /// The subcommand to run. - #[structopt(subcommand)] // Note that we mark a field as a subcommand + #[clap(subcommand)] // Note that we mark a field as a subcommand pub cmd: command::Command, /// Log verbosity is based off the number of v used - #[structopt(long = "verbose", short = "v", parse(from_occurrences))] + #[clap(long = "verbose", short = 'v', action = ArgAction::Count)] pub verbosity: u8, - #[structopt(long = "quiet", short = "q")] + #[clap(long = "quiet", short = 'q')] /// No output printed to stdout pub quiet: bool, - #[structopt(long = "log-level", default_value = "info")] + #[clap(long = "log-level", default_value = "info")] /// The maximum level of messages that should be logged by wasm-pack. [possible values: info, warn, error] pub log_level: LogLevel, } diff --git a/src/main.rs b/src/main.rs index c77f845d..048561aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ extern crate atty; extern crate env_logger; extern crate human_panic; extern crate log; -extern crate structopt; +extern crate clap; extern crate wasm_pack; extern crate which; @@ -14,7 +14,7 @@ use std::env; use std::panic; use std::sync::mpsc; use std::thread; -use structopt::StructOpt; +use clap::Parser; use wasm_pack::{ build::{self, WasmPackVersion}, command::run_wasm_pack, @@ -79,7 +79,7 @@ fn run() -> Result<()> { } } - let args = Cli::from_args(); + let args = Cli::parse(); PBAR.set_log_level(args.log_level); diff --git a/tests/all/main.rs b/tests/all/main.rs index c99a871c..a7cdb8bf 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -8,7 +8,7 @@ extern crate binary_install; extern crate serde_json; #[macro_use] extern crate serial_test; -extern crate structopt; +extern crate clap; extern crate tempfile; extern crate wasm_pack;