Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make highlight_line() and parse_line() return Result #426

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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