1 //! Highlights the files given on the command line, in parallel.
2 //! Prints the highlighted output to stdout.
3
4 use syntect::parsing::SyntaxSet;
5 use syntect::highlighting::{ThemeSet, Style};
6 use syntect::easy::HighlightFile;
7 use rayon::prelude::*;
8
9 use std::fs::File;
10 use std::io::{BufReader, BufRead};
11
main()12 fn main() {
13 let files: Vec<String> = std::env::args().skip(1).collect();
14
15 if files.is_empty() {
16 println!("Please provide some files to highlight.");
17 return;
18 }
19
20 let syntax_set = SyntaxSet::load_defaults_newlines();
21 let theme_set = ThemeSet::load_defaults();
22
23 // We first collect the contents of the files...
24 let contents: Vec<Vec<String>> = files.par_iter()
25 .map(|filename| {
26 let mut lines = Vec::new();
27 // We use `String::new()` and `read_line()` instead of `BufRead::lines()`
28 // in order to preserve the newlines and get better highlighting.
29 let mut line = String::new();
30 let mut reader = BufReader::new(File::open(filename).unwrap());
31 while reader.read_line(&mut line).unwrap() > 0 {
32 lines.push(line);
33 line = String::new();
34 }
35 lines
36 })
37 .collect();
38
39 // ...so that the highlighted regions have valid lifetimes...
40 let regions: Vec<Vec<(Style, &str)>> = files.par_iter()
41 .zip(&contents)
42 .map(|(filename, contents)| {
43 let mut regions = Vec::new();
44 let theme = &theme_set.themes["base16-ocean.dark"];
45 let mut highlighter = HighlightFile::new(filename, &syntax_set, theme).unwrap();
46
47 for line in contents {
48 for region in highlighter.highlight_lines.highlight(line, &syntax_set) {
49 regions.push(region);
50 }
51 }
52
53 regions
54 })
55 .collect();
56
57 // ...and then print them all out.
58 for file_regions in regions {
59 print!("{}", syntect::util::as_24_bit_terminal_escaped(&file_regions[..], true));
60 }
61 }
62