Skip to content

Commit

Permalink
Merge pull request #426 from Enselic/parse-and-highlight-line-with-re…
Browse files Browse the repository at this point in the history
…sult

Make `highlight_line()` and `parse_line()` return `Result`
  • Loading branch information
trishume committed Mar 13, 2022
2 parents 9f3517d + 71e1b78 commit ce1ba5b
Show file tree
Hide file tree
Showing 18 changed files with 104 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Expand Up @@ -80,7 +80,7 @@ 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 LinesWithEndings::from(s) {
let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps);
let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap();
let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
print!("{}", escaped);
}
Expand Down
2 changes: 1 addition & 1 deletion benches/highlight_utils/mod.rs
Expand Up @@ -7,7 +7,7 @@ pub fn do_highlight(s: &str, syntax_set: &SyntaxSet, syntax: &SyntaxReference, t
let mut h = HighlightLines::new(syntax, theme);
let mut count = 0;
for line in s.lines() {
let regions = h.highlight_line(line, syntax_set);
let regions = h.highlight_line(line, syntax_set).unwrap();
count += regions.len();
}
count
Expand Down
2 changes: 1 addition & 1 deletion benches/parsing.rs
Expand Up @@ -8,7 +8,7 @@ fn do_parse(s: &str, ss: &SyntaxSet, syntax: &SyntaxReference) -> usize {
let mut state = ParseState::new(syntax);
let mut count = 0;
for line in s.lines() {
let ops = state.parse_line(line, ss);
let ops = state.parse_line(line, ss).unwrap();
count += ops.len();
}
count
Expand Down
2 changes: 1 addition & 1 deletion examples/latex-demo.rs
Expand Up @@ -13,7 +13,7 @@ fn main() {

let mut h = HighlightLines::new(syntax, &ts.themes["InspiredGitHub"]);
for line in LinesWithEndings::from(s) { // LinesWithEndings enables use of newlines mode
let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps);
let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap();
let escaped = as_latex_escaped(&ranges[..]);
println!("\n{:?}", line);
println!("\n{}", escaped);
Expand Down
2 changes: 1 addition & 1 deletion examples/parsyncat.rs
Expand Up @@ -45,7 +45,7 @@ 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) {
for region in highlighter.highlight_lines.highlight_line(line, &syntax_set).unwrap() {
regions.push(region);
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/syncat.rs
Expand Up @@ -103,7 +103,7 @@ fn main() {
}

{
let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss);
let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss).unwrap();
print!("{}", as_24_bit_terminal_escaped(&regions[..], true));
}
line.clear();
Expand Down
4 changes: 2 additions & 2 deletions examples/synhtml-css-classes.rs
Expand Up @@ -46,7 +46,7 @@ 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);
for line in LinesWithEndings::from(code_rs) {
rs_html_generator.parse_html_for_line_which_includes_newline(line);
rs_html_generator.parse_html_for_line_which_includes_newline(line).unwrap();
}
let html_rs = rs_html_generator.finalize();

Expand All @@ -64,7 +64,7 @@ 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);
for line in LinesWithEndings::from(code_cpp) {
cpp_html_generator.parse_html_for_line_which_includes_newline(line);
cpp_html_generator.parse_html_for_line_which_includes_newline(line).unwrap();
}
let html_cpp = cpp_html_generator.finalize();

Expand Down
2 changes: 1 addition & 1 deletion examples/synstats.rs
Expand Up @@ -133,7 +133,7 @@ fn count(ss: &SyntaxSet, path: &Path, stats: &mut Stats) {
let mut stack = ScopeStack::new();
while reader.read_line(&mut line).unwrap() > 0 {
{
let ops = state.parse_line(&line, ss);
let ops = state.parse_line(&line, ss).unwrap();
stats.chars += line.len();
count_line(&ops, &line, &mut stack, stats);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/syntest.rs
Expand Up @@ -273,7 +273,7 @@ fn test_file(
current_line_number, stack
);
}
let ops = state.parse_line(&line, ss);
let ops = state.parse_line(&line, ss).unwrap();
if out_opts.debug && !line_only_has_assertion {
if ops.is_empty() && !line.is_empty() {
println!("no operations for this line...");
Expand Down
21 changes: 11 additions & 10 deletions src/easy.rs
Expand Up @@ -2,6 +2,7 @@
//! files without caring about intermediate semantic representation
//! and caching.

use crate::Error;
use crate::parsing::{ScopeStack, ParseState, SyntaxReference, SyntaxSet, ScopeStackOp};
use crate::highlighting::{Highlighter, HighlightState, HighlightIterator, Theme, Style};
use std::io::{self, BufReader};
Expand Down Expand Up @@ -34,7 +35,7 @@ use std::path::Path;
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
/// for line in LinesWithEndings::from(s) { // LinesWithEndings enables use of newlines mode
/// let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps);
/// let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap();
/// let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
/// print!("{}", escaped);
/// }
Expand All @@ -58,18 +59,18 @@ 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)
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) -> Vec<(Style, &'b str)> {
pub fn highlight_line<'b>(&mut self, line: &'b str, syntax_set: &SyntaxSet) -> Result<Vec<(Style, &'b str)>, Error> {
// println!("{}", self.highlight_state.path);
let ops = self.parse_state.parse_line(line, syntax_set);
let ops = self.parse_state.parse_line(line, syntax_set)?;
// use util::debug_print_ops;
// debug_print_ops(line, &ops);
let iter =
HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
iter.collect()
Ok(iter.collect())
}
}

Expand Down Expand Up @@ -113,7 +114,7 @@ impl<'a> HighlightFile<'a> {
/// let mut line = String::new();
/// while highlighter.reader.read_line(&mut line)? > 0 {
/// {
/// let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss);
/// let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss).unwrap();
/// print!("{}", as_24_bit_terminal_escaped(&regions[..], true));
/// } // until NLL this scope is needed so we can clear the buffer after
/// line.clear(); // read_line appends so we need to clear between lines
Expand All @@ -137,7 +138,7 @@ impl<'a> HighlightFile<'a> {
/// let mut highlighter = HighlightFile::new("testdata/highlight_test.erb", &ss, &ts.themes["base16-ocean.dark"]).unwrap();
/// for maybe_line in highlighter.reader.lines() {
/// let line = maybe_line.unwrap();
/// let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss);
/// let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight_line(&line, &ss).unwrap();
/// println!("{}", as_24_bit_terminal_escaped(&regions[..], true));
/// }
/// ```
Expand Down Expand Up @@ -271,7 +272,7 @@ 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);
let ranges = h.highlight_line("pub struct Wow { hi: u64 }", &ss).expect("#[cfg(test)]");
assert!(ranges.len() > 4);
}

Expand All @@ -292,7 +293,7 @@ mod tests {
let ss = SyntaxSet::load_defaults_nonewlines();
let mut state = ParseState::new(ss.find_syntax_by_extension("rb").unwrap());
let line = "lol =5+2";
let ops = state.parse_line(line, &ss);
let ops = state.parse_line(line, &ss).expect("#[cfg(test)]");

let mut stack = ScopeStack::new();
let mut token_count = 0;
Expand Down Expand Up @@ -320,7 +321,7 @@ mod tests {
let mut stack = ScopeStack::new();

for line in lines.iter() {
let ops = state.parse_line(line, &ss);
let ops = state.parse_line(line, &ss).expect("#[cfg(test)]");
println!("{:?}", ops);

let mut iterated_ops: Vec<&ScopeStackOp> = Vec::new();
Expand Down
8 changes: 4 additions & 4 deletions src/highlighting/highlighter.rs
Expand Up @@ -389,7 +389,7 @@ mod tests {

let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
let line = "module Bob::Wow::Troll::Five; 5; end";
let ops = state.parse_line(line, &ps);
let ops = state.parse_line(line, &ps).expect("#[cfg(test)]");
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
let regions: Vec<(Style, &str)> = iter.collect();
// println!("{:#?}", regions);
Expand Down Expand Up @@ -426,15 +426,15 @@ mod tests {
// We start by parsing a python multiline-comment: """
let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
let line = r#"""""#;
let ops = state.parse_line(line, &ps);
let ops = state.parse_line(line, &ps).expect("#[cfg(test)]");
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
assert_eq!(1, iter.count());
let path = highlight_state.path;

// We then parse the next line with a highlight state built from the previous state
let mut highlight_state = HighlightState::new(&highlighter, path);
let line = "multiline comment";
let ops = state.parse_line(line, &ps);
let ops = state.parse_line(line, &ps).expect("#[cfg(test)]");
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
let regions: Vec<(Style, &str)> = iter.collect();

Expand Down Expand Up @@ -548,7 +548,7 @@ mod tests {

let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
let line = "module Bob::Wow::Troll::Five; 5; end";
let ops = state.parse_line(line, &ps);
let ops = state.parse_line(line, &ps).expect("#[cfg(test)]");
let iter = RangedHighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
let regions: Vec<(Style, &str, Range<usize>)> = iter.collect();
// println!("{:#?}", regions);
Expand Down
2 changes: 1 addition & 1 deletion src/highlighting/theme.rs
Expand Up @@ -31,7 +31,7 @@ pub struct ThemeSettings {
/// Color of the caret.
pub caret: Option<Color>,
/// Color of the line the caret is in.
/// Only used when the `higlight_line` setting is set to `true`.
/// Only used when the `highlight_line` setting is set to `true`.
pub line_highlight: Option<Color>,

/// The color to use for the squiggly underline drawn under misspelled words.
Expand Down
24 changes: 13 additions & 11 deletions src/html.rs
Expand Up @@ -87,8 +87,8 @@ impl<'a> ClassedHTMLGenerator<'a> {
///
/// *Note:* This function requires `line` to include a newline at the end and
/// also use of the `load_defaults_newlines` version of the syntaxes.
pub fn parse_html_for_line_which_includes_newline(&mut self, line: &str) {
let parsed_line = self.parse_state.parse_line(line, self.syntax_set);
pub fn parse_html_for_line_which_includes_newline(&mut self, line: &str) -> Result<(), Error>{
let parsed_line = self.parse_state.parse_line(line, self.syntax_set)?;
let (formatted_line, delta) = line_tokens_to_classed_spans(
line,
parsed_line.as_slice(),
Expand All @@ -97,6 +97,8 @@ impl<'a> ClassedHTMLGenerator<'a> {
);
self.open_spans += delta;
self.html.push_str(formatted_line.as_str());

Ok(())
}

/// Parse the line of code and update the internal HTML buffer with tagged HTML
Expand All @@ -110,7 +112,7 @@ impl<'a> ClassedHTMLGenerator<'a> {
/// but this function can't be changed without breaking compatibility so is deprecated.
#[deprecated(since="4.5.0", note="Please use `parse_html_for_line_which_includes_newline` instead")]
pub fn parse_html_for_line(&mut self, line: &str) {
self.parse_html_for_line_which_includes_newline(line);
self.parse_html_for_line_which_includes_newline(line).expect("Please use `parse_html_for_line_which_includes_newline` instead");
// retain newline
self.html.push('\n');
}
Expand Down Expand Up @@ -274,7 +276,7 @@ pub fn highlighted_html_for_string(
let (mut output, bg) = start_highlighted_html_snippet(theme);

for line in LinesWithEndings::from(s) {
let regions = highlighter.highlight_line(line, ss);
let regions = highlighter.highlight_line(line, ss)?;
append_highlighted_html_for_styled_line(
&regions[..],
IncludeBackground::IfDifferent(bg),
Expand Down Expand Up @@ -302,7 +304,7 @@ pub fn highlighted_html_for_file<P: AsRef<Path>>(
let mut line = String::new();
while highlighter.reader.read_line(&mut line)? > 0 {
{
let regions = highlighter.highlight_lines.highlight_line(&line, ss);
let regions = highlighter.highlight_lines.highlight_line(&line, ss)?;
append_highlighted_html_for_styled_line(
&regions[..],
IncludeBackground::IfDifferent(bg),
Expand Down Expand Up @@ -433,7 +435,7 @@ fn write_css_color(s: &mut String, c: Color) {
///
/// let syntax = ps.find_syntax_by_name("Ruby").unwrap();
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let regions = h.highlight_line("5", &ps);
/// let regions = h.highlight_line("5", &ps).unwrap();
/// let html = styled_line_to_highlighted_html(&regions[..], IncludeBackground::No).unwrap();
/// assert_eq!(html, "<span style=\"color:#d08770;\">5</span>");
/// ```
Expand Down Expand Up @@ -535,7 +537,7 @@ mod tests {
let syntax = ss.find_syntax_by_name("Markdown").unwrap();
let mut state = ParseState::new(syntax);
let line = "[w](t.co) *hi* **five**";
let ops = state.parse_line(line, &ss);
let ops = state.parse_line(line, &ss).expect("#[cfg(test)]");
let mut stack = ScopeStack::new();

// use util::debug_print_ops;
Expand Down Expand Up @@ -619,7 +621,7 @@ mod tests {
let mut html_generator =
ClassedHTMLGenerator::new_with_class_style(syntax, &syntax_set, ClassStyle::Spaced);
for line in LinesWithEndings::from(current_code) {
html_generator.parse_html_for_line_which_includes_newline(line);
html_generator.parse_html_for_line_which_includes_newline(line).expect("#[cfg(test)]");
}
html_generator.finalize();
}
Expand All @@ -633,7 +635,7 @@ mod tests {
let mut html_generator =
ClassedHTMLGenerator::new_with_class_style(syntax, &syntax_set, ClassStyle::Spaced);
for line in LinesWithEndings::from(current_code) {
html_generator.parse_html_for_line_which_includes_newline(line);
html_generator.parse_html_for_line_which_includes_newline(line).expect("#[cfg(test)]");
}
let html = html_generator.finalize();
assert_eq!(html, "<span class=\"source r\">x <span class=\"keyword operator arithmetic r\">+</span> y\n</span>");
Expand All @@ -650,7 +652,7 @@ mod tests {
ClassStyle::SpacedPrefixed { prefix: "foo-" },
);
for line in LinesWithEndings::from(current_code) {
html_generator.parse_html_for_line_which_includes_newline(line);
html_generator.parse_html_for_line_which_includes_newline(line).expect("#[cfg(test)]");
}
let html = html_generator.finalize();
assert_eq!(html, "<span class=\"foo-source foo-r\">x <span class=\"foo-keyword foo-operator foo-arithmetic foo-r\">+</span> y\n</span>");
Expand All @@ -668,7 +670,7 @@ fn main() {
let mut html_generator =
ClassedHTMLGenerator::new_with_class_style(syntax, &syntax_set, ClassStyle::Spaced);
for line in LinesWithEndings::from(code) {
html_generator.parse_html_for_line_which_includes_newline(line);
html_generator.parse_html_for_line_which_includes_newline(line).expect("#[cfg(test)]");
}
let html = html_generator.finalize();
assert_eq!(html, "<span class=\"source rust\"><span class=\"comment line double-slash rust\"><span class=\"punctuation definition comment rust\">//</span> Rust source\n</span><span class=\"meta function rust\"><span class=\"meta function rust\"><span class=\"storage type function rust\">fn</span> </span><span class=\"entity name function rust\">main</span></span><span class=\"meta function rust\"><span class=\"meta function parameters rust\"><span class=\"punctuation section parameters begin rust\">(</span></span><span class=\"meta function rust\"><span class=\"meta function parameters rust\"><span class=\"punctuation section parameters end rust\">)</span></span></span></span><span class=\"meta function rust\"> </span><span class=\"meta function rust\"><span class=\"meta block rust\"><span class=\"punctuation section block begin rust\">{</span>\n <span class=\"support macro rust\">println!</span><span class=\"meta group rust\"><span class=\"punctuation section group begin rust\">(</span></span><span class=\"meta group rust\"><span class=\"string quoted double rust\"><span class=\"punctuation definition string begin rust\">&quot;</span>Hello World!<span class=\"punctuation definition string end rust\">&quot;</span></span></span><span class=\"meta group rust\"><span class=\"punctuation section group end rust\">)</span></span><span class=\"punctuation terminator rust\">;</span>\n</span><span class=\"meta block rust\"><span class=\"punctuation section block end rust\">}</span></span></span>\n</span>");
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Expand Up @@ -54,6 +54,10 @@ pub enum Error {
/// An error occurred while loading a syntax or theme
#[error("Loading error: {0}")]
LoadingError(#[from] LoadingError),
/// An error occurred while parsing
#[cfg(feature = "parsing")]
#[error("Parsing error: {0}")]
ParsingError(#[from] crate::parsing::ParsingError),
/// Formatting error
#[error("Formatting error: {0}")]
Fmt(#[from] std::fmt::Error),
Expand Down

0 comments on commit ce1ba5b

Please sign in to comment.