Repository: dandavison/delta
Pull request #698 (2021-08-22 00:47:33)

Refactor: use Option to model sometimes-null highlighter
The highlighter is only needed when a language has been identified for
highlighting. Prior to this commit a dummy highlighter was being created
in place of no highlighter at all

Ref #659


Patch:
diff --git a/src/cli.rs b/src/cli.rs
index b48d52f..f7ad735 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -496,8 +496,7 @@ pub struct Opt {
 
     #[structopt(long = "max-line-length", default_value = "512")]
     /// Truncate lines longer than this. To prevent any truncation, set to zero. Note that
-    /// syntax-highlighting very long lines (e.g. minified .js) will be very slow if they are not
-    /// truncated.
+    /// delta will be slow on very long lines (e.g. minified .js) if truncation is disabled.
     pub max_line_length: usize,
 
     /// The width of underline/overline decorations. Use --width=variable to extend decorations and
diff --git a/src/hunk_header.rs b/src/hunk_header.rs
index 3a19252..c076041 100644
--- a/src/hunk_header.rs
+++ b/src/hunk_header.rs
@@ -147,7 +147,7 @@ fn write_to_output_buffer(
         let syntax_style_sections = Painter::get_syntax_style_sections_for_lines(
             &lines,
             &delta::State::HunkHeader,
-            &mut painter.highlighter,
+            painter.highlighter.as_mut(),
             painter.config,
         );
         Painter::paint_lines(
diff --git a/src/paint.rs b/src/paint.rs
index 0e56923..88f26bf 100644
--- a/src/paint.rs
+++ b/src/paint.rs
@@ -20,7 +20,7 @@ pub struct Painter<'a> {
     pub plus_lines: Vec<(String, State)>,
     pub writer: &'a mut dyn Write,
     pub syntax: &'a SyntaxReference,
-    pub highlighter: HighlightLines<'a>,
+    pub highlighter: Option<HighlightLines<'a>>,
     pub config: &'a config::Config,
     pub output_buffer: String,
     pub line_numbers_data: line_numbers::LineNumbersData<'a>,
@@ -29,8 +29,6 @@ pub struct Painter<'a> {
 impl<'a> Painter<'a> {
     pub fn new(writer: &'a mut dyn Write, config: &'a config::Config) -> Self {
         let default_syntax = Self::get_syntax(&config.syntax_set, None);
-        // TODO: Avoid doing this.
-        let dummy_highlighter = HighlightLines::new(default_syntax, &config.syntax_dummy_theme);
 
         let line_numbers_data = if config.line_numbers {
             line_numbers::LineNumbersData::from_format_strings(
@@ -45,7 +43,7 @@ impl<'a> Painter<'a> {
             plus_lines: Vec::new(),
             output_buffer: String::new(),
             syntax: default_syntax,
-            highlighter: dummy_highlighter,
+            highlighter: None,
             writer,
             config,
             line_numbers_data,
@@ -69,7 +67,7 @@ impl<'a> Painter<'a> {
 
     pub fn set_highlighter(&mut self) {
         if let Some(ref syntax_theme) = self.config.syntax_theme {
-            self.highlighter = HighlightLines::new(self.syntax, syntax_theme)
+            self.highlighter = Some(HighlightLines::new(self.syntax, syntax_theme))
         };
     }
 
@@ -127,13 +125,13 @@ impl<'a> Painter<'a> {
         let minus_line_syntax_style_sections = Self::get_syntax_style_sections_for_lines(
             &self.minus_lines,
             &State::HunkMinus(None),
-            &mut self.highlighter,
+            self.highlighter.as_mut(),
             self.config,
         );
         let plus_line_syntax_style_sections = Self::get_syntax_style_sections_for_lines(
             &self.plus_lines,
             &State::HunkPlus(None),
-            &mut self.highlighter,
+            self.highlighter.as_mut(),
             self.config,
         );
         let (minus_line_diff_style_sections, plus_line_diff_style_sections, line_alignment) =
@@ -204,7 +202,7 @@ impl<'a> Painter<'a> {
         let syntax_style_sections = Painter::get_syntax_style_sections_for_lines(
             &lines,
             &state,
-            &mut self.highlighter,
+            self.highlighter.as_mut(),
             self.config,
         );
         let diff_style_sections = vec![(self.config.zero_style, lines[0].0.as_str())]; // TODO: compute style from state
@@ -477,20 +475,28 @@ impl<'a> Painter<'a> {
     pub fn get_syntax_style_sections_for_lines<'s>(
         lines: &'s [(String, State)],
         state: &State,
-        highlighter: &mut HighlightLines,
+        highlighter: Option<&mut HighlightLines>,
         config: &config::Config,
     ) -> Vec<Vec<(SyntectStyle, &'s str)>> {
-        let fake = !Painter::should_compute_syntax_highlighting(state, config);
         let mut line_sections = Vec::new();
-        for (line, _) in lines.iter() {
-            if fake {
-                line_sections.push(vec![(config.null_syntect_style, line.as_str())])
-            } else {
+        match (
+            highlighter,
+            Painter::should_compute_syntax_highlighting(state, config),
+        ) {
+            (Some(highlighter), true) => {
                 // The first character is a space injected by delta. See comment in
                 // Painter:::prepare.
-                let mut this_line_sections = highlighter.highlight(&line[1..], &config.syntax_set);
-                this_line_sections.insert(0, (config.null_syntect_style, &line[..1]));
-                line_sections.push(this_line_sections);
+                for (line, _) in lines.iter() {
+                    let mut this_line_sections =
+                        highlighter.highlight(&line[1..], &config.syntax_set);
+                    this_line_sections.insert(0, (config.null_syntect_style, &line[..1]));
+                    line_sections.push(this_line_sections);
+                }
+            }
+            _ => {
+                for (line, _) in lines.iter() {
+                    line_sections.push(vec![(config.null_syntect_style, line.as_str())])
+                }
             }
         }
         line_sections


Test patch:
diff --git a/src/tests/ansi_test_utils.rs b/src/tests/ansi_test_utils.rs
index dd16056..d2db3ee 100644
--- a/src/tests/ansi_test_utils.rs
+++ b/src/tests/ansi_test_utils.rs
@@ -133,7 +133,7 @@ pub mod ansi_test_utils {
         let syntax_style_sections = paint::Painter::get_syntax_style_sections_for_lines(
             &lines,
             &state,
-            &mut painter.highlighter,
+            painter.highlighter.as_mut(),
             config,
         );
         let diff_style_sections = vec![vec![(syntax_highlighted_style, lines[0].0.as_str())]];