diff options
author | Catherine Noll <noll.catherine@gmail.com> | 2020-06-07 14:54:22 -0400 |
---|---|---|
committer | Catherine Noll <noll.catherine@gmail.com> | 2020-06-08 22:43:24 -0400 |
commit | d5ca6d944dbf62e71fe2b75242e342f8b0b953b3 (patch) | |
tree | f90852ace8e9aea953588b632b8b7ca0754b4b02 /src/paint.rs | |
parent | bb82773f61f207537d25d4f5d73be458e3e379cf (diff) |
Add --number option for showing line numbers. Also adds related options:
- format string for specifying minus number line
- format string for specifying plus number line
- minus number style
- plus number style
- minus format string style
- plus format string style
Diffstat (limited to 'src/paint.rs')
-rw-r--r-- | src/paint.rs | 103 |
1 files changed, 101 insertions, 2 deletions
diff --git a/src/paint.rs b/src/paint.rs index bfd029ef..b18a4399 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -1,3 +1,5 @@ +use lazy_static::lazy_static; +use regex::Regex; use std::io::Write; use ansi_term; @@ -22,6 +24,8 @@ pub struct Painter<'a> { pub highlighter: HighlightLines<'a>, pub config: &'a config::Config<'a>, pub output_buffer: String, + pub minus_line_number: usize, + pub plus_line_number: usize, } impl<'a> Painter<'a> { @@ -37,6 +41,8 @@ impl<'a> Painter<'a> { highlighter: dummy_highlighter, writer, config, + minus_line_number: 0, + plus_line_number: 0, } } @@ -71,11 +77,23 @@ impl<'a> Painter<'a> { ); let (minus_line_diff_style_sections, plus_line_diff_style_sections) = Self::get_diff_style_sections(&self.minus_lines, &self.plus_lines, self.config); + + let mut minus_line_numbers = Vec::new(); + let mut plus_line_numbers = Vec::new(); + for _line in &self.minus_lines { + minus_line_numbers.push(Some((Some(self.minus_line_number), None))); + self.minus_line_number += 1; + } + for _line in &self.plus_lines { + plus_line_numbers.push(Some((None, Some(self.plus_line_number)))); + self.plus_line_number += 1; + } // TODO: lines and style sections contain identical line text if !self.minus_lines.is_empty() { Painter::paint_lines( minus_line_syntax_style_sections, minus_line_diff_style_sections, + minus_line_numbers, &mut self.output_buffer, self.config, self.config.minus_line_marker, @@ -88,6 +106,7 @@ impl<'a> Painter<'a> { Painter::paint_lines( plus_line_syntax_style_sections, plus_line_diff_style_sections, + plus_line_numbers, &mut self.output_buffer, self.config, self.config.plus_line_marker, @@ -105,6 +124,7 @@ impl<'a> Painter<'a> { pub fn paint_lines( syntax_style_sections: Vec<Vec<(SyntectStyle, &str)>>, diff_style_sections: Vec<Vec<(Style, &str)>>, + line_number_sections: Vec<Option<(Option<usize>, Option<usize>)>>, output_buffer: &mut String, config: &config::Config, prefix: &str, @@ -120,8 +140,11 @@ impl<'a> Painter<'a> { // 2. We must ensure that we fill rightwards with the appropriate // non-emph background color. In that case we don't use the last // style of the line, because this might be emph. - for (syntax_sections, diff_sections) in - syntax_style_sections.iter().zip(diff_style_sections.iter()) + + for ((syntax_sections, diff_sections), line_numbers) in syntax_style_sections + .iter() + .zip(diff_style_sections.iter()) + .zip(line_number_sections.iter()) { let non_emph_style = if style_sections_contain_more_than_one_style(diff_sections) { non_emph_style // line contains an emph section @@ -130,6 +153,45 @@ impl<'a> Painter<'a> { }; let mut ansi_strings = Vec::new(); let mut handled_prefix = false; + if config.show_line_numbers && line_numbers.is_some() { + let (minus, plus) = line_numbers.unwrap(); + let (minus_before, minus_number, minus_after) = + get_line_number_components(minus, &config.number_minus_format); + let (plus_before, plus_number, plus_after) = + get_line_number_components(plus, &config.number_plus_format); + + ansi_strings.push( + config + .number_minus_format_style + .ansi_term_style + .paint(minus_before), + ); + ansi_strings.push( + config + .number_minus_style + .ansi_term_style + .paint(minus_number), + ); + ansi_strings.push( + config + .number_minus_format_style + .ansi_term_style + .paint(minus_after), + ); + ansi_strings.push( + config + .number_plus_format_style + .ansi_term_style + .paint(plus_before), + ); + ansi_strings.push(config.number_plus_style.ansi_term_style.paint(plus_number)); + ansi_strings.push( + config + .number_plus_format_style + .ansi_term_style + .paint(plus_after), + ); + } for (section_style, mut text) in superimpose_style_sections( syntax_sections, diff_sections, @@ -499,3 +561,40 @@ mod superimpose_style_sections { } } } + +lazy_static! { + static ref LINE_NUMBER_REGEXP: Regex = + Regex::new(r"(?P<before>.*)(?P<ln>%ln)(?P<after>.*)").unwrap(); +} + +fn format_line_number(line_number: Option<usize>) -> String { + match line_number { + Some(x) => format!("{:^4}", x), + None => format!(" "), + } +} + +fn get_line_number_components( + number: Option<usize>, + number_format: &str, +) -> (String, String, String) { + let _caps = LINE_NUMBER_REGEXP.captures(number_format); + + let caps = match _caps { + Some(_) => _caps.unwrap(), + None => return (number_format.to_string(), "".to_string(), "".to_string()), + }; + + let before = caps.name("before").unwrap().as_str(); + let ln = caps.name("ln"); + let after = caps.name("after").unwrap().as_str(); + let display_number = match ln { + Some(_) => number, + None => None, + }; + ( + before.to_string(), + format_line_number(display_number), + after.to_string(), + ) +} |