Merge pull request #2340 from tree-sitter/highlights-conformance
feat: add --check flag to `tree-sitter highlight`
This commit is contained in:
commit
2a277879ab
4 changed files with 100 additions and 2 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -859,8 +859,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter-highlight"
|
name = "tree-sitter-highlight"
|
||||||
version = "0.20.1"
|
version = "0.20.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
"regex",
|
"regex",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,11 @@ fn run() -> Result<()> {
|
||||||
.long("html")
|
.long("html")
|
||||||
.short("H"),
|
.short("H"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("check")
|
||||||
|
.help("Check that highlighting captures conform strictly to standards")
|
||||||
|
.long("check"),
|
||||||
|
)
|
||||||
.arg(&scope_arg)
|
.arg(&scope_arg)
|
||||||
.arg(&time_arg)
|
.arg(&time_arg)
|
||||||
.arg(&quiet_arg)
|
.arg(&quiet_arg)
|
||||||
|
|
@ -543,6 +548,7 @@ fn run() -> Result<()> {
|
||||||
let time = matches.is_present("time");
|
let time = matches.is_present("time");
|
||||||
let quiet = matches.is_present("quiet");
|
let quiet = matches.is_present("quiet");
|
||||||
let html_mode = quiet || matches.is_present("html");
|
let html_mode = quiet || matches.is_present("html");
|
||||||
|
let should_check = matches.is_present("check");
|
||||||
let paths = collect_paths(matches.value_of("paths-file"), matches.values_of("paths"))?;
|
let paths = collect_paths(matches.value_of("paths-file"), matches.values_of("paths"))?;
|
||||||
|
|
||||||
if html_mode && !quiet {
|
if html_mode && !quiet {
|
||||||
|
|
@ -573,6 +579,25 @@ fn run() -> Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(highlight_config) = language_config.highlight_config(language)? {
|
if let Some(highlight_config) = language_config.highlight_config(language)? {
|
||||||
|
if should_check {
|
||||||
|
let names = highlight_config.nonconformant_capture_names();
|
||||||
|
if names.is_empty() {
|
||||||
|
eprintln!("All highlight captures conform to standards.");
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"Non-standard highlight {} detected:",
|
||||||
|
if names.len() > 1 {
|
||||||
|
"captures"
|
||||||
|
} else {
|
||||||
|
"capture"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
for name in names {
|
||||||
|
eprintln!("* {}", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let source = fs::read(path)?;
|
let source = fs::read(path)?;
|
||||||
if html_mode {
|
if html_mode {
|
||||||
highlight::html(
|
highlight::html(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tree-sitter-highlight"
|
name = "tree-sitter-highlight"
|
||||||
description = "Library for performing syntax highlighting with Tree-sitter"
|
description = "Library for performing syntax highlighting with Tree-sitter"
|
||||||
version = "0.20.1"
|
version = "0.20.2"
|
||||||
authors = [
|
authors = [
|
||||||
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
|
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
|
||||||
"Tim Clem <timothy.clem@gmail.com>",
|
"Tim Clem <timothy.clem@gmail.com>",
|
||||||
|
|
@ -18,6 +18,7 @@ rust-version.workspace = true
|
||||||
crate-type = ["lib", "staticlib"]
|
crate-type = ["lib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
lazy_static = "1.2.0"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ pub mod c_lib;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub use c_lib as c;
|
pub use c_lib as c;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::{iter, mem, ops, str, usize};
|
use std::{iter, mem, ops, str, usize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -14,6 +16,64 @@ const CANCELLATION_CHECK_INTERVAL: usize = 100;
|
||||||
const BUFFER_HTML_RESERVE_CAPACITY: usize = 10 * 1024;
|
const BUFFER_HTML_RESERVE_CAPACITY: usize = 10 * 1024;
|
||||||
const BUFFER_LINES_RESERVE_CAPACITY: usize = 1000;
|
const BUFFER_LINES_RESERVE_CAPACITY: usize = 1000;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref STANDARD_CAPTURE_NAMES: HashSet<&'static str> = vec![
|
||||||
|
"attribute",
|
||||||
|
"carriage-return",
|
||||||
|
"comment",
|
||||||
|
"comment.documentation",
|
||||||
|
"constant",
|
||||||
|
"constant.builtin",
|
||||||
|
"constructor",
|
||||||
|
"constructor.builtin",
|
||||||
|
"embedded",
|
||||||
|
"error",
|
||||||
|
"escape",
|
||||||
|
"function",
|
||||||
|
"function.builtin",
|
||||||
|
"keyword",
|
||||||
|
"markup",
|
||||||
|
"markup.bold",
|
||||||
|
"markup.heading",
|
||||||
|
"markup.italic",
|
||||||
|
"markup.link",
|
||||||
|
"markup.link.url",
|
||||||
|
"markup.list",
|
||||||
|
"markup.list.checked",
|
||||||
|
"markup.list.numbered",
|
||||||
|
"markup.list.unchecked",
|
||||||
|
"markup.list.unnumbered",
|
||||||
|
"markup.quote",
|
||||||
|
"markup.raw",
|
||||||
|
"markup.raw.block",
|
||||||
|
"markup.raw.inline",
|
||||||
|
"markup.strikethrough",
|
||||||
|
"module",
|
||||||
|
"number",
|
||||||
|
"operator",
|
||||||
|
"property",
|
||||||
|
"property.builtin",
|
||||||
|
"punctuation",
|
||||||
|
"punctuation.bracket",
|
||||||
|
"punctuation.delimiter",
|
||||||
|
"punctuation.special",
|
||||||
|
"string",
|
||||||
|
"string.escape",
|
||||||
|
"string.regexp",
|
||||||
|
"string.special",
|
||||||
|
"string.special.symbol",
|
||||||
|
"tag",
|
||||||
|
"type",
|
||||||
|
"type.builtin",
|
||||||
|
"variable",
|
||||||
|
"variable.builtin",
|
||||||
|
"variable.member",
|
||||||
|
"variable.parameter",
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
/// Indicates which highlight should be applied to a region of source code.
|
/// Indicates which highlight should be applied to a region of source code.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Highlight(pub usize);
|
pub struct Highlight(pub usize);
|
||||||
|
|
@ -321,6 +381,17 @@ impl HighlightConfiguration {
|
||||||
best_index.map(Highlight)
|
best_index.map(Highlight)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
.iter()
|
||||||
|
.filter(|&n| !(n.starts_with('_') || STANDARD_CAPTURE_NAMES.contains(n.as_str())))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> HighlightIterLayer<'a> {
|
impl<'a> HighlightIterLayer<'a> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue