summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThomas Otto <th1000s@posteo.net>2021-01-30 11:57:51 +0100
committerDan Davison <dandavison7@gmail.com>2021-09-19 19:39:50 -0400
commitb9952f91ccd6a016d38be0f87bdcf1bb5b06ca76 (patch)
tree9ccd69805c41b6e04bf809726721ee769badcdc5 /src
parentdb04d5e4ec02ea30e208c64f6f77e1cbfccb2688 (diff)
Option to set the background extension mode to ANSI or spaces
In side-by-side mode, if `background_color_extends_to_terminal_width` is set, the left panel color is extended via spaces, but the right one via an ANSI sequence which instructs the terminal emulator to fill the background color rightwards. The command line option --line-fill-method ansi|spaces can change how the right panel background is filled. Add enums `BgShouldFill` and `BgFillMethod` to better distinguish if the background should be filled, and if so, how.
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs5
-rw-r--r--src/config.rs13
-rw-r--r--src/features/line_numbers.rs10
-rw-r--r--src/features/side_by_side.rs285
-rw-r--r--src/handlers/blame.rs3
-rw-r--r--src/handlers/hunk_header.rs4
-rw-r--r--src/options/set.rs1
-rw-r--r--src/paint.rs81
-rw-r--r--src/subcommands/show_config.rs6
-rw-r--r--src/tests/ansi_test_utils.rs2
10 files changed, 246 insertions, 164 deletions
diff --git a/src/cli.rs b/src/cli.rs
index bb15b168..f0f6165a 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -526,6 +526,11 @@ pub struct Opt {
/// delta will be slow on very long lines (e.g. minified .js) if truncation is disabled.
pub max_line_length: usize,
+ /// How to extend the background color to the end of the line in side-by-side mode. Can
+ /// be ansi (default) or spaces. Has no effect if --width=variable is given.
+ #[structopt(long = "line-fill-method")]
+ pub line_fill_method: Option<String>,
+
/// The width of underline/overline decorations. Use --width=variable to extend decorations and
/// background colors to the end of the text only. Otherwise background colors extend to the
/// full terminal width.
diff --git a/src/config.rs b/src/config.rs
index 1b035f2b..fbd58044 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -16,6 +16,7 @@ use crate::env;
use crate::features::navigate;
use crate::features::side_by_side;
use crate::git_config::{GitConfig, GitConfigEntry};
+use crate::paint::BgFillMethod;
use crate::style::{self, Style};
pub struct Config {
@@ -51,6 +52,7 @@ pub struct Config {
pub hyperlinks_file_link_format: String,
pub inspect_raw_lines: cli::InspectRawLines,
pub keep_plus_minus_markers: bool,
+ pub line_fill_method: BgFillMethod,
pub line_numbers: bool,
pub line_numbers_left_format: String,
pub line_numbers_left_style: Style,
@@ -187,6 +189,16 @@ impl From<cli::Opt> for Config {
let file_renamed_label = opt.file_renamed_label;
let hunk_label = opt.hunk_label;
+ let line_fill_method = match opt.line_fill_method.as_deref() {
+ // Note that "default" is not documented
+ Some("ansi") | Some("default") | None => BgFillMethod::TryAnsiSequence,
+ Some("spaces") => BgFillMethod::Spaces,
+ _ => {
+ eprintln!("Invalid option for line-fill-method: Expected \"ansi\" or \"spaces\".");
+ process::exit(1);
+ }
+ };
+
let navigate_regexp = if opt.navigate || opt.show_themes {
Some(navigate::make_navigate_regexp(
opt.show_themes,
@@ -245,6 +257,7 @@ impl From<cli::Opt> for Config {
hyperlinks_file_link_format: opt.hyperlinks_file_link_format,
inspect_raw_lines: opt.computed.inspect_raw_lines,
keep_plus_minus_markers: opt.keep_plus_minus_markers,
+ line_fill_method,
line_numbers: opt.line_numbers,
line_numbers_left_format: opt.line_numbers_left_format,
line_numbers_left_style,
diff --git a/src/features/line_numbers.rs b/src/features/line_numbers.rs
index 3032bc00..0d282557 100644
--- a/src/features/line_numbers.rs
+++ b/src/features/line_numbers.rs
@@ -383,7 +383,7 @@ pub mod tests {
let mut lines = output.lines().skip(7);
let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
assert_eq!(strip_ansi_codes(line_1), " 1 ⋮ │a = 1");
- assert_eq!(strip_ansi_codes(line_2), " 2 ⋮ │b = 2");
+ assert_eq!(strip_ansi_codes(line_2), " 2 ⋮ │b = 23456");
}
#[test]
@@ -407,7 +407,7 @@ pub mod tests {
let mut lines = output.lines().skip(7);
let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
assert_eq!(strip_ansi_codes(line_1), " ⋮ 1 │a = 1");
- assert_eq!(strip_ansi_codes(line_2), " ⋮ 2 │b = 2");
+ assert_eq!(strip_ansi_codes(line_2), " ⋮ 2 │b = 234567");
}
#[test]
@@ -489,7 +489,7 @@ pub mod tests {
let mut lines = output.lines().skip(5);
let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
assert_eq!(strip_ansi_codes(line_1), " 1 ⋮ │-a = 1");
- assert_eq!(strip_ansi_codes(line_2), " 2 ⋮ │-b = 2");
+ assert_eq!(strip_ansi_codes(line_2), " 2 ⋮ │-b = 23456");
}
#[test]
@@ -514,7 +514,7 @@ index 223ca50..e69de29 100644
+++ w/a.py
@@ -1,2 +0,0 @@
-a = 1
--b = 2
+-b = 23456
";
pub const TWO_PLUS_LINES_DIFF: &str = "\
@@ -525,7 +525,7 @@ index 0000000..223ca50
+++ i/a.py
@@ -0,0 +1,2 @@
+a = 1
-+b = 2
++b = 234567
";
pub const ONE_MINUS_ONE_PLUS_LINE_DIFF: &str = "\
diff --git a/src/features/side_by_side.rs b/src/features/side_by_side.rs
index ae5911ef..6d85b7af 100644
--- a/src/features/side_by_side.rs
+++ b/src/features/side_by_side.rs
@@ -10,6 +10,7 @@ use crate::delta::State;
use crate::features::line_numbers;
use crate::features::OptionValueFunction;
use crate::paint::Painter;
+use crate::paint::{BgFillMethod, BgShouldFill};
use crate::plusminus::*;
use crate::style::Style;
@@ -92,7 +93,7 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
output_buffer: &mut String,
config: &Config,
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
- background_color_extends_to_terminal_width: Option<bool>,
+ background_color_extends_to_terminal_width: PlusMinus<BgShouldFill>,
) {
for (minus_line_index, plus_line_index) in line_alignment {
output_buffer.push_str(&paint_left_panel_minus_line(
@@ -109,7 +110,7 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
} else {
None
},
- background_color_extends_to_terminal_width,
+ background_color_extends_to_terminal_width[Left],
config,
));
output_buffer.push_str(&paint_right_panel_plus_line(
@@ -126,7 +127,7 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
} else {
None
},
- background_color_extends_to_terminal_width,
+ background_color_extends_to_terminal_width[Right],
config,
));
output_buffer.push('\n');
@@ -137,63 +138,50 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
pub fn paint_zero_lines_side_by_side(
syntax_style_sections: Vec<Vec<(SyntectStyle, &str)>>,
diff_style_sections: Vec<Vec<(Style, &str)>>,
- state: &State,
output_buffer: &mut String,
config: &Config,
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
painted_prefix: Option<ansi_term::ANSIString>,
- background_color_extends_to_terminal_width: Option<bool>,
+ background_color_extends_to_terminal_width: BgShouldFill,
) {
+ let state = State::HunkZero;
+
for (line_index, (syntax_sections, diff_sections)) in syntax_style_sections
.iter()
.zip_eq(diff_style_sections.iter())
.enumerate()
{
- let (mut left_panel_line, left_panel_line_is_empty) = Painter::paint_line(
- syntax_sections,
- diff_sections,
- state,
- line_numbers_data,
- Some(PanelSide::Left),
- painted_prefix.clone(),
- config,
- );
- // TODO: Avoid doing the superimpose_style_sections work twice.
- // HACK: These are getting incremented twice, so knock them back down once.
- if let Some(d) = line_numbers_data.as_mut() {
- d.line_number[Left] -= 1;
- d.line_number[Right] -= 1;
- }
- right_pad_left_panel_line(
- &mut left_panel_line,
- left_panel_line_is_empty,
- Some(line_index),
- &diff_style_sections,
- &State::HunkZero,
- background_color_extends_to_terminal_width,
- config,
- );
- output_buffer.push_str(&left_panel_line);
+ for panel_side in &[Left, Right] {
+ let (mut panel_line, panel_line_is_empty) = Painter::paint_line(
+ syntax_sections,
+ diff_sections,
+ &state,
+ line_numbers_data,
+ Some(*panel_side),
+ painted_prefix.clone(),
+ config,
+ );
+ pad_panel_line_to_width(
+ &mut panel_line,
+ panel_line_is_empty,
+ Some(line_index),
+ &diff_style_sections,
+ &state,
+ *panel_side,
+ background_color_extends_to_terminal_width,
+ config,
+ );
+ output_buffer.push_str(&panel_line);
- let (mut right_panel_line, right_panel_line_is_empty) = Painter::paint_line(
- syntax_sections,
- diff_sections,
- state,
- line_numbers_data,
- Some(PanelSide::Right),
- painted_prefix.clone(),
- config,
- );
- right_fill_right_panel_line(
- &mut right_panel_line,
- right_panel_line_is_empty,
- Some(line_index),
- &diff_style_sections,
- &State::HunkZero,
- background_color_extends_to_terminal_width,
- config,
- );
- output_buffer.push_str(&right_panel_line);
+ if panel_side == &Left {
+ // TODO: Avoid doing the superimpose_style_sections work twice.
+ // HACK: These are getting incremented twice, so knock them back down once.
+ if let Some(d) = line_numbers_data.as_mut() {
+ d.line_number[Left] -= 1;
+ d.line_number[Right] -= 1;
+ }
+ }
+ }
output_buffer.push('\n');
}
}
@@ -206,7 +194,7 @@ fn paint_left_panel_minus_line<'a>(
state: &'a State,
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
painted_prefix: Option<ansi_term::ANSIString>,
- background_color_extends_to_terminal_width: Option<bool>,
+ background_color_extends_to_terminal_width: BgShouldFill,
config: &Config,
) -> String {
let (mut panel_line, panel_line_is_empty) = paint_minus_or_plus_panel_line(
@@ -219,12 +207,13 @@ fn paint_left_panel_minus_line<'a>(
painted_prefix,
config,
);
- right_pad_left_panel_line(
+ pad_panel_line_to_width(
&mut panel_line,
panel_line_is_empty,
line_index,
diff_style_sections,
state,
+ Left,
background_color_extends_to_terminal_width,
config,
);
@@ -240,7 +229,7 @@ fn paint_right_panel_plus_line<'a>(
state: &'a State,
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
painted_prefix: Option<ansi_term::ANSIString>,
- background_color_extends_to_terminal_width: Option<bool>,
+ background_color_extends_to_terminal_width: BgShouldFill,
config: &Config,
) -> String {
let (mut panel_line, panel_line_is_empty) = paint_minus_or_plus_panel_line(
@@ -253,41 +242,53 @@ fn paint_right_panel_plus_line<'a>(
painted_prefix,
config,
);
- right_fill_right_panel_line(
+
+ pad_panel_line_to_width(
&mut panel_line,
panel_line_is_empty,
line_index,
diff_style_sections,
state,
+ Right,
background_color_extends_to_terminal_width,
config,
);
+
panel_line
}
-fn get_right_fill_style_for_left_panel(
+fn get_right_fill_style_for_panel(
line_is_empty: bool,
line_index: Option<usize>,
diff_style_sections: &[Vec<(Style, &str)>],
state: &State,
- background_color_extends_to_terminal_width: Option<bool>,
+ panel_side: PanelSide,
+ background_color_extends_to_terminal_width: BgShouldFill,
config: &Config,
-) -> Style {
+) -> (Option<BgFillMethod>, Style) {
+ // If in the the left panel then it must be filled with spaces.
+ let none_or_override = if panel_side == Left {
+ Some(BgFillMethod::Spaces)
+ } else {
+ None
+ };
+
match (line_is_empty, line_index) {
- (true, _) => config.null_style,
- (false, None) => config.null_style,
+ (true, _) => (none_or_override, config.null_style),
+ (false, None) => (none_or_override, config.null_style),
(false, Some(index)) => {
- let (should_fill, fill_style) =
+ let (bg_fill_mode, fill_style) =
Painter::get_should_right_fill_background_color_and_fill_style(
&diff_style_sections[index],
state,
background_color_extends_to_terminal_width,
config,
);
- if should_fill {
- fill_style
- } else {
- config.null_style
+
+ match bg_fill_mode {
+ None => (none_or_override, config.null_style),
+ _ if panel_side == Left => (Some(BgFillMethod::Spaces), fill_style),
+ _ => (bg_fill_mode, fill_style),
}
}
}
@@ -375,21 +376,20 @@ fn paint_minus_or_plus_panel_line(
(line, line_is_empty)
}
-/// Right-pad a line in the left panel with (possibly painted) spaces. A line in the left panel is
-/// either a minus line or a zero line.
-#[allow(clippy::comparison_chain)]
-fn right_pad_left_panel_line(
+/// Right-fill the background color of a line in a panel. If in the left panel this is always
+/// done with spaces. The right panel can be filled with spaces or using ANSI sequences
+/// instructing the terminal emulator to fill the background color rightwards.
+#[allow(clippy::too_many_arguments, clippy::comparison_chain)]
+fn pad_panel_line_to_width(
panel_line: &mut String,
panel_line_is_empty: bool,
line_index: Option<usize>,
diff_style_sections: &[Vec<(Style, &str)>],
state: &State,
- background_color_extends_to_terminal_width: Option<bool>,
+ panel_side: PanelSide,
+ background_color_extends_to_terminal_width: BgShouldFill,
config: &Config,
) {
- // The left panel uses spaces to pad to the midpoint. This differs from the right panel,
- // and from the non-side-by-side implementation.
-
// Emit empty line marker if the panel line is empty but not empty-by-construction. IOW if the
// other panel contains a real line, and we are currently emitting an empty counterpart panel
// to form the other half of the line, then don't emit the empty line marker.
@@ -400,81 +400,46 @@ fn right_pad_left_panel_line(
panel_line,
Some(" "),
),
+ State::HunkPlus(_) => Painter::mark_empty_line(
+ &config.plus_empty_line_marker_style,
+ panel_line,
+ Some(" "),
+ ),
State::HunkZero => {}
_ => unreachable!(),
};
};
- // Pad with (maybe painted) spaces to the panel width.
+
let text_width = ansi::measure_text_width(panel_line);
- let panel_width = config.side_by_side_data[Left].width;
- if text_width < panel_width {
- let fill_style = get_right_fill_style_for_left_panel(
- panel_line_is_empty,
- line_index,
- diff_style_sections,
- state,
- background_color_extends_to_terminal_width,
- config,
- );
- panel_line.push_str(
- &fill_style
- .paint(" ".repeat(panel_width - text_width))
- .to_string(),
- );
- } else if text_width > panel_width {
+ let panel_width = config.side_by_side_data[panel_side].width;
+
+ if text_width > panel_width {
*panel_line =
ansi::truncate_str(panel_line, panel_width, &config.truncation_symbol).to_string();
}
-}
-/// Right-fill the background color of a line in the right panel. A line in the right panel is
-/// either a zero line or a plus line. The fill is achieved using ANSI sequences instructing the
-/// terminal emulator to fill the background color rightwards; it does not involve appending spaces
-/// to the line.
-fn right_fill_right_panel_line(
- panel_line: &mut String,
- panel_line_is_empty: bool,
- line_index: Option<usize>,
- diff_style_sections: &[Vec<(Style, &str)>],
- state: &State,
- background_color_extends_to_terminal_width: Option<bool>,
- config: &Config,
-) {
- *panel_line = ansi::truncate_str(
- &panel_line,
- config.side_by_side_data[Right].width,
- &config.truncation_symbol,
- )
- .to_string();
-
- // Unlike `right_pad_left_panel_line`, the line-end emissions here are basically the same as
- // the non side-by-side implementation in Painter::paint_lines.
- let (should_right_fill_background_color, fill_style) = if let Some(index) = line_index {
- Painter::get_should_right_fill_background_color_and_fill_style(
- &diff_style_sections[index],
- state,
- background_color_extends_to_terminal_width,
- config,
- )
- } else {
- (false, config.null_style)
- };
+ let (bg_fill_mode, fill_style) = get_right_fill_style_for_panel(
+ panel_line_is_empty,
+ line_index,
+ diff_style_sections,
+ state,
+ panel_side,
+ background_color_extends_to_terminal_width,
+ config,
+ );
- if should_right_fill_background_color {
- Painter::right_fill_background_color(panel_line, fill_style);
- } else if panel_line_is_empty && line_index.is_some() {
- // Emit empty line marker when the panel line is empty but not empty-by-construction. See
- // parallel comment in `paint_left_panel_minus_line`.
- match state {
- State::HunkPlus(_) => Painter::mark_empty_line(
- &config.plus_empty_line_marker_style,
- panel_line,
- Some(" "),
- ),
- State::HunkZero => {}
- _ => unreachable!(),
+ match bg_fill_mode {
+ Some(BgFillMethod::TryAnsiSequence) => {
+ Painter::right_fill_background_color(panel_line, fill_style)
}
- };
+ Some(BgFillMethod::Spaces) if text_width >= panel_width => (),
+ Some(BgFillMethod::Spaces) => panel_line.push_str(
+ &fill_style
+ .paint(" ".repeat(panel_width - text_width))
+ .to_string(),
+ ),
+ None => (),
+ }
}
#[cfg(test)]
@@ -490,7 +455,23 @@ pub mod tests {
let mut lines = output.lines().skip(7);
let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
assert_eq!("│ 1 │a = 1 │ │", strip_ansi_codes(line_1));
- assert_eq!("│ 2 │b = 2 │ │", strip_ansi_codes(line_2));
+ assert_eq!("│ 2 │b = 23456 │ │", strip_ansi_codes(line_2));
+ }
+
+ #[test]
+ fn test_two_minus_lines_truncated() {
+ let mut config = make_config_from_args(&[
+ "--side-by-side",
+ "--width",
+ "28",
+ "--line-fill-method=spaces",
+ ]);
+ config.truncation_symbol = ">".into();
+ let output = run_delta(TWO_MINUS_LINES_DIFF, &config);
+ let mut lines = output.lines().skip(7);
+ let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
+ assert_eq!("│ 1 │a = 1 │ │", strip_ansi_codes(line_1));
+ assert_eq!("│ 2 │b = 234>│ │", strip_ansi_codes(line_2));
}
#[test]
@@ -499,8 +480,36 @@ pub mod tests {
let output = run_delta(TWO_PLUS_LINES_DIFF, &config);
let mut lines = output.lines().skip(7);
let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
- assert_eq!("│ │ │ 1 │a = 1", strip_ansi_codes(line_1));
- assert_eq!("│ │ │ 2 │b = 2", strip_ansi_codes(line_2));
+ let sac = strip_ansi_codes; // alias to help with `cargo fmt`-ing:
+ assert_eq!("│ │ │ 1 │a = 1", sac(line_1));
+ assert_eq!("│ │ │ 2 │b = 234567", sac(line_2));
+ }
+
+ #[test]
+ fn test_two_plus_lines_truncated() {
+ let mut config = make_config_from_args(&[
+ "--side-by-side",
+ "--width",
+ "30",
+ "--line-fill-method=spaces",
+ ]);
+ config.truncation_symbol = ">".into();
+ let output = run_delta(TWO_PLUS_LINES_DIFF, &config);
+ let mut lines = output.lines().skip(7);
+ let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
+ assert_eq!("│ │ │ 1 │a = 1 ", strip_ansi_codes(line_1));
+ assert_eq!("│ │ │ 2 │b = 2345>", strip_ansi_codes(line_2));
+ }
+
+ #[test]
+ fn test_two_plus_lines_exact_fit() {
+ let mut config = make_config_from_args(&["--side-by-side", "--width", "32"]);
+ config.truncation_symbol = ">".into();
+ let output = run_delta(TWO_PLUS_LINES_DIFF, &config);
+ let mut lines = output.lines().skip(7);
+ let (line_1, line_2) = (lines.next().unwrap(), lines.next().unwrap());
+ assert_eq!("│ │ │ 1 │a = 1", strip_ansi_codes(line_1));
+ assert_eq!("│ │ │ 2 │b = 234567", strip_ansi_codes(line_2));
}
#[test]
diff --git a/src/handlers/blame.rs b/src/handlers/blame.rs
index d7486303..af1057d9 100644
--- a/src/handlers/blame.rs
+++ b/src/handlers/blame.rs
@@ -6,6 +6,7 @@ use crate::color;
use crate::config;
use crate::delta::{self, State, StateMachine};
use crate::format;
+use crate::paint::BgShouldFill;
use crate::style::Style;
impl<'a> StateMachine<'a> {
@@ -56,7 +57,7 @@ impl<'a> StateMachine<'a> {
blame.code,
style,
self.state.clone(),
- true,
+ BgShouldFill::default(),
);
handled_line = true
}
diff --git a/src/handlers/hunk_header.rs b/src/handlers/hunk_header.rs
index 1d10d4fb..b601ef54 100644
--- a/src/handlers/hunk_header.rs
+++ b/src/handlers/hunk_header.rs
@@ -28,7 +28,7 @@ use super::draw;
use crate::config::Config;
use crate::delta::{self, State, StateMachine};
use crate::features;
-use crate::paint::Painter;
+use crate::paint::{BgShouldFill, Painter};
use crate::style::DecorationStyle;
impl<'a> StateMachine<'a> {
@@ -247,7 +247,7 @@ fn write_to_output_buffer(
&line,
config.hunk_header_style,
delta::State::HunkHeader("".to_owned(), "".to_owned()),
- false,
+ BgShouldFill::No,
);
painter.output_buffer.pop(); // trim newline
}
diff --git a/src/options/set.rs b/src/options/set.rs
index a896820a..1f533269 100644
--- a/src/options/set.rs
+++ b/src/options/set.rs
@@ -158,6 +158,7 @@ pub fn set_options(
minus_non_emph_style,
minus_non_emph_style,
navigate,
+ line_fill_method,
line_numbers,
line_numbers_left_format,
line_numbers_left_style,
diff --git a/src/paint.rs b/src/paint.rs
index 7b31047d..3015187a 100644
--- a/src/paint.rs
+++ b/src/paint.rs
@@ -28,6 +28,28 @@ pub struct Painter<'a> {
pub line_numbers_data: line_numbers::LineNumbersData<'a>,
}
+// How the background of a line is filled up to the end
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum BgFillMethod {
+ // Fill the background with ANSI spaces if possible,
+ // but might fallback to Spaces (e.g. in the left side-by-side panel)
+ TryAnsiSequence,
+ Spaces,
+}
+
+// If the background of a line extends to the end, and if configured to do so, how.
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum BgShouldFill {
+ With(BgFillMethod),
+ No,
+}
+
+impl Default for BgShouldFill {
+ fn default() -> Self {
+ BgShouldFill::With(BgFillMethod::TryAnsiSequence)
+ }
+}
+
impl<'a> Painter<'a> {
pub fn new(writer: &'a mut dyn Write, config: &'a config::Config) -> Self {
let default_syntax = Self::get_syntax(&config.syntax_set, None);
@@ -154,6 +176,13 @@ impl<'a> Painter<'a> {
self.plus_lines.iter().map(|(_, state)| state).collect(),
);
+ let bg_fill_left_right = PlusMinus::new(
+ // Using an ANSI sequence to fill the left panel would not work
+ BgShouldFill::With(BgFillMethod::Spaces),
+ // Use the configured method for the right panel
+ BgShouldFill::With(self.config.line_fill_method),
+ );
+
side_by_side::paint_minus_and_plus_lines_side_by_side(
syntax_left_right,
diff_left_right,
@@ -162,7 +191,7 @@ impl<'a> Painter<'a> {
&mut self.output_buffer,
self.config,
&mut Some(&mut self.line_numbers_data),
- None,
+ bg_fill_left_right,
);
} else {
if !self.minus_lines.is_empty() {
@@ -179,7 +208,7 @@ impl<'a> Painter<'a> {
None
},
Some(self.config.minus_empty_line_marker_style),
- None,
+ BgShouldFill::default(),
);
}
if !self.plus_lines.is_empty() {
@@ -196,7 +225,7 @@ impl<'a> Painter<'a> {
None
},
Some(self.config.plus_empty_line_marker_style),
- None,
+ BgShouldFill::default(),
);
}
}
@@ -224,12 +253,11 @@ impl<'a> Painter<'a> {
side_by_side::paint_zero_lines_side_by_side(
syntax_style_sections,
vec![diff_style_sections],
- &State::HunkZero,
&mut self.output_buffer,
self.config,
&mut Some(&mut self.line_numbers_data),
painted_prefix,
- None,
+ BgShouldFill::With(BgFillMethod::Spaces),
);
} else {
Painter::paint_lines(
@@ -241,7 +269,7 @@ impl<'a> Painter<'a> {
&mut Some(&mut self.line_numbers_data),
painted_prefix,
None,
- None,
+ BgShouldFill::With(BgFillMethod::Spaces),
);
}
}
@@ -258,7 +286,7 @@ impl<'a> Painter<'a> {
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
painted_prefix: Option<ansi_term::ANSIString>,
empty_line_style: Option<Style>, // a style with background color to highlight an empty line
- background_color_extends_to_terminal_width: Option<bool>,
+ background_color_extends_to_terminal_width: BgShouldFill,
) {
// There's some unfortunate hackery going on here for two reasons:
//
@@ -281,15 +309,23 @@ impl<'a> Painter<'a> {
painted_prefix.clone(),
config,
);
- let (should_right_fill_background_color, fill_style) =
+ let (bg_fill_mode, fill_style) =
Painter::get_should_right_fill_background_color_and_fill_style(
diff_sections,
state,
background_color_extends_to_terminal_width,
config,
);
- if should_right_fill_background_color {
+
+ if let Some(BgFillMethod::TryAnsiSequence) = bg_fill_mode {
Painter::right_fill_background_color(&mut line, fill_style);
+ } else if let Some(BgFillMethod::Spaces) = bg_fill_mode {
+ let text_width = ansi::measure_text_width(&line);
+ line.push_str(
+ &fill_style
+ .paint(" ".repeat(config.