summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cli.rs11
-rw-r--r--src/config.rs48
-rw-r--r--src/delta.rs2
-rw-r--r--src/paint.rs24
-rw-r--r--src/set_options.rs2
-rw-r--r--src/style.rs8
-rw-r--r--src/tests/ansi_test_utils.rs1
-rw-r--r--src/tests/test_example_diffs.rs118
8 files changed, 211 insertions, 3 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 52cbe0e7..e91b7056 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -404,6 +404,17 @@ pub struct Opt {
#[structopt(parse(from_os_str))]
pub plus_file: Option<PathBuf>,
+ /// Style for removed empty line marker (used only if --minus-style has no background color)
+ #[structopt(
+ long = "--minus-empty-line-marker-style",
+ default_value = "normal auto"
+ )]
+ pub minus_empty_line_marker_style: String,
+
+ /// Style for added empty line marker (used only if --plus-style has no background color)
+ #[structopt(long = "--plus-empty-line-marker-style", default_value = "normal auto")]
+ pub plus_empty_line_marker_style: String,
+
#[structopt(long = "minus-color")]
/// Deprecated: use --minus-style='normal my_background_color'.
pub deprecated_minus_background_color: Option<String>,
diff --git a/src/config.rs b/src/config.rs
index ee2b4c16..794acc7d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -44,6 +44,7 @@ pub struct Config {
pub max_line_distance: f64,
pub max_line_distance_for_naively_paired_lines: f64,
pub minus_emph_style: Style,
+ pub minus_empty_line_marker_style: Style,
pub minus_file: Option<PathBuf>,
pub minus_non_emph_style: Style,
pub minus_style: Style,
@@ -58,6 +59,7 @@ pub struct Config {
pub number_plus_style: Style,
pub paging_mode: PagingMode,
pub plus_emph_style: Style,
+ pub plus_empty_line_marker_style: Style,
pub plus_file: Option<PathBuf>,
pub plus_non_emph_style: Style,
pub plus_style: Style,
@@ -207,10 +209,12 @@ impl From<cli::Opt> for Config {
minus_style,
minus_emph_style,
minus_non_emph_style,
+ minus_empty_line_marker_style,
zero_style,
plus_style,
plus_emph_style,
plus_non_emph_style,
+ plus_empty_line_marker_style,
) = make_hunk_styles(&opt, is_light_mode, true_color);
let (commit_style, file_style, hunk_header_style) =
@@ -268,6 +272,7 @@ impl From<cli::Opt> for Config {
max_line_distance: opt.max_line_distance,
max_line_distance_for_naively_paired_lines,
minus_emph_style,
+ minus_empty_line_marker_style,
minus_file: opt.minus_file.map(|s| s.clone()),
minus_non_emph_style,
minus_style,
@@ -282,6 +287,7 @@ impl From<cli::Opt> for Config {
number_plus_style,
paging_mode,
plus_emph_style,
+ plus_empty_line_marker_style,
plus_file: opt.plus_file.map(|s| s.clone()),
plus_non_emph_style,
plus_style,
@@ -303,7 +309,17 @@ fn make_hunk_styles<'a>(
opt: &'a cli::Opt,
is_light_mode: bool,
true_color: bool,
-) -> (Style, Style, Style, Style, Style, Style, Style) {
+) -> (
+ Style,
+ Style,
+ Style,
+ Style,
+ Style,
+ Style,
+ Style,
+ Style,
+ Style,
+) {
let minus_style = Style::from_str(
&opt.minus_style,
None,
@@ -337,6 +353,20 @@ fn make_hunk_styles<'a>(
false,
);
+ // The style used to highlight a removed empty line when otherwise it would be invisible due to
+ // lack of background color in minus-style.
+ let minus_empty_line_marker_style = Style::from_str(
+ &opt.minus_empty_line_marker_style,
+ None,
+ Some(color::get_minus_background_color_default(
+ is_light_mode,
+ true_color,
+ )),
+ None,
+ true_color,
+ false,
+ );
+
let zero_style = Style::from_str(&opt.zero_style, None, None, None, true_color, false);
let plus_style = Style::from_str(
@@ -372,14 +402,30 @@ fn make_hunk_styles<'a>(
false,
);
+ // The style used to highlight an added empty line when otherwise it would be invisible due to
+ // lack of background color in plus-style.
+ let plus_empty_line_marker_style = Style::from_str(
+ &opt.plus_empty_line_marker_style,
+ None,
+ Some(color::get_plus_background_color_default(
+ is_light_mode,
+ true_color,
+ )),
+ None,
+ true_color,
+ false,
+ );
+
(
minus_style,
minus_emph_style,
minus_non_emph_style,
+ minus_empty_line_marker_style,
zero_style,
plus_style,
plus_emph_style,
plus_non_emph_style,
+ plus_empty_line_marker_style,
)
}
diff --git a/src/delta.rs b/src/delta.rs
index 36ea6a56..366520ec 100644
--- a/src/delta.rs
+++ b/src/delta.rs
@@ -405,6 +405,7 @@ fn handle_hunk_header_line(
"",
config.null_style,
config.null_style,
+ None,
Some(false),
);
painter.output_buffer.pop(); // trim newline
@@ -495,6 +496,7 @@ fn handle_hunk_line(
config.zero_style,
config.zero_style,
None,
+ None,
);
painter.minus_line_number += 1;
painter.plus_line_number += 1;
diff --git a/src/paint.rs b/src/paint.rs
index 62a7f64f..d9dddd62 100644
--- a/src/paint.rs
+++ b/src/paint.rs
@@ -14,6 +14,8 @@ use crate::paint::superimpose_style_sections::superimpose_style_sections;
use crate::style::Style;
pub const ANSI_CSI_CLEAR_TO_EOL: &str = "\x1b[0K";
+pub const ANSI_CSI_CLEAR_TO_BOL: &str = "\x1b[1K";
+pub const ANSI_CSI_CURSOR_BACK_1: &str = "\x1b[1D";
pub const ANSI_SGR_RESET: &str = "\x1b[0m";
pub struct Painter<'a> {
@@ -103,6 +105,7 @@ impl<'a> Painter<'a> {
},
self.config.minus_style,
self.config.minus_non_emph_style,
+ Some(self.config.minus_empty_line_marker_style),
None,
);
}
@@ -120,6 +123,7 @@ impl<'a> Painter<'a> {
},
self.config.plus_style,
self.config.plus_non_emph_style,
+ Some(self.config.plus_empty_line_marker_style),
None,
);
}
@@ -138,6 +142,7 @@ impl<'a> Painter<'a> {
prefix: &str,
style: Style, // style for right fill if line contains no emph sections
non_emph_style: Style, // style for right fill if line contains emph sections
+ empty_line_style: Option<Style>, // a style with background color to highlight an empty line
background_color_extends_to_terminal_width: Option<bool>,
) {
// There's some unfortunate hackery going on here for two reasons:
@@ -214,7 +219,7 @@ impl<'a> Painter<'a> {
}
// Set style for the right-fill.
let mut have_background_for_right_fill = false;
- if non_emph_style.ansi_term_style.background.is_some() {
+ if non_emph_style.has_background_color() {
ansi_strings.push(non_emph_style.ansi_term_style.paint(""));
have_background_for_right_fill = true;
}
@@ -224,7 +229,9 @@ impl<'a> Painter<'a> {
Some(boolean) => boolean,
None => config.background_color_extends_to_terminal_width,
};
- if background_color_extends_to_terminal_width && have_background_for_right_fill {
+ let right_fill_background_color =
+ background_color_extends_to_terminal_width && have_background_for_right_fill;
+ if right_fill_background_color {
// HACK: How to properly incorporate the ANSI_CSI_CLEAR_TO_EOL into ansi_strings?
if line
.to_lowercase()
@@ -238,6 +245,19 @@ impl<'a> Painter<'a> {
} else {
output_buffer.push_str(&line);
}
+ if line.is_empty() && !right_fill_background_color {
+ if let Some(empty_line_style) = empty_line_style {
+ output_buffer.push_str(
+ &empty_line_style
+ .ansi_term_style
+ .paint(format!(
+ "{}{}",
+ ANSI_CSI_CLEAR_TO_BOL, ANSI_CSI_CURSOR_BACK_1
+ ))
+ .to_string(),
+ );
+ }
+ }
output_buffer.push_str("\n");
}
}
diff --git a/src/set_options.rs b/src/set_options.rs
index fe5705c4..007cb326 100644
--- a/src/set_options.rs
+++ b/src/set_options.rs
@@ -188,6 +188,7 @@ pub fn set_options(
// dynamically to the value of the former.
("minus-style", String, minus_style),
("minus-emph-style", String, minus_emph_style),
+ ("minus-empty-line-marker-style", String, minus_empty_line_marker_style),
("minus-non-emph-style", String, minus_non_emph_style),
("navigate", bool, navigate),
("number", bool, show_line_numbers),
@@ -206,6 +207,7 @@ pub fn set_options(
// dynamically to the value of the former.
("plus-style", String, plus_style),
("plus-emph-style", String, plus_emph_style),
+ ("plus-empty-line-marker-style", String, plus_empty_line_marker_style),
("plus-non-emph-style", String, plus_non_emph_style),
("syntax_theme", Option<String>, syntax_theme),
("tabs", usize, tab_width),
diff --git a/src/style.rs b/src/style.rs
index 6b11725f..7e7bea35 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -49,6 +49,14 @@ impl Style {
}
}
+ pub fn has_background_color(&self) -> bool {
+ if self.ansi_term_style.is_reverse {
+ self.ansi_term_style.foreground.is_some()
+ } else {
+ self.ansi_term_style.background.is_some()
+ }
+ }
+
/// Construct Style from style and decoration-style strings supplied on command line, together
/// with defaults. A style string is a space-separated string containing 0, 1, or 2 colors
/// (foreground and then background) and an arbitrary number of style attributes. See `delta
diff --git a/src/tests/ansi_test_utils.rs b/src/tests/ansi_test_utils.rs
index 7d0ccf36..cc796db8 100644
--- a/src/tests/ansi_test_utils.rs
+++ b/src/tests/ansi_test_utils.rs
@@ -114,6 +114,7 @@ pub mod ansi_test_utils {
config.null_style,
config.null_style,
None,
+ None,
);
output_buffer
}
diff --git a/src/tests/test_example_diffs.rs b/src/tests/test_example_diffs.rs
index 85123080..1e4bc1d0 100644
--- a/src/tests/test_example_diffs.rs
+++ b/src/tests/test_example_diffs.rs
@@ -2,6 +2,8 @@
mod tests {
use console::strip_ansi_codes;
+ use crate::paint;
+ use crate::style;
use crate::tests::ansi_test_utils::ansi_test_utils;
use crate::tests::integration_test_utils::integration_test_utils;
@@ -1007,6 +1009,104 @@ impl<'a> Alignment<'a> { │
));
}
+ #[test]
+ fn test_removed_empty_line_highlight() {
+ let minus_empty_line_marker_style = "bold yellow magenta ul";
+ _do_test_removed_empty_line_highlight(minus_empty_line_marker_style, "red reverse", true);
+ _do_test_removed_empty_line_highlight(minus_empty_line_marker_style, "normal red", true);
+ _do_test_removed_empty_line_highlight(minus_empty_line_marker_style, "red", false);
+ _do_test_removed_empty_line_highlight(
+ minus_empty_line_marker_style,
+ "normal red reverse",
+ false,
+ );
+ }
+
+ fn _do_test_removed_empty_line_highlight(
+ empty_line_marker_style: &str,
+ base_style: &str,
+ base_style_has_background_color: bool,
+ ) {
+ _do_test_empty_line_highlight(
+ "--minus-empty-line-marker-style",
+ empty_line_marker_style,
+ "--minus-style",
+ base_style,
+ base_style_has_background_color,
+ DIFF_WITH_REMOVED_EMPTY_LINE,
+ );
+ }
+
+ #[test]
+ fn test_added_empty_line_highlight() {
+ let plus_empty_line_marker_style = "bold yellow magenta ul";
+ _do_test_added_empty_line_highlight(plus_empty_line_marker_style, "green reverse", true);
+ _do_test_added_empty_line_highlight(plus_empty_line_marker_style, "normal green", true);
+ _do_test_added_empty_line_highlight(plus_empty_line_marker_style, "green", false);
+ _do_test_added_empty_line_highlight(
+ plus_empty_line_marker_style,
+ "normal green reverse",
+ false,
+ );
+ }
+
+ fn _do_test_added_empty_line_highlight(
+ empty_line_marker_style: &str,
+ base_style: &str,
+ base_style_has_background_color: bool,
+ ) {
+ _do_test_empty_line_highlight(
+ "--plus-empty-line-marker-style",
+ empty_line_marker_style,
+ "--plus-style",
+ base_style,
+ base_style_has_background_color,
+ DIFF_WITH_ADDED_EMPTY_LINE,
+ );
+ }
+
+ fn _do_test_empty_line_highlight(
+ empty_line_marker_style_name: &str,
+ empty_line_marker_style: &str,
+ base_style_name: &str,
+ base_style: &str,
+ base_style_has_background_color: bool,
+ example_diff: &str,
+ ) {
+ let config = integration_test_utils::make_config(&[
+ base_style_name,
+ base_style,
+ empty_line_marker_style_name,
+ empty_line_marker_style,
+ ]);
+ let output = integration_test_utils::run_delta(example_diff, &config);
+ let line = output.lines().nth(6).unwrap();
+ if base_style_has_background_color {
+ let style = style::Style::from_str(base_style, None, None, None, true, false);
+ assert_eq!(
+ line,
+ &style
+ .ansi_term_style
+ .paint(paint::ANSI_CSI_CLEAR_TO_EOL)
+ .to_string()
+ );
+ } else {
+ let style =
+ style::Style::from_str(empty_line_marker_style, None, None, None, true, false);
+ assert_eq!(
+ line,
+ &style
+ .ansi_term_style
+ .paint(format!(
+ "{}{}",
+ paint::ANSI_CSI_CLEAR_TO_BOL,
+ paint::ANSI_CSI_CURSOR_BACK_1
+ ))
+ .to_string()
+ );
+ }
+ }
+
const GIT_DIFF_SINGLE_HUNK: &str = "\
commit 94907c0f136f46dc46ffae2dc92dca9af7eb7c2e
Author: Dan Davison <dandavison7@gmail.com>
@@ -1442,4 +1542,22 @@ index cba6064..ba1a4de 100644
- Co
+ let col = Co
"#;
+
+ const DIFF_WITH_REMOVED_EMPTY_LINE: &str = r"
+diff --git i/a w/a
+index 8b13789..e69de29 100644
+--- i/a
++++ w/a
+@@ -1 +0,0 @@
+-
+";
+
+ const DIFF_WITH_ADDED_EMPTY_LINE: &str = r"
+diff --git i/a w/a
+index e69de29..8b13789 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++
+";
}