diff --git a/CHANGELOG.md b/CHANGELOG.md index 852e32b8..3894731d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Switched from structopt to clap for command line argument parsing. ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) diff --git a/Cargo.lock b/Cargo.lock index fe8466ae..326db2ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,13 +217,48 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term", + "bitflags", + "textwrap 0.11.0", + "unicode-width", +] + +[[package]] +name = "clap" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +dependencies = [ "atty", "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", "strsim", - "textwrap", - "unicode-width", - "vec_map", + "termcolor", + "textwrap 0.15.0", +] + +[[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 1.0.39", + "quote 1.0.18", + "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]] @@ -269,7 +304,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools", @@ -738,12 +773,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[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" @@ -1272,6 +1304,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "output_vt100" version = "0.1.3" @@ -1764,6 +1802,7 @@ dependencies = [ "anyhow", "backtrace", "bincode", + "clap 3.1.18", "criterion", "crossbeam-channel", "csv", @@ -1795,7 +1834,6 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "structopt", "tempfile", "termcolor", "thiserror", @@ -1998,33 +2036,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[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 1.0.39", - "quote 1.0.18", - "syn", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" @@ -2085,6 +2099,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.31" @@ -2257,12 +2277,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-width" version = "0.1.9" @@ -2303,12 +2317,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" diff --git a/Cargo.toml b/Cargo.toml index 958396a4..cc2828ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,11 +78,11 @@ ritz = "0.1.0" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } serde_json = "1.0.68" -structopt = "0.3.23" termcolor = "1.1.2" thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } uuid = { version = "1.0.0", features = ["v4", "serde"] } +clap = { version = "3.1.18", features = ["derive"] } [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/src/cli/build.rs b/src/cli/build.rs index 38273f82..081aef3a 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,9 +4,9 @@ use std::{ }; use anyhow::Context; +use clap::Parser; use fs_err::File; use memofs::Vfs; -use structopt::StructOpt; use tokio::runtime::Runtime; use crate::serve_session::ServeSession; @@ -17,20 +17,20 @@ const UNKNOWN_OUTPUT_KIND_ERR: &str = "Could not detect what kind of file to bui Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx."; /// Generates a model or place file from the Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct BuildCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Where to output the result. /// /// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx. - #[structopt(long, short)] + #[clap(long, short)] pub output: PathBuf, /// Whether to automatically rebuild when any input files change. - #[structopt(long)] + #[clap(long)] pub watch: bool, } diff --git a/src/cli/doc.rs b/src/cli/doc.rs index 9a344997..61a8d416 100644 --- a/src/cli/doc.rs +++ b/src/cli/doc.rs @@ -1,7 +1,7 @@ -use structopt::StructOpt; +use clap::Parser; /// Open Rojo's documentation in your browser. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct DocCommand {} impl DocCommand { diff --git a/src/cli/fmt_project.rs b/src/cli/fmt_project.rs index e227fa44..9351d635 100644 --- a/src/cli/fmt_project.rs +++ b/src/cli/fmt_project.rs @@ -1,15 +1,15 @@ use std::path::PathBuf; use anyhow::Context; -use structopt::StructOpt; +use clap::Parser; use crate::project::Project; /// Reformat a Rojo project using the standard JSON formatting rules. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct FmtProjectCommand { /// Path to the project to format. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, } diff --git a/src/cli/init.rs b/src/cli/init.rs index 3117b61f..795ec04d 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -4,9 +4,9 @@ use std::process::{Command, Stdio}; use std::str::FromStr; use anyhow::{bail, format_err}; +use clap::Parser; use fs_err as fs; use fs_err::OpenOptions; -use structopt::StructOpt; use super::resolve_path; @@ -22,14 +22,14 @@ static PLACE_README: &str = include_str!("../../assets/default-place-project/REA static PLACE_GIT_IGNORE: &str = include_str!("../../assets/default-place-project/gitignore.txt"); /// Initializes a new Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct InitCommand { /// Path to the place to create the project. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub path: PathBuf, /// The kind of project to create, 'place' or 'model'. Defaults to place. - #[structopt(long, default_value = "place")] + #[clap(long, default_value = "place")] pub kind: InitKind, } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 2d498b4a..36b32940 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,4 @@ -//! Defines Rojo's CLI through structopt types. +//! Defines Rojo's CLI through clap types. mod build; mod doc; @@ -11,7 +11,7 @@ mod upload; use std::{borrow::Cow, env, path::Path, str::FromStr}; -use structopt::StructOpt; +use clap::Parser; use thiserror::Error; pub use self::build::BuildCommand; @@ -23,15 +23,15 @@ pub use self::serve::ServeCommand; pub use self::sourcemap::SourcemapCommand; pub use self::upload::UploadCommand; -/// Command line options that Rojo accepts, defined using the structopt crate. -#[derive(Debug, StructOpt)] -#[structopt(name = "Rojo", about, author)] +/// Command line options that Rojo accepts, defined using the clap crate. +#[derive(Debug, Parser)] +#[clap(name = "Rojo", version, about, author)] pub struct Options { - #[structopt(flatten)] + #[clap(flatten)] pub global: GlobalOptions, /// Subcommand to run in this invocation. - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Subcommand, } @@ -50,14 +50,14 @@ impl Options { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GlobalOptions { /// Sets verbosity level. Can be specified multiple times. - #[structopt(long("verbose"), short, global(true), parse(from_occurrences))] + #[clap(long("verbose"), short, global(true), parse(from_occurrences))] pub verbosity: u8, /// Set color behavior. Valid values are auto, always, and never. - #[structopt(long("color"), global(true), default_value("auto"))] + #[clap(long("color"), global(true), default_value("auto"))] pub color: ColorChoice, } @@ -109,7 +109,7 @@ pub struct ColorChoiceParseError { attempted: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { Init(InitCommand), Serve(ServeCommand), diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 5ab98e07..aa8773b3 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -3,9 +3,9 @@ use std::{ io::BufWriter, }; +use clap::Parser; use memofs::{InMemoryFs, Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; -use structopt::StructOpt; use crate::serve_session::ServeSession; @@ -13,14 +13,14 @@ static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin. static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm"; /// Install Rojo's plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct PluginCommand { - #[structopt(subcommand)] + #[clap(subcommand)] subcommand: PluginSubcommand, } /// Manages Rojo's Roblox Studio plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum PluginSubcommand { /// Install the plugin in Roblox Studio's plugins folder. If the plugin is /// already installed, installing it again will overwrite the current plugin diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 56b46121..9d2aa343 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -5,8 +5,8 @@ use std::{ sync::Arc, }; +use clap::Parser; use memofs::Vfs; -use structopt::StructOpt; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{serve_session::ServeSession, web::LiveServer}; @@ -17,19 +17,19 @@ const DEFAULT_BIND_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); const DEFAULT_PORT: u16 = 34872; /// Expose a Rojo project to the Rojo Studio plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ServeCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// The IP address to listen on. Defaults to `127.0.0.1`. - #[structopt(long)] + #[clap(long)] pub address: Option, /// The port to listen on. Defaults to the project's preference, or `34872` if /// it has none. - #[structopt(long)] + #[clap(long)] pub port: Option, } diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 8cda48ff..9d761e71 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -3,11 +3,11 @@ use std::{ path::{Path, PathBuf}, }; +use clap::Parser; use fs_err::File; use memofs::Vfs; use rbx_dom_weak::types::Ref; use serde::Serialize; -use structopt::StructOpt; use crate::{ serve_session::ServeSession, @@ -33,22 +33,22 @@ struct SourcemapNode { } /// Generates a sourcemap file from the Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct SourcemapCommand { /// Path to the project to use for the sourcemap. Defaults to the current /// directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Where to output the sourcemap. Omit this to use stdout instead of /// writing to a file. /// /// Should end in .json. - #[structopt(long, short)] + #[clap(long, short)] pub output: Option, /// If non-script files should be included or not. Defaults to false. - #[structopt(long)] + #[clap(long)] pub include_non_scripts: bool, } diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 2f4d2d63..d8404099 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -2,38 +2,38 @@ use std::path::PathBuf; use std::str::FromStr; use anyhow::{bail, format_err, Context}; +use clap::Parser; use memofs::Vfs; use reqwest::{ header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}, StatusCode, }; -use structopt::StructOpt; use crate::{auth_cookie::get_auth_cookie, serve_session::ServeSession}; use super::resolve_path; /// Builds the project and uploads it to Roblox. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct UploadCommand { /// Path to the project to upload. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically. - #[structopt(long)] + #[clap(long)] pub cookie: Option, /// API key obtained from create.roblox.com/credentials. Rojo will use the Open Cloud API when this is provided. Only supports uploading to a place. - #[structopt(long = "api_key")] + #[clap(long = "api_key")] pub api_key: Option, /// The Universe ID of the given place. Required when using the Open Cloud API. - #[structopt(long = "universe_id")] + #[clap(long = "universe_id")] pub universe_id: Option, /// Asset ID to upload to. - #[structopt(long = "asset_id")] + #[clap(long = "asset_id")] pub asset_id: u64, } diff --git a/src/main.rs b/src/main.rs index 34d89d8a..10920bd3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use std::{env, panic, process}; use backtrace::Backtrace; -use structopt::StructOpt; +use clap::Parser; use librojo::cli::Options; @@ -49,7 +49,7 @@ fn main() { process::exit(1); })); - let options = Options::from_args(); + let options = Options::parse(); let log_filter = match options.global.verbosity { 0 => "info",