fix: retain numbered declarations in reserved sticky rows
This commit is contained in:
+99
-7
@@ -3774,6 +3774,7 @@ fn draw_diff(
|
||||
let viewport = panels
|
||||
.diff_wrap
|
||||
.get_or_insert_with(DiffWrapViewport::default);
|
||||
viewport.lefts = [before_left, after_left];
|
||||
viewport.update(
|
||||
diff,
|
||||
file,
|
||||
@@ -4561,6 +4562,7 @@ struct DiffWrapViewport {
|
||||
before: crate::wrap::WrapCache,
|
||||
after: crate::wrap::WrapCache,
|
||||
widths: [usize; 2],
|
||||
lefts: [usize; 2],
|
||||
heights: [usize; 2],
|
||||
visible_names: [Vec<Point>; 2],
|
||||
top: DiffWrapPosition,
|
||||
@@ -4763,6 +4765,55 @@ impl DiffWrapViewport {
|
||||
});
|
||||
}
|
||||
if scope.iter().any(|side| *side) && self.rows.len() + 1 < height {
|
||||
if self.rows.is_empty() {
|
||||
// The sticky slot can still show the adjacent declaration as source.
|
||||
let previous = self.step(diff, file, position, false);
|
||||
let declaration = self.row(diff, file, previous);
|
||||
let visible = |side: usize| {
|
||||
let focus = if side == 0 {
|
||||
Focus::Before
|
||||
} else {
|
||||
Focus::After
|
||||
};
|
||||
let Some(context) = contexts[side] else {
|
||||
return false;
|
||||
};
|
||||
if diff.display_source_row(focus, previous.display)
|
||||
!= Some(context.name.row)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let source = if side == 0 { &file.before } else { &file.after };
|
||||
let prefix = &source[context.name.row][..context.name.column];
|
||||
let column = display_column(prefix, usize::MAX);
|
||||
if declaration.unwrapped {
|
||||
let pane = if diff.view_mode == ViewMode::Unified {
|
||||
usize::from(diff.focus != Focus::Before)
|
||||
} else {
|
||||
side
|
||||
};
|
||||
self.lefts[pane] <= column
|
||||
&& column
|
||||
< self.lefts[pane].saturating_add(self.widths[pane])
|
||||
} else {
|
||||
declaration.segments[side].is_some_and(|segment| {
|
||||
segment.start <= column && column < segment.end
|
||||
})
|
||||
}
|
||||
};
|
||||
let restore = if diff.view_mode == ViewMode::Unified {
|
||||
let side = usize::from(
|
||||
diff.display_focus(previous.display) != Some(Focus::Before),
|
||||
);
|
||||
scope[side] && visible(side)
|
||||
} else {
|
||||
(0..2).all(|side| !scope[side] || visible(side))
|
||||
};
|
||||
if previous != position && restore {
|
||||
self.rows.push(declaration);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
self.rows.push(WrappedDiffRow {
|
||||
position,
|
||||
segments: [None; 2],
|
||||
@@ -8237,7 +8288,6 @@ mod tests {
|
||||
Some(2),
|
||||
"Keep the nearest enclosing function's sticky context, not earlier declarations"
|
||||
);
|
||||
assert_eq!(viewport.rows[0].scope, [true; 2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -8402,6 +8452,48 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_scope_sticky_row_keeps_adjacent_declaration_numbered() {
|
||||
let after = "\n#[allow(clippy::too_many_arguments)]\nfn draw_diff_scope_labels(\n frame: &mut Frame,\n diff: &DiffState,\n) {\n work();\n}\n";
|
||||
for (mode, axis, wrap) in [
|
||||
(ViewMode::Split, SplitAxis::Vertical, false),
|
||||
(ViewMode::Split, SplitAxis::Horizontal, false),
|
||||
(ViewMode::Split, SplitAxis::Vertical, true),
|
||||
(ViewMode::Unified, SplitAxis::Vertical, false),
|
||||
(ViewMode::Unified, SplitAxis::Vertical, true),
|
||||
] {
|
||||
let mut file = syntax_diff_file("tui.rs", "", after);
|
||||
file.hunks = crate::diff::line_hunks(&file.before, false, &file.after, false);
|
||||
let mut diff = diff_comparison(vec![file]);
|
||||
diff.files_visible = false;
|
||||
diff.focus = Focus::After;
|
||||
diff.split_axis = axis;
|
||||
diff.word_wrap = wrap;
|
||||
diff.set_view_mode(mode);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(160, 24)).unwrap();
|
||||
let mut panels = WheelPanels::default();
|
||||
for source in [0, 1, 2, 3, 4, 3, 2] {
|
||||
diff.top = diff.source_display_row(Focus::After, source).unwrap();
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
let area = diff_inner(panels.diff.as_ref().unwrap().regions[2].0);
|
||||
let text = pane_screen(&terminal, area);
|
||||
if source <= 3 {
|
||||
let declaration = text
|
||||
.lines()
|
||||
.find(|line| line.contains("fn draw_diff_scope_labels("));
|
||||
assert!(
|
||||
declaration.is_some_and(|line| line.contains("3+")),
|
||||
"The declaration must keep its source number, not become an unnumbered sticky label at top source {source}:\n{text}"
|
||||
);
|
||||
} else {
|
||||
assert!(text.lines().any(|line| {
|
||||
line.contains("draw_diff_scope_labels") && !line.contains("fn ")
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_scope_labels_follow_declaration_visibility() {
|
||||
let before = "@decorate()\nclass PolicyActiveStatusEnum(BaseEnum):\n ACTIVE = 1\n EXPIRED = 2\n FUTURE = 3\n UNKNOWN = 4\n";
|
||||
@@ -8420,7 +8512,7 @@ mod tests {
|
||||
diff.set_view_mode(mode);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(160, 32)).unwrap();
|
||||
let mut panels = WheelPanels::default();
|
||||
for (source, visible) in [(0, false), (2, true), (1, false), (2, true)] {
|
||||
for (source, visible) in [(0, false), (2, false), (3, true), (1, false), (2, false)] {
|
||||
diff.top = diff.source_display_row(Focus::After, source).unwrap();
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
let text = screen_text(&terminal);
|
||||
@@ -8436,7 +8528,7 @@ mod tests {
|
||||
0
|
||||
}
|
||||
);
|
||||
assert!(text.contains("ACTIVE = 1"));
|
||||
assert!(text.contains("EXPIRED = 2"));
|
||||
}
|
||||
}
|
||||
let before = "def old_name():\n shared()\n tail()\n";
|
||||
@@ -8466,7 +8558,7 @@ mod tests {
|
||||
let mut diff = diff_comparison(vec![file]);
|
||||
diff.files_visible = false;
|
||||
diff.set_view_mode(mode);
|
||||
diff.top = diff.source_display_row(Focus::After, 1).unwrap();
|
||||
diff.top = diff.source_display_row(Focus::After, 4).unwrap();
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(160, 40)).unwrap();
|
||||
let mut panels = WheelPanels::default();
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
@@ -8520,7 +8612,7 @@ mod tests {
|
||||
diff.files_visible = false;
|
||||
diff.split_axis = axis;
|
||||
diff.word_wrap = wrapping;
|
||||
diff.top = diff.source_display_row(Focus::Before, 2).unwrap();
|
||||
diff.top = diff.source_display_row(Focus::Before, 3).unwrap();
|
||||
let mut terminal =
|
||||
Terminal::new(ratatui::backend::TestBackend::new(160, 48)).unwrap();
|
||||
let mut panels = WheelPanels::default();
|
||||
@@ -8550,7 +8642,7 @@ mod tests {
|
||||
}
|
||||
let syntax = panels.diff_syntax.as_ref().unwrap();
|
||||
let parses = (syntax.before.parse_counts(), syntax.after.parse_counts());
|
||||
diff.top = diff.source_display_row(Focus::Before, 2).unwrap();
|
||||
diff.top = diff.source_display_row(Focus::Before, 3).unwrap();
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
let rows = &panels.diff_wrap.as_ref().unwrap().rows;
|
||||
assert_eq!(rows[0].scope, [true; 2]);
|
||||
@@ -8569,7 +8661,7 @@ mod tests {
|
||||
}
|
||||
let mut narrow = diff_comparison(vec![syntax_diff_file("scope.rs", before, &after)]);
|
||||
narrow.files_visible = false;
|
||||
narrow.top = narrow.source_display_row(Focus::Before, 2).unwrap();
|
||||
narrow.top = narrow.source_display_row(Focus::Before, 3).unwrap();
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(40, 30)).unwrap();
|
||||
let mut panels = WheelPanels::default();
|
||||
render_diff(&mut terminal, &narrow, &mut panels);
|
||||
|
||||
Reference in New Issue
Block a user