diff --git a/src/app.rs b/src/app.rs index a9ac691e..5b00658c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -16,7 +16,7 @@ use errors::*; use line_range::LineRange; use style::{OutputComponent, OutputComponents, OutputWrap}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum PagingMode { Always, QuitIfOneScreen, @@ -41,6 +41,10 @@ pub struct Config<'a> { /// The character width of the terminal pub term_width: usize, + /// The width of tab characters. + /// Currently, a value of 0 will cause tabs to be passed through without expanding them. + pub tab_width: usize, + /// Whether or not to simply loop through all input (`cat` mode) pub loop_through: bool, @@ -130,7 +134,7 @@ impl App { to read from standard input.", ).multiple(true) .empty_values(false), - ) + ) .arg( Arg::with_name("language") .short("l") @@ -144,195 +148,209 @@ impl App { language names and file extensions." ).takes_value(true), ).arg( - Arg::with_name("list-languages") - .long("list-languages") - .conflicts_with("list-themes") - .help("Display all supported languages.") - .long_help("Display a list of supported languages for syntax highlighting."), - ).arg( - Arg::with_name("theme") - .long("theme") - .overrides_with("theme") - .takes_value(true) - .help("Set the color theme for syntax highlighting.") - .long_help( - "Set the theme for syntax highlighting. Use '--list-themes' to \ + Arg::with_name("list-languages") + .long("list-languages") + .conflicts_with("list-themes") + .help("Display all supported languages.") + .long_help("Display a list of supported languages for syntax highlighting."), + ).arg( + Arg::with_name("theme") + .long("theme") + .overrides_with("theme") + .takes_value(true) + .help("Set the color theme for syntax highlighting.") + .long_help( + "Set the theme for syntax highlighting. Use '--list-themes' to \ see all available themes. To set a default theme, export the \ BAT_THEME environment variable (e.g.: export \ BAT_THEME=\"TwoDark\").", - ), - ).arg( - Arg::with_name("list-themes") - .long("list-themes") - .help("Display all supported highlighting themes.") - .long_help("Display a list of supported themes for syntax highlighting."), - ).arg( - Arg::with_name("style") - .long("style") - .value_name("style-components") - .use_delimiter(true) - .takes_value(true) - .possible_values(&[ - "auto", "full", "plain", "changes", "header", "grid", "numbers", - ]).default_value("auto") - .help("Comma-separated list of style elements to display.") - .long_help( - "Configure which elements (line numbers, file headers, grid \ + ), + ).arg( + Arg::with_name("list-themes") + .long("list-themes") + .help("Display all supported highlighting themes.") + .long_help("Display a list of supported themes for syntax highlighting."), + ).arg( + Arg::with_name("style") + .long("style") + .value_name("style-components") + .use_delimiter(true) + .takes_value(true) + .possible_values(&[ + "auto", "full", "plain", "changes", "header", "grid", "numbers", + ]).default_value("auto") + .help("Comma-separated list of style elements to display.") + .long_help( + "Configure which elements (line numbers, file headers, grid \ borders, Git modifications, ..) to display in addition to the \ file contents. The argument is a comma-separated list of \ components to display (e.g. 'numbers,changes,grid') or a \ pre-defined style ('full')", - ), - ).arg( - Arg::with_name("plain") - .overrides_with("plain") - .short("p") - .long("plain") - .conflicts_with("style") - .conflicts_with("number") - .help("Show plain style (alias for '--style=plain').") - .long_help( - "Only show plain style, no decorations. This is an alias for \ + ), + ).arg( + Arg::with_name("plain") + .overrides_with("plain") + .short("p") + .long("plain") + .conflicts_with("style") + .conflicts_with("number") + .help("Show plain style (alias for '--style=plain').") + .long_help( + "Only show plain style, no decorations. This is an alias for \ '--style=plain'", - ), - ).arg( - Arg::with_name("number") - .long("number") - .overrides_with("number") - .short("n") - .conflicts_with("style") - .help("Show line numbers (alias for '--style=numbers').") - .long_help( - "Only show line numbers, no other decorations. This is an alias for \ + ), + ).arg( + Arg::with_name("number") + .long("number") + .overrides_with("number") + .short("n") + .conflicts_with("style") + .help("Show line numbers (alias for '--style=numbers').") + .long_help( + "Only show line numbers, no other decorations. This is an alias for \ '--style=numbers'", - ), - ).arg( - Arg::with_name("line-range") - .long("line-range") - .overrides_with("line-range") - .takes_value(true) - .value_name("N:M") - .help("Only print the lines from N to M.") - .long_help( - "Only print the specified range of lines for each file. \ + ), + ).arg( + Arg::with_name("line-range") + .long("line-range") + .overrides_with("line-range") + .takes_value(true) + .value_name("N:M") + .help("Only print the lines from N to M.") + .long_help( + "Only print the specified range of lines for each file. \ For example:\n \ '--line-range 30:40' prints lines 30 to 40\n \ '--line-range :40' prints lines 1 to 40\n \ '--line-range 40:' prints lines 40 to the end of the file", - ), - ).arg( - Arg::with_name("color") - .long("color") - .overrides_with("color") - .takes_value(true) - .value_name("when") - .possible_values(&["auto", "never", "always"]) - .default_value("auto") - .help("When to use colors.") - .long_help("Specify when to use colored output. The automatic mode \ + ), + ).arg( + Arg::with_name("color") + .long("color") + .overrides_with("color") + .takes_value(true) + .value_name("when") + .possible_values(&["auto", "never", "always"]) + .default_value("auto") + .help("When to use colors.") + .long_help("Specify when to use colored output. The automatic mode \ only enables colors if an interactive terminal is detected."), - ).arg( - Arg::with_name("decorations") - .long("decorations") - .overrides_with("decorations") - .takes_value(true) - .value_name("when") - .possible_values(&["auto", "never", "always"]) - .default_value("auto") - .help("When to show the decorations specified by '--style'.") - .long_help("Specify when to use the decorations that have been specified \ + ).arg( + Arg::with_name("decorations") + .long("decorations") + .overrides_with("decorations") + .takes_value(true) + .value_name("when") + .possible_values(&["auto", "never", "always"]) + .default_value("auto") + .help("When to show the decorations specified by '--style'.") + .long_help("Specify when to use the decorations that have been specified \ via '--style'. The automatic mode only enables decorations if \ an interactive terminal is detected."), - ).arg( - Arg::with_name("paging") - .long("paging") - .overrides_with("paging") - .takes_value(true) - .value_name("when") - .possible_values(&["auto", "never", "always"]) - .default_value("auto") - .help("Specify when to use the pager.") - .long_help("Specify when to use the pager. To control which pager \ + ).arg( + Arg::with_name("paging") + .long("paging") + .overrides_with("paging") + .takes_value(true) + .value_name("when") + .possible_values(&["auto", "never", "always"]) + .default_value("auto") + .help("Specify when to use the pager.") + .long_help("Specify when to use the pager. To control which pager \ is used, set the PAGER or BAT_PAGER environment \ variables (the latter takes precedence). The default \ pager is 'less'. To disable the pager permanently, set \ BAT_PAGER to an empty string."), - ).arg( - Arg::with_name("wrap") - .long("wrap") - .overrides_with("wrap") - .takes_value(true) - .value_name("mode") - .possible_values(&["auto", "never", "character"]) - .default_value("auto") - .help("Specify the text-wrapping mode.") - .long_help("Specify the text-wrapping mode."), - ).arg( - Arg::with_name("unbuffered") - .short("u") - .hidden_short_help(true) - .long_help( - "This option exists for POSIX-compliance reasons ('u' is for \ + ).arg( + Arg::with_name("wrap") + .long("wrap") + .overrides_with("wrap") + .takes_value(true) + .value_name("mode") + .possible_values(&["auto", "never", "character"]) + .default_value("auto") + .help("Specify the text-wrapping mode.") + .long_help("Specify the text-wrapping mode."), + ).arg( + Arg::with_name("unbuffered") + .short("u") + .hidden_short_help(true) + .long_help( + "This option exists for POSIX-compliance reasons ('u' is for \ 'unbuffered'). The output is always unbuffered - this option \ is simply ignored.", + ), + ).arg( + Arg::with_name("tabs") + .long("tabs") + .takes_value(true) + .value_name("tabs") + .validator( + |t| t.parse::() + .map_err(|_t| "must be a number") + .map(|_t| ()) // Convert to Result<(), &str> + .map_err(|e| e.to_string()) // Convert to Result<(), String> + ) + .help("Sets the tab width.") + .long_help("Sets the tab width. Use a width of 0 to pass tabs through \ + directly"), + ).arg( + Arg::with_name("terminal-width") + .long("terminal-width") + .takes_value(true) + .value_name("width") + .hidden(true) + .help("Set the width of the terminal"), + ).subcommand( + SubCommand::with_name("cache") + .about("Modify the syntax-definition and theme cache") + .arg( + Arg::with_name("init") + .long("init") + .short("i") + .help("Initialize the syntax/theme cache.") + .long_help( + "Initialize the syntax/theme cache by loading from the \ + source directory (default: the configuration directory).", + ), + ).arg( + Arg::with_name("clear") + .long("clear") + .short("c") + .help("Remove the cached syntax definitions and themes."), + ).arg( + Arg::with_name("config-dir") + .long("config-dir") + .short("d") + .help("Show bat's configuration directory."), + ).group( + ArgGroup::with_name("cache-actions") + .args(&["init", "clear", "config-dir"]) + .required(arg_group_required), + ).arg( + Arg::with_name("source") + .long("source") + .requires("init") + .takes_value(true) + .value_name("dir") + .help("Use a different directory to load syntaxes and themes from."), + ).arg( + Arg::with_name("target") + .long("target") + .requires("init") + .takes_value(true) + .value_name("dir") + .help( + "Use a different directory to store the cached syntax and theme set.", ), ).arg( - Arg::with_name("terminal-width") - .long("terminal-width") - .takes_value(true) - .value_name("width") - .hidden(true) - .help("Set the width of the terminal"), - ).subcommand( - SubCommand::with_name("cache") - .about("Modify the syntax-definition and theme cache") - .arg( - Arg::with_name("init") - .long("init") - .short("i") - .help("Initialize the syntax/theme cache.") - .long_help( - "Initialize the syntax/theme cache by loading from the \ - source directory (default: the configuration directory).", - ), - ).arg( - Arg::with_name("clear") - .long("clear") - .short("c") - .help("Remove the cached syntax definitions and themes."), - ).arg( - Arg::with_name("config-dir") - .long("config-dir") - .short("d") - .help("Show bat's configuration directory."), - ).group( - ArgGroup::with_name("cache-actions") - .args(&["init", "clear", "config-dir"]) - .required(arg_group_required), - ).arg( - Arg::with_name("source") - .long("source") - .requires("init") - .takes_value(true) - .value_name("dir") - .help("Use a different directory to load syntaxes and themes from."), - ).arg( - Arg::with_name("target") - .long("target") - .requires("init") - .takes_value(true) - .value_name("dir") - .help( - "Use a different directory to store the cached syntax and theme set.", - ), - ).arg( - Arg::with_name("blank") - .long("blank") - .requires("init") - .help("Create completely new syntax and theme sets \ + Arg::with_name("blank") + .long("blank") + .requires("init") + .help("Create completely new syntax and theme sets \ (instead of appending to the default sets).") - ), - ).help_message("Print this help message.") + ), + ).help_message("Print this help message.") .version_message("Show version information.") .get_matches() } @@ -341,6 +359,27 @@ impl App { let files = self.files(); let output_components = self.output_components()?; + let paging_mode = match self.matches.value_of("paging") { + Some("always") => PagingMode::Always, + Some("never") => PagingMode::Never, + Some("auto") | _ => if files.contains(&InputFile::StdIn) { + // If we are reading from stdin, only enable paging if we write to an + // interactive terminal and if we do not *read* from an interactive + // terminal. + if self.interactive_output && !atty::is(Stream::Stdin) { + PagingMode::QuitIfOneScreen + } else { + PagingMode::Never + } + } else { + if self.interactive_output { + PagingMode::QuitIfOneScreen + } else { + PagingMode::Never + } + }, + }; + Ok(Config { true_color: is_truecolor_terminal(), language: self.matches.value_of("language"), @@ -364,26 +403,7 @@ impl App { Some("never") => false, Some("auto") | _ => self.interactive_output, }, - paging_mode: match self.matches.value_of("paging") { - Some("always") => PagingMode::Always, - Some("never") => PagingMode::Never, - Some("auto") | _ => if files.contains(&InputFile::StdIn) { - // If we are reading from stdin, only enable paging if we write to an - // interactive terminal and if we do not *read* from an interactive - // terminal. - if self.interactive_output && !atty::is(Stream::Stdin) { - PagingMode::QuitIfOneScreen - } else { - PagingMode::Never - } - } else { - if self.interactive_output { - PagingMode::QuitIfOneScreen - } else { - PagingMode::Never - } - }, - }, + paging_mode, term_width: self .matches .value_of("terminal-width") @@ -393,6 +413,19 @@ impl App { || self.matches.value_of("color") == Some("always") || self.matches.value_of("decorations") == Some("always")), files, + tab_width: self + .matches + .value_of("tabs") + .map(String::from) + .or_else(|| env::var("BAT_TABS").ok()) + .and_then(|t| t.parse().ok()) + .unwrap_or( + if output_components.plain() && paging_mode == PagingMode::Never { + 0 + } else { + 8 + }, + ), theme: self .matches .value_of("theme") diff --git a/src/main.rs b/src/main.rs index ff87f9b8..bc3d11aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod decorations; mod diff; mod line_range; mod output; +mod preprocessor; mod printer; mod style; mod terminal; diff --git a/src/preprocessor.rs b/src/preprocessor.rs new file mode 100644 index 00000000..0a99e07d --- /dev/null +++ b/src/preprocessor.rs @@ -0,0 +1,34 @@ +use console::AnsiCodeIterator; + +/// Expand tabs like an ANSI-enabled expand(1). +pub fn expand(line: &str, width: usize, cursor: &mut usize) -> String { + let mut buffer = String::with_capacity(line.len() * 2); + + for chunk in AnsiCodeIterator::new(line) { + match chunk { + (text, true) => buffer.push_str(text), + (mut text, false) => { + while let Some(index) = text.find('\t') { + // Add previous text. + if index > 0 { + *cursor += index; + buffer.push_str(&text[0..index]); + } + + // Add tab. + let spaces = width - (*cursor % width); + *cursor += spaces; + buffer.push_str(&*" ".repeat(spaces)); + + // Next. + text = &text[index + 1..text.len()]; + } + + *cursor += text.len(); + buffer.push_str(text); + } + } + } + + buffer +} diff --git a/src/printer.rs b/src/printer.rs index 552c0869..99901b35 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -16,6 +16,7 @@ use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineN use diff::get_git_diff; use diff::LineChanges; use errors::*; +use preprocessor::expand; use style::OutputWrap; use terminal::{as_terminal_escaped, to_ansi_color}; @@ -152,6 +153,14 @@ impl<'a> InteractivePrinter<'a> { Ok(()) } + + fn preprocess(&self, text: &str, cursor: &mut usize) -> String { + if self.config.tab_width > 0 { + expand(text, self.config.tab_width, cursor) + } else { + text.to_string() + } + } } impl<'a> Printer for InteractivePrinter<'a> { @@ -204,7 +213,7 @@ impl<'a> Printer for InteractivePrinter<'a> { line_number: usize, line_buffer: &[u8], ) -> Result<()> { - let line = String::from_utf8_lossy(&line_buffer); + let line = String::from_utf8_lossy(&line_buffer).to_string(); let regions = self.highlighter.highlight(line.as_ref()); if out_of_range { @@ -213,6 +222,7 @@ impl<'a> Printer for InteractivePrinter<'a> { let mut cursor: usize = 0; let mut cursor_max: usize = self.config.term_width; + let mut cursor_total: usize = 0; let mut panel_wrap: Option = None; // Line decorations. @@ -234,19 +244,14 @@ impl<'a> Printer for InteractivePrinter<'a> { let true_color = self.config.true_color; let colored_output = self.config.colored_output; - write!( - handle, - "{}", - regions - .iter() - .map(|&(style, text)| as_terminal_escaped( - style, - text, - true_color, - colored_output, - )).collect::>() - .join("") - )?; + for &(style, region) in regions.iter() { + let text = &*self.preprocess(region, &mut cursor_total); + write!( + handle, + "{}", + as_terminal_escaped(style, &*text, true_color, colored_output,) + )?; + } if line.bytes().next_back() != Some(b'\n') { write!(handle, "\n")?; @@ -273,7 +278,11 @@ impl<'a> Printer for InteractivePrinter<'a> { // Regular text. (text, false) => { - let text = text.trim_right_matches(|c| c == '\r' || c == '\n'); + let text = self.preprocess( + text.trim_right_matches(|c| c == '\r' || c == '\n'), + &mut cursor_total, + ); + let mut chars = text.chars(); let mut remaining = text.chars().count(); diff --git a/tests/snapshots/generate_snapshots.py b/tests/snapshots/generate_snapshots.py index 6d25f0f1..fcbfdba9 100755 --- a/tests/snapshots/generate_snapshots.py +++ b/tests/snapshots/generate_snapshots.py @@ -1,43 +1,64 @@ #!/usr/bin/env python3 + import itertools import subprocess import pathlib import shutil + def generate_snapshots(): single_styles = ["changes", "grid", "header", "numbers"] collective_styles = ["full", "plain"] for num in range(len(single_styles)): for grouped in itertools.combinations(single_styles, num + 1): - generate_snapshot(",".join(grouped)) + generate_style_snapshot(",".join(grouped)) for style in collective_styles: - generate_snapshot(style) + generate_style_snapshot(style) -def generate_snapshot(option): - command = "../../target/debug/bat --style={0} sample.rs > output/{0}.snapshot.txt".format( - option + generate_snapshot("tabs_passthrough", "--tabs=0 --style=full --wrap=never") + generate_snapshot("tabs_passthrough_wrapped", "--tabs=0 --style=full --wrap=character") + generate_snapshot("tabs_4", "--tabs=4 --style=full --wrap=never") + generate_snapshot("tabs_4_wrapped", "--tabs=4 --style=full --wrap=character") + generate_snapshot("tabs_8", "--tabs=8 --style=full --wrap=never") + generate_snapshot("tabs_8_wrapped", "--tabs=8 --style=full --wrap=character") + + +def generate_style_snapshot(style): + generate_snapshot(style.replace(",", "_"), "--style={}".format(style)) + + +def generate_snapshot(name, arguments): + command = "cargo run -- --paging=never --color=never --decorations=always " + command += "{args} sample.rs > output/{name}.snapshot.txt".format( + name=name, + args=arguments ) - print("generating snapshot for {}".format(option)) + print("generating snapshot for {}".format(name)) subprocess.call(command, shell=True) + def build_bat(): print("building bat") subprocess.call("cargo build", cwd="../..", shell=True) + def prepare_output_dir(): shutil.rmtree("output", ignore_errors=True) pathlib.Path("output").mkdir() + def modify_sample_file(): print("modifying sample.rs to show changes") shutil.copyfile("sample.modified.rs", "sample.rs") + def undo_sample_file_modification(): print("undoing sample.rs modifications") subprocess.call("git checkout -- sample.rs", shell=True) + build_bat() prepare_output_dir() modify_sample_file() diff --git a/tests/snapshots/output/changes.snapshot.txt b/tests/snapshots/output/changes.snapshot.txt index 28d87201..73520d6f 100644 --- a/tests/snapshots/output/changes.snapshot.txt +++ b/tests/snapshots/output/changes.snapshot.txt @@ -16,7 +16,21 @@ _ fn main() { fn area(rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height } -+ + + fn perimeter(rectangle: &Rectangle) -> u32 { + (rectangle.width + rectangle.height) * 2 + } ++ + // Tab alignment: + /* + Indent + 1 2 3 4 + 1 ? + 22 ? + 333 ? + 4444 ? + 55555 ? + 666666 ? + 7777777 ? + 88888888 ? +~ */ diff --git a/tests/snapshots/output/changes,grid.snapshot.txt b/tests/snapshots/output/changes_grid.snapshot.txt similarity index 77% rename from tests/snapshots/output/changes,grid.snapshot.txt rename to tests/snapshots/output/changes_grid.snapshot.txt index 3350711a..83e75583 100644 --- a/tests/snapshots/output/changes,grid.snapshot.txt +++ b/tests/snapshots/output/changes_grid.snapshot.txt @@ -16,8 +16,22 @@ _ │ fn main() { │ fn area(rectangle: &Rectangle) -> u32 { │ rectangle.width * rectangle.height │ } -+ │ + │ + │ fn perimeter(rectangle: &Rectangle) -> u32 { + │ (rectangle.width + rectangle.height) * 2 + │ } ++ │ + │ // Tab alignment: + │ /* + │ Indent + │ 1 2 3 4 + │ 1 ? + │ 22 ? + │ 333 ? + │ 4444 ? + │ 55555 ? + │ 666666 ? + │ 7777777 ? + │ 88888888 ? +~ │ */ ──┴───────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/changes,grid,header.snapshot.txt b/tests/snapshots/output/changes_grid_header.snapshot.txt similarity index 84% rename from tests/snapshots/output/changes,grid,header.snapshot.txt rename to tests/snapshots/output/changes_grid_header.snapshot.txt index 655b6e24..0a32baa8 100644 --- a/tests/snapshots/output/changes,grid,header.snapshot.txt +++ b/tests/snapshots/output/changes_grid_header.snapshot.txt @@ -19,8 +19,22 @@ _ │ fn main() { │ fn area(rectangle: &Rectangle) -> u32 { │ rectangle.width * rectangle.height │ } -+ │ + │ + │ fn perimeter(rectangle: &Rectangle) -> u32 { + │ (rectangle.width + rectangle.height) * 2 + │ } ++ │ + │ // Tab alignment: + │ /* + │ Indent + │ 1 2 3 4 + │ 1 ? + │ 22 ? + │ 333 ? + │ 4444 ? + │ 55555 ? + │ 666666 ? + │ 7777777 ? + │ 88888888 ? +~ │ */ ──┴───────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/changes_grid_header_numbers.snapshot.txt b/tests/snapshots/output/changes_grid_header_numbers.snapshot.txt new file mode 100644 index 00000000..221306da --- /dev/null +++ b/tests/snapshots/output/changes_grid_header_numbers.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/changes,grid,numbers.snapshot.txt b/tests/snapshots/output/changes_grid_numbers.snapshot.txt similarity index 74% rename from tests/snapshots/output/changes,grid,numbers.snapshot.txt rename to tests/snapshots/output/changes_grid_numbers.snapshot.txt index 0d718425..1e1789ee 100644 --- a/tests/snapshots/output/changes,grid,numbers.snapshot.txt +++ b/tests/snapshots/output/changes_grid_numbers.snapshot.txt @@ -16,8 +16,22 @@ 16 │ fn area(rectangle: &Rectangle) -> u32 { 17 │ rectangle.width * rectangle.height 18 │ } - 19 + │ + 19 │ 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { 21 + │ (rectangle.width + rectangle.height) * 2 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ ───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/changes,header.snapshot.txt b/tests/snapshots/output/changes_header.snapshot.txt similarity index 73% rename from tests/snapshots/output/changes,header.snapshot.txt rename to tests/snapshots/output/changes_header.snapshot.txt index 82fe8c47..8d1d1b8a 100644 --- a/tests/snapshots/output/changes,header.snapshot.txt +++ b/tests/snapshots/output/changes_header.snapshot.txt @@ -17,7 +17,21 @@ _ fn main() { fn area(rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height } -+ + + fn perimeter(rectangle: &Rectangle) -> u32 { + (rectangle.width + rectangle.height) * 2 + } ++ + // Tab alignment: + /* + Indent + 1 2 3 4 + 1 ? + 22 ? + 333 ? + 4444 ? + 55555 ? + 666666 ? + 7777777 ? + 88888888 ? +~ */ diff --git a/tests/snapshots/output/changes,header,numbers.snapshot.txt b/tests/snapshots/output/changes_header_numbers.snapshot.txt similarity index 70% rename from tests/snapshots/output/changes,header,numbers.snapshot.txt rename to tests/snapshots/output/changes_header_numbers.snapshot.txt index 77145eb9..ddc32872 100644 --- a/tests/snapshots/output/changes,header,numbers.snapshot.txt +++ b/tests/snapshots/output/changes_header_numbers.snapshot.txt @@ -17,7 +17,21 @@ 16 fn area(rectangle: &Rectangle) -> u32 { 17 rectangle.width * rectangle.height 18 } - 19 + + 19 20 + fn perimeter(rectangle: &Rectangle) -> u32 { 21 + (rectangle.width + rectangle.height) * 2 22 + } + 23 + + 24 // Tab alignment: + 25 /* + 26 Indent + 27 1 2 3 4 + 28 1 ? + 29 22 ? + 30 333 ? + 31 4444 ? + 32 55555 ? + 33 666666 ? + 34 7777777 ? + 35 88888888 ? + 36 ~ */ diff --git a/tests/snapshots/output/changes,numbers.snapshot.txt b/tests/snapshots/output/changes_numbers.snapshot.txt similarity index 69% rename from tests/snapshots/output/changes,numbers.snapshot.txt rename to tests/snapshots/output/changes_numbers.snapshot.txt index bdfe745b..298ee617 100644 --- a/tests/snapshots/output/changes,numbers.snapshot.txt +++ b/tests/snapshots/output/changes_numbers.snapshot.txt @@ -16,7 +16,21 @@ 16 fn area(rectangle: &Rectangle) -> u32 { 17 rectangle.width * rectangle.height 18 } - 19 + + 19 20 + fn perimeter(rectangle: &Rectangle) -> u32 { 21 + (rectangle.width + rectangle.height) * 2 22 + } + 23 + + 24 // Tab alignment: + 25 /* + 26 Indent + 27 1 2 3 4 + 28 1 ? + 29 22 ? + 30 333 ? + 31 4444 ? + 32 55555 ? + 33 666666 ? + 34 7777777 ? + 35 88888888 ? + 36 ~ */ diff --git a/tests/snapshots/output/full.snapshot.txt b/tests/snapshots/output/full.snapshot.txt index cee4737f..221306da 100644 --- a/tests/snapshots/output/full.snapshot.txt +++ b/tests/snapshots/output/full.snapshot.txt @@ -19,8 +19,22 @@ 16 │ fn area(rectangle: &Rectangle) -> u32 { 17 │ rectangle.width * rectangle.height 18 │ } - 19 + │ + 19 │ 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { 21 + │ (rectangle.width + rectangle.height) * 2 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ ───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/grid.snapshot.txt b/tests/snapshots/output/grid.snapshot.txt index bef9a7e6..45917643 100644 --- a/tests/snapshots/output/grid.snapshot.txt +++ b/tests/snapshots/output/grid.snapshot.txt @@ -20,4 +20,18 @@ fn area(rectangle: &Rectangle) -> u32 { fn perimeter(rectangle: &Rectangle) -> u32 { (rectangle.width + rectangle.height) * 2 } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ ──────────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/grid,header.snapshot.txt b/tests/snapshots/output/grid_header.snapshot.txt similarity index 88% rename from tests/snapshots/output/grid,header.snapshot.txt rename to tests/snapshots/output/grid_header.snapshot.txt index 50c16941..fa74ec09 100644 --- a/tests/snapshots/output/grid,header.snapshot.txt +++ b/tests/snapshots/output/grid_header.snapshot.txt @@ -23,4 +23,18 @@ fn area(rectangle: &Rectangle) -> u32 { fn perimeter(rectangle: &Rectangle) -> u32 { (rectangle.width + rectangle.height) * 2 } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ ──────────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/grid,header,numbers.snapshot.txt b/tests/snapshots/output/grid_header_numbers.snapshot.txt similarity index 83% rename from tests/snapshots/output/grid,header,numbers.snapshot.txt rename to tests/snapshots/output/grid_header_numbers.snapshot.txt index e9f1a9cf..733b9848 100644 --- a/tests/snapshots/output/grid,header,numbers.snapshot.txt +++ b/tests/snapshots/output/grid_header_numbers.snapshot.txt @@ -23,4 +23,18 @@ 20 │ fn perimeter(rectangle: &Rectangle) -> u32 { 21 │ (rectangle.width + rectangle.height) * 2 22 │ } + 23 │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 │ */ ─────┴────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/grid,numbers.snapshot.txt b/tests/snapshots/output/grid_numbers.snapshot.txt similarity index 75% rename from tests/snapshots/output/grid,numbers.snapshot.txt rename to tests/snapshots/output/grid_numbers.snapshot.txt index 799f9617..c7d8fb13 100644 --- a/tests/snapshots/output/grid,numbers.snapshot.txt +++ b/tests/snapshots/output/grid_numbers.snapshot.txt @@ -20,4 +20,18 @@ 20 │ fn perimeter(rectangle: &Rectangle) -> u32 { 21 │ (rectangle.width + rectangle.height) * 2 22 │ } + 23 │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 │ */ ─────┴────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/header.snapshot.txt b/tests/snapshots/output/header.snapshot.txt index 0889edfd..6b9b5701 100644 --- a/tests/snapshots/output/header.snapshot.txt +++ b/tests/snapshots/output/header.snapshot.txt @@ -21,3 +21,17 @@ fn area(rectangle: &Rectangle) -> u32 { fn perimeter(rectangle: &Rectangle) -> u32 { (rectangle.width + rectangle.height) * 2 } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ diff --git a/tests/snapshots/output/header,numbers.snapshot.txt b/tests/snapshots/output/header_numbers.snapshot.txt similarity index 72% rename from tests/snapshots/output/header,numbers.snapshot.txt rename to tests/snapshots/output/header_numbers.snapshot.txt index a681e6b4..4d445b5f 100644 --- a/tests/snapshots/output/header,numbers.snapshot.txt +++ b/tests/snapshots/output/header_numbers.snapshot.txt @@ -21,3 +21,17 @@ 20 fn perimeter(rectangle: &Rectangle) -> u32 { 21 (rectangle.width + rectangle.height) * 2 22 } + 23 + 24 // Tab alignment: + 25 /* + 26 Indent + 27 1 2 3 4 + 28 1 ? + 29 22 ? + 30 333 ? + 31 4444 ? + 32 55555 ? + 33 666666 ? + 34 7777777 ? + 35 88888888 ? + 36 */ diff --git a/tests/snapshots/output/numbers.snapshot.txt b/tests/snapshots/output/numbers.snapshot.txt index c1341d29..90ca33c5 100644 --- a/tests/snapshots/output/numbers.snapshot.txt +++ b/tests/snapshots/output/numbers.snapshot.txt @@ -20,3 +20,17 @@ 20 fn perimeter(rectangle: &Rectangle) -> u32 { 21 (rectangle.width + rectangle.height) * 2 22 } + 23 + 24 // Tab alignment: + 25 /* + 26 Indent + 27 1 2 3 4 + 28 1 ? + 29 22 ? + 30 333 ? + 31 4444 ? + 32 55555 ? + 33 666666 ? + 34 7777777 ? + 35 88888888 ? + 36 */ diff --git a/tests/snapshots/output/plain.snapshot.txt b/tests/snapshots/output/plain.snapshot.txt index dbc49f9f..30cbdde6 100644 --- a/tests/snapshots/output/plain.snapshot.txt +++ b/tests/snapshots/output/plain.snapshot.txt @@ -20,3 +20,17 @@ fn area(rectangle: &Rectangle) -> u32 { fn perimeter(rectangle: &Rectangle) -> u32 { (rectangle.width + rectangle.height) * 2 } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ diff --git a/tests/snapshots/output/tabs_4.snapshot.txt b/tests/snapshots/output/tabs_4.snapshot.txt new file mode 100644 index 00000000..87689c7b --- /dev/null +++ b/tests/snapshots/output/tabs_4.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/tabs_4_wrapped.snapshot.txt b/tests/snapshots/output/tabs_4_wrapped.snapshot.txt new file mode 100644 index 00000000..87689c7b --- /dev/null +++ b/tests/snapshots/output/tabs_4_wrapped.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/tabs_8.snapshot.txt b/tests/snapshots/output/tabs_8.snapshot.txt new file mode 100644 index 00000000..221306da --- /dev/null +++ b/tests/snapshots/output/tabs_8.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/tabs_8_wrapped.snapshot.txt b/tests/snapshots/output/tabs_8_wrapped.snapshot.txt new file mode 100644 index 00000000..221306da --- /dev/null +++ b/tests/snapshots/output/tabs_8_wrapped.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/changes,grid,header,numbers.snapshot.txt b/tests/snapshots/output/tabs_passthrough.snapshot.txt similarity index 84% rename from tests/snapshots/output/changes,grid,header,numbers.snapshot.txt rename to tests/snapshots/output/tabs_passthrough.snapshot.txt index cee4737f..3ad018a1 100644 --- a/tests/snapshots/output/changes,grid,header,numbers.snapshot.txt +++ b/tests/snapshots/output/tabs_passthrough.snapshot.txt @@ -19,8 +19,22 @@ 16 │ fn area(rectangle: &Rectangle) -> u32 { 17 │ rectangle.width * rectangle.height 18 │ } - 19 + │ + 19 │ 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { 21 + │ (rectangle.width + rectangle.height) * 2 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ ───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/output/tabs_passthrough_wrapped.snapshot.txt b/tests/snapshots/output/tabs_passthrough_wrapped.snapshot.txt new file mode 100644 index 00000000..3ad018a1 --- /dev/null +++ b/tests/snapshots/output/tabs_passthrough_wrapped.snapshot.txt @@ -0,0 +1,40 @@ +───────┬──────────────────────────────────────────────────────────────────────── + │ File: sample.rs +───────┼──────────────────────────────────────────────────────────────────────── + 1 │ struct Rectangle { + 2 │ width: u32, + 3 │ height: u32, + 4 │ } + 5 │ + 6 _ │ fn main() { + 7 │ let rect1 = Rectangle { width: 30, height: 50 }; + 8 │ + 9 │ println!( + 10 ~ │ "The perimeter of the rectangle is {} pixels.", + 11 ~ │ perimeter(&rect1) + 12 │ ); + 13 + │ println!(r#"This line contains invalid utf8: "�����"#; + 14 │ } + 15 │ + 16 │ fn area(rectangle: &Rectangle) -> u32 { + 17 │ rectangle.width * rectangle.height + 18 │ } + 19 │ + 20 + │ fn perimeter(rectangle: &Rectangle) -> u32 { + 21 + │ (rectangle.width + rectangle.height) * 2 + 22 + │ } + 23 + │ + 24 │ // Tab alignment: + 25 │ /* + 26 │ Indent + 27 │ 1 2 3 4 + 28 │ 1 ? + 29 │ 22 ? + 30 │ 333 ? + 31 │ 4444 ? + 32 │ 55555 ? + 33 │ 666666 ? + 34 │ 7777777 ? + 35 │ 88888888 ? + 36 ~ │ */ +───────┴──────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/sample.modified.rs b/tests/snapshots/sample.modified.rs index bb1a7943..866f359d 100644 --- a/tests/snapshots/sample.modified.rs +++ b/tests/snapshots/sample.modified.rs @@ -20,3 +20,17 @@ fn area(rectangle: &Rectangle) -> u32 { fn perimeter(rectangle: &Rectangle) -> u32 { (rectangle.width + rectangle.height) * 2 } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ diff --git a/tests/snapshots/sample.rs b/tests/snapshots/sample.rs index 00ec0eb6..6ee6489b 100644 --- a/tests/snapshots/sample.rs +++ b/tests/snapshots/sample.rs @@ -16,3 +16,17 @@ fn main() { fn area(rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height } + +// Tab alignment: +/* + Indent + 1 2 3 4 +1 ? +22 ? +333 ? +4444 ? +55555 ? +666666 ? +7777777 ? +88888888 ? +*/ \ No newline at end of file diff --git a/tests/tester.rs b/tests/tester.rs index 9885ff46..87de6462 100644 --- a/tests/tester.rs +++ b/tests/tester.rs @@ -38,13 +38,17 @@ impl BatTester { BatTester { temp_dir, exe } } - pub fn test_snapshot(&self, style: &str) { + pub fn test_snapshot(&self, name: &str, style: &str, tab_width: u32, wrap: bool) { let output = Command::new(&self.exe) .current_dir(self.temp_dir.path()) .args(&[ "sample.rs", + "--paging=never", + "--color=never", "--decorations=always", "--terminal-width=80", + &format!("--wrap={}", if wrap { "character" } else { "never" }), + &format!("--tabs={}", tab_width), &format!("--style={}", style), ]).output() .expect("bat failed"); @@ -55,7 +59,7 @@ impl BatTester { .replace("tests/snapshots/", ""); let mut expected = String::new(); - let mut file = File::open(format!("tests/snapshots/output/{}.snapshot.txt", style)) + let mut file = File::open(format!("tests/snapshots/output/{}.snapshot.txt", name)) .expect("snapshot file missing"); file.read_to_string(&mut expected) .expect("could not read snapshot file"); diff --git a/tests/tests.rs b/tests/tests.rs index d0313304..6e76c8b5 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -3,33 +3,39 @@ mod tester; use tester::BatTester; macro_rules! snapshot_tests { - ($($test_name: ident: $style: expr,)*) => { + ($($test_name: ident: $style: expr => [wrap: $wrap:expr, tabs: $tabs:expr],)*) => { $( #[test] fn $test_name() { let bat_tester = BatTester::new(); - bat_tester.test_snapshot($style); + bat_tester.test_snapshot(stringify!($test_name), $style, $tabs, $wrap); } )* }; } snapshot_tests! { - changes: "changes", - grid: "grid", - header: "header", - numbers: "numbers", - changes_grid: "changes,grid", - changes_header: "changes,header", - changes_numbers: "changes,numbers", - grid_header: "grid,header", - grid_numbers: "grid,numbers", - header_numbers: "header,numbers", - changes_grid_header: "changes,grid,header", - changes_grid_numbers: "changes,grid,numbers", - changes_header_numbers: "changes,header,numbers", - grid_header_numbers: "grid,header,numbers", - changes_grid_header_numbers: "changes,grid,header,numbers", - full: "full", - plain: "plain", + changes: "changes" => [wrap: false, tabs: 8], + grid: "grid" => [wrap: false, tabs: 8], + header: "header" => [wrap: false, tabs: 8], + numbers: "numbers" => [wrap: false, tabs: 8], + changes_grid: "changes,grid" => [wrap: false, tabs: 8], + changes_header: "changes,header" => [wrap: false, tabs: 8], + changes_numbers: "changes,numbers" => [wrap: false, tabs: 8], + grid_header: "grid,header" => [wrap: false, tabs: 8], + grid_numbers: "grid,numbers" => [wrap: false, tabs: 8], + header_numbers: "header,numbers" => [wrap: false, tabs: 8], + changes_grid_header: "changes,grid,header" => [wrap: false, tabs: 8], + changes_grid_numbers: "changes,grid,numbers" => [wrap: false, tabs: 8], + changes_header_numbers: "changes,header,numbers" => [wrap: false, tabs: 8], + grid_header_numbers: "grid,header,numbers" => [wrap: false, tabs: 8], + changes_grid_header_numbers: "changes,grid,header,numbers" => [wrap: false, tabs: 8], + full: "full" => [wrap: false, tabs: 8], + plain: "plain" => [wrap: false, tabs: 0], + tabs_passthrough_wrapped: "full" => [wrap: true, tabs: 0], + tabs_4_wrapped: "full" => [wrap: true, tabs: 4], + tabs_8_wrapped: "full" => [wrap: true, tabs: 8], + tabs_passthrough: "full" => [wrap: false, tabs: 0], + tabs_4: "full" => [wrap: false, tabs: 4], + tabs_8: "full" => [wrap: false, tabs: 8], }