diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 6c6ed01..6ad3c36 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -37,6 +37,6 @@ fn main() { }; let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, false); println!("{}", dlf.format(&dl)); } diff --git a/examples/footer.rs b/examples/footer.rs index 7cbc949..1814be1 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -34,6 +34,6 @@ fn main() { }; let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, false); println!("{}", dlf.format(&dl)); } diff --git a/examples/format.rs b/examples/format.rs index 30d86b5..d6a77ae 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -55,6 +55,6 @@ fn main() { }; let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, false); println!("{}", dlf.format(&dl)); } diff --git a/examples/multislice.rs b/examples/multislice.rs index e1f2946..47981b7 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -31,6 +31,6 @@ fn main() { }; let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, false); println!("{}", dlf.format(&dl)); } diff --git a/src/display_list/structs.rs b/src/display_list/structs.rs index ecd9eb4..0d3e0bc 100644 --- a/src/display_list/structs.rs +++ b/src/display_list/structs.rs @@ -131,7 +131,7 @@ pub enum DisplayMarkType { /// use annotate_snippets::display_list::*; /// use annotate_snippets::formatter::DisplayListFormatter; /// - /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors /// /// let dl = DisplayList { /// body: vec![ @@ -161,7 +161,7 @@ pub enum DisplayMarkType { /// use annotate_snippets::display_list::*; /// use annotate_snippets::formatter::DisplayListFormatter; /// - /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors /// /// let dl = DisplayList { /// body: vec![ @@ -214,7 +214,7 @@ pub enum DisplayHeaderType { /// use annotate_snippets::display_list::*; /// use annotate_snippets::formatter::DisplayListFormatter; /// - /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors /// /// let dl = DisplayList { /// body: vec![ @@ -236,7 +236,7 @@ pub enum DisplayHeaderType { /// use annotate_snippets::display_list::*; /// use annotate_snippets::formatter::DisplayListFormatter; /// - /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors /// /// let dl = DisplayList { /// body: vec![ diff --git a/src/formatter/mod.rs b/src/formatter/mod.rs index 189c90d..eb1392d 100644 --- a/src/formatter/mod.rs +++ b/src/formatter/mod.rs @@ -20,9 +20,11 @@ fn repeat_char(c: char, n: usize) -> String { s.repeat(n) } -/// DisplayListFormatter' constructor accepts a single argument which -/// allows the formatter to optionally apply colors and emphasis -/// using `ansi_term` crate. +/// DisplayListFormatter' constructor accepts two arguments: +/// +/// * `color` allows the formatter to optionally apply colors and emphasis +/// using the `ansi_term` crate. +/// * `anonymized_line_numbers` will replace line numbers in the left column with the text `LL`. /// /// Example: /// @@ -30,7 +32,7 @@ fn repeat_char(c: char, n: usize) -> String { /// use annotate_snippets::formatter::DisplayListFormatter; /// use annotate_snippets::display_list::{DisplayList, DisplayLine, DisplaySourceLine}; /// -/// let dlf = DisplayListFormatter::new(false); // Don't use colors +/// let dlf = DisplayListFormatter::new(false, false); // Don't use colors, Don't anonymize line numbers /// /// let dl = DisplayList { /// body: vec![ @@ -48,23 +50,33 @@ fn repeat_char(c: char, n: usize) -> String { /// ``` pub struct DisplayListFormatter { stylesheet: Box, + anonymized_line_numbers: bool, } impl DisplayListFormatter { - /// Constructor for the struct. The argument `color` selects - /// the stylesheet depending on the user preferences and `ansi_term` - /// crate availability. - pub fn new(color: bool) -> Self { + const ANONYMIZED_LINE_NUM: &'static str = "LL"; + + /// Constructor for the struct. + /// + /// The argument `color` selects the stylesheet depending on the user preferences and + /// `ansi_term` crate availability. + /// + /// The argument `anonymized_line_numbers` will replace line numbers in the left column with + /// the text `LL`. This can be useful to enable when running UI tests, such as in the Rust + /// test suite. + pub fn new(color: bool, anonymized_line_numbers: bool) -> Self { if color { Self { #[cfg(feature = "ansi_term")] stylesheet: Box::new(AnsiTermStylesheet {}), #[cfg(not(feature = "ansi_term"))] stylesheet: Box::new(NoColorStylesheet {}), + anonymized_line_numbers, } } else { Self { stylesheet: Box::new(NoColorStylesheet {}), + anonymized_line_numbers, } } } @@ -75,7 +87,13 @@ impl DisplayListFormatter { DisplayLine::Source { lineno: Some(lineno), .. - } => cmp::max(lineno.to_string().len(), max), + } => { + if self.anonymized_line_numbers { + Self::ANONYMIZED_LINE_NUM.len() + } else { + cmp::max(lineno.to_string().len(), max) + } + }, _ => max, }); let inline_marks_width = dl.body.iter().fold(0, |max, line| match line { @@ -285,7 +303,11 @@ impl DisplayListFormatter { inline_marks, line, } => { - let lineno = self.format_lineno(*lineno, lineno_width); + let lineno = if self.anonymized_line_numbers { + Self::ANONYMIZED_LINE_NUM.to_string() + } else { + self.format_lineno(*lineno, lineno_width) + }; let marks = self.format_inline_marks(inline_marks, inline_marks_width); let lf = self.format_source_line(line); let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); diff --git a/tests/fixtures.rs b/tests/fixtures.rs index 869ca2e..b6fc147 100644 --- a/tests/fixtures.rs +++ b/tests/fixtures.rs @@ -46,7 +46,7 @@ fn test_fixtures() { let expected_out = read_file(&path_out).expect("Failed to read file"); let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, false); let actual_out = dlf.format(&dl); println!("{}", expected_out); println!("{}", actual_out.trim_end()); diff --git a/tests/formatter.rs b/tests/formatter.rs index 2f5dee6..c0bdc11 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -11,7 +11,7 @@ fn test_source_empty() { line: DisplaySourceLine::Empty, }]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), " |"); } @@ -37,7 +37,7 @@ fn test_source_content() { }, ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -65,7 +65,7 @@ fn test_source_annotation_standalone_singleline() { }, }]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), " | ^^^^^ Example string"); } @@ -109,7 +109,7 @@ fn test_source_annotation_standalone_multiline() { }, ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -241,7 +241,7 @@ fn test_source_annotation_standalone_multi_annotation() { }, ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), " | ----- info: Example string\n | Second line\n | warning: This is a note\n | Second line of the warning\n | ----- info: This is an info\n | ----- help: This is help\n | This is an annotation of type none"); } @@ -270,7 +270,7 @@ fn test_fold_line() { }, ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -286,7 +286,7 @@ fn test_raw_origin_initial_nopos() { header_type: DisplayHeaderType::Initial, })]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), "--> src/test.rs"); } @@ -299,7 +299,7 @@ fn test_raw_origin_initial_pos() { header_type: DisplayHeaderType::Initial, })]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), "--> src/test.rs:23:15"); } @@ -312,7 +312,7 @@ fn test_raw_origin_continuation() { header_type: DisplayHeaderType::Continuation, })]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), "::: src/test.rs:23:15"); } @@ -332,7 +332,7 @@ fn test_raw_annotation_unaligned() { continuation: false, })]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), "error[E0001]: This is an error"); } @@ -366,7 +366,7 @@ fn test_raw_annotation_unaligned_multiline() { }), ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -389,7 +389,7 @@ fn test_raw_annotation_aligned() { continuation: false, })]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), " = error[E0001]: This is an error"); } @@ -423,7 +423,7 @@ fn test_raw_annotation_aligned_multiline() { }), ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -472,7 +472,7 @@ fn test_different_annotation_types() { }), ]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!( dlf.format(&dl), @@ -491,7 +491,50 @@ fn test_inline_marks_empty_line() { line: DisplaySourceLine::Empty, }]); - let dlf = DisplayListFormatter::new(false); + let dlf = DisplayListFormatter::new(false, false); assert_eq!(dlf.format(&dl), " | |",); } + +#[test] +fn test_anon_lines() { + let dl = DisplayList::from(vec![ + DisplayLine::Source { + lineno: Some(56), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "This is an example".to_string(), + range: (0, 19), + }, + }, + DisplayLine::Source { + lineno: Some(57), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: "of content lines".to_string(), + range: (0, 19), + }, + }, + ]); + + let dlf = DisplayListFormatter::new(false, true); + + assert_eq!( + dlf.format(&dl), + "LL | This is an example\nLL | of content lines" + ); +} + +#[test] +fn test_raw_origin_initial_pos_anon_lines() { + let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { + path: "src/test.rs".to_string(), + pos: Some((23, 15)), + header_type: DisplayHeaderType::Initial, + })]); + + let dlf = DisplayListFormatter::new(false, true); + + // Using anonymized_line_numbers should not affect the inital position + assert_eq!(dlf.format(&dl), "--> src/test.rs:23:15"); +}