Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,16 @@ pub struct Opt {
/// Display diffs in side-by-side layout.
pub side_by_side: bool,

#[arg(long = "side-by-side-min-width", default_value = "0", value_name = "N")]
/// Minimum terminal width required to enable side-by-side mode. Defaults to 0.
///
/// If the terminal width is less than this value, side-by-side mode will be disabled
/// regardless of the --side-by-side option. This allows automatic fallback to unified
/// diff when the terminal is too narrow to display side-by-side diffs comfortably.
/// Set to 0 to always use side-by-side when enabled. If not specified, side-by-side
/// will be used when enabled regardless of terminal width.
pub side_by_side_min_width: usize,

#[arg(long = "syntax-theme", value_name = "SYNTAX_THEME")]
/// The syntax-highlighting theme to use.
///
Expand Down
73 changes: 71 additions & 2 deletions src/options/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ pub fn set_options(
show_colors,
show_themes,
side_by_side,
side_by_side_min_width,
wrap_max_lines,
wrap_right_prefix_symbol,
wrap_right_percent,
Expand Down Expand Up @@ -242,6 +243,13 @@ pub fn set_options(
cli::InspectRawLines::from_str(&opt.inspect_raw_lines).unwrap();
opt.computed.paging_mode = parse_paging_mode(&opt.paging_mode);

// Apply side-by-side-min-width: disable side-by-side if terminal is too narrow.
if opt.side_by_side_min_width > 0
&& opt.computed.available_terminal_width < opt.side_by_side_min_width
{
opt.side_by_side = false;
}

// --color-only is used for interactive.diffFilter (git add -p). side-by-side, and
// **-decoration-style cannot be used there (does not emit lines in 1-1 correspondence with raw git output).
// See #274.
Expand Down Expand Up @@ -608,8 +616,15 @@ fn set_widths_and_isatty(opt: &mut cli::Opt) {

// If one extra character for e.g. `less --status-column` is required use "-1"
// as an argument, also see #41, #10, #115 and #727.
opt.computed.available_terminal_width =
crate::utils::workarounds::windows_msys2_width_fix(term_stdout.size(), &term_stdout);
#[cfg(test)]
{
opt.computed.available_terminal_width = tests::TERMINAL_WIDTH_IN_TESTS;
}
#[cfg(not(test))]
{
opt.computed.available_terminal_width =
crate::utils::workarounds::windows_msys2_width_fix(term_stdout.size(), &term_stdout);
}

let (decorations_width, background_color_extends_to_terminal_width) = match opt.width.as_deref()
{
Expand Down Expand Up @@ -863,4 +878,58 @@ pub mod tests {
assert_eq!(parse_width_specifier(" - 12 ", term_width).unwrap(), 0);
assert_eq!(parse_width_specifier(" 2 - 2 ", term_width).unwrap(), 0);
}

#[test]
fn test_side_by_side_min_width_disables_sbs_when_terminal_narrow() {
// Tests use TERMINAL_WIDTH_IN_TESTS = 43
// When min-width is greater than terminal width, side-by-side should be disabled
let opt = integration_test_utils::make_options_from_args(&[
"--side-by-side",
"--side-by-side-min-width",
"100",
]);
assert!(!opt.side_by_side);
}

#[test]
fn test_side_by_side_min_width_allows_sbs_when_terminal_wide_enough() {
// Tests use TERMINAL_WIDTH_IN_TESTS = 43
// When min-width is less than or equal to terminal width, side-by-side should remain enabled
let opt = integration_test_utils::make_options_from_args(&[
"--side-by-side",
"--side-by-side-min-width",
"40",
]);
assert!(opt.side_by_side);
}

#[test]
fn test_side_by_side_min_width_zero_always_allows_sbs() {
// When min-width is 0, side-by-side should always be allowed
let opt = integration_test_utils::make_options_from_args(&[
"--side-by-side",
"--side-by-side-min-width",
"0",
]);
assert!(opt.side_by_side);
}

#[test]
fn test_side_by_side_min_width_from_git_config() {
use std::fs::remove_file;
let git_config_contents = b"
[delta]
side-by-side = true
side-by-side-min-width = 100
";
let git_config_path = "delta__test_side_by_side_min_width_from_git_config.gitconfig";
let opt = integration_test_utils::make_options_from_args_and_git_config(
&[],
Some(git_config_contents),
Some(git_config_path),
);
// Terminal width in tests is 43, min-width is 100, so side-by-side should be disabled
assert!(!opt.side_by_side);
remove_file(git_config_path).unwrap();
}
}