diff --git a/cli/src/main.rs b/cli/src/main.rs index cbcbb181..6e9aa552 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Context, Error, Result}; use clap::{App, AppSettings, Arg, SubCommand}; use glob::glob; +use std::collections::HashSet; use std::path::{Path, PathBuf}; use std::{env, fs, u64}; use tree_sitter::{ffi, Point}; @@ -257,6 +258,12 @@ fn run() -> Result<()> { .help("Check that highlighting captures conform strictly to standards") .long("check"), ) + .arg( + Arg::with_name("captures-path") + .help("Path to a file with captures") + .long("captures-path") + .takes_value(true), + ) .arg(&scope_arg) .arg(&time_arg) .arg(&quiet_arg) @@ -602,7 +609,22 @@ fn run() -> Result<()> { language_config.highlight_config(language, apply_all_captures)? { if should_check { - let names = highlight_config.nonconformant_capture_names(); + let names = if let Some(path) = matches.value_of("captures-path") { + let path = Path::new(path); + let file = fs::read_to_string(path)?; + let capture_names = file + .lines() + .filter_map(|line| { + if line.trim().is_empty() || line.trim().starts_with(';') { + return None; + } + line.split(';').next().map(|s| s.trim().trim_matches('"')) + }) + .collect::>(); + highlight_config.nonconformant_capture_names(&capture_names) + } else { + highlight_config.nonconformant_capture_names(&HashSet::new()) + }; if names.is_empty() { eprintln!("All highlight captures conform to standards."); } else { diff --git a/highlight/src/lib.rs b/highlight/src/lib.rs index 4e72e729..4e96fe41 100644 --- a/highlight/src/lib.rs +++ b/highlight/src/lib.rs @@ -390,12 +390,16 @@ impl HighlightConfiguration { // Return the list of this configuration's capture names that are neither present in the // list of predefined 'canonical' names nor start with an underscore (denoting 'private' captures // used as part of capture internals). - pub fn nonconformant_capture_names(&self) -> Vec<&String> { - return self - .names() + pub fn nonconformant_capture_names(&self, capture_names: &HashSet<&str>) -> Vec<&String> { + let capture_names = if capture_names.is_empty() { + &*STANDARD_CAPTURE_NAMES + } else { + &capture_names + }; + self.names() .iter() - .filter(|&n| !(n.starts_with('_') || STANDARD_CAPTURE_NAMES.contains(n.as_str()))) - .collect(); + .filter(|&n| !(n.starts_with('_') || capture_names.contains(n.as_str()))) + .collect() } }