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
22 changes: 22 additions & 0 deletions src/side_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ fn push_output<T: Write>(
// the diff always want to put all tabs possible in the usable are,
// even in the middle space between the gutters if possible.

// Pad to the middle of the gutter so the marker doesn't drift on wider gutters (#269).
format_tabs_and_spaces(half_width + 1, separator_pos, config, output)?;
output.write_all(&[symbol])?;
if !right_ln.is_empty() {
format_tabs_and_spaces(separator_pos + 1, column_two_offset, config, output)?;
Expand Down Expand Up @@ -1003,6 +1005,26 @@ mod tests {
assert_eq!(contains_string(&output, "equal"), 2)
}

// Regression for #269: the `-y` marker must sit at the gutter middle at any width.
#[test]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also add a test in tests/integration.rs with -y --width=40

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Shortened both comments and added an integration test covering -y --width=40 in both --expand-tabs and the default (tab-path) modes, asserting the marker sits at the gutter middle.

fn test_gutter_marker_column_wide_gutter() {
let params = Params {
tabsize: 8,
expand_tabs: true,
width: 40,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please also test with expand_tabs: false?
that is the default, and the padding goes through the tab path

..Default::default()
};
let mut output = vec![];
diff(b"aa\n", b"", &mut output, &params);
let text = String::from_utf8(output).unwrap();
let line = text.lines().next().unwrap();
assert_eq!(
line.find('<'),
Some(19),
"gutter marker '<' should be at column 19 for --width=40, got: {line:?}"
);
}

#[test]
fn test_different_lines() {
let params = generate_params();
Expand Down
48 changes: 48 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,54 @@ mod diff {

Ok(())
}

// Visual (tab-aware) column of the `-y` gutter marker on the first output line.
fn side_marker_visual_column(output: &[u8], tabsize: usize) -> Option<usize> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we just compare the whole stdout instead of this helper?
simpler, and it would also check the exact tabs/spaces emitted

let text = String::from_utf8_lossy(output);
let line = text.lines().next()?;
let mut col = 0;
for c in line.chars() {
match c {
'<' | '|' | '>' => return Some(col),
'\t' => col += tabsize - (col % tabsize),
_ => col += 1,
}
}
None
}

// Regression for #269: the `-y` gutter marker must sit at the middle of the gutter.
#[test]
fn sdiff_gutter_marker_column() -> Result<(), Box<dyn std::error::Error>> {
let mut file1 = NamedTempFile::new()?;
file1.write_all("aa\n".as_bytes())?;
let mut file2 = NamedTempFile::new()?;
file2.write_all("bb\n".as_bytes())?;

// --expand-tabs: padding is spaces, marker lands at visual column 19.
let mut cmd = cargo_bin_cmd!("diffutils");
cmd.arg("diff")
.arg("-y")
.arg("--width=40")
.arg("--expand-tabs")
.arg(file1.path())
.arg(file2.path());
let output = cmd.output().unwrap().stdout;
assert_eq!(side_marker_visual_column(&output, 8), Some(19));

// Default (expand_tabs: false): padding goes through the tab path, but the
// marker must still land at the same visual column.
let mut cmd = cargo_bin_cmd!("diffutils");
cmd.arg("diff")
.arg("-y")
.arg("--width=40")
.arg(file1.path())
.arg(file2.path());
let output = cmd.output().unwrap().stdout;
assert_eq!(side_marker_visual_column(&output, 8), Some(19));

Ok(())
}
}

mod cmp {
Expand Down
Loading