summaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs96
1 files changed, 93 insertions, 3 deletions
diff --git a/src/config.rs b/src/config.rs
index 5a013a1b..4a93cfe2 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -7,7 +7,9 @@ use structopt::clap;
use syntect::highlighting::Style as SyntectStyle;
use syntect::highlighting::Theme as SyntaxTheme;
use syntect::parsing::SyntaxSet;
+use unicode_segmentation::UnicodeSegmentation;
+use crate::ansi;
use crate::bat_utils::output::PagingMode;
use crate::cli;
use crate::color;
@@ -19,6 +21,37 @@ use crate::features::side_by_side;
use crate::git_config::{GitConfig, GitConfigEntry};
use crate::paint::BgFillMethod;
use crate::style::{self, Style};
+use crate::syntect_color;
+use crate::wrapping::WrapConfig;
+
+pub const INLINE_SYMBOL_WIDTH_1: usize = 1;
+
+fn remove_percent_suffix(arg: &str) -> &str {
+ match &arg.strip_suffix('%') {
+ Some(s) => s,
+ None => arg,
+ }
+}
+
+fn ensure_display_width_1(what: &str, arg: String) -> String {
+ match arg.grapheme_indices(true).count() {
+ INLINE_SYMBOL_WIDTH_1 => arg,
+ width => fatal(format!(
+ "Invalid value for {}, display width of \"{}\" must be {} but is {}",
+ what, arg, INLINE_SYMBOL_WIDTH_1, width
+ )),
+ }
+}
+
+fn adapt_wrap_max_lines_argument(arg: String) -> usize {
+ if arg == "∞" || arg == "unlimited" || arg.starts_with("inf") {
+ 0
+ } else {
+ arg.parse::<usize>()
+ .unwrap_or_else(|err| fatal(format!("Invalid wrap-max-lines argument: {}", err)))
+ + 1
+ }
+}
pub struct Config {
pub available_terminal_width: usize,
@@ -51,6 +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 inspect_raw_lines: cli::InspectRawLines,
pub keep_plus_minus_markers: bool,
pub line_fill_method: BgFillMethod,
@@ -96,6 +130,7 @@ pub struct Config {
pub true_color: bool,
pub truncation_symbol: String,
pub whitespace_error_style: Style,
+ pub wrap_config: WrapConfig,
pub zero_style: Style,
}
@@ -210,6 +245,8 @@ impl From<cli::Opt> for Config {
None
};
+ let wrap_max_lines_plus1 = adapt_wrap_max_lines_argument(opt.wrap_max_lines);
+
Self {
available_terminal_width: opt.computed.available_terminal_width,
background_color_extends_to_terminal_width: opt
@@ -254,8 +291,20 @@ 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_color::syntect_color_from_ansi_name("blue").unwrap(),
+ ..SyntectStyle::default()
+ }),
keep_plus_minus_markers: opt.keep_plus_minus_markers,
- line_fill_method,
+ line_fill_method: if opt.side_by_side {
+ // Panels in side-by-side always sum up to an even number, if the terminal has
+ // an odd width then extending the background color with an ANSI sequence
+ // would indicate the wrong width and extend beyond truncated or wrapped content,
+ // thus spaces are used here by default.
+ BgFillMethod::Spaces
+ } else {
+ line_fill_method
+ },
line_numbers: opt.line_numbers,
line_numbers_left_format: opt.line_numbers_left_format,
line_numbers_left_style,
@@ -267,7 +316,23 @@ impl From<cli::Opt> for Config {
line_buffer_size: opt.line_buffer_size,
max_line_distance: opt.max_line_distance,
max_line_distance_for_naively_paired_lines,
- max_line_length: opt.max_line_length,
+ max_line_length: match (opt.side_by_side, wrap_max_lines_plus1) {
+ (false, _) | (true, 1) => opt.max_line_length,
+ // Ensure there is enough text to wrap, either don't truncate the input at all (0)
+ // or ensure there is enough for the requested number of lines.
+ // The input can contain ANSI sequences, so round up a bit. This is enough for
+ // normal `git diff`, but might not be with ANSI heavy input.
+ (true, 0) => 0,
+ (true, wrap_max_lines) => {
+ let single_pane_width = opt.computed.available_terminal_width / 2;
+ let add_25_percent_or_term_width =
+ |x| x + std::cmp::max((x * 250) / 1000, single_pane_width) as usize;
+ std::cmp::max(
+ opt.max_line_length,
+ add_25_percent_or_term_width(single_pane_width * wrap_max_lines),
+ )
+ }
+ },
minus_emph_style,
minus_empty_line_marker_style,
minus_file: opt.minus_file,
@@ -296,7 +361,32 @@ impl From<cli::Opt> for Config {
tab_width: opt.tab_width,
tokenization_regex,
true_color: opt.computed.true_color,
- truncation_symbol: "→".to_string(),
+ truncation_symbol: format!("{}→{}", ansi::ANSI_SGR_REVERSE, ansi::ANSI_SGR_RESET),
+ wrap_config: WrapConfig {
+ left_symbol: ensure_display_width_1("wrap-left-symbol", opt.wrap_left_symbol),
+ right_symbol: ensure_display_width_1("wrap-right-symbol", opt.wrap_right_symbol),
+ right_prefix_symbol: ensure_display_width_1(
+ "wrap-right-prefix-symbol",
+ opt.wrap_right_prefix_symbol,
+ ),
+ use_wrap_right_permille: {
+ let arg = &opt.wrap_right_percent;
+ let percent = remove_percent_suffix(arg)
+ .parse::<f64>()
+ .unwrap_or_else(|err| {
+ fatal(format!(
+ "Could not parse wrap-right-percent argument {}: {}.",
+ &arg, err
+ ))
+ });
+ if percent.is_finite() && percent > 0.0 && percent < 100.0 {
+ (percent * 10.0).round() as usize
+ } else {
+ fatal("Invalid value for wrap-right-percent, not between 0 and 100.")
+ }
+ },
+ max_lines: wrap_max_lines_plus1,
+ },
whitespace_error_style,
zero_style,
}