diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..2bf706c3 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# initial cargo fmt +cc41c3803b20b79147fa606f950658bc12e50dc2 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b0e19484..2a6382ac 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,7 +20,11 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: stable minus 2 releases # MSRV policy = last three versions of stable - components: clippy + components: clippy, rustfmt + + - name: Run cargo fmt --check + run: cargo fmt -- --check + - name: Run cargo clippy run: | # Must run before `cargo check` until we use Rust 1.52 diff --git a/benches/highlight_utils/mod.rs b/benches/highlight_utils/mod.rs index 3883ff72..2170a166 100644 --- a/benches/highlight_utils/mod.rs +++ b/benches/highlight_utils/mod.rs @@ -1,9 +1,14 @@ use syntect::easy::HighlightLines; -use syntect::highlighting::{Theme}; +use syntect::highlighting::Theme; use syntect::parsing::{SyntaxReference, SyntaxSet}; /// Common helper for benchmarking highlighting. -pub fn do_highlight(s: &str, syntax_set: &SyntaxSet, syntax: &SyntaxReference, theme: &Theme) -> usize { +pub fn do_highlight( + s: &str, + syntax_set: &SyntaxSet, + syntax: &SyntaxReference, + theme: &Theme, +) -> usize { let mut h = HighlightLines::new(syntax, theme); let mut count = 0; for line in s.lines() { diff --git a/benches/highlighting.rs b/benches/highlighting.rs index a9389443..1b020958 100644 --- a/benches/highlighting.rs +++ b/benches/highlighting.rs @@ -1,8 +1,8 @@ -use criterion::{Bencher, Criterion, criterion_group, criterion_main}; -use syntect::parsing::{SyntaxSet, ScopeStack}; -use syntect::highlighting::{ThemeSet}; -use syntect::html::highlighted_html_for_string; +use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use std::str::FromStr; +use syntect::highlighting::ThemeSet; +use syntect::html::highlighted_html_for_string; +use syntect::parsing::{ScopeStack, SyntaxSet}; mod highlight_utils; mod utils; @@ -17,18 +17,14 @@ fn highlight_file(b: &mut Bencher, file: &str) { let syntax = ss.find_syntax_for_file(path).unwrap().unwrap(); let s = std::fs::read_to_string(path).unwrap(); - b.iter(|| { - highlight_utils::do_highlight(&s, &ss, syntax, &ts.themes["base16-ocean.dark"]) - }); + b.iter(|| highlight_utils::do_highlight(&s, &ss, syntax, &ts.themes["base16-ocean.dark"])); } fn stack_matching(b: &mut Bencher) { let s = "source.js meta.group.js meta.group.js meta.block.js meta.function-call.method.js meta.group.js meta.object-literal.js meta.block.js meta.function-call.method.js meta.group.js variable.other.readwrite.js"; let stack = ScopeStack::from_str(s).unwrap(); let selector = ScopeStack::from_str("source meta.function-call.method").unwrap(); - b.iter(|| { - selector.does_match(stack.as_slice()) - }); + b.iter(|| selector.does_match(stack.as_slice())); } fn highlight_html(b: &mut Bencher) { @@ -39,9 +35,7 @@ fn highlight_html(b: &mut Bencher) { let syntax = ss.find_syntax_for_file(path).unwrap().unwrap(); let s = std::fs::read_to_string(path).unwrap(); - b.iter(|| { - highlighted_html_for_string(&s, &ss, syntax, &ts.themes["base16-ocean.dark"]) - }); + b.iter(|| highlighted_html_for_string(&s, &ss, syntax, &ts.themes["base16-ocean.dark"])); } fn highlighting_benchmark(c: &mut Criterion) { diff --git a/benches/load_and_highlight.rs b/benches/load_and_highlight.rs index 87a7015f..b8c80ca6 100644 --- a/benches/load_and_highlight.rs +++ b/benches/load_and_highlight.rs @@ -25,7 +25,7 @@ fn load_and_highlight_benchmark(c: &mut criterion::Criterion) { "highlight_test.erb", "InspiredGitHub.tmTheme", "Ruby.sublime-syntax", - "parser.rs" + "parser.rs", ] { group.bench_with_input(format!("\"{}\"", input), input, |b, s| run(b, s)); } diff --git a/benches/loading.rs b/benches/loading.rs index b4aa24b8..a7f4c096 100644 --- a/benches/loading.rs +++ b/benches/loading.rs @@ -1,24 +1,17 @@ -use criterion::{Bencher, Criterion, criterion_group, criterion_main}; -use syntect::parsing::{SyntaxSet, SyntaxSetBuilder}; +use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use syntect::highlighting::ThemeSet; - +use syntect::parsing::{SyntaxSet, SyntaxSetBuilder}; fn bench_load_internal_dump(b: &mut Bencher) { - b.iter(|| { - SyntaxSet::load_defaults_newlines() - }); + b.iter(|| SyntaxSet::load_defaults_newlines()); } fn bench_load_internal_themes(b: &mut Bencher) { - b.iter(|| { - ThemeSet::load_defaults() - }); + b.iter(|| ThemeSet::load_defaults()); } fn bench_load_theme(b: &mut Bencher) { - b.iter(|| { - ThemeSet::get_theme("testdata/spacegray/base16-ocean.dark.tmTheme") - }); + b.iter(|| ThemeSet::get_theme("testdata/spacegray/base16-ocean.dark.tmTheme")); } fn bench_add_from_folder(b: &mut Bencher) { @@ -38,7 +31,9 @@ fn bench_link_syntaxes(b: &mut Bencher) { fn bench_from_dump_file(b: &mut Bencher) { b.iter(|| { - let _: SyntaxSet = syntect::dumps::from_uncompressed_dump_file("assets/default_newlines.packdump").unwrap(); + let _: SyntaxSet = + syntect::dumps::from_uncompressed_dump_file("assets/default_newlines.packdump") + .unwrap(); }) } diff --git a/benches/parsing.rs b/benches/parsing.rs index 58790201..e42075ae 100644 --- a/benches/parsing.rs +++ b/benches/parsing.rs @@ -1,4 +1,4 @@ -use criterion::{Bencher, Criterion, criterion_group, criterion_main}; +use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use std::time::Duration; use syntect::parsing::{ParseState, SyntaxReference, SyntaxSet}; diff --git a/examples/gendata.rs b/examples/gendata.rs index 47dd6a8b..fc650938 100644 --- a/examples/gendata.rs +++ b/examples/gendata.rs @@ -5,29 +5,32 @@ //! //! An example of how this script is used to generate the pack files included //! with syntect can be found under `make packs` in the Makefile. -use syntect::parsing::SyntaxSetBuilder; -use syntect::highlighting::ThemeSet; -use syntect::dumps::*; use std::env; +use syntect::dumps::*; +use syntect::highlighting::ThemeSet; +use syntect::parsing::SyntaxSetBuilder; fn usage_and_exit() -> ! { - println!("USAGE: gendata synpack source-dir \ + println!( + "USAGE: gendata synpack source-dir \ newlines.packdump nonewlines.packdump \ [metadata.packdump] [metadata extra-source-dir]\n \ - gendata themepack source-dir themepack.themedump"); + gendata themepack source-dir themepack.themedump" + ); ::std::process::exit(2); } fn main() { let mut a = env::args().skip(1); match (a.next(), a.next(), a.next(), a.next(), a.next(), a.next()) { - (Some(ref cmd), - Some(ref package_dir), - Some(ref packpath_newlines), - Some(ref packpath_nonewlines), - ref _option_metapath, - ref _option_metasource, - ) if cmd == "synpack" => { + ( + Some(ref cmd), + Some(ref package_dir), + Some(ref packpath_newlines), + Some(ref packpath_nonewlines), + ref _option_metapath, + ref _option_metasource, + ) if cmd == "synpack" => { let mut builder = SyntaxSetBuilder::new(); builder.add_plain_text_syntax(); builder.add_from_folder(package_dir, true).unwrap(); @@ -36,12 +39,16 @@ fn main() { let mut builder_nonewlines = SyntaxSetBuilder::new(); builder_nonewlines.add_plain_text_syntax(); - builder_nonewlines.add_from_folder(package_dir, false).unwrap(); + builder_nonewlines + .add_from_folder(package_dir, false) + .unwrap(); #[cfg(feature = "metadata")] { if let Some(metasource) = _option_metasource { - builder_nonewlines.add_from_folder(metasource, false).unwrap(); + builder_nonewlines + .add_from_folder(metasource, false) + .unwrap(); } } @@ -54,7 +61,6 @@ fn main() { dump_to_file(&ss_nonewlines.metadata(), metapath).unwrap(); } } - } (Some(ref s), Some(ref theme_dir), Some(ref packpath), ..) if s == "themepack" => { let ts = ThemeSet::load_from_folder(theme_dir).unwrap(); diff --git a/examples/latex-demo.rs b/examples/latex-demo.rs index d29cdc2e..d40dd2ff 100644 --- a/examples/latex-demo.rs +++ b/examples/latex-demo.rs @@ -1,7 +1,7 @@ use syntect::easy::HighlightLines; +use syntect::highlighting::{Style, ThemeSet}; use syntect::parsing::SyntaxSet; -use syntect::highlighting::{ThemeSet,Style}; -use syntect::util::{as_latex_escaped,LinesWithEndings}; +use syntect::util::{as_latex_escaped, LinesWithEndings}; fn main() { // Load these once at the start of your program @@ -12,7 +12,8 @@ fn main() { let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}\n"; let mut h = HighlightLines::new(syntax, &ts.themes["InspiredGitHub"]); - for line in LinesWithEndings::from(s) { // LinesWithEndings enables use of newlines mode + for line in LinesWithEndings::from(s) { + // LinesWithEndings enables use of newlines mode let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap(); let escaped = as_latex_escaped(&ranges[..]); println!("\n{:?}", line); diff --git a/examples/parsyncat.rs b/examples/parsyncat.rs index 7bbfefb7..4f9aa39e 100644 --- a/examples/parsyncat.rs +++ b/examples/parsyncat.rs @@ -1,13 +1,13 @@ //! Highlights the files given on the command line, in parallel. //! Prints the highlighted output to stdout. -use syntect::parsing::SyntaxSet; -use syntect::highlighting::{ThemeSet, Style}; -use syntect::easy::HighlightFile; use rayon::prelude::*; +use syntect::easy::HighlightFile; +use syntect::highlighting::{Style, ThemeSet}; +use syntect::parsing::SyntaxSet; use std::fs::File; -use std::io::{BufReader, BufRead}; +use std::io::{BufRead, BufReader}; fn main() { let files: Vec = std::env::args().skip(1).collect(); @@ -21,7 +21,8 @@ fn main() { let theme_set = ThemeSet::load_defaults(); // We first collect the contents of the files... - let contents: Vec> = files.par_iter() + let contents: Vec> = files + .par_iter() .map(|filename| { let mut lines = Vec::new(); // We use `String::new()` and `read_line()` instead of `BufRead::lines()` @@ -37,7 +38,8 @@ fn main() { .collect(); // ...so that the highlighted regions have valid lifetimes... - let regions: Vec> = files.par_iter() + let regions: Vec> = files + .par_iter() .zip(&contents) .map(|(filename, contents)| { let mut regions = Vec::new(); @@ -45,7 +47,11 @@ fn main() { let mut highlighter = HighlightFile::new(filename, &syntax_set, theme).unwrap(); for line in contents { - for region in highlighter.highlight_lines.highlight_line(line, &syntax_set).unwrap() { + for region in highlighter + .highlight_lines + .highlight_line(line, &syntax_set) + .unwrap() + { regions.push(region); } } @@ -56,6 +62,9 @@ fn main() { // ...and then print them all out. for file_regions in regions { - print!("{}", syntect::util::as_24_bit_terminal_escaped(&file_regions[..], true)); + print!( + "{}", + syntect::util::as_24_bit_terminal_escaped(&file_regions[..], true) + ); } } diff --git a/examples/syncat.rs b/examples/syncat.rs index d21795bc..05a97401 100644 --- a/examples/syncat.rs +++ b/examples/syncat.rs @@ -2,11 +2,11 @@ use getopts::Options; use std::borrow::Cow; use std::io::BufRead; use std::path::Path; +use syntect::dumps::{dump_to_file, from_dump_file}; +use syntect::easy::HighlightFile; +use syntect::highlighting::{Style, Theme, ThemeSet}; use syntect::parsing::SyntaxSet; -use syntect::highlighting::{Theme, ThemeSet, Style}; use syntect::util::as_24_bit_terminal_escaped; -use syntect::easy::HighlightFile; -use syntect::dumps::{from_dump_file, dump_to_file}; fn load_theme(tm_file: &str, enable_caching: bool) -> Theme { let tm_path = Path::new(tm_file); @@ -30,16 +30,35 @@ fn main() { let args: Vec = std::env::args().collect(); let mut opts = Options::new(); opts.optflag("l", "list-file-types", "Lists supported file types"); - opts.optflag("L", "list-embedded-themes", "Lists themes present in the executable"); + opts.optflag( + "L", + "list-embedded-themes", + "Lists themes present in the executable", + ); opts.optopt("t", "theme-file", "THEME_FILE", "Theme file to use. May be a path, or an embedded theme. Embedded themes will take precendence. Default: base16-ocean.dark"); - opts.optopt("s", "extra-syntaxes", "SYNTAX_FOLDER", "Additional folder to search for .sublime-syntax files in."); - opts.optflag("e", "no-default-syntaxes", "Doesn't load default syntaxes, intended for use with --extra-syntaxes."); - opts.optflag("n", "no-newlines", "Uses the no newlines versions of syntaxes and dumps."); + opts.optopt( + "s", + "extra-syntaxes", + "SYNTAX_FOLDER", + "Additional folder to search for .sublime-syntax files in.", + ); + opts.optflag( + "e", + "no-default-syntaxes", + "Doesn't load default syntaxes, intended for use with --extra-syntaxes.", + ); + opts.optflag( + "n", + "no-newlines", + "Uses the no newlines versions of syntaxes and dumps.", + ); opts.optflag("c", "cache-theme", "Cache the parsed theme file."); let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - Err(f) => { panic!("{}", f.to_string()) } + Ok(m) => m, + Err(f) => { + panic!("{}", f.to_string()) + } }; let no_newlines = matches.opt_present("no-newlines"); @@ -65,25 +84,27 @@ fn main() { for sd in ss.syntaxes() { println!("- {} (.{})", sd.name, sd.file_extensions.join(", .")); } - } else if matches.opt_present("list-embedded-themes") { println!("Embedded themes:"); for t in ts.themes.keys() { println!("- {}", t); } - } else if matches.free.is_empty() { let brief = format!("USAGE: {} [options] FILES", args[0]); println!("{}", opts.usage(&brief)); - } else { - let theme_file : String = matches.opt_str("theme-file") + let theme_file: String = matches + .opt_str("theme-file") .unwrap_or_else(|| "base16-ocean.dark".to_string()); - let theme = ts.themes.get(&theme_file) + let theme = ts + .themes + .get(&theme_file) .map(Cow::Borrowed) - .unwrap_or_else(|| Cow::Owned(load_theme(&theme_file, matches.opt_present("cache-theme")))); + .unwrap_or_else(|| { + Cow::Owned(load_theme(&theme_file, matches.opt_present("cache-theme"))) + }); for src in &matches.free[..] { if matches.free.len() > 1 { @@ -103,7 +124,10 @@ fn main() { } { - let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss).unwrap(); + let regions: Vec<(Style, &str)> = highlighter + .highlight_lines + .highlight_line(&line, &ss) + .unwrap(); print!("{}", as_24_bit_terminal_escaped(®ions[..], true)); } line.clear(); diff --git a/examples/synhtml-css-classes.rs b/examples/synhtml-css-classes.rs index fb7289c2..24b0db9a 100644 --- a/examples/synhtml-css-classes.rs +++ b/examples/synhtml-css-classes.rs @@ -11,11 +11,10 @@ //! mode. use syntect::highlighting::ThemeSet; use syntect::html::css_for_theme_with_class_style; -use syntect::html::{ClassedHTMLGenerator, ClassStyle}; +use syntect::html::{ClassStyle, ClassedHTMLGenerator}; use syntect::parsing::SyntaxSet; use syntect::util::LinesWithEndings; - use std::fs::File; use std::io::{BufWriter, Write}; use std::path::Path; @@ -25,7 +24,7 @@ fn main() -> Result<(), std::io::Error> { // generate html let ss = SyntaxSet::load_defaults_newlines(); - let html_file = File::create(Path::new("synhtml-css-classes.html"))?; + let html_file = File::create(Path::new("synhtml-css-classes.html"))?; let mut html = BufWriter::new(&html_file); // write html header @@ -33,7 +32,10 @@ fn main() -> Result<(), std::io::Error> { writeln!(html, "")?; writeln!(html, " ")?; writeln!(html, " synhtml-css-classes.rs")?; - writeln!(html, " ")?; + writeln!( + html, + " " + )?; writeln!(html, " ")?; writeln!(html, " ")?; @@ -44,9 +46,12 @@ fn main() { }"; let sr_rs = ss.find_syntax_by_extension("rs").unwrap(); - let mut rs_html_generator = ClassedHTMLGenerator::new_with_class_style(sr_rs, &ss, ClassStyle::Spaced); + let mut rs_html_generator = + ClassedHTMLGenerator::new_with_class_style(sr_rs, &ss, ClassStyle::Spaced); for line in LinesWithEndings::from(code_rs) { - rs_html_generator.parse_html_for_line_which_includes_newline(line).unwrap(); + rs_html_generator + .parse_html_for_line_which_includes_newline(line) + .unwrap(); } let html_rs = rs_html_generator.finalize(); @@ -62,9 +67,12 @@ int main() { }"; let sr_cpp = ss.find_syntax_by_extension("cpp").unwrap(); - let mut cpp_html_generator = ClassedHTMLGenerator::new_with_class_style(sr_cpp, &ss, ClassStyle::Spaced); + let mut cpp_html_generator = + ClassedHTMLGenerator::new_with_class_style(sr_cpp, &ss, ClassStyle::Spaced); for line in LinesWithEndings::from(code_cpp) { - cpp_html_generator.parse_html_for_line_which_includes_newline(line).unwrap(); + cpp_html_generator + .parse_html_for_line_which_includes_newline(line) + .unwrap(); } let html_cpp = cpp_html_generator.finalize(); diff --git a/examples/synhtml.rs b/examples/synhtml.rs index bc23c70c..f7c8be47 100644 --- a/examples/synhtml.rs +++ b/examples/synhtml.rs @@ -1,8 +1,8 @@ //! Prints highlighted HTML for a file to stdout. //! Basically just wraps a body around `highlighted_html_for_file` -use syntect::parsing::SyntaxSet; use syntect::highlighting::{Color, ThemeSet}; use syntect::html::highlighted_html_for_file; +use syntect::parsing::SyntaxSet; fn main() { let ss = SyntaxSet::load_defaults_newlines(); @@ -19,10 +19,16 @@ fn main() { font-size:13px; font-family: Consolas, \"Liberation Mono\", Menlo, Courier, monospace; }"; - println!("{}", &args[1], style); + println!( + "{}", + &args[1], style + ); let theme = &ts.themes["base16-ocean.dark"]; let c = theme.settings.background.unwrap_or(Color::WHITE); - println!("\n", c.r, c.g, c.b); + println!( + "\n", + c.r, c.g, c.b + ); let html = highlighted_html_for_file(&args[1], &ss, theme).unwrap(); println!("{}", html); println!(""); diff --git a/examples/synstats.rs b/examples/synstats.rs index 8d455398..d6dc3025 100644 --- a/examples/synstats.rs +++ b/examples/synstats.rs @@ -6,15 +6,15 @@ //! Another thing it does that other line count programs can't always //! do is properly count comments in embedded syntaxes. For example //! JS, CSS and Ruby comments embedded in ERB files. -use syntect::parsing::{SyntaxSet, ParseState, ScopeStackOp, ScopeStack}; +use syntect::easy::ScopeRegionIterator; use syntect::highlighting::{ScopeSelector, ScopeSelectors}; -use syntect::easy::{ScopeRegionIterator}; +use syntect::parsing::{ParseState, ScopeStack, ScopeStackOp, SyntaxSet}; -use std::path::Path; -use std::io::{BufRead, BufReader}; use std::fs::File; -use walkdir::{DirEntry, WalkDir}; +use std::io::{BufRead, BufReader}; +use std::path::Path; use std::str::FromStr; +use walkdir::{DirEntry, WalkDir}; #[derive(Debug)] struct Selectors { @@ -28,9 +28,15 @@ impl Default for Selectors { fn default() -> Selectors { Selectors { comment: ScopeSelector::from_str("comment - comment.block.attribute").unwrap(), - doc_comment: ScopeSelectors::from_str("comment.line.documentation, comment.block.documentation").unwrap(), + doc_comment: ScopeSelectors::from_str( + "comment.line.documentation, comment.block.documentation", + ) + .unwrap(), function: ScopeSelector::from_str("entity.name.function").unwrap(), - types: ScopeSelectors::from_str("entity.name.class, entity.name.struct, entity.name.enum, entity.name.type").unwrap(), + types: ScopeSelectors::from_str( + "entity.name.class, entity.name.struct, entity.name.enum, entity.name.type", + ) + .unwrap(), } } } @@ -57,28 +63,58 @@ fn print_stats(stats: &Stats) { println!("File count: {:>6}", stats.files); println!("Total characters: {:>6}", stats.chars); println!(); - println!("Function count: {:>6}", stats.functions); + println!( + "Function count: {:>6}", + stats.functions + ); println!("Type count (structs, enums, classes): {:>6}", stats.types); println!(); - println!("Code lines (traditional SLOC): {:>6}", stats.code_lines); + println!( + "Code lines (traditional SLOC): {:>6}", + stats.code_lines + ); println!("Total lines (w/ comments & blanks): {:>6}", stats.lines); - println!("Comment lines (comment but no code): {:>6}", stats.comment_lines); - println!("Blank lines (lines-blank-comment): {:>6}", stats.lines-stats.code_lines-stats.comment_lines); + println!( + "Comment lines (comment but no code): {:>6}", + stats.comment_lines + ); + println!( + "Blank lines (lines-blank-comment): {:>6}", + stats.lines - stats.code_lines - stats.comment_lines + ); println!(); - println!("Lines with a documentation comment: {:>6}", stats.doc_comment_lines); - println!("Total words written in doc comments: {:>6}", stats.doc_comment_words); - println!("Total words written in all comments: {:>6}", stats.comment_words); - println!("Characters of comment: {:>6}", stats.comment_chars); + println!( + "Lines with a documentation comment: {:>6}", + stats.doc_comment_lines + ); + println!( + "Total words written in doc comments: {:>6}", + stats.doc_comment_words + ); + println!( + "Total words written in all comments: {:>6}", + stats.comment_words + ); + println!( + "Characters of comment: {:>6}", + stats.comment_chars + ); } fn is_ignored(entry: &DirEntry) -> bool { - entry.file_name() - .to_str() - .map(|s| s.starts_with('.') && s.len() > 1 || s.ends_with(".md")) - .unwrap_or(false) + entry + .file_name() + .to_str() + .map(|s| s.starts_with('.') && s.len() > 1 || s.ends_with(".md")) + .unwrap_or(false) } -fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stack: &mut ScopeStack, stats: &mut Stats) { +fn count_line( + ops: &[(usize, ScopeStackOp)], + line: &str, + stack: &mut ScopeStack, + stats: &mut Stats, +) { stats.lines += 1; let mut line_has_comment = false; @@ -86,12 +122,29 @@ fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stack: &mut ScopeStack, let mut line_has_code = false; for (s, op) in ScopeRegionIterator::new(ops, line) { stack.apply(op).unwrap(); - if s.is_empty() { // in this case we don't care about blank tokens + if s.is_empty() { + // in this case we don't care about blank tokens continue; } - if stats.selectors.comment.does_match(stack.as_slice()).is_some() { - let words = s.split_whitespace().filter(|w| w.chars().all(|c| c.is_alphanumeric() || c == '.' || c == '\'')).count(); - if stats.selectors.doc_comment.does_match(stack.as_slice()).is_some() { + if stats + .selectors + .comment + .does_match(stack.as_slice()) + .is_some() + { + let words = s + .split_whitespace() + .filter(|w| { + w.chars() + .all(|c| c.is_alphanumeric() || c == '.' || c == '\'') + }) + .count(); + if stats + .selectors + .doc_comment + .does_match(stack.as_slice()) + .is_some() + { line_has_doc_comment = true; stats.doc_comment_words += words; } @@ -101,7 +154,12 @@ fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stack: &mut ScopeStack, } else if !s.chars().all(|c| c.is_whitespace()) { line_has_code = true; } - if stats.selectors.function.does_match(stack.as_slice()).is_some() { + if stats + .selectors + .function + .does_match(stack.as_slice()) + .is_some() + { stats.functions += 1; } if stats.selectors.types.does_match(stack.as_slice()).is_some() { @@ -122,7 +180,7 @@ fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stack: &mut ScopeStack, fn count(ss: &SyntaxSet, path: &Path, stats: &mut Stats) { let syntax = match ss.find_syntax_for_file(path).unwrap_or(None) { Some(syntax) => syntax, - None => return + None => return, }; stats.files += 1; let mut state = ParseState::new(syntax); @@ -145,11 +203,7 @@ fn main() { let ss = SyntaxSet::load_defaults_newlines(); // note we load the version with newlines let args: Vec = std::env::args().collect(); - let path = if args.len() < 2 { - "." - } else { - &args[1] - }; + let path = if args.len() < 2 { "." } else { &args[1] }; println!("################## Files ###################"); let mut stats = Stats::default(); diff --git a/src/dumps.rs b/src/dumps.rs index 1fe0d8e5..cb3be70d 100644 --- a/src/dumps.rs +++ b/src/dumps.rs @@ -12,31 +12,31 @@ //! [`dump_to_uncompressed_file`]: fn.dump_to_uncompressed_file.html //! [`ThemeSet`]: ../highlighting/struct.ThemeSet.html //! [`dump_to_file`]: fn.dump_to_file.html -use bincode::Result; +#[cfg(feature = "default-themes")] +use crate::highlighting::ThemeSet; +#[cfg(feature = "default-syntaxes")] +use crate::parsing::SyntaxSet; #[cfg(feature = "dump-load")] use bincode::deserialize_from; #[cfg(feature = "dump-create")] use bincode::serialize_into; -use std::fs::File; +use bincode::Result; #[cfg(feature = "dump-load")] -use std::io::BufRead; -#[cfg(feature = "dump-create")] -use std::io::{BufWriter, Write}; -#[cfg(feature = "default-syntaxes")] -use crate::parsing::SyntaxSet; -#[cfg(feature = "default-themes")] -use crate::highlighting::ThemeSet; -use std::path::Path; +use flate2::bufread::ZlibDecoder; #[cfg(feature = "dump-create")] use flate2::write::ZlibEncoder; -#[cfg(feature = "dump-load")] -use flate2::bufread::ZlibDecoder; #[cfg(feature = "dump-create")] use flate2::Compression; +#[cfg(feature = "dump-load")] +use serde::de::DeserializeOwned; #[cfg(feature = "dump-create")] use serde::ser::Serialize; +use std::fs::File; #[cfg(feature = "dump-load")] -use serde::de::DeserializeOwned; +use std::io::BufRead; +#[cfg(feature = "dump-create")] +use std::io::{BufWriter, Write}; +use std::path::Path; /// Dumps an object to the given writer in a compressed binary format /// @@ -117,7 +117,11 @@ pub fn from_uncompressed_data(v: &[u8]) -> Result { /// Private low level helper function used to implement the public API. #[cfg(feature = "dump-create")] -fn serialize_to_writer_impl(to_dump: &T, output: W, use_compression: bool) -> Result<()> { +fn serialize_to_writer_impl( + to_dump: &T, + output: W, + use_compression: bool, +) -> Result<()> { if use_compression { let mut encoder = ZlibEncoder::new(output, Compression::best()); serialize_into(&mut encoder, to_dump) @@ -128,7 +132,10 @@ fn serialize_to_writer_impl(to_dump: &T, output: W, use_ /// Private low level helper function used to implement the public API. #[cfg(feature = "dump-load")] -fn deserialize_from_reader_impl(input: R, use_compression: bool) -> Result { +fn deserialize_from_reader_impl( + input: R, + use_compression: bool, +) -> Result { if use_compression { let mut decoder = ZlibDecoder::new(input); deserialize_from(&mut decoder) @@ -159,10 +166,11 @@ impl SyntaxSet { /// [`load_defaults_newlines`]: #method.load_defaults_nonewlines /// [`SyntaxSetBuilder::add_from_folder`]: struct.SyntaxSetBuilder.html#method.add_from_folder pub fn load_defaults_nonewlines() -> SyntaxSet { - #[cfg(feature = "metadata")] { - let mut ps: SyntaxSet = from_uncompressed_data(include_bytes!("../assets/default_nonewlines.packdump")).unwrap(); + let mut ps: SyntaxSet = + from_uncompressed_data(include_bytes!("../assets/default_nonewlines.packdump")) + .unwrap(); let metadata = from_binary(include_bytes!("../assets/default_metadata.packdump")); ps.metadata = metadata; ps @@ -180,10 +188,11 @@ impl SyntaxSet { /// /// [`load_defaults_nonewlines`]: #method.load_defaults_nonewlines pub fn load_defaults_newlines() -> SyntaxSet { - #[cfg(feature = "metadata")] { - let mut ps: SyntaxSet = from_uncompressed_data(include_bytes!("../assets/default_newlines.packdump")).unwrap(); + let mut ps: SyntaxSet = + from_uncompressed_data(include_bytes!("../assets/default_newlines.packdump")) + .unwrap(); let metadata = from_binary(include_bytes!("../assets/default_metadata.packdump")); ps.metadata = metadata; ps @@ -210,7 +219,12 @@ impl ThemeSet { #[cfg(test)] mod tests { - #[cfg(all(feature = "yaml-load", feature = "dump-create", feature = "dump-load", feature = "parsing"))] + #[cfg(all( + feature = "yaml-load", + feature = "dump-create", + feature = "dump-load", + feature = "parsing" + ))] #[test] fn can_dump_and_load() { use super::*; @@ -232,12 +246,16 @@ mod tests { use crate::parsing::SyntaxSetBuilder; let mut builder1 = SyntaxSetBuilder::new(); - builder1.add_from_folder("testdata/Packages", false).unwrap(); + builder1 + .add_from_folder("testdata/Packages", false) + .unwrap(); let ss1 = builder1.build(); let bin1 = dump_binary(&ss1); let mut builder2 = SyntaxSetBuilder::new(); - builder2.add_from_folder("testdata/Packages", false).unwrap(); + builder2 + .add_from_folder("testdata/Packages", false) + .unwrap(); let ss2 = builder2.build(); let bin2 = dump_binary(&ss2); // This is redundant, but assert_eq! can be really slow on a large diff --git a/src/easy.rs b/src/easy.rs index 012e8ccc..c1b599cc 100644 --- a/src/easy.rs +++ b/src/easy.rs @@ -2,11 +2,11 @@ //! files without caring about intermediate semantic representation //! and caching. +use crate::highlighting::{HighlightIterator, HighlightState, Highlighter, Style, Theme}; +use crate::parsing::{ParseState, ScopeStack, ScopeStackOp, SyntaxReference, SyntaxSet}; use crate::Error; -use crate::parsing::{ScopeStack, ParseState, SyntaxReference, SyntaxSet, ScopeStackOp}; -use crate::highlighting::{Highlighter, HighlightState, HighlightIterator, Theme, Style}; -use std::io::{self, BufReader}; use std::fs::File; +use std::io::{self, BufReader}; use std::path::Path; // use util::debug_print_ops; @@ -57,13 +57,25 @@ impl<'a> HighlightLines<'a> { } } - #[deprecated(since="5.0.0", note="Renamed to `highlight_line` to make it clear it should be passed a single line at a time")] - pub fn highlight<'b>(&mut self, line: &'b str, syntax_set: &SyntaxSet) -> Vec<(Style, &'b str)> { - self.highlight_line(line, syntax_set).expect("`highlight` is deprecated, use `highlight_line` instead") + #[deprecated( + since = "5.0.0", + note = "Renamed to `highlight_line` to make it clear it should be passed a single line at a time" + )] + pub fn highlight<'b>( + &mut self, + line: &'b str, + syntax_set: &SyntaxSet, + ) -> Vec<(Style, &'b str)> { + self.highlight_line(line, syntax_set) + .expect("`highlight` is deprecated, use `highlight_line` instead") } /// Highlights a line of a file - pub fn highlight_line<'b>(&mut self, line: &'b str, syntax_set: &SyntaxSet) -> Result, Error> { + pub fn highlight_line<'b>( + &mut self, + line: &'b str, + syntax_set: &SyntaxSet, + ) -> Result, Error> { // println!("{}", self.highlight_state.path); let ops = self.parse_state.parse_line(line, syntax_set)?; // use util::debug_print_ops; @@ -142,13 +154,15 @@ impl<'a> HighlightFile<'a> { /// println!("{}", as_24_bit_terminal_escaped(®ions[..], true)); /// } /// ``` - pub fn new>(path_obj: P, - ss: &SyntaxSet, - theme: &'a Theme) - -> io::Result> { + pub fn new>( + path_obj: P, + ss: &SyntaxSet, + theme: &'a Theme, + ) -> io::Result> { let path: &Path = path_obj.as_ref(); let f = File::open(path)?; - let syntax = ss.find_syntax_for_file(path)? + let syntax = ss + .find_syntax_for_file(path)? .unwrap_or_else(|| ss.find_syntax_plain_text()); Ok(HighlightFile { @@ -260,9 +274,9 @@ impl<'a> Iterator for ScopeRegionIterator<'a> { #[cfg(test)] mod tests { use super::*; - use crate::parsing::{SyntaxSet, ParseState, ScopeStack}; #[cfg(feature = "default-themes")] use crate::highlighting::ThemeSet; + use crate::parsing::{ParseState, ScopeStack, SyntaxSet}; use std::str::FromStr; #[cfg(all(feature = "default-syntaxes", feature = "default-themes"))] @@ -272,7 +286,9 @@ mod tests { let ts = ThemeSet::load_defaults(); let syntax = ss.find_syntax_by_extension("rs").unwrap(); let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]); - let ranges = h.highlight_line("pub struct Wow { hi: u64 }", &ss).expect("#[cfg(test)]"); + let ranges = h + .highlight_line("pub struct Wow { hi: u64 }", &ss) + .expect("#[cfg(test)]"); assert!(ranges.len() > 4); } @@ -281,10 +297,12 @@ mod tests { fn can_highlight_file() { let ss = SyntaxSet::load_defaults_nonewlines(); let ts = ThemeSet::load_defaults(); - HighlightFile::new("testdata/highlight_test.erb", - &ss, - &ts.themes["base16-ocean.dark"]) - .unwrap(); + HighlightFile::new( + "testdata/highlight_test.erb", + &ss, + &ts.themes["base16-ocean.dark"], + ) + .unwrap(); } #[cfg(feature = "default-syntaxes")] @@ -299,11 +317,15 @@ mod tests { let mut token_count = 0; for (s, op) in ScopeRegionIterator::new(&ops, line) { stack.apply(op).expect("#[cfg(test)]"); - if s.is_empty() { // in this case we don't care about blank tokens + if s.is_empty() { + // in this case we don't care about blank tokens continue; } if token_count == 1 { - assert_eq!(stack, ScopeStack::from_str("source.ruby keyword.operator.assignment.ruby").unwrap()); + assert_eq!( + stack, + ScopeStack::from_str("source.ruby keyword.operator.assignment.ruby").unwrap() + ); assert_eq!(s, "="); } token_count += 1; diff --git a/src/highlighting/highlighter.rs b/src/highlighting/highlighter.rs index 573feccb..94f808a3 100644 --- a/src/highlighting/highlighter.rs +++ b/src/highlighting/highlighter.rs @@ -6,10 +6,12 @@ use std::iter::Iterator; use std::ops::Range; -use crate::parsing::{Scope, ScopeStack, BasicScopeStackOp, ScopeStackOp, MatchPower, ATOM_LEN_BITS}; use super::selector::ScopeSelector; -use super::theme::{Theme, ThemeItem}; use super::style::{Color, FontStyle, Style, StyleModifier}; +use super::theme::{Theme, ThemeItem}; +use crate::parsing::{ + BasicScopeStackOp, MatchPower, Scope, ScopeStack, ScopeStackOp, ATOM_LEN_BITS, +}; /// Basically a wrapper around a [`Theme`] preparing it to be used for highlighting. /// @@ -90,7 +92,7 @@ pub struct RangedHighlightIterator<'a, 'b> { /// [`Style`]: struct.Style.html #[derive(Debug)] pub struct HighlightIterator<'a, 'b> { - ranged_iterator: RangedHighlightIterator<'a, 'b> + ranged_iterator: RangedHighlightIterator<'a, 'b>, } impl HighlightState { @@ -121,11 +123,12 @@ impl HighlightState { } impl<'a, 'b> RangedHighlightIterator<'a, 'b> { - pub fn new(state: &'a mut HighlightState, - changes: &'a [(usize, ScopeStackOp)], - text: &'b str, - highlighter: &'a Highlighter<'_>) - -> RangedHighlightIterator<'a, 'b> { + pub fn new( + state: &'a mut HighlightState, + changes: &'a [(usize, ScopeStackOp)], + text: &'b str, + highlighter: &'a Highlighter<'_>, + ) -> RangedHighlightIterator<'a, 'b> { RangedHighlightIterator { index: 0, pos: 0, @@ -154,34 +157,44 @@ impl<'a, 'b> Iterator for RangedHighlightIterator<'a, 'b> { // println!("{} - {:?} {}:{}", self.index, self.pos, self.state.path.len(), self.state.styles.len()); let style = *self.state.styles.last().unwrap_or(&Style::default()); let text = &self.text[self.pos..end]; - let range = Range { start: self.pos, end }; + let range = Range { + start: self.pos, + end, + }; { // closures mess with the borrow checker's ability to see different struct fields let m_path = &mut self.state.path; let m_styles = &mut self.state.styles; let m_caches = &mut self.state.single_caches; let highlighter = &self.highlighter; - m_path.apply_with_hook(&command, |op, cur_stack| { - // println!("{:?} - {:?}", op, cur_stack); - match op { - BasicScopeStackOp::Push(_) => { - // we can push multiple times so this might have changed - let new_cache = { - if let Some(prev_cache) = m_caches.last() { - highlighter.update_single_cache_for_push(prev_cache, cur_stack) - } else { - highlighter.update_single_cache_for_push(&ScoredStyle::from_style(highlighter.get_default()), cur_stack) - } - }; - m_styles.push(highlighter.finalize_style_with_multis(&new_cache, cur_stack)); - m_caches.push(new_cache); - } - BasicScopeStackOp::Pop => { - m_styles.pop(); - m_caches.pop(); + m_path + .apply_with_hook(&command, |op, cur_stack| { + // println!("{:?} - {:?}", op, cur_stack); + match op { + BasicScopeStackOp::Push(_) => { + // we can push multiple times so this might have changed + let new_cache = { + if let Some(prev_cache) = m_caches.last() { + highlighter.update_single_cache_for_push(prev_cache, cur_stack) + } else { + highlighter.update_single_cache_for_push( + &ScoredStyle::from_style(highlighter.get_default()), + cur_stack, + ) + } + }; + m_styles.push( + highlighter.finalize_style_with_multis(&new_cache, cur_stack), + ); + m_caches.push(new_cache); + } + BasicScopeStackOp::Pop => { + m_styles.pop(); + m_caches.pop(); + } } - } - }).ok()?; + }) + .ok()?; } self.pos = end; self.index += 1; @@ -193,21 +206,22 @@ impl<'a, 'b> Iterator for RangedHighlightIterator<'a, 'b> { } } impl<'a, 'b> HighlightIterator<'a, 'b> { - pub fn new(state: &'a mut HighlightState, - changes: &'a [(usize, ScopeStackOp)], - text: &'b str, - highlighter: &'a Highlighter<'_>) - -> HighlightIterator<'a, 'b> { - HighlightIterator { - ranged_iterator: RangedHighlightIterator { - index: 0, - pos: 0, - changes, - text, - highlighter, - state - } - } + pub fn new( + state: &'a mut HighlightState, + changes: &'a [(usize, ScopeStackOp)], + text: &'b str, + highlighter: &'a Highlighter<'_>, + ) -> HighlightIterator<'a, 'b> { + HighlightIterator { + ranged_iterator: RangedHighlightIterator { + index: 0, + pos: 0, + changes, + text, + highlighter, + state, + }, + } } } @@ -299,9 +313,13 @@ impl<'a> Highlighter<'a> { let mut new_style = cur.clone(); let last_scope = path[path.len() - 1]; - for &(scope, ref modif) in self.single_selectors.iter().filter(|a| a.0.is_prefix_of(last_scope)) { - let single_score = f64::from(scope.len()) * - f64::from(ATOM_LEN_BITS * ((path.len() - 1) as u16)).exp2(); + for &(scope, ref modif) in self + .single_selectors + .iter() + .filter(|a| a.0.is_prefix_of(last_scope)) + { + let single_score = f64::from(scope.len()) + * f64::from(ATOM_LEN_BITS * ((path.len() - 1) as u16)).exp2(); new_style.apply(modif, MatchPower(single_score)); } @@ -311,7 +329,8 @@ impl<'a> Highlighter<'a> { fn finalize_style_with_multis(&self, cur: &ScoredStyle, path: &[Scope]) -> Style { let mut new_style = cur.clone(); - let mult_iter = self.multi_selectors + let mult_iter = self + .multi_selectors .iter() .filter_map(|(sel, style)| sel.does_match(path).map(|score| (score, style))); for (score, modif) in mult_iter { @@ -328,7 +347,7 @@ impl<'a> Highlighter<'a> { pub fn style_for_stack(&self, stack: &[Scope]) -> Style { let mut single_cache = ScoredStyle::from_style(self.get_default()); for i in 0..stack.len() { - single_cache = self.update_single_cache_for_push(&single_cache, &stack[0..i+1]); + single_cache = self.update_single_cache_for_push(&single_cache, &stack[0..i + 1]); } self.finalize_style_with_multis(&single_cache, stack) } @@ -345,18 +364,14 @@ impl<'a> Highlighter<'a> { /// [`StyleModifier`]: struct.StyleModifier.html /// [`style_for_stack`]: #method.style_for_stack pub fn style_mod_for_stack(&self, path: &[Scope]) -> StyleModifier { - let mut matching_items : Vec<(MatchPower, &ThemeItem)> = self.theme + let mut matching_items: Vec<(MatchPower, &ThemeItem)> = self + .theme .scopes .iter() - .filter_map(|item| { - item.scope - .does_match(path) - .map(|score| (score, item)) - }) + .filter_map(|item| item.scope.does_match(path).map(|score| (score, item))) .collect(); matching_items.sort_by_key(|&(score, _)| score); - let sorted = matching_items.iter() - .map(|(_, item)| item); + let sorted = matching_items.iter().map(|(_, item)| item); let mut modifier = StyleModifier { background: None, @@ -374,8 +389,8 @@ impl<'a> Highlighter<'a> { #[cfg(test)] mod tests { use super::*; - use crate::highlighting::{ThemeSet, Style, Color, FontStyle}; - use crate::parsing::{ SyntaxSet, ScopeStack, ParseState}; + use crate::highlighting::{Color, FontStyle, Style, ThemeSet}; + use crate::parsing::{ParseState, ScopeStack, SyntaxSet}; #[test] fn can_parse() { @@ -393,31 +408,36 @@ mod tests { let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter); let regions: Vec<(Style, &str)> = iter.collect(); // println!("{:#?}", regions); - assert_eq!(regions[11], - (Style { - foreground: Color { - r: 208, - g: 135, - b: 112, - a: 0xFF, - }, - background: Color { - r: 43, - g: 48, - b: 59, - a: 0xFF, - }, - font_style: FontStyle::empty(), - }, - "5")); + assert_eq!( + regions[11], + ( + Style { + foreground: Color { + r: 208, + g: 135, + b: 112, + a: 0xFF, + }, + background: Color { + r: 43, + g: 48, + b: 59, + a: 0xFF, + }, + font_style: FontStyle::empty(), + }, + "5" + ) + ); } #[test] fn can_parse_with_highlight_state_from_cache() { let ps = SyntaxSet::load_from_folder("testdata/Packages").unwrap(); let mut state = { - let syntax = ps.find_syntax_by_scope( - Scope::new("source.python").unwrap()).unwrap(); + let syntax = ps + .find_syntax_by_scope(Scope::new("source.python").unwrap()) + .unwrap(); ParseState::new(syntax) }; let ts = ThemeSet::load_defaults(); @@ -439,35 +459,54 @@ mod tests { let regions: Vec<(Style, &str)> = iter.collect(); // We expect the line to be styled as a comment. - assert_eq!(regions[0], - (Style { - foreground: Color { - // (Comment: #65737E) - r: 101, - g: 115, - b: 126, - a: 0xFF, - }, - background: Color { - r: 43, - g: 48, - b: 59, - a: 0xFF, - }, - font_style: FontStyle::empty(), - }, - "multiline comment")); + assert_eq!( + regions[0], + ( + Style { + foreground: Color { + // (Comment: #65737E) + r: 101, + g: 115, + b: 126, + a: 0xFF, + }, + background: Color { + r: 43, + g: 48, + b: 59, + a: 0xFF, + }, + font_style: FontStyle::empty(), + }, + "multiline comment" + ) + ); } // see issues #133 and #203, this test tests the fixes for those issues #[test] fn tricky_cases() { + use crate::highlighting::{ScopeSelectors, ThemeSettings}; use crate::parsing::ScopeStack; use std::str::FromStr; - use crate::highlighting::{ThemeSettings, ScopeSelectors}; - let c1 = Color { r: 1, g: 1, b: 1, a: 255 }; - let c2 = Color { r: 2, g: 2, b: 2, a: 255 }; - let def_bg = Color { r: 255, g: 255, b: 255, a: 255 }; + let c1 = Color { + r: 1, + g: 1, + b: 1, + a: 255, + }; + let c2 = Color { + r: 2, + g: 2, + b: 2, + a: 255, + }; + let def_bg = Color { + r: 255, + g: 255, + b: 255, + a: 255, + }; let test_color_scheme = Theme { name: None, author: None, @@ -523,17 +562,46 @@ mod tests { let regions: Vec