diff --git a/Cargo.lock b/Cargo.lock index 42d6983e..44ee2946 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,17 +185,27 @@ 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", "atty", "bitflags", + "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]] @@ -837,6 +847,7 @@ dependencies = [ "assert_cmd", "chrono", "clap", + "clap_complete", "elasticlunr-rs", "env_logger", "futures-util", @@ -1053,6 +1064,15 @@ dependencies = [ "winapi 0.3.9", ] +[[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 = "output_vt100" version = "0.1.2" @@ -1590,9 +1610,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" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" @@ -1659,12 +1679,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 = "time" @@ -1872,12 +1889,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -1902,12 +1913,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[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" diff --git a/Cargo.toml b/Cargo.toml index e0aef886..e19cf12e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,8 @@ description = "Creates a book from markdown files" [dependencies] anyhow = "1.0.28" chrono = "0.4" -clap = "2.24" +clap = { version = "3.0", features = ["cargo"] } +clap_complete = "3.0" env_logger = "0.7.1" handlebars = "4.0" lazy_static = "1.0" diff --git a/examples/nop-preprocessor.rs b/examples/nop-preprocessor.rs index 486fd86d..d53d8745 100644 --- a/examples/nop-preprocessor.rs +++ b/examples/nop-preprocessor.rs @@ -7,7 +7,7 @@ use semver::{Version, VersionReq}; use std::io; use std::process; -pub fn make_app() -> App<'static, 'static> { +pub fn make_app() -> App<'static> { App::new("nop-preprocessor") .about("A mdbook preprocessor which does precisely nothing") .subcommand( diff --git a/src/cmd/build.rs b/src/cmd/build.rs index d1c66302..fd421a39 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -4,7 +4,7 @@ use mdbook::errors::Result; use mdbook::MDBook; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("build") .about("Builds a book from its markdown files") .arg_from_usage( diff --git a/src/cmd/clean.rs b/src/cmd/clean.rs index b58f937e..0f368dda 100644 --- a/src/cmd/clean.rs +++ b/src/cmd/clean.rs @@ -5,7 +5,7 @@ use mdbook::MDBook; use std::fs; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("clean") .about("Deletes a built book") .arg_from_usage( diff --git a/src/cmd/init.rs b/src/cmd/init.rs index ed0aa17d..d777c081 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -8,7 +8,7 @@ use std::io::Write; use std::process::Command; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("init") .about("Creates the boilerplate structure and files for a new book") // the {n} denotes a newline which will properly aligned in all help messages diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index c5394f8a..0b46a1e5 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -18,7 +18,7 @@ use warp::Filter; const LIVE_RELOAD_ENDPOINT: &str = "__livereload"; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("serve") .about("Serves a book at http://localhost:3000, and rebuilds it on changes") .arg_from_usage( @@ -32,7 +32,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { ) .arg( Arg::with_name("hostname") - .short("n") + .short('n') .long("hostname") .takes_value(true) .default_value("localhost") @@ -41,7 +41,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { ) .arg( Arg::with_name("port") - .short("p") + .short('p') .long("port") .takes_value(true) .default_value("3000") diff --git a/src/cmd/test.rs b/src/cmd/test.rs index f6d97aa6..50470793 100644 --- a/src/cmd/test.rs +++ b/src/cmd/test.rs @@ -4,7 +4,7 @@ use mdbook::errors::Result; use mdbook::MDBook; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("test") .about("Tests that a book's Rust code samples compile") .arg_from_usage( @@ -17,10 +17,11 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { (Defaults to the Current Directory when omitted)'", ) .arg(Arg::with_name("library-path") - .short("L") + .short('L') .long("library-path") .value_name("dir") .takes_value(true) + .use_delimiter(true) .require_delimiter(true) .multiple(true) .empty_values(false) diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs index b27516b0..992246ae 100644 --- a/src/cmd/watch.rs +++ b/src/cmd/watch.rs @@ -10,7 +10,7 @@ use std::thread::sleep; use std::time::Duration; // Create clap subcommand arguments -pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { +pub fn make_subcommand<'help>() -> App<'help> { SubCommand::with_name("watch") .about("Watches a book's files and rebuilds it on changes") .arg_from_usage( diff --git a/src/main.rs b/src/main.rs index 1f286d2d..36f0fc02 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,8 @@ extern crate log; use anyhow::anyhow; use chrono::Local; -use clap::{App, AppSettings, Arg, ArgMatches, Shell, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; +use clap_complete::Shell; use env_logger::Builder; use log::LevelFilter; use mdbook::utils; @@ -25,25 +26,31 @@ fn main() { // Check which subcomamnd the user ran... let res = match app.get_matches().subcommand() { - ("init", Some(sub_matches)) => cmd::init::execute(sub_matches), - ("build", Some(sub_matches)) => cmd::build::execute(sub_matches), - ("clean", Some(sub_matches)) => cmd::clean::execute(sub_matches), + Some(("init", sub_matches)) => cmd::init::execute(sub_matches), + Some(("build", sub_matches)) => cmd::build::execute(sub_matches), + Some(("clean", sub_matches)) => cmd::clean::execute(sub_matches), #[cfg(feature = "watch")] - ("watch", Some(sub_matches)) => cmd::watch::execute(sub_matches), + Some(("watch", sub_matches)) => cmd::watch::execute(sub_matches), #[cfg(feature = "serve")] - ("serve", Some(sub_matches)) => cmd::serve::execute(sub_matches), - ("test", Some(sub_matches)) => cmd::test::execute(sub_matches), - ("completions", Some(sub_matches)) => (|| { + Some(("serve", sub_matches)) => cmd::serve::execute(sub_matches), + Some(("test", sub_matches)) => cmd::test::execute(sub_matches), + Some(("completions", sub_matches)) => (|| { let shell: Shell = sub_matches .value_of("shell") .ok_or_else(|| anyhow!("Shell name missing."))? .parse() .map_err(|s| anyhow!("Invalid shell: {}", s))?; - create_clap_app().gen_completions_to("mdbook", shell, &mut std::io::stdout().lock()); + let mut complete_app = create_clap_app(); + clap_complete::generate( + shell, + &mut complete_app, + "mdbook", + &mut std::io::stdout().lock(), + ); Ok(()) })(), - (_, _) => unreachable!(), + _ => unreachable!(), }; if let Err(e) = res { @@ -54,7 +61,7 @@ fn main() { } /// Create a list of valid arguments and sub-commands -fn create_clap_app<'a, 'b>() -> App<'a, 'b> { +fn create_clap_app() -> App<'static> { let app = App::new(crate_name!()) .about(crate_description!()) .author("Mathieu David ") @@ -76,7 +83,7 @@ fn create_clap_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("shell") .takes_value(true) - .possible_values(&Shell::variants()) + .possible_values(Shell::possible_values()) .help("the shell to generate completions for") .value_name("SHELL") .required(true), @@ -137,3 +144,8 @@ fn open>(path: P) { error!("Error opening web browser: {}", e); } } + +#[test] +fn verify_app() { + create_clap_app().debug_assert(); +}