diff options
-rw-r--r-- | src/delta.rs | 15 | ||||
-rw-r--r-- | src/edits.rs | 93 | ||||
-rw-r--r-- | src/paint.rs | 129 | ||||
-rw-r--r-- | src/parse.rs | 9 |
4 files changed, 114 insertions, 132 deletions
diff --git a/src/delta.rs b/src/delta.rs index 551dad17..c41e5f1b 100644 --- a/src/delta.rs +++ b/src/delta.rs @@ -173,17 +173,17 @@ fn handle_hunk_meta_line( let (code_fragment, line_number) = parse::parse_hunk_metadata(&line); if code_fragment.len() > 0 { let syntax_style_sections = Painter::get_line_syntax_style_sections( - &code_fragment, + code_fragment, &mut painter.highlighter, &painter.config, true, ); Painter::paint_lines( &mut painter.output_buffer, - &vec![syntax_style_sections], - &vec![vec![( + vec![syntax_style_sections], + vec![vec![( style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, - code_fragment.clone(), + code_fragment, )]], ); painter.output_buffer.pop(); // trim newline @@ -238,11 +238,8 @@ fn handle_hunk_line(painter: &mut Painter, line: &str, state: State, config: &Co ); Painter::paint_lines( &mut painter.output_buffer, - &vec![syntax_style_sections], - &vec![vec![( - style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, - line.clone(), - )]], + vec![syntax_style_sections], + vec![vec![(style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, &line)]], ); State::HunkZero } diff --git a/src/edits.rs b/src/edits.rs index 20893b4e..73accc48 100644 --- a/src/edits.rs +++ b/src/edits.rs @@ -31,17 +31,17 @@ use crate::edits::string_pair::StringPair; end of the line: the line by definition has no trailing whitespace. */ -pub fn infer_edit_sections<EditOperationTag>( - minus_lines: &Vec<String>, - plus_lines: &Vec<String>, +pub fn infer_edit_sections<'m, 'p, EditOperationTag>( + minus_lines: &'m Vec<String>, + plus_lines: &'p Vec<String>, minus_line_noop: EditOperationTag, delete: EditOperationTag, plus_line_noop: EditOperationTag, insert: EditOperationTag, similarity_threshold: f64, ) -> ( - Vec<Vec<(EditOperationTag, String)>>, - Vec<Vec<(EditOperationTag, String)>>, + Vec<Vec<(EditOperationTag, &'m str)>>, + Vec<Vec<(EditOperationTag, &'p str)>>, ) where EditOperationTag: Copy, @@ -88,18 +88,18 @@ where && plus_edit.appears_genuine(similarity_threshold) { minus_line_sections.push(vec![ - (minus_line_noop, minus[0..change_begin].to_string()), - (delete, minus[change_begin..minus_change_end].to_string()), - (minus_line_noop, minus[minus_change_end..].to_string()), + (minus_line_noop, &minus[0..change_begin]), + (delete, &minus[change_begin..minus_change_end]), + (minus_line_noop, &minus[minus_change_end..]), ]); plus_line_sections.push(vec![ - (plus_line_noop, plus[0..change_begin].to_string()), - (insert, plus[change_begin..plus_change_end].to_string()), - (plus_line_noop, plus[plus_change_end..].to_string()), + (plus_line_noop, &plus[0..change_begin]), + (insert, &plus[change_begin..plus_change_end]), + (plus_line_noop, &plus[plus_change_end..]), ]); } else { - minus_line_sections.push(vec![(minus_line_noop, minus.to_string())]); - plus_line_sections.push(vec![(plus_line_noop, plus.to_string())]); + minus_line_sections.push(vec![(minus_line_noop, minus)]); + plus_line_sections.push(vec![(plus_line_noop, plus)]); } } (minus_line_sections, plus_line_sections) @@ -135,9 +135,11 @@ mod tests { #[test] fn test_infer_edit_sections_1() { + let minus_lines = vec!["aaa\n".to_string()]; + let plus_lines = vec!["aba\n".to_string()]; let actual_edits = infer_edit_sections( - &vec!["aaa\n".to_string()], - &vec!["aba\n".to_string()], + &minus_lines, + &plus_lines, MinusNoop, Delete, PlusNoop, @@ -145,16 +147,8 @@ mod tests { 1.0, ); let expected_edits = ( - vec![as_strings(vec![ - (MinusNoop, "a"), - (Delete, "a"), - (MinusNoop, "a\n"), - ])], - vec![as_strings(vec![ - (PlusNoop, "a"), - (Insert, "b"), - (PlusNoop, "a\n"), - ])], + vec![vec![(MinusNoop, "a"), (Delete, "a"), (MinusNoop, "a\n")]], + vec![vec![(PlusNoop, "a"), (Insert, "b"), (PlusNoop, "a\n")]], ); assert_consistent(&expected_edits); @@ -164,9 +158,11 @@ mod tests { #[test] fn test_infer_edit_sections_1_nonascii() { + let minus_lines = vec!["áaa\n".to_string()]; + let plus_lines = vec!["ááb\n".to_string()]; let actual_edits = infer_edit_sections( - &vec!["áaa\n".to_string()], - &vec!["ááb\n".to_string()], + &minus_lines, + &plus_lines, MinusNoop, Delete, PlusNoop, @@ -174,16 +170,8 @@ mod tests { 1.0, ); let expected_edits = ( - vec![as_strings(vec![ - (MinusNoop, "á"), - (Delete, "aa"), - (MinusNoop, "\n"), - ])], - vec![as_strings(vec![ - (PlusNoop, "á"), - (Insert, "áb"), - (PlusNoop, "\n"), - ])], + vec![vec![(MinusNoop, "á"), (Delete, "aa"), (MinusNoop, "\n")]], + vec![vec![(PlusNoop, "á"), (Insert, "áb"), (PlusNoop, "\n")]], ); assert_consistent(&expected_edits); @@ -193,9 +181,12 @@ mod tests { #[test] fn test_infer_edit_sections_2() { + let minus_lines = vec!["d.iteritems()\n".to_string()]; + let plus_lines = vec!["d.items()\n".to_string()]; + let actual_edits = infer_edit_sections( - &vec!["d.iteritems()\n".to_string()], - &vec!["d.items()\n".to_string()], + &minus_lines, + &plus_lines, MinusNoop, Delete, PlusNoop, @@ -203,26 +194,26 @@ mod tests { 1.0, ); let expected_edits = ( - vec![as_strings(vec![ + vec![vec![ (MinusNoop, "d."), (Delete, "iter"), (MinusNoop, "items()\n"), - ])], - vec![as_strings(vec![ + ]], + vec![vec![ (PlusNoop, "d."), (Insert, ""), (PlusNoop, "items()\n"), - ])], + ]], ); assert_consistent(&expected_edits); assert_consistent(&actual_edits); assert_eq!(actual_edits, expected_edits); } - type EditSection = (EditOperationTag, String); - type EditSections = Vec<EditSection>; - type LineEditSections = Vec<EditSections>; - type Edits = (LineEditSections, LineEditSections); + type EditSection<'a> = (EditOperationTag, &'a str); + type EditSections<'a> = Vec<EditSection<'a>>; + type LineEditSections<'a> = Vec<EditSections<'a>>; + type Edits<'a> = (LineEditSections<'a>, LineEditSections<'a>); fn assert_consistent(edits: &Edits) { let (minus_line_edit_sections, plus_line_edit_sections) = edits; @@ -247,14 +238,6 @@ mod tests { (total, delta) } - fn as_strings(sections: Vec<(EditOperationTag, &str)>) -> EditSections { - let mut new_sections = Vec::new(); - for (edit, s) in sections { - new_sections.push((edit, s.to_string())); - } - new_sections - } - // For debugging test failures: #[allow(dead_code)] diff --git a/src/paint.rs b/src/paint.rs index 7672918b..d15e2dcb 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -46,23 +46,28 @@ impl<'a> Painter<'a> { pub fn paint_buffered_lines(&mut self) { let (minus_line_syntax_style_sections, plus_line_syntax_style_sections) = - self.get_syntax_style_sections(); + Self::get_syntax_style_sections( + &self.minus_lines, + &self.plus_lines, + &mut self.highlighter, + self.config, + ); let (minus_line_diff_style_sections, plus_line_diff_style_sections) = - self.get_diff_style_sections(); + Self::get_diff_style_sections(&self.minus_lines, &self.plus_lines, self.config); // TODO: lines and style sections contain identical line text if self.minus_lines.len() > 0 { Painter::paint_lines( &mut self.output_buffer, - &minus_line_syntax_style_sections, - &minus_line_diff_style_sections, + minus_line_syntax_style_sections, + minus_line_diff_style_sections, ); self.minus_lines.clear(); } if self.plus_lines.len() > 0 { Painter::paint_lines( &mut self.output_buffer, - &plus_line_syntax_style_sections, - &plus_line_diff_style_sections, + plus_line_syntax_style_sections, + plus_line_diff_style_sections, ); self.plus_lines.clear(); } @@ -72,11 +77,11 @@ impl<'a> Painter<'a> { /// highlighting styles, and write colored lines to output buffer. pub fn paint_lines( output_buffer: &mut String, - syntax_style_sections: &Vec<Vec<(Style, String)>>, - diff_style_sections: &Vec<Vec<(StyleModifier, String)>>, + syntax_style_sections: Vec<Vec<(Style, &str)>>, + diff_style_sections: Vec<Vec<(StyleModifier, &str)>>, ) { for (syntax_sections, diff_sections) in - syntax_style_sections.iter().zip(diff_style_sections) + syntax_style_sections.iter().zip(diff_style_sections.iter()) { for (style, text) in superimpose_style_sections(syntax_sections, diff_sections) { paint_text(&text, style, output_buffer).unwrap(); @@ -92,24 +97,27 @@ impl<'a> Painter<'a> { } /// Perform syntax highlighting for minus and plus lines in buffer. - fn get_syntax_style_sections( - &mut self, - ) -> (Vec<Vec<(Style, String)>>, Vec<Vec<(Style, String)>>) { + fn get_syntax_style_sections<'m, 'p>( + minus_lines: &'m Vec<String>, + plus_lines: &'p Vec<String>, + highlighter: &mut HighlightLines, + config: &config::Config, + ) -> (Vec<Vec<(Style, &'m str)>>, Vec<Vec<(Style, &'p str)>>) { let mut minus_line_sections = Vec::new(); - for line in self.minus_lines.iter() { + for line in minus_lines.iter() { minus_line_sections.push(Painter::get_line_syntax_style_sections( &line, - &mut self.highlighter, - &self.config, - self.config.opt.highlight_removed, + highlighter, + &config, + config.opt.highlight_removed, )); } let mut plus_line_sections = Vec::new(); - for line in self.plus_lines.iter() { + for line in plus_lines.iter() { plus_line_sections.push(Painter::get_line_syntax_style_sections( &line, - &mut self.highlighter, - &self.config, + highlighter, + &config, true, )); } @@ -117,57 +125,57 @@ impl<'a> Painter<'a> { } pub fn get_line_syntax_style_sections( - line: &str, + line: &'a str, highlighter: &mut HighlightLines, config: &config::Config, should_syntax_highlight: bool, - ) -> Vec<(Style, String)> { + ) -> Vec<(Style, &'a str)> { if should_syntax_highlight { - highlighter - .highlight(line, &config.syntax_set) - .iter() - .map(|(style, s)| (*style, s.to_string())) - .collect::<Vec<(Style, String)>>() + highlighter.highlight(line, &config.syntax_set) } else { - vec![(config.no_style, line.to_string())] + vec![(config.no_style, line)] } } /// Set background styles to represent diff for minus and plus lines in buffer. - fn get_diff_style_sections( - &mut self, + fn get_diff_style_sections<'m, 'p>( + minus_lines: &'m Vec<String>, + plus_lines: &'p Vec<String>, + config: &config::Config, ) -> ( - Vec<Vec<(StyleModifier, String)>>, - Vec<Vec<(StyleModifier, String)>>, + Vec<Vec<(StyleModifier, &'m str)>>, + Vec<Vec<(StyleModifier, &'p str)>>, ) { - if self.minus_lines.len() == self.plus_lines.len() { + if minus_lines.len() == plus_lines.len() { edits::infer_edit_sections( - &self.minus_lines, - &self.plus_lines, - self.config.minus_style_modifier, - self.config.minus_emph_style_modifier, - self.config.plus_style_modifier, - self.config.plus_emph_style_modifier, + minus_lines, + plus_lines, + config.minus_style_modifier, + config.minus_emph_style_modifier, + config.plus_style_modifier, + config.plus_emph_style_modifier, 0.66, ) } else { - self.get_diff_style_sections_plain() + Self::get_diff_style_sections_plain(minus_lines, plus_lines, config) } } - fn get_diff_style_sections_plain( - &mut self, + fn get_diff_style_sections_plain<'m, 'p>( + minus_lines: &'m Vec<String>, + plus_lines: &'p Vec<String>, + config: &config::Config, ) -> ( - Vec<Vec<(StyleModifier, String)>>, - Vec<Vec<(StyleModifier, String)>>, + Vec<Vec<(StyleModifier, &'m str)>>, + Vec<Vec<(StyleModifier, &'p str)>>, ) { let mut minus_line_sections = Vec::new(); - for line in self.minus_lines.iter() { - minus_line_sections.push(vec![(self.config.minus_style_modifier, line.to_string())]); + for line in minus_lines.iter() { + minus_line_sections.push(vec![(config.minus_style_modifier, &line[..])]); } let mut plus_line_sections = Vec::new(); - for line in self.plus_lines.iter() { - plus_line_sections.push(vec![(self.config.plus_style_modifier, line.to_string())]); + for line in plus_lines.iter() { + plus_line_sections.push(vec![(config.plus_style_modifier, &line[..])]); } (minus_line_sections, plus_line_sections) } @@ -204,8 +212,8 @@ mod superimpose_style_sections { use syntect::highlighting::{Style, StyleModifier}; pub fn superimpose_style_sections( - sections_1: &Vec<(Style, String)>, - sections_2: &Vec<(StyleModifier, String)>, + sections_1: &Vec<(Style, &str)>, + sections_2: &Vec<(StyleModifier, &str)>, ) -> Vec<(Style, String)> { coalesce(superimpose( explode(sections_1) @@ -215,13 +223,13 @@ mod superimpose_style_sections { )) } - fn explode<T>(style_sections: &Vec<(T, String)>) -> Vec<(T, char)> + fn explode<T>(style_sections: &Vec<(T, &str)>) -> Vec<(T, char)> where T: Copy, { let mut exploded: Vec<(T, char)> = Vec::new(); - for (style, string) in style_sections { - for c in string.chars() { + for (style, s) in style_sections { + for c in s.chars() { exploded.push((*style, c)); } } @@ -289,10 +297,9 @@ mod superimpose_style_sections { #[test] fn test_superimpose_style_sections_1() { - let string = String::from("ab"); - let sections_1 = vec![(STYLE, string.clone())]; - let sections_2 = vec![(STYLE_MODIFIER, string.clone())]; - let superimposed = vec![(SUPERIMPOSED_STYLE, string.clone())]; + let sections_1 = vec![(STYLE, "ab")]; + let sections_2 = vec![(STYLE_MODIFIER, "ab")]; + let superimposed = vec![(SUPERIMPOSED_STYLE, "ab".to_string())]; assert_eq!( superimpose_style_sections(§ions_1, §ions_2), superimposed @@ -301,11 +308,8 @@ mod superimpose_style_sections { #[test] fn test_superimpose_style_sections_2() { - let sections_1 = vec![(STYLE, String::from("ab"))]; - let sections_2 = vec![ - (STYLE_MODIFIER, String::from("a")), - (STYLE_MODIFIER, String::from("b")), - ]; + let sections_1 = vec![(STYLE, "ab")]; + let sections_2 = vec![(STYLE_MODIFIER, "a"), (STYLE_MODIFIER, "b")]; let superimposed = vec![(SUPERIMPOSED_STYLE, String::from("ab"))]; assert_eq!( superimpose_style_sections(§ions_1, §ions_2), @@ -316,9 +320,8 @@ mod superimpose_style_sections { #[test] fn test_explode() { let arbitrary = 0; - let string = String::from("ab"); assert_eq!( - explode(&vec![(arbitrary, string)]), + explode(&vec![(arbitrary, "ab")]), vec![(arbitrary, 'a'), (arbitrary, 'b')] ) } diff --git a/src/parse.rs b/src/parse.rs index 981293d4..7485b9c9 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -44,7 +44,7 @@ pub fn get_file_change_description_from_file_paths(minus_file: &str, plus_file: /// Given input like /// "@@ -74,15 +74,14 @@ pub fn delta(" /// Return " pub fn delta(" -pub fn parse_hunk_metadata(line: &str) -> (String, String) { +pub fn parse_hunk_metadata(line: &str) -> (&str, &str) { let mut iter = line.split("@@").skip(1); let line_number = iter .next() @@ -54,9 +54,8 @@ pub fn parse_hunk_metadata(line: &str) -> (String, String) { .next() .and_then(|s| s.split(",").next()) }) - .unwrap_or("") - .to_string(); - let code_fragment = iter.next().unwrap_or("").to_string(); + .unwrap_or(""); + let code_fragment = iter.next().unwrap_or(""); (code_fragment, line_number) } @@ -107,7 +106,7 @@ mod tests { fn test_parse_hunk_metadata() { assert_eq!( parse_hunk_metadata("@@ -74,15 +75,14 @@ pub fn delta(\n"), - (" pub fn delta(\n".to_string(), "75".to_string()) + (" pub fn delta(\n", "75") ); } } |