diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index f8b421e..6ed8779 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -23,7 +23,7 @@ jobs: - macos toolchain: - stable - - 1.67.1 + - 1.70.0 name: Test on ${{ matrix.platform }} with ${{ matrix.toolchain }} runs-on: "${{ matrix.platform }}-latest" diff --git a/Cargo.toml b/Cargo.toml index 80efbf1..2b3a2d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ repository = "https://github.com/watchexec/cargo-watch" readme = "README.md" edition = "2021" -rust-version = "1.67.1" +rust-version = "1.70.0" exclude = ["/.github"] [[bin]] diff --git a/README.md b/README.md index 694468a..b5d0ebf 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you've used [nodemon], [guard], or [entr], it will probably feel familiar. [guard]: http://guardgem.org/ - In the public domain / licensed with CC0. -- Minimum Supported Rust Version: 1.67.1. +- Minimum Supported Rust Version: 1.70.0. - Only the last five stable versions are supported. - MSRV increases beyond that range at publish time will not incur major version bumps. diff --git a/src/args.rs b/src/args.rs index 6c61891..f1e8677 100644 --- a/src/args.rs +++ b/src/args.rs @@ -237,19 +237,35 @@ pub fn parse() -> ArgMatches<'static> { .short("L") .takes_value(true) ) - .arg( - Arg::with_name("cmd:trail") - .raw(true) - .help("Full command to run. -x and -s will be ignored!"), - ) .arg( Arg::with_name("skip-local-deps") .help("Don't try to find local dependencies of the current crate and watch their working directories. Only watch the current directory.") .long("skip-local-deps") ) + .subcommand(special_cargo_subc("bench")) + .subcommand(special_cargo_subc("build")) + .subcommand(special_cargo_subc("check")) + .subcommand(special_cargo_subc("clippy")) + .subcommand(special_cargo_subc("test")) + .arg( + Arg::with_name("cmd:trail") + .raw(true) + .help("Full command to run. -x and -s will be ignored!"), + ) .after_help(footnote.as_str()), ); + fn special_cargo_subc(name: &str) -> App { + SubCommand::with_name(name) + .setting(AppSettings::AllowLeadingHyphen) + .setting(AppSettings::DisableHelpFlags) + .setting(AppSettings::DisableHelpSubcommand) + .setting(AppSettings::DisableVersion) + .setting(AppSettings::Hidden) + .setting(AppSettings::TrailingVarArg) + .arg(Arg::with_name("args").multiple(true)) + } + // Allow invocation of cargo-watch with both `cargo-watch watch ARGS` // (as invoked by cargo) and `cargo-watch ARGS`. let mut args: Vec = env::args().collect(); diff --git a/src/options.rs b/src/options.rs index 394b671..3b506cc 100644 --- a/src/options.rs +++ b/src/options.rs @@ -6,7 +6,7 @@ use std::{ }; use cargo_metadata::{MetadataCommand, Node, Package, PackageId}; -use clap::{value_t, values_t, ArgMatches}; +use clap::{value_t, values_t, ArgMatches, ErrorKind}; use log::{debug, warn}; use watchexec::{ config::{Config, ConfigBuilder}, @@ -21,9 +21,32 @@ pub fn set_commands(builder: &mut ConfigBuilder, matches: &ArgMatches) { // and before the remaining arguments let features = value_t!(matches, "features", String).ok(); + let subcommand_cargo = { + let (name, args) = matches.subcommand(); + if name == "" { + None + } else if let Some(args) = args { + let args = values_t!(args, "args", String).unwrap_or_else(|e| e.exit()).join(" "); + Some(format!("{name} {args}")) + } else { + // shouldn't happen per clap2, but just in case: + Some(name.to_string()) + } + }; + // Cargo commands are in front of the rest - if matches.is_present("cmd:cargo") { - for cargo in values_t!(matches, "cmd:cargo", String).unwrap_or_else(|e| e.exit()) { + if matches.is_present("cmd:cargo") || subcommand_cargo.is_some() { + let normal_cargos = values_t!(matches, "cmd:cargo", String).unwrap_or_else(|e| { + if e.kind == ErrorKind::ArgumentNotFound { + Vec::new() + } else { + e.exit() + } + }); + for cargo in normal_cargos + .into_iter() + .chain(subcommand_cargo.into_iter()) + { let mut cmd: String = "cargo ".into(); let cargo = cargo.trim_start(); // features are supported for the following