diff --git a/docs/src/config.md b/docs/src/config.md index 6eeede4..b0bf922 100644 --- a/docs/src/config.md +++ b/docs/src/config.md @@ -29,6 +29,7 @@ please refer to the subsections of this documentation page [display] compact = false use_pager = true +show_title = false [style.command_name] foreground = "red" diff --git a/docs/src/config_display.md b/docs/src/config_display.md index 36d5f23..56b5cd3 100644 --- a/docs/src/config_display.md +++ b/docs/src/config_display.md @@ -21,3 +21,13 @@ Set this to enforce more compact output, where empty lines are stripped out [display] compact = true + +## `show_title` + +Display the command name at the top of the page output (default `false`). + + [display] + show_title = true + +When enabled, the command name will be displayed at the top of the output, +styled with the `command_name` style configuration. \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index bac3f74..446b841 100644 --- a/src/config.rs +++ b/src/config.rs @@ -157,6 +157,8 @@ struct RawDisplayConfig { pub compact: bool, #[serde(default)] pub use_pager: bool, + #[serde(default)] + pub show_title: bool, } impl From<&RawDisplayConfig> for DisplayConfig { @@ -164,6 +166,7 @@ impl From<&RawDisplayConfig> for DisplayConfig { Self { compact: raw_display_config.compact, use_pager: raw_display_config.use_pager, + show_title: raw_display_config.show_title, } } } @@ -263,6 +266,7 @@ pub struct StyleConfig { pub struct DisplayConfig { pub compact: bool, pub use_pager: bool, + pub show_title: bool, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/formatter.rs b/src/formatter.rs index 369efce..d86de9b 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -12,6 +12,7 @@ pub enum PageSnippet<'a> { NormalCode(&'a str), Description(&'a str), Text(&'a str), + Title(&'a str), Linebreak, } @@ -20,7 +21,9 @@ impl PageSnippet<'_> { use PageSnippet::*; match self { - CommandName(s) | Variable(s) | NormalCode(s) | Description(s) | Text(s) => s.is_empty(), + CommandName(s) | Variable(s) | NormalCode(s) | Description(s) | Text(s) | Title(s) => { + s.is_empty() + } Linebreak => false, } } @@ -31,6 +34,7 @@ pub fn highlight_lines( lines: L, process_snippet: &mut F, keep_empty_lines: bool, + show_title: bool, ) -> Result<(), E> where L: Iterator, @@ -45,8 +49,12 @@ where } } LineType::Title(title) => { - debug!("Ignoring title"); - + if show_title { + process_snippet(PageSnippet::Linebreak)?; + process_snippet(PageSnippet::Title(&title))?; + } else { + debug!("Ignoring title"); + } // This is safe as long as the parsed title is only the command, // and the iterator yields values in order of appearance. command = title; diff --git a/src/output.rs b/src/output.rs index 046abe8..5f1aeae 100644 --- a/src/output.rs +++ b/src/output.rs @@ -69,6 +69,7 @@ pub fn print_page( LineIterator::new(reader), &mut process_snippet, !config.display.compact, + config.display.show_title, ) .context("Could not write to stdout")?; } @@ -92,6 +93,7 @@ fn print_snippet( NormalCode(s) => write!(writer, "{}", s.paint(style.example_code)), Description(s) => writeln!(writer, " {}", s.paint(style.description)), Text(s) => writeln!(writer, " {}", s.paint(style.example_text)), + Title(s) => writeln!(writer, " {}", s.paint(style.command_name)), Linebreak => writeln!(writer), } } diff --git a/tests/lib.rs b/tests/lib.rs index eceb427..ef5777d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -807,6 +807,42 @@ fn test_correct_rendering_with_config() { .stdout(diff(expected)); } +/// An end-to-end integration test for rendering with show_title config option enabled. +#[test] +fn test_show_title_config() { + // Test that default behavior without show_title shows no title + let testenv = TestEnv::new().install_default_cache(); + let expected_no_title = include_str!("rendered/inkscape-default.expected"); + + testenv + .command() + .args(["--color", "always", "inkscape-v2"]) + .assert() + .success() + .stdout(diff(expected_no_title)); + + // Configure to enable show_title + testenv.append_to_config("display.show_title = true\n"); + + let expected_no_color = include_str!("rendered/inkscape-with-title-no-color.expected"); + + testenv + .command() + .args(["inkscape-v2"]) + .assert() + .success() + .stdout(diff(expected_no_color)); + + let expected = include_str!("rendered/inkscape-with-title.expected"); + + testenv + .command() + .args(["--color", "always", "inkscape-v2"]) + .assert() + .success() + .stdout(diff(expected)); +} + #[test] fn test_spaces_find_command() { let testenv = TestEnv::new().install_default_cache(); diff --git a/tests/rendered/inkscape-with-title-no-color.expected b/tests/rendered/inkscape-with-title-no-color.expected new file mode 100644 index 0000000..b6a4572 --- /dev/null +++ b/tests/rendered/inkscape-with-title-no-color.expected @@ -0,0 +1,34 @@ + + inkscape + + An SVG (Scalable Vector Graphics) editing program. + Use -z to not open the GUI and only process files in the console. + + Open an SVG file in the Inkscape GUI: + + inkscape filename.svg + + Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): + + inkscape filename.svg -e filename.png + + Export an SVG file into a bitmap of 600x400 pixels (aspect ratio distortion may occur): + + inkscape filename.svg -e filename.png -w 600 -h 400 + + Export a single object, given its ID, into a bitmap: + + inkscape filename.svg -i id -e object.png + + Export an SVG document to PDF, converting all texts to paths: + + inkscape filename.svg | inkscape | inkscape --export-pdf=inkscape.pdf | inkscape | inkscape --export-text-to-path + + Duplicate the object with id="path123", rotate the duplicate 90 degrees, save the file, and quit Inkscape: + + inkscape filename.svg --select=path123 --verb=EditDuplicate --verb=ObjectRotate90 --verb=FileSave --verb=FileQuit + + Some invalid command just to test the correct highlighting of the command name: + + inkscape --use-inkscape=v3.0 file + diff --git a/tests/rendered/inkscape-with-title.expected b/tests/rendered/inkscape-with-title.expected new file mode 100644 index 0000000..7e7d428 --- /dev/null +++ b/tests/rendered/inkscape-with-title.expected @@ -0,0 +1,34 @@ + + inkscape + + An SVG (Scalable Vector Graphics) editing program. + Use -z to not open the GUI and only process files in the console. + + Open an SVG file in the Inkscape GUI: + + inkscape filename.svg + + Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): + + inkscape filename.svg -e filename.png + + Export an SVG file into a bitmap of 600x400 pixels (aspect ratio distortion may occur): + + inkscape filename.svg -e filename.png -w 600 -h 400 + + Export a single object, given its ID, into a bitmap: + + inkscape filename.svg -i id -e object.png + + Export an SVG document to PDF, converting all texts to paths: + + inkscape filename.svg | inkscape | inkscape --export-pdf=inkscape.pdf | inkscape | inkscape --export-text-to-path + + Duplicate the object with id="path123", rotate the duplicate 90 degrees, save the file, and quit Inkscape: + + inkscape filename.svg --select=path123 --verb=EditDuplicate --verb=ObjectRotate90 --verb=FileSave --verb=FileQuit + + Some invalid command just to test the correct highlighting of the command name: + + inkscape --use-inkscape=v3.0 file +