summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock42
-rw-r--r--Cargo.toml3
-rw-r--r--src/cli.rs191
-rw-r--r--src/config.rs214
-rw-r--r--src/delta.rs778
-rw-r--r--src/main.rs1
-rw-r--r--src/paint.rs95
-rw-r--r--src/tests/ansi_test_utils.rs111
-rw-r--r--src/tests/integration_test_utils.rs68
-rw-r--r--src/tests/mod.rs4
-rw-r--r--src/tests/test_example_diffs.rs575
-rw-r--r--src/tests/test_hunk_highlighting.rs160
12 files changed, 1383 insertions, 859 deletions
diff --git a/Cargo.lock b/Cargo.lock
index feca3110..6a0336e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -14,6 +14,14 @@ dependencies = [
]
[[package]]
+name = "ansi-parser"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "ansi_colours"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -122,6 +130,19 @@ dependencies = [
]
[[package]]
+name = "bit-set"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "bitflags"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,6 +281,11 @@ dependencies = [
]
[[package]]
+name = "either"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "encode_unicode"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -337,14 +363,17 @@ dependencies = [
name = "git-delta"
version = "0.1.1"
dependencies = [
+ "ansi-parser 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_colours 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"box_drawing 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bytelines 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"console 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"shell-words 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -397,6 +426,14 @@ dependencies = [
]
[[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -934,6 +971,7 @@ dependencies = [
[metadata]
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
+"checksum ansi-parser 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "761ac675f1638a6a49e26f6ac3a4067ca3fefa8029816ae4ef8d3fa3d06a5194"
"checksum ansi_colours 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0f302a81afc6a7f4350c04f0ba7cfab529cc009bca3324b3fb5764e6add8b6"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
@@ -946,6 +984,8 @@ dependencies = [
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"
"checksum bindgen 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb0e5a5f74b2bafe0b39379f616b5975e08bcaca4e779c078d5c31324147e9ba"
+"checksum bit-set 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
+"checksum bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum blake2b_simd 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0"
"checksum box_drawing 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea27d8d5fd867b17523bf6788b1175fa9867f34669d057e9adaf76e27bcea44b"
@@ -963,6 +1003,7 @@ dependencies = [
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
+"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd"
"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
"checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd"
@@ -978,6 +1019,7 @@ dependencies = [
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
"checksum humantime 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b6c53306532d3c8e8087b44e6580e10db51a023cf9b433cea2ac38066b92da"
"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
+"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
diff --git a/Cargo.toml b/Cargo.toml
index 96171ec8..15c9407c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,12 +17,15 @@ path = "src/main.rs"
[dependencies]
ansi_colours = "1.0.1"
+ansi-parser = "0.6.5"
ansi_term = "0.12.1"
atty = "0.2.14"
+bit-set = "0.5.2"
box_drawing = "0.1.2"
bytelines = "2.2.2"
console = "0.11.2"
dirs = "2.0"
+itertools = "0.9.0"
lazy_static = "1.4"
regex = "1.2.1"
shell-words = "0.1.0"
diff --git a/src/cli.rs b/src/cli.rs
index b9c05d86..6eb5c9e9 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -2,12 +2,14 @@ use std::process;
use std::str::FromStr;
use std::string::ToString;
+use bit_set::BitSet;
use console::Term;
use structopt::StructOpt;
use crate::bat::assets::HighlightingAssets;
use crate::bat::output::PagingMode;
use crate::config;
+use crate::delta::State;
use crate::env;
use crate::style;
@@ -68,21 +70,37 @@ pub struct Opt {
pub dark: bool,
#[structopt(long = "minus-color")]
- /// The background color to use for removed lines.
+ /// The background color for removed lines.
pub minus_color: Option<String>,
#[structopt(long = "minus-emph-color")]
- /// The background color to use for emphasized sections of removed lines.
+ /// The background color for emphasized sections of removed lines.
pub minus_emph_color: Option<String>,
+ #[structopt(long = "minus-foreground-color")]
+ /// The foreground color for removed lines.
+ pub minus_foreground_color: Option<String>,
+
+ #[structopt(long = "minus-emph-foreground-color")]
+ /// The foreground color for emphasized sections of removed lines.
+ pub minus_emph_foreground_color: Option<String>,
+
#[structopt(long = "plus-color")]
- /// The background color to use for added lines.
+ /// The background color for added lines.
pub plus_color: Option<String>,
#[structopt(long = "plus-emph-color")]
- /// The background color to use for emphasized sections of added lines.
+ /// The background color for emphasized sections of added lines.
pub plus_emph_color: Option<String>,
+ #[structopt(long = "plus-foreground-color")]
+ /// Disable syntax highlighting and instead use this foreground color for added lines.
+ pub plus_foreground_color: Option<String>,
+
+ #[structopt(long = "plus-emph-foreground-color")]
+ /// Disable syntax highlighting and instead use this foreground color for emphasized sections of added lines.
+ pub plus_emph_foreground_color: Option<String>,
+
#[structopt(long = "theme", env = "BAT_THEME")]
/// The code syntax highlighting theme to use. Use --theme=none to disable syntax highlighting.
/// If the theme is not set using this option, it will be taken from the BAT_THEME environment
@@ -91,10 +109,15 @@ pub struct Opt {
/// --file-color, --hunk-color to configure the colors of other parts of the diff output.
pub theme: Option<String>,
+ /// A string consisting only of the characters '-', '0', '+', specifying
+ /// which of the 3 diff hunk line-types (removed, unchanged, added) should
+ /// be syntax-highlighted. "all" and "none" are also valid values.
+ #[structopt(long = "syntax-highlight", default_value = "0+")]
+ pub lines_to_be_syntax_highlighted: String,
+
#[structopt(long = "highlight-removed")]
- /// Apply syntax highlighting to removed lines. The default is to
- /// apply syntax highlighting to unchanged and new lines only.
- pub highlight_removed: bool,
+ /// DEPRECATED: use --syntax-highlight.
+ pub highlight_minus_lines: bool,
#[structopt(long = "color-only")]
/// Do not alter the input in any way other than applying colors. Equivalent to
@@ -296,6 +319,7 @@ pub fn process_command_line_arguments<'a>(
true_color,
available_terminal_width,
paging_mode,
+ get_lines_to_be_syntax_highlighted(opt),
)
}
@@ -304,3 +328,156 @@ fn is_truecolor_terminal() -> bool {
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
.unwrap_or(false)
}
+
+fn get_lines_to_be_syntax_highlighted(opt: &Opt) -> BitSet {
+ if opt.highlight_minus_lines {
+ eprintln!("--highlight-removed is deprecated: use --syntax-highlight.");
+ }
+
+ let syntax_highlight_lines = match opt.lines_to_be_syntax_highlighted.to_lowercase().as_ref() {
+ "none" => "",
+ // This is the default value of the new option: honor the deprecated option if it has been used.
+ "0+" => match opt.highlight_minus_lines {
+ true => "-0+",
+ false => "0+",
+ },
+ "all" => "-0+",
+ s => s,
+ }
+ .to_string();
+
+ let mut lines_to_be_syntax_highlighted = BitSet::new();
+ for line_type in syntax_highlight_lines.chars() {
+ lines_to_be_syntax_highlighted.insert(match line_type {
+ '-' => State::HunkMinus as usize,
+ '0' => State::HunkZero as usize,
+ '+' => State::HunkPlus as usize,
+ s => {
+ eprintln!("Invalid --syntax-highlight value: {}. Valid characters are \"-\", \"0\", \"+\".", s);
+ process::exit(1);
+ }
+ });
+ }
+ lines_to_be_syntax_highlighted
+}
+
+#[cfg(test)]
+mod tests {
+ use std::env;
+
+ use crate::bat::assets::HighlightingAssets;
+ use crate::cli;
+ use crate::style;
+ use crate::tests::integration_test_utils::integration_test_utils;
+
+ #[test]
+ fn test_theme_selection() {
+ #[derive(PartialEq)]
+ enum Mode {
+ Light,
+ Dark,
+ };
+ let assets = HighlightingAssets::new();
+ for (
+ theme_option,
+ bat_theme_env_var,
+ mode_option, // (--light, --dark)
+ expected_theme,
+ expected_mode,
+ ) in vec![
+ (None, "", None, style::DEFAULT_DARK_THEME, Mode::Dark),
+ (Some("GitHub".to_string()), "", None, "GitHub", Mode::Light),
+ (
+ Some("GitHub".to_string()),
+ "1337",
+ None,
+ "GitHub",
+ Mode::Light,
+ ),
+ (None, "1337", None, "1337", Mode::Dark),
+ (
+ None,
+ "<not set>",
+ None,
+ style::DEFAULT_DARK_THEME,
+ Mode::Dark,
+ ),
+ (
+ None,
+ "",
+ Some(Mode::Light),
+ style::DEFAULT_LIGHT_THEME,
+ Mode::Light,
+ ),
+ (
+ None,
+ "",
+ Some(Mode::Dark),
+ style::DEFAULT_DARK_THEME,
+ Mode::Dark,
+ ),
+ (
+ None,
+ "<@@@@@>",
+ Some(Mode::Light),
+ style::DEFAULT_LIGHT_THEME,
+ Mode::Light,
+ ),
+ (None, "1337", Some(Mode::Light), "1337", Mode::Light),
+ (Some("none".to_string()), "", None, "none", Mode::Dark),
+ (
+ Some("None".to_string()),
+ "",
+ Some(Mode::Light),
+ "None",
+ Mode::Light,
+ ),
+ ] {
+ if bat_theme_env_var == "<not set>" {
+ env::remove_var("BAT_THEME")
+ } else {
+ env::set_var("BAT_THEME", bat_theme_env_var);
+ }
+ let is_true_color = true;
+ let mut options = integration_test_utils::get_command_line_options();
+ options.theme = theme_option;
+ match mode_option {
+ Some(Mode::Light) => {
+ options.light = true;
+ options.dark = false;
+ }
+ Some(Mode::Dark) => {
+ options.light = false;
+ options.dark = true;
+ }
+ None => {
+ options.light = false;
+ options.dark = false;
+ }
+ }
+ let config = cli::process_command_line_arguments(&assets, &options);
+ assert_eq!(config.theme_name, expected_theme);
+ if style::is_no_syntax_highlighting_theme_name(expected_theme) {
+ assert!(config.theme.is_none())
+ } else {
+ assert_eq!(config.theme.unwrap().name.as_ref().unwrap(), expected_theme);
+ }
+ assert_eq!(
+ config.minus_style_modifier.background.unwrap(),
+ style::get_minus_color_default(expected_mode == Mode::Light, is_true_color)
+ );
+ assert_eq!(
+ config.minus_emph_style_modifier.background.unwrap(),
+ style::get_minus_emph_color_default(expected_mode == Mode::Light, is_true_color)
+ );
+ assert_eq!(
+ config.plus_style_modifier.background.unwrap(),
+ style::get_plus_color_default(expected_mode == Mode::Light, is_true_color)
+ );
+ assert_eq!(
+ config.plus_emph_style_modifier.background.unwrap(),
+ style::get_plus_emph_color_default(expected_mode == Mode::Light, is_true_color)
+ );
+ }
+ }
+}
diff --git a/src/config.rs b/src/config.rs
index 9fc757d3..f9e42196 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,11 +1,13 @@
use std::process;
use std::str::FromStr;
+use bit_set::BitSet;
use syntect::highlighting::{Color, Style, StyleModifier, Theme, ThemeSet};
use syntect::parsing::SyntaxSet;
use crate::bat::output::PagingMode;
use crate::cli;
+use crate::delta::State;
use crate::env;
use crate::paint;
use crate::style;
@@ -15,13 +17,15 @@ pub struct Config<'a> {
pub theme_name: String,
pub max_line_distance: f64,
pub max_line_distance_for_naively_paired_lines: f64,
+ pub minus_foreground_style_modifier: Option<StyleModifier>,
pub minus_style_modifier: StyleModifier,
pub minus_emph_style_modifier: StyleModifier,
+ pub plus_foreground_style_modifier: Option<StyleModifier>,
pub plus_style_modifier: StyleModifier,
pub plus_emph_style_modifier: StyleModifier,
pub minus_line_marker: &'a str,
pub plus_line_marker: &'a str,
- pub highlight_removed: bool,
+ pub lines_to_be_syntax_highlighted: BitSet,
pub commit_style: cli::SectionStyle,
pub commit_color: Color,
pub file_style: cli::SectionStyle,
@@ -38,6 +42,37 @@ pub struct Config<'a> {
pub paging_mode: PagingMode,
}
+#[allow(dead_code)]
+pub enum ColorLayer {
+ Background,
+ Foreground,
+}
+use ColorLayer::*;
+use State::*;
+
+impl<'a> Config<'a> {
+ #[allow(dead_code)]
+ pub fn get_color(&self, state: &State, layer: ColorLayer) -> Option<Color> {
+ let modifier = match state {
+ HunkMinus => Some(self.minus_style_modifier),
+ HunkZero => None,
+ HunkPlus => Some(self.plus_style_modifier),
+ _ => panic!("Invalid"),
+ };
+ match (modifier, layer) {
+ (Some(modifier), Background) => modifier.background,
+ (Some(modifier), Foreground) => modifier.foreground,
+ (None, _) => None,
+ }
+ }
+
+ #[allow(dead_code)]
+ pub fn should_syntax_highlight(&self, state: &State) -> bool {
+ self.lines_to_be_syntax_highlighted
+ .contains((*state).clone() as usize)
+ }
+}
+
pub fn get_config<'a>(
opt: &'a cli::Opt,
syntax_set: &'a SyntaxSet,
@@ -45,6 +80,7 @@ pub fn get_config<'a>(
true_color: bool,
terminal_width: usize,
paging_mode: PagingMode,
+ lines_to_be_syntax_highlighted: BitSet,
) -> Config<'a> {
// Implement --color-only
let keep_plus_minus_markers = if opt.color_only {
@@ -54,20 +90,14 @@ pub fn get_config<'a>(
};
let background_color_extends_to_terminal_width = opt.width != Some("variable".to_string());
let tab_width = if opt.color_only { 0 } else { opt.tab_width };
- let commit_style = if opt.color_only {
- cli::SectionStyle::Plain
- } else {
- opt.commit_style
- };
- let file_style = if opt.color_only {
- cli::SectionStyle::Plain
+ let (commit_style, file_style, hunk_style) = if opt.color_only {
+ (
+ cli::SectionStyle::Plain,
+ cli::SectionStyle::Plain,
+ cli::SectionStyle::Plain,
+ )
} else {
- opt.file_style
- };
- let hunk_style = if opt.color_only {
- cli::SectionStyle::Plain
- } else {
- opt.hunk_style
+ (opt.commit_style, opt.file_style, opt.hunk_style)
};
let theme_name_from_bat_pager = env::get_env_var("BAT_THEME");
@@ -78,56 +108,26 @@ pub fn get_config<'a>(
theme_set,
);
+ let (
+ minus_style_modifier,
+ plus_style_modifier,
+ minus_emph_style_modifier,
+ plus_emph_style_modifier,
+ minus_foreground_style_modifier,
+ plus_foreground_style_modifier,
+ ) = make_style_modifiers(
+ &lines_to_be_syntax_highlighted,
+ opt,
+ is_light_mode,
+ true_color,
+ );
+
let theme = if style::is_no_syntax_highlighting_theme_name(&theme_name) {
None
} else {
Some(&theme_set.themes[&theme_name])
};
- let minus_style_modifier = StyleModifier {
- background: Some(color_from_rgb_or_ansi_code_with_default(
- opt.minus_color.as_ref(),
- style::get_minus_color_default(is_light_mode, true_color),
- )),
- foreground: if opt.highlight_removed {
- None
- } else {
- Some(style::NO_COLOR)
- },
- font_style: None,
- };
-
- let minus_emph_style_modifier = StyleModifier {
- background: Some(color_from_rgb_or_ansi_code_with_default(
- opt.minus_emph_color.as_ref(),
- style::get_minus_emph_color_default(is_light_mode, true_color),
- )),
- foreground: if opt.highlight_removed {
- None
- } else {
- Some(style::NO_COLOR)
- },
- font_style: None,
- };
-
- let plus_style_modifier = StyleModifier {
- background: Some(color_from_rgb_or_ansi_code_with_default(
- opt.plus_color.as_ref(),
- style::get_plus_color_default(is_light_mode, true_color),
- )),
- foreground: None,
- font_style: None,
- };
-
- let plus_emph_style_modifier = StyleModifier {
- background: Some(color_from_rgb_or_ansi_code_with_default(
- opt.plus_emph_color.as_ref(),
- style::get_plus_emph_color_default(is_light_mode, true_color),
- )),
- foreground: None,
- font_style: None,
- };
-
let minus_line_marker = if keep_plus_minus_markers { "-" } else { " " };
let plus_line_marker = if keep_plus_minus_markers { "+" } else { " " };
@@ -141,11 +141,13 @@ pub fn get_config<'a>(
theme_name,
max_line_distance: opt.max_line_distance,
max_line_distance_for_naively_paired_lines,
+ minus_foreground_style_modifier,
minus_style_modifier,
minus_emph_style_modifier,
+ plus_foreground_style_modifier,
plus_style_modifier,
plus_emph_style_modifier,
- highlight_removed: opt.highlight_removed,
+ lines_to_be_syntax_highlighted,
minus_line_marker,
plus_line_marker,
commit_style,
@@ -220,6 +222,100 @@ fn valid_theme_name_or_none(theme_name: Option<&String>, theme_set: &ThemeSet) -
}
}
+fn make_style_modifiers<'a>(
+ lines_to_be_syntax_highlighted: &BitSet,
+ opt: &'a cli::Opt,
+ is_light_mode: bool,
+ true_color: bool,
+) -> (
+ StyleModifier,
+ StyleModifier,
+ StyleModifier,
+ StyleModifier,
+ Option<StyleModifier>,
+ Option<StyleModifier>,
+) {
+ // Background styles
+ let minus_background_style_modifier = StyleModifier {
+ background: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.minus_color.as_ref(),
+ style::get_minus_color_default(is_light_mode, true_color),
+ )),
+ foreground: if lines_to_be_syntax_highlighted.contains(State::HunkMinus as usize) {
+ None
+ } else {
+ Some(style::NO_COLOR)
+ },
+ font_style: None,
+ };
+
+ let plus_background_style_modifier = StyleModifier {
+ background: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.plus_color.as_ref(),
+ style::get_plus_color_default(is_light_mode, true_color),
+ )),
+ foreground: None,
+ font_style: None,
+ };
+
+ // Background emph styles
+ let minus_background_emph_style_modifier = StyleModifier {
+ background: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.minus_emph_color.as_ref(),
+ style::get_minus_emph_color_default(is_light_mode, true_color),
+ )),
+ foreground: if lines_to_be_syntax_highlighted.contains(State::HunkMinus as usize) {
+ None
+ } else {
+ Some(style::NO_COLOR)
+ },
+ font_style: None,
+ };
+
+ let plus_background_emph_style_modifier = StyleModifier {
+ background: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.plus_emph_color.as_ref(),
+ style::get_plus_emph_color_default(is_light_mode, true_color),
+ )),
+ foreground: None,
+ font_style: None,
+ };
+
+ // Foreground styles (these replace syntax highlighting).
+ let minus_foreground_style_modifier = match opt.minus_foreground_color.is_some() {
+ true => Some(StyleModifier {
+ background: None,
+ foreground: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.minus_foreground_color.as_ref(),
+ style::get_minus_emph_color_default(is_light_mode, true_color),
+ )),
+ font_style: None,
+ }),
+ false => None,
+ };
+
+ let plus_foreground_style_modifier = match opt.plus_foreground_color.is_some() {
+ true => Some(StyleModifier {
+ background: None,
+ foreground: Some(color_from_rgb_or_ansi_code_with_default(
+ opt.plus_foreground_color.as_ref(),
+ style::get_plus_emph_color_default(is_light_mode, true_color),
+ )),
+ font_style: None,
+ }),
+ false => None,
+ };
+
+ (
+ minus_background_style_modifier,
+ plus_background_style_modifier,
+ minus_background_emph_style_modifier,
+ plus_background_emph_style_modifier,
+ minus_foreground_style_modifier,
+ plus_foreground_style_modifier,
+ )
+}
+
fn color_from_rgb_or_ansi_code(s: &str) -> Color {
let die = || {
eprintln!("Invalid color: {}", s);
diff --git a/src/delta.rs b/src/delta.rs
index 05fc0760..bcbf3e07 100644
--- a/src/delta.rs
+++ b/src/delta.rs
@@ -13,7 +13,7 @@ use crate::paint::{self, Painter};
use crate::parse;
use crate::style;
-#[derive(Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub enum State {
CommitMeta, // In commit metadata section
FileMeta, // In diff metadata section, between (possible) commit metadata and first hunk
@@ -262,8 +262,8 @@ fn handle_hunk_meta_line(
let syntax_style_sections = Painter::get_line_syntax_style_sections(
&code_fragment,
&mut painter.highlighter,
+ None,
&painter.config,
- true,
);
Painter::paint_lines(
vec![syntax_style_sections],
@@ -330,25 +330,33 @@ fn handle_hunk_line(
State::HunkPlus
}
Some(' ') => {
+ let state = State::HunkZero;
let prefix = if line.is_empty() { "" } else { &line[..1] };
painter.paint_buffered_lines();
let line = prepare(&line, true, config);
- let syntax_style_sections = Painter::get_line_syntax_style_sections(
- &line,
- &mut painter.highlighter,
- &painter.config,
- true,
- );
+ let syntax_style_sections = if config.should_syntax_highlight(&state) {
+ Painter::get_line_syntax_style_sections(
+ &line,
+ &mut painter.highlighter,
+ None,
+ &painter.config,
+ )
+ } else {
+ vec![(style::get_no_style(), line.as_str())]
+ };
+ let diff_style_sections =
+ vec![(style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, line.as_str())];