From bd49fbab125199701b07065754f14a45472121f5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 6 Dec 2019 11:41:21 -0800 Subject: [PATCH] cli: Allow globs and exclusions (via '!' prefix) as args to `parse` --- Cargo.lock | 7 +++++++ cli/Cargo.toml | 13 +++++++------ cli/src/error.rs | 12 ++++++++++++ cli/src/main.rs | 43 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db092496..8d1e5e7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,6 +236,11 @@ dependencies = [ "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "idna" version = "0.1.5" @@ -750,6 +755,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -913,6 +919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" +"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index dded6821..06530168 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -19,19 +19,20 @@ name = "benchmark" harness = false [dependencies] -cc = "1.0" ansi_term = "0.11" -difference = "2.0" -lazy_static = "1.2.0" -smallbitvec = "2.3.0" +cc = "1.0" clap = "2.32" +difference = "2.0" dirs = "2.0.2" +glob = "0.3.0" +lazy_static = "1.2.0" libloading = "0.5" once_cell = "0.1.8" +regex = "1" +regex-syntax = "0.6.4" serde = "1.0" serde_derive = "1.0" -regex-syntax = "0.6.4" -regex = "1" +smallbitvec = "2.3.0" tiny_http = "0.6" webbrowser = "0.5.1" diff --git a/cli/src/error.rs b/cli/src/error.rs index b57f0dd5..73dcb732 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -93,6 +93,18 @@ impl From for Error { } } +impl From for Error { + fn from(error: glob::PatternError) -> Self { + Error::new(error.to_string()) + } +} + +impl From for Error { + fn from(error: glob::GlobError) -> Self { + Error::new(error.to_string()) + } +} + impl From for Error { fn from(error: regex_syntax::ast::Error) -> Self { Error::new(error.to_string()) diff --git a/cli/src/main.rs b/cli/src/main.rs index 94ec290a..f5d5d3ac 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,6 @@ use clap::{App, AppSettings, Arg, SubCommand}; use error::Error; +use glob::glob; use std::path::Path; use std::process::exit; use std::{env, fs, u64}; @@ -64,6 +65,7 @@ fn run() -> error::Result<()> { .arg(Arg::with_name("quiet").long("quiet").short("q")) .arg(Arg::with_name("time").long("time").short("t")) .arg(Arg::with_name("allow-cancellation").long("cancel")) + .arg(Arg::with_name("files-").long("cancel")) .arg(Arg::with_name("timeout").long("timeout").takes_value(true)) .arg( Arg::with_name("edits") @@ -198,16 +200,12 @@ fn run() -> error::Result<()> { let timeout = matches .value_of("timeout") .map_or(0, |t| u64::from_str_radix(t, 10).unwrap()); - let paths = matches - .values_of("path") - .unwrap() - .into_iter() - .collect::>(); + let paths = collect_paths(matches.values_of("path").unwrap())?; let max_path_length = paths.iter().map(|p| p.chars().count()).max().unwrap(); let mut has_error = false; loader.find_all_languages(&config.parser_directories)?; for path in paths { - let path = Path::new(path); + let path = Path::new(&path); let language = select_language(&mut loader, path, ¤t_dir, matches.value_of("scope"))?; has_error |= parse::parse_file_at_path( @@ -319,6 +317,39 @@ fn run() -> error::Result<()> { Ok(()) } +fn collect_paths<'a>(paths: impl Iterator) -> error::Result> { + let mut result = Vec::new(); + + let mut incorporate_path = |path: &str, positive| { + if positive { + result.push(path.to_string()); + } else { + if let Some(index) = result.iter().position(|p| p == path) { + result.remove(index); + } + } + }; + + for mut path in paths { + let mut positive = true; + if path.starts_with("!") { + positive = false; + path = path.trim_start_matches("!"); + } + + if Path::new(path).exists() { + incorporate_path(path, positive); + } else { + for path in glob(path)? { + if let Some(path) = path?.to_str() { + incorporate_path(path, positive); + } + } + } + } + Ok(result) +} + fn select_language( loader: &mut loader::Loader, path: &Path,