Skip to content
This repository has been archived by the owner on Feb 12, 2018. It is now read-only.

Commit

Permalink
Add easy wrapper for highlighting lines
Browse files Browse the repository at this point in the history
  • Loading branch information
trishume committed Jun 14, 2016
1 parent 776e739 commit 4b1ce42
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 36 deletions.
19 changes: 7 additions & 12 deletions benches/highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,27 @@ use test::Bencher;

use syntect::package_set::PackageSet;
use syntect::theme_set::ThemeSet;
use syntect::scope::ScopeStack;
use syntect::parser::*;
use syntect::theme::highlighter::*;
use syntect::theme::style::*;
use syntect::easy::HighlightLines;
use std::fs::File;
use std::path::Path;
use std::io::Read;

fn highlight_file(b: &mut Bencher, path_s: &str) {
// don't load from dump so we don't count lazy regex compilation time
let ps = PackageSet::load_from_folder("testdata/Packages").unwrap();
let highlighter = Highlighter::new(ThemeSet::get_theme("testdata/spacegray/base16-ocean.\
dark.tmTheme")
.unwrap());
let ts = ThemeSet::load_defaults();

let path = Path::new(path_s);
let extension = path.extension().unwrap().to_str().unwrap();
let mut f = File::open(path).unwrap();
let mut s = String::new();
f.read_to_string(&mut s).unwrap();

let syntax = ps.find_syntax_by_extension(extension).unwrap();
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
b.iter(|| {
let mut state = ParseState::new(syntax);
let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
for line in s.lines() {
let ops = state.parse_line(&line);
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], &line, &highlighter);
let regions: Vec<(Style, &str)> = iter.collect();
let regions = h.highlight(line);
test::black_box(&regions);
}
});
Expand Down
21 changes: 5 additions & 16 deletions examples/syncat.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
extern crate syntect;
use syntect::scope::ScopeStack;
use syntect::package_set::PackageSet;
use syntect::theme_set::ThemeSet;
use syntect::parser::*;
use syntect::theme::highlighter::*;
use syntect::theme::style::*;
use syntect::theme::style::Style;
use syntect::util::as_24_bit_terminal_escaped;
use syntect::easy::HighlightLines;

use std::io::BufReader;
use std::io::BufRead;
Expand All @@ -15,7 +13,6 @@ use std::fs::File;
fn main() {
let ps = PackageSet::load_defaults_nonewlines();
let ts = ThemeSet::load_defaults();
let highlighter = Highlighter::new(&ts.themes["base16-ocean.dark"]);

let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
Expand All @@ -28,19 +25,11 @@ fn main() {
let f = File::open(path).unwrap();
let file = BufReader::new(&f);

let mut state = {
let syntax = ps.find_syntax_by_extension(extension).unwrap();
ParseState::new(syntax)
};

let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
let syntax = ps.find_syntax_by_extension(extension).unwrap();
let mut highlighter = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
for maybe_line in file.lines() {
let line = maybe_line.unwrap();
// println!("{}", highlight_state.path);
let ops = state.parse_line(&line);
// debug_print_ops(&line, &ops);
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], &line, &highlighter);
let regions: Vec<(Style, &str)> = iter.collect();
let regions: Vec<(Style, &str)> = highlighter.highlight(&line);
let escaped = as_24_bit_terminal_escaped(&regions[..], true);
println!("{}", escaped);
}
Expand Down
79 changes: 79 additions & 0 deletions src/easy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use scope::ScopeStack;
use parser::*;
use theme::highlighter::*;
use theme::style::*;
use theme::theme::Theme;
use syntax_definition::SyntaxDefinition;
// use util::debug_print_ops;

/// Simple way to go directly from lines of text to coloured
/// tokens.
///
/// Depending on how you load the packages (see the `PackageSet` docs)
/// you can either pass this strings with trailing `\n`s or without.
///
/// # Example
/// Prints coloured lines of a string to the terminal
///
/// ```
/// use syntect::easy::HighlightLines;
/// use syntect::package_set::PackageSet;
/// use syntect::theme_set::ThemeSet;
/// use syntect::theme::style::Style;
/// use syntect::util::as_24_bit_terminal_escaped;
///
/// // Load these once at the start of your program
/// let ps = PackageSet::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 s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
/// for line in s.lines() {
/// let ranges: Vec<(Style, &str)> = h.highlight(line);
/// let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
/// println!("{}", escaped);
/// }
/// ```
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,
}
}

/// Highlights a line of a file
pub fn highlight<'b>(&mut self, line: &'b str) -> Vec<(Style, &'b str)> {
// println!("{}", self.highlight_state.path);
let ops = self.parse_state.parse_line(&line);
// debug_print_ops(line, &ops);
let iter = HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
iter.collect()
}
}

#[cfg(test)]
mod tests {
use easy::*;
#[test]
fn can_highlight_lines() {
use package_set::PackageSet;
use theme_set::ThemeSet;
let ps = PackageSet::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);
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ pub mod parser;
pub mod theme;
pub mod util;
pub mod dumps;
pub mod easy;
16 changes: 8 additions & 8 deletions src/theme/highlighter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ pub struct HighlightState {
}

#[derive(Debug)]
pub struct HighlightIterator<'a> {
pub struct HighlightIterator<'a,'b> {
index: usize,
pos: usize,
changes: &'a [(usize, ScopeStackOp)],
text: &'a str,
text: &'b str,
highlighter: &'a Highlighter<'a>,
state: &'a mut HighlightState,
}
Expand All @@ -44,12 +44,12 @@ impl HighlightState {
}
}

impl<'a> HighlightIterator<'a> {
impl<'a,'b> HighlightIterator<'a,'b> {
pub fn new(state: &'a mut HighlightState,
changes: &'a [(usize, ScopeStackOp)],
text: &'a str,
text: &'b str,
highlighter: &'a Highlighter)
-> HighlightIterator<'a> {
-> HighlightIterator<'a,'b> {
HighlightIterator {
index: 0,
pos: 0,
Expand All @@ -61,10 +61,10 @@ impl<'a> HighlightIterator<'a> {
}
}

impl<'a> Iterator for HighlightIterator<'a> {
type Item = (Style, &'a str);
impl<'a,'b> Iterator for HighlightIterator<'a,'b> {
type Item = (Style, &'b str);

fn next(&mut self) -> Option<(Style, &'a str)> {
fn next(&mut self) -> Option<(Style, &'b str)> {
if self.pos == self.text.len() && self.index >= self.changes.len() {
return None;
}
Expand Down

0 comments on commit 4b1ce42

Please sign in to comment.