diff --git a/src/formatter.rs b/src/formatter.rs index 06d575e..b596832 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -7,6 +7,7 @@ use crate::{config::Indent, extensions::FindFrom, types::LineType}; #[derive(Debug, Clone, Copy, Eq)] /// Represents a snippet from a page of a specific highlighting class. pub enum PageSnippet { + Indent(T), CommandName(T), Variable(T), NormalCode(T), @@ -23,6 +24,7 @@ impl PageSnippet { F: FnOnce(T) -> U, { match self { + PageSnippet::Indent(s) => PageSnippet::Indent(f(s)), PageSnippet::CommandName(s) => PageSnippet::CommandName(f(s)), PageSnippet::Variable(s) => PageSnippet::Variable(f(s)), PageSnippet::NormalCode(s) => PageSnippet::NormalCode(f(s)), @@ -37,7 +39,8 @@ impl PageSnippet { impl, U> PartialEq> for PageSnippet { fn eq(&self, other: &PageSnippet) -> bool { match (self, other) { - (PageSnippet::CommandName(s), PageSnippet::CommandName(t)) + (PageSnippet::Indent(s), PageSnippet::Indent(t)) + | (PageSnippet::CommandName(s), PageSnippet::CommandName(t)) | (PageSnippet::Variable(s), PageSnippet::Variable(t)) | (PageSnippet::NormalCode(s), PageSnippet::NormalCode(t)) | (PageSnippet::Description(s), PageSnippet::Description(t)) @@ -54,9 +57,8 @@ impl PageSnippet<&str> { use PageSnippet::*; match self { - CommandName(s) | Variable(s) | NormalCode(s) | Description(s) | Text(s) | Title(s) => { - s.is_empty() - } + Indent(s) | CommandName(s) | Variable(s) | NormalCode(s) | Description(s) | Text(s) + | Title(s) => s.is_empty(), Linebreak => false, } } @@ -87,7 +89,7 @@ where LineType::Title(title) => { if show_title { process_snippet(PageSnippet::Linebreak)?; - process_snippet(PageSnippet::Title(&base_indent))?; + process_snippet(PageSnippet::Indent(&base_indent))?; process_snippet(PageSnippet::Title(&title))?; process_snippet(PageSnippet::Linebreak)?; } else { @@ -99,17 +101,17 @@ where debug!("Detected command name: {}", &command); } LineType::Description(text) => { - process_snippet(PageSnippet::Description(&base_indent))?; + process_snippet(PageSnippet::Indent(&base_indent))?; process_snippet(PageSnippet::Description(&text))?; process_snippet(PageSnippet::Linebreak)?; } LineType::ExampleText(text) => { - process_snippet(PageSnippet::Text(&base_indent))?; + process_snippet(PageSnippet::Indent(&base_indent))?; process_snippet(PageSnippet::Text(&text))?; process_snippet(PageSnippet::Linebreak)?; } LineType::ExampleCode(text) => { - process_snippet(PageSnippet::NormalCode(&command_indent))?; + process_snippet(PageSnippet::Indent(&command_indent))?; highlight_code(&command, &text, process_snippet)?; process_snippet(PageSnippet::Linebreak)?; } @@ -242,6 +244,45 @@ fn is_freestanding_substring(surrounding: &str, substring: (usize, usize)) -> bo mod tests { use super::*; + #[test] + fn indentation_uses_dedicated_snippets() { + let lines = [ + LineType::Title("tldr".to_owned()), + LineType::Description("description".to_owned()), + LineType::ExampleText("example".to_owned()), + LineType::ExampleCode("tldr --help".to_owned()), + ]; + let mut snippets = Vec::new(); + + highlight_lines( + lines.into_iter(), + &mut |snippet| { + snippets.push(snippet.map(str::to_owned)); + Ok::<(), ()>(()) + }, + true, + true, + Indent { + base: 2, + command: 4, + }, + ) + .unwrap(); + + assert_eq!( + snippets + .iter() + .filter(|snippet| matches!(snippet, PageSnippet::Indent(_))) + .collect::>(), + [ + &PageSnippet::Indent(" ".to_owned()), + &PageSnippet::Indent(" ".to_owned()), + &PageSnippet::Indent(" ".to_owned()), + &PageSnippet::Indent(" ".to_owned()) + ] + ); + } + #[test] fn test_is_freestanding_substring() { assert!(is_freestanding_substring("I love tldr", (0, 1))); diff --git a/src/output.rs b/src/output.rs index 6243b44..c2bebaa 100644 --- a/src/output.rs +++ b/src/output.rs @@ -87,6 +87,7 @@ fn print_snippet( use PageSnippet::*; match snip { + Indent(s) => write!(writer, "{s}"), CommandName(s) | Title(s) => write!(writer, "{}", s.paint(style.command_name)), Variable(s) => write!(writer, "{}", s.paint(style.example_variable)), NormalCode(s) => write!(writer, "{}", s.paint(style.example_code)), @@ -95,3 +96,21 @@ fn print_snippet( Linebreak => writeln!(writer), } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn indent_output_is_unstyled() { + let mut output = Vec::new(); + let style = StyleConfig { + example_code: yansi::Style::new().underline(), + ..StyleConfig::default() + }; + + print_snippet(&mut output, PageSnippet::Indent(" "), &style).unwrap(); + + assert_eq!(output, b" "); + } +} diff --git a/tests/rendered/apt.ja.expected b/tests/rendered/apt.ja.expected index efdd35d..e79bf7e 100644 --- a/tests/rendered/apt.ja.expected +++ b/tests/rendered/apt.ja.expected @@ -3,35 +3,35 @@ Ubuntuのバージョンが16.04か、それ以降で対話モードを使う場合`apt-get`の代わりとして使用します。 詳しくはこちら: - 利用可能なパーケージとバージョンのリストの更新(他の`apt`コマンドの前での実行を推奨): + 利用可能なパーケージとバージョンのリストの更新(他の`apt`コマンドの前での実行を推奨): - sudo apt update + sudo apt update - 指定されたパッケージの検索: + 指定されたパッケージの検索: - apt search パッケージ + apt search パッケージ - パッケージの情報を出力: + パッケージの情報を出力: - apt show パッケージ + apt show パッケージ - パッケージのインストール、または利用可能な最新バージョンに更新: + パッケージのインストール、または利用可能な最新バージョンに更新: - sudo apt install パッケージ + sudo apt install パッケージ - パッケージの削除(`sudo apt remove --purge`の場合設定ファイルも削除): + パッケージの削除(`sudo apt remove --purge`の場合設定ファイルも削除): - sudo apt remove パッケージ + sudo apt remove パッケージ - インストールされている全てのパッケージを最新のバージョンにアップグレード: + インストールされている全てのパッケージを最新のバージョンにアップグレード: - sudo apt upgrade + sudo apt upgrade - インストールできるすべてのパッケージを表示: + インストールできるすべてのパッケージを表示: - apt list + apt list - インストールされた全てのパッケージを表示(依存関係も表示): + インストールされた全てのパッケージを表示(依存関係も表示): - apt list --installed + apt list --installed diff --git a/tests/rendered/inkscape-default.expected b/tests/rendered/inkscape-default.expected index 3b37f0e..5b91247 100644 --- a/tests/rendered/inkscape-default.expected +++ b/tests/rendered/inkscape-default.expected @@ -2,31 +2,31 @@ 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: + Open an SVG file in the Inkscape GUI: - inkscape filename.svg + inkscape filename.svg - Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): + Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): - inkscape filename.svg -e filename.png + inkscape filename.svg -e filename.png - Export an SVG file into a bitmap of 600x400 pixels (aspect ratio distortion may occur): + 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 + inkscape filename.svg -e filename.png -w 600 -h 400 - Export a single object, given its ID, into a bitmap: + Export a single object, given its ID, into a bitmap: - inkscape filename.svg -i id -e object.png + inkscape filename.svg -i id -e object.png - Export an SVG document to PDF, converting all texts to paths: + 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 + 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: + 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 + 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: + Some invalid command just to test the correct highlighting of the command name: - inkscape --use-inkscape=v3.0 file + inkscape --use-inkscape=v3.0 file diff --git a/tests/rendered/inkscape-with-config.expected b/tests/rendered/inkscape-with-config.expected index 33540a3..e79b219 100644 --- a/tests/rendered/inkscape-with-config.expected +++ b/tests/rendered/inkscape-with-config.expected @@ -2,31 +2,31 @@ 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: + 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): + 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): + 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: + 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: + 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: + 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: + 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 index ff2de4a..7e81d41 100644 --- a/tests/rendered/inkscape-with-title.expected +++ b/tests/rendered/inkscape-with-title.expected @@ -1,34 +1,34 @@ - inkscape + 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: + Open an SVG file in the Inkscape GUI: - inkscape filename.svg + inkscape filename.svg - Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): + Export an SVG file into a bitmap with the default format (PNG) and the default resolution (90 DPI): - inkscape filename.svg -e filename.png + inkscape filename.svg -e filename.png - Export an SVG file into a bitmap of 600x400 pixels (aspect ratio distortion may occur): + 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 + inkscape filename.svg -e filename.png -w 600 -h 400 - Export a single object, given its ID, into a bitmap: + Export a single object, given its ID, into a bitmap: - inkscape filename.svg -i id -e object.png + inkscape filename.svg -i id -e object.png - Export an SVG document to PDF, converting all texts to paths: + 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 + 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: + 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 + 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: + Some invalid command just to test the correct highlighting of the command name: - inkscape --use-inkscape=v3.0 file + inkscape --use-inkscape=v3.0 file