summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-04-21 09:07:36 -0400
committerThomas Otto <th1000s@posteo.net>2021-10-16 14:07:30 +0200
commit32aef48ccf6d03a1c316228b9d0398c38e22f8fc (patch)
treefff66585b1ec9f7207362ff0aedb5f9eb3229b6d
parent7c93d279e60253fc380d73f2f84fe5e2a4a274e6 (diff)
Add inline-hint-style option and use for side-by-side wrap symbols
-rw-r--r--src/cli.rs6
-rw-r--r--src/config.rs17
-rw-r--r--src/options/set.rs1
-rw-r--r--src/syntect_utils.rs73
-rw-r--r--src/wrapping.rs39
5 files changed, 123 insertions, 13 deletions
diff --git a/src/cli.rs b/src/cli.rs
index e2f75674..caa18de6 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -447,6 +447,12 @@ pub struct Opt {
#[structopt(long = "default-language")]
pub default_language: Option<String>,
+ #[structopt(long = "inline-hint-style", default_value = "blue")]
+ /// Style (foreground, background, attributes) for content added by delta to
+ /// the original diff such as special characters to highlight tabs, and the
+ /// symbols used to indicate wrapped lines. See STYLES section.
+ pub inline_hint_style: String,
+
/// The regular expression used to decide what a word is for the within-line highlight
/// algorithm. For less fine-grained matching than the default try --word-diff-regex="\S+"
/// --max-line-distance=1.0 (this is more similar to `git --word-diff`).
diff --git a/src/config.rs b/src/config.rs
index 15b3b75d..d89af7d5 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -21,7 +21,7 @@ use crate::features::side_by_side;
use crate::git_config::{GitConfig, GitConfigEntry};
use crate::paint::BgFillMethod;
use crate::style::{self, Style};
-use crate::syntect_utils;
+use crate::syntect_utils::FromDeltaStyle;
use crate::wrapping::WrapConfig;
pub const INLINE_SYMBOL_WIDTH_1: usize = 1;
@@ -84,7 +84,7 @@ pub struct Config {
pub hyperlinks: bool,
pub hyperlinks_commit_link_format: Option<String>,
pub hyperlinks_file_link_format: String,
- pub inline_hint_color: Option<SyntectStyle>,
+ pub inline_hint_style: Style,
pub inspect_raw_lines: cli::InspectRawLines,
pub keep_plus_minus_markers: bool,
pub line_fill_method: BgFillMethod,
@@ -209,6 +209,13 @@ impl From<cli::Opt> for Config {
&opt.computed.available_terminal_width,
);
+ let inline_hint_style = Style::from_str(
+ &opt.inline_hint_style,
+ None,
+ None,
+ opt.computed.true_color,
+ false,
+ );
let git_minus_style = match opt.git_config_entries.get("color.diff.old") {
Some(GitConfigEntry::Style(s)) => Style::from_git_str(s),
_ => *style::GIT_DEFAULT_MINUS_STYLE,
@@ -291,10 +298,7 @@ impl From<cli::Opt> for Config {
hyperlinks_commit_link_format: opt.hyperlinks_commit_link_format,
hyperlinks_file_link_format: opt.hyperlinks_file_link_format,
inspect_raw_lines: opt.computed.inspect_raw_lines,
- inline_hint_color: Some(SyntectStyle {
- foreground: syntect_utils::syntect_color_from_ansi_name("blue").unwrap(),
- ..SyntectStyle::default()
- }),
+ inline_hint_style,
keep_plus_minus_markers: opt.keep_plus_minus_markers,
line_fill_method: if opt.side_by_side {
// Panels in side-by-side always sum up to an even number, if the terminal has
@@ -386,6 +390,7 @@ impl From<cli::Opt> for Config {
}
},
max_lines: wrap_max_lines_plus1,
+ inline_hint_syntect_style: SyntectStyle::from_delta_style(inline_hint_style),
},
whitespace_error_style,
zero_style,
diff --git a/src/options/set.rs b/src/options/set.rs
index 1d6f13ed..8f53d5b7 100644
--- a/src/options/set.rs
+++ b/src/options/set.rs
@@ -145,6 +145,7 @@ pub fn set_options(
hyperlinks,
hyperlinks_commit_link_format,
hyperlinks_file_link_format,
+ inline_hint_style,
inspect_raw_lines,
keep_plus_minus_markers,
line_buffer_size,
diff --git a/src/syntect_utils.rs b/src/syntect_utils.rs
index 3569b318..6f7e4af5 100644
--- a/src/syntect_utils.rs
+++ b/src/syntect_utils.rs
@@ -1,8 +1,9 @@
use std::str::FromStr;
-use syntect::highlighting::Color;
+use syntect::highlighting::{Color, FontStyle, Style};
use crate::color;
+use crate::style as delta_style;
pub fn syntect_color_from_ansi_name(name: &str) -> Option<Color> {
color::ansi_16_color_name_to_number(name).and_then(syntect_color_from_ansi_number)
@@ -13,3 +14,73 @@ pub fn syntect_color_from_ansi_name(name: &str) -> Option<Color> {
pub fn syntect_color_from_ansi_number(n: u8) -> Option<Color> {
Color::from_str(&format!("#{:02x}000000", n)).ok()
}
+
+pub trait FromAnsiTermStyle {
+ fn from_ansi_term_style(ansi_term_style: ansi_term::Style) -> Self;
+}
+
+impl FromAnsiTermStyle for Style {
+ fn from_ansi_term_style(ansi_term_style: ansi_term::Style) -> Self {
+ let default = Self::default();
+ Self {
+ foreground: if let Some(color) = ansi_term_style.foreground {
+ Color::from_ansi_term_color(color)
+ } else {
+ default.foreground
+ },
+ background: if let Some(color) = ansi_term_style.background {
+ Color::from_ansi_term_color(color)
+ } else {
+ default.background
+ },
+ font_style: FontStyle::from_ansi_term_style(ansi_term_style),
+ }
+ }
+}
+
+impl FromAnsiTermStyle for FontStyle {
+ fn from_ansi_term_style(ansi_term_style: ansi_term::Style) -> Self {
+ let mut font_style = FontStyle::empty();
+ if ansi_term_style.is_bold {
+ font_style |= FontStyle::BOLD
+ }
+ if ansi_term_style.is_italic {
+ font_style |= FontStyle::ITALIC
+ }
+ if ansi_term_style.is_underline {
+ font_style |= FontStyle::UNDERLINE
+ }
+ font_style
+ }
+}
+
+pub trait FromAnsiTermColor {
+ fn from_ansi_term_color(ansi_term_color: ansi_term::Color) -> Self;
+}
+
+impl FromAnsiTermColor for Color {
+ fn from_ansi_term_color(ansi_term_color: ansi_term::Color) -> Self {
+ match ansi_term_color {
+ ansi_term::Color::Black => syntect_color_from_ansi_number(0).unwrap(),
+ ansi_term::Color::Red => syntect_color_from_ansi_number(1).unwrap(),
+ ansi_term::Color::Green => syntect_color_from_ansi_number(2).unwrap(),
+ ansi_term::Color::Yellow => syntect_color_from_ansi_number(3).unwrap(),
+ ansi_term::Color::Blue => syntect_color_from_ansi_number(4).unwrap(),
+ ansi_term::Color::Purple => syntect_color_from_ansi_number(5).unwrap(),
+ ansi_term::Color::Cyan => syntect_color_from_ansi_number(6).unwrap(),
+ ansi_term::Color::White => syntect_color_from_ansi_number(7).unwrap(),
+ ansi_term::Color::Fixed(n) => syntect_color_from_ansi_number(n).unwrap(),
+ ansi_term::Color::RGB(r, g, b) => Self { r, g, b, a: 0xFF },
+ }
+ }
+}
+
+pub trait FromDeltaStyle {
+ fn from_delta_style(delta_style: delta_style::Style) -> Self;
+}
+
+impl FromDeltaStyle for Style {
+ fn from_delta_style(delta_style: delta_style::Style) -> Self {
+ Self::from_ansi_term_style(delta_style.ansi_term_style)
+ }
+}
diff --git a/src/wrapping.rs b/src/wrapping.rs
index abb19db1..d183afe1 100644
--- a/src/wrapping.rs
+++ b/src/wrapping.rs
@@ -26,6 +26,7 @@ pub struct WrapConfig {
// This value is --wrap-max-lines + 1, and unlimited is 0, see
// adapt_wrap_max_lines_argument()
pub max_lines: usize,
+ pub inline_hint_syntect_style: SyntectStyle,
}
/// Wrap the given `line` if it is longer than `line_width`. Wrap to at most
@@ -344,10 +345,23 @@ pub fn wrap_plusminus_block<'c: 'a, 'a>(
.unwrap_or_else(|| panic!("bad syntax alignment {}", errhint)),
must_wrap,
line_width,
- &SyntectStyle::default(),
- &config.inline_hint_color,
+ &config.null_syntect_style,
+ &Some(config.wrap_config.inline_hint_syntect_style),
);
+ // TODO: Why is the background color set to white when
+ // ansi_term_style.background is None?
+ let inline_hint_style = if config
+ .inline_hint_style
+ .ansi_term_style
+ .background
+ .is_some()
+ {
+ Some(config.inline_hint_style)
+ } else {
+ None
+ };
+
let (start2, extended_to2) = wrap_if_too_long(
config,
wrapped_diff,
@@ -357,7 +371,7 @@ pub fn wrap_plusminus_block<'c: 'a, 'a>(
must_wrap,
line_width,
fill_style,
- &None,
+ &inline_hint_style,
);
// The underlying text is the same for the style and diff, so
@@ -510,18 +524,31 @@ pub fn wrap_zero_block<'c: 'a, 'a>(
syntax_style_sections.into_iter().flatten(),
line_width,
&SyntectStyle::default(),
- &config.inline_hint_color,
+ &Some(config.wrap_config.inline_hint_syntect_style),
);
+
+ // TODO: Why is the background color set to white when
+ // ansi_term_style.background is None?
+ let inline_hint_style = if config
+ .inline_hint_style
+ .ansi_term_style
+ .background
+ .is_some()
+ {
+ Some(config.inline_hint_style)
+ } else {
+ None
+ };
let diff_style = wrap_line(
config,
diff_style_sections.into_iter().flatten(),
line_width,
- // To actually highlight `config.inline_hint_color` characters:
+ // To actually highlight inline hint characters:
&Style {
is_syntax_highlighted: true,
..config.null_style
},
- &None,
+ &inline_hint_style,
);
states.resize_with(syntax_style.len(), || State::HunkZeroWrapped);