From 6cdb57ebb53857ffad8eeb1287ea4a863f9f62fa Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 12 Feb 2021 14:03:45 -0500 Subject: [PATCH] Allow user to specify tab replacement string Fixes #522 --- src/cli.rs | 14 ++++++++++---- src/config.rs | 8 ++++++-- src/main.rs | 4 ++-- src/options/set.rs | 1 + src/paint.rs | 13 +++++++++---- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 41f6eb89f..3fd9de578 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -470,10 +470,16 @@ pub struct Opt { #[structopt(short = "w", long = "width")] pub width: Option, - /// The number of spaces to replace tab characters with. Use --tabs=0 to pass tab characters - /// through directly, but note that in that case delta will calculate line widths assuming tabs - /// occupy one character's width on the screen: if your terminal renders tabs as more than than - /// one character wide then delta's output will look incorrect. + /// A string to use to display tab characters with. By default, each tab character will be + /// replaced by space characters. (See `tabs`) + #[structopt(long = "tab-string")] + pub tab_string: Option, + + /// The number of spaces to replace tab characters with, if tab-string has not been + /// supplied. Use --tabs=0 to pass tab characters through directly, but note that in that case + /// delta will calculate line widths assuming tabs occupy one character's width on the screen: + /// if your terminal renders tabs as more than than one character wide then delta's output will + /// look incorrect. #[structopt(long = "tabs", default_value = "4")] pub tab_width: usize, diff --git a/src/config.rs b/src/config.rs index 23b7b97d0..02608eb24 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,7 +73,7 @@ pub struct Config { pub syntax_dummy_theme: SyntaxTheme, pub syntax_set: SyntaxSet, pub syntax_theme: Option, - pub tab_width: usize, + pub tab_string: String, pub tokenization_regex: Regex, pub true_color: bool, pub truncation_symbol: String, @@ -218,7 +218,11 @@ impl From for Config { syntax_dummy_theme: SyntaxTheme::default(), syntax_set: opt.computed.syntax_set, syntax_theme: opt.computed.syntax_theme, - tab_width: opt.tab_width, + tab_string: if let Some(s) = opt.tab_string { + s + } else { + " ".repeat(opt.tab_width) + }, tokenization_regex, true_color: opt.computed.true_color, truncation_symbol: "→".to_string(), diff --git a/src/main.rs b/src/main.rs index 5757fbab3..3587d1846 100644 --- a/src/main.rs +++ b/src/main.rs @@ -258,7 +258,7 @@ fn show_config(config: &config::Config, writer: &mut dyn Write) -> std::io::Resu side-by-side = {side_by_side} syntax-theme = {syntax_theme} width = {width} - tabs = {tab_width} + tab_string = '{tab_string}' word-diff-regex = {tokenization_regex}", max_line_distance = config.max_line_distance, max_line_length = config.max_line_length, @@ -278,7 +278,7 @@ fn show_config(config: &config::Config, writer: &mut dyn Write) -> std::io::Resu cli::Width::Fixed(width) => width.to_string(), cli::Width::Variable => "variable".to_string(), }, - tab_width = config.tab_width, + tab_string = config.tab_string, tokenization_regex = format_option_value(&config.tokenization_regex.to_string()), )?; Ok(()) diff --git a/src/options/set.rs b/src/options/set.rs index 354eeea6f..24c4901b1 100644 --- a/src/options/set.rs +++ b/src/options/set.rs @@ -170,6 +170,7 @@ pub fn set_options( plus_non_emph_style, raw, side_by_side, + tab_string, tab_width, tokenization_regex, true_color, diff --git a/src/paint.rs b/src/paint.rs index bf85fb138..415726a1b 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -114,10 +114,15 @@ impl<'a> Painter<'a> { where I: Iterator, { - if self.config.tab_width > 0 { - let tab_replacement = " ".repeat(self.config.tab_width); - line.map(|s| if s == "\t" { &tab_replacement } else { s }) - .collect::() + if !self.config.tab_string.is_empty() { + line.map(|s| { + if s == "\t" { + &self.config.tab_string + } else { + s + } + }) + .collect::() } else { line.collect::() }