use parsing::{ScopeStack, ParseState, SyntaxDefinition, SyntaxSet};
use highlighting::{Highlighter, HighlightState, HighlightIterator, Theme, Style};
use std::io::{BufReader, self};
use std::fs::File;
use std::path::Path;
pub struct HighlightLines<'a> {
highlighter: Highlighter<'a>,
parse_state: ParseState,
highlight_state: HighlightState,
}
impl<'a> HighlightLines<'a> {
pub fn new(syntax: &SyntaxDefinition, theme: &'a Theme) -> HighlightLines<'a> {
let highlighter = Highlighter::new(theme);
let hstate = HighlightState::new(&highlighter, ScopeStack::new());
HighlightLines {
highlighter: highlighter,
parse_state: ParseState::new(syntax),
highlight_state: hstate,
}
}
pub fn highlight<'b>(&mut self, line: &'b str) -> Vec<(Style, &'b str)> {
let ops = self.parse_state.parse_line(&line);
let iter =
HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
iter.collect()
}
}
pub struct HighlightFile<'a> {
pub reader: BufReader<File>,
pub highlight_lines: HighlightLines<'a>,
}
impl<'a> HighlightFile<'a> {
pub fn new<P: AsRef<Path>>(path_obj: P, ss: &SyntaxSet, theme: &'a Theme) -> io::Result<HighlightFile<'a>> {
let path: &Path = path_obj.as_ref();
let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");
let f = try!(File::open(path));
let reader = BufReader::new(f);
let syntax = ss.find_syntax_by_extension(extension).unwrap_or_else(|| ss.find_syntax_plain_text());
Ok(HighlightFile {
reader: reader,
highlight_lines: HighlightLines::new(syntax, theme),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use parsing::SyntaxSet;
use highlighting::ThemeSet;
#[test]
fn can_highlight_lines() {
let ps = SyntaxSet::load_defaults_nonewlines();
let ts = ThemeSet::load_defaults();
let syntax = ps.find_syntax_by_extension("rs").unwrap();
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
let ranges = h.highlight("pub struct Wow { hi: u64 }");
assert!(ranges.len() > 4);
}
#[test]
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();
}
}