fix: preserve diff backgrounds and align file markers
This commit is contained in:
+73
-77
@@ -3319,9 +3319,6 @@ fn draw_diff_pane(
|
||||
continue;
|
||||
};
|
||||
let segment = segments.and_then(|segments| segments[usize::from(!before)]);
|
||||
if segments.is_some() && segment.is_none() {
|
||||
continue;
|
||||
}
|
||||
let left = segment.map_or(left, |segment| segment.start);
|
||||
let text_width = segment.map_or(width, |segment| segment.end - segment.start);
|
||||
let paint_width = segment.map_or(width, |segment| {
|
||||
@@ -3339,6 +3336,12 @@ fn draw_diff_pane(
|
||||
} else {
|
||||
Color::Reset
|
||||
};
|
||||
frame
|
||||
.buffer_mut()
|
||||
.set_style(row_area, Style::default().bg(background));
|
||||
if segments.is_some() && segment.is_none() {
|
||||
continue;
|
||||
}
|
||||
frame.render_widget(
|
||||
Paragraph::new(visible_text(source_text, left, text_width.min(width), true))
|
||||
.style(Style::default().fg(Color::Reset).bg(background)),
|
||||
@@ -4635,27 +4638,25 @@ fn draw_file_list(
|
||||
let old_path = changed
|
||||
.and_then(|file| file.old_path.as_deref())
|
||||
.or(entry.old_path);
|
||||
let prefix = format!(
|
||||
"{} {:indent$}",
|
||||
if selected { ">" } else { " " },
|
||||
"",
|
||||
indent = if picker.view == FileView::Tree {
|
||||
entry.depth * 2
|
||||
} else {
|
||||
0
|
||||
},
|
||||
);
|
||||
let mut spans = Vec::with_capacity(if status.is_some() { 7 } else { 3 });
|
||||
spans.push(Span::raw(prefix));
|
||||
if changed.is_some() {
|
||||
let reviewed = entry.catalog_index.is_some_and(|index| {
|
||||
let mut spans = Vec::with_capacity(8);
|
||||
let reviewed = changed.is_some()
|
||||
&& entry.catalog_index.is_some_and(|index| {
|
||||
changed_files.is_some_and(|(_, reviewed)| reviewed.contains(&index))
|
||||
});
|
||||
spans.push(Span::raw(if selected { ">" } else { " " }));
|
||||
if changed_files.is_some() {
|
||||
spans.push(Span::styled(
|
||||
if reviewed { "✓ " } else { " " },
|
||||
if reviewed { "✓" } else { " " },
|
||||
Style::default().fg(Color::Green),
|
||||
));
|
||||
} else {
|
||||
spans.push(Span::raw(" "));
|
||||
}
|
||||
spans.push(Span::raw(if picker.view == FileView::Tree {
|
||||
" ".repeat(entry.depth * 2)
|
||||
} else {
|
||||
String::new()
|
||||
}));
|
||||
if let Some(status) = status {
|
||||
let color = match status {
|
||||
FileStatus::Added => Color::Green,
|
||||
@@ -6825,6 +6826,44 @@ mod tests {
|
||||
assert_eq!(diff.focus, Focus::Before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_row_tint_covers_blank_lines_and_wrapped_gutters() {
|
||||
for wrapped in [false, true] {
|
||||
let mut diff = diff_comparison(vec![syntax_diff_file(
|
||||
"changed.txt",
|
||||
"old old old old old old old old old old old old old old old old old old old old\n",
|
||||
"new\n",
|
||||
)]);
|
||||
diff.files_visible = false;
|
||||
diff.word_wrap = wrapped;
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(60, 20)).unwrap();
|
||||
let mut panels = WheelPanels {
|
||||
diff_colors: DiffColors::new(Some(LIGHT_DIFF_THEME)),
|
||||
..WheelPanels::default()
|
||||
};
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
for side in 0..2 {
|
||||
let area = diff_inner(panels.diff.as_ref().unwrap().regions[side + 1].0);
|
||||
let buffer = terminal.backend().buffer();
|
||||
let empty = (area.y..area.bottom())
|
||||
.find(|&y| buffer[(area.x, y)].symbol() == "2")
|
||||
.unwrap();
|
||||
for y in area.y..=empty {
|
||||
for x in area.x..area.x + 3 {
|
||||
assert_eq!(
|
||||
buffer[(x, y)].bg,
|
||||
panels.diff_colors.row[side],
|
||||
"{wrapped} {side} {x} {y}"
|
||||
);
|
||||
}
|
||||
}
|
||||
for x in area.x..area.right() {
|
||||
assert_eq!(buffer[(x, empty)].bg, panels.diff_colors.row[side]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_added_rows_hatch_missing_before_but_tint_real_empty_after_lines() {
|
||||
let mut diff = diff_comparison(vec![ChangedFile {
|
||||
@@ -7152,14 +7191,26 @@ mod tests {
|
||||
.unwrap_or_else(|| panic!("missing {expected}"));
|
||||
assert_eq!(buffer[(x, y)].fg, color);
|
||||
assert_eq!(
|
||||
buffer[(x - 2, y)].symbol(),
|
||||
buffer[(2, y)].symbol(),
|
||||
if catalog_index == index { "✓" } else { " " }
|
||||
);
|
||||
assert_eq!(buffer[(x - 1, y)].symbol(), " ");
|
||||
let depth = picker
|
||||
.entries()
|
||||
.find(|entry| entry.catalog_index == Some(catalog_index))
|
||||
.unwrap()
|
||||
.depth;
|
||||
assert_eq!(
|
||||
x,
|
||||
3 + if view == FileView::Tree {
|
||||
depth as u16 * 2
|
||||
} else {
|
||||
0
|
||||
}
|
||||
);
|
||||
if catalog_index == index {
|
||||
assert_eq!(buffer[(x - 2, y)].fg, Color::Green);
|
||||
assert_eq!(buffer[(2, y)].fg, Color::Green);
|
||||
assert_eq!(
|
||||
buffer[(x - 2, y)].bg,
|
||||
buffer[(2, y)].bg,
|
||||
if focused {
|
||||
Color::Blue
|
||||
} else {
|
||||
@@ -7206,7 +7257,6 @@ mod tests {
|
||||
})
|
||||
.unwrap();
|
||||
let text = screen_text(&terminal);
|
||||
assert!(text.contains("✓ M "));
|
||||
assert_eq!(text.matches('✓').count(), 1);
|
||||
assert!(!text.contains("R r.txt"));
|
||||
assert_eq!(
|
||||
@@ -7234,60 +7284,6 @@ mod tests {
|
||||
assert!(!screen_text(&terminal).contains('✓'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reviewed_file_prefix_tracks_state_and_clips_in_narrow_panes() {
|
||||
let mut file = deletion_file();
|
||||
file.path = "界.txt".into();
|
||||
file.status = FileStatus::Modified;
|
||||
let files = [file];
|
||||
let mut picker = FilePicker::from_paths(PathBuf::new(), [(0, files[0].path.clone())]);
|
||||
picker.set_view(FileView::List);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(12, 3)).unwrap();
|
||||
let mut reviewed = BTreeSet::new();
|
||||
for marked in [true, false, true] {
|
||||
if marked {
|
||||
reviewed.insert(0);
|
||||
} else {
|
||||
reviewed.remove(&0);
|
||||
}
|
||||
for width in 1..=8 {
|
||||
terminal
|
||||
.draw(|frame| {
|
||||
frame.render_widget(
|
||||
Paragraph::new("XXXXXXXXXXXX\nXXXXXXXXXXXX\nXXXXXXXXXXXX"),
|
||||
frame.area(),
|
||||
);
|
||||
draw_file_list(
|
||||
frame,
|
||||
&picker,
|
||||
Rect::new(0, 0, width, 3),
|
||||
"",
|
||||
&mut WheelPanels::default(),
|
||||
Some((&files, &reviewed)),
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
let prefix = if marked { "> ✓ M " } else { "> M " };
|
||||
for (x, symbol) in prefix.chars().take(usize::from(width)).enumerate() {
|
||||
assert_eq!(buffer[(x as u16, 1)].symbol(), symbol.to_string());
|
||||
}
|
||||
for x in width..12 {
|
||||
assert_eq!(buffer[(x, 1)].symbol(), "X");
|
||||
}
|
||||
if width >= 3 && marked {
|
||||
assert_eq!(buffer[(2, 1)].fg, Color::Green);
|
||||
}
|
||||
if width >= 5 {
|
||||
assert_eq!(buffer[(4, 1)].fg, Color::Yellow);
|
||||
}
|
||||
if width >= 8 {
|
||||
assert_eq!(buffer[(6, 1)].symbol(), "界");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normal_file_markers_keep_clean_rows_and_match_diff_colors_in_every_view() {
|
||||
use crate::repository::WorkingFileChange;
|
||||
|
||||
Reference in New Issue
Block a user