improve: show whole-diff totals alongside file stats
This commit is contained in:
@@ -77,6 +77,9 @@ fn omitted_options_inherit_and_explicit_groups_replace_defaults() {
|
||||
|
||||
#[test]
|
||||
fn both_positions_accept_all_builtins_and_custom_styles() {
|
||||
let defaults = ChromeLine::top();
|
||||
assert_eq!(defaults.right, ["diff", "shell", "battery"]);
|
||||
assert_eq!(defaults.segment("diff"), defaults.segment("shell"));
|
||||
let names = [
|
||||
"tabs",
|
||||
"mode",
|
||||
@@ -90,6 +93,7 @@ fn both_positions_accept_all_builtins_and_custom_styles() {
|
||||
"lsp",
|
||||
"position",
|
||||
"battery",
|
||||
"diff",
|
||||
"workspace",
|
||||
];
|
||||
let options = serde_json::json!({
|
||||
@@ -119,7 +123,7 @@ fn both_positions_accept_all_builtins_and_custom_styles() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_placeholder_is_valid_in_every_segment_and_bar() {
|
||||
fn comparison_placeholders_are_valid_in_every_segment_and_bar() {
|
||||
for name in [
|
||||
"tabs",
|
||||
"mode",
|
||||
@@ -133,11 +137,12 @@ fn view_placeholder_is_valid_in_every_segment_and_bar() {
|
||||
"lsp",
|
||||
"position",
|
||||
"battery",
|
||||
"diff",
|
||||
"workspace",
|
||||
] {
|
||||
let options = serde_json::json!({
|
||||
"left": [name],
|
||||
(name): {"title": "{index}:{view}{name}:{path}{modified}"}
|
||||
(name): {"title": "{index}:{view}{name}{changes}:{path}{modified}"}
|
||||
});
|
||||
let lines: Lines = serde_json::from_value(serde_json::json!({
|
||||
"top": options,
|
||||
@@ -147,7 +152,7 @@ fn view_placeholder_is_valid_in_every_segment_and_bar() {
|
||||
for line in [&lines.top, &lines.bottom] {
|
||||
assert_eq!(
|
||||
line.segment(name).title,
|
||||
"{index}:{view}{name}:{path}{modified}"
|
||||
"{index}:{view}{name}{changes}:{path}{modified}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,6 +789,7 @@ fn comparison() -> Comparison {
|
||||
files: vec![
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "renamed.txt".into(),
|
||||
old_path: Some("old.txt".into()),
|
||||
status: FileStatus::Renamed,
|
||||
@@ -827,6 +828,7 @@ fn comparison() -> Comparison {
|
||||
},
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "added.txt".into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Added,
|
||||
@@ -845,6 +847,7 @@ fn comparison() -> Comparison {
|
||||
},
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "removed.bin".into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Removed,
|
||||
@@ -860,6 +863,19 @@ fn comparison() -> Comparison {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_counts_use_frozen_metadata_only_until_hunks_are_loaded() {
|
||||
let mut file = comparison().files.remove(0);
|
||||
file.loaded = false;
|
||||
assert_eq!(file.line_counts(), None);
|
||||
file.stats = Some((99, 98));
|
||||
assert_eq!(file.line_counts(), Some((99, 98)));
|
||||
file.loaded = true;
|
||||
assert_eq!(file.line_counts(), Some((2, 2)));
|
||||
file.hunks.clear();
|
||||
assert_eq!(file.line_counts(), Some((0, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_layout_cycles_only_present_panes_and_normalizes_selection() {
|
||||
let mut state = live_state(vec!["old".into()], vec!["new".into()], true);
|
||||
@@ -1566,6 +1582,7 @@ fn closing_diff_rejects_pending_file_details_even_after_reopening() {
|
||||
catalog.files.clear();
|
||||
catalog.files.push(ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: detail.path.clone(),
|
||||
old_path: detail.old_path.clone(),
|
||||
status: detail.status,
|
||||
@@ -1816,6 +1833,7 @@ fn live_state(before: Vec<String>, after: Vec<String>, eof: bool) -> DiffState {
|
||||
editable_paths: BTreeSet::from([PathBuf::from("file")]),
|
||||
files: vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "file".into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Modified,
|
||||
@@ -2503,6 +2521,7 @@ fn reverting_loaded_file_keeps_unloaded_changes_selectable() {
|
||||
state.pending = None;
|
||||
state.comparison.as_mut().unwrap().files.push(ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "unloaded.txt".into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Modified,
|
||||
@@ -2731,6 +2750,7 @@ fn lazy_selection_waits_for_details_rejects_stale_files_and_reuses_loaded_cache(
|
||||
for detail in &details {
|
||||
catalog.files.push(ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: detail.path.clone(),
|
||||
old_path: detail.old_path.clone(),
|
||||
status: detail.status,
|
||||
|
||||
@@ -1887,6 +1887,7 @@ fn hidden_tab_diff_results_restore_visible_insert_interaction_and_route_request_
|
||||
editable_paths: Default::default(),
|
||||
files: vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
path: "file.txt".into(),
|
||||
old_path: None,
|
||||
@@ -3053,6 +3054,7 @@ fn working_diff(editor: &mut Editor, root: &Path, paths: &[&str]) -> Box<[(PathB
|
||||
let lines: Vec<String> = text.lines().map(str::to_owned).collect();
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
path: PathBuf::from(*path),
|
||||
old_path: None,
|
||||
@@ -3115,6 +3117,7 @@ fn historical_diff(editor: &mut Editor, root: &Path, before: Vec<String>, after:
|
||||
editable_paths: Default::default(),
|
||||
files: vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
path: "file.txt".into(),
|
||||
old_path: None,
|
||||
@@ -4078,6 +4081,7 @@ fn bookmark_refresh_reloads_paths_and_preserves_view_until_lazy_content_arrives(
|
||||
let cursor = editor.cursor();
|
||||
let file = |path: &str, loaded| ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: path.into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Modified,
|
||||
@@ -4288,6 +4292,7 @@ fn completed_working_refresh_serializes_lazy_selection_and_invalidates_pending_n
|
||||
if changed {
|
||||
let file = crate::diff::ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "nested/new.txt".into(),
|
||||
old_path: Some("nested/old.txt".into()),
|
||||
status: crate::diff::FileStatus::Renamed,
|
||||
@@ -4329,6 +4334,7 @@ fn lazy_lsp_target(editor: &mut Editor) -> crate::diff::ChangedFile {
|
||||
let comparison = diff.comparison.as_mut().unwrap();
|
||||
comparison.files.push(ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "nested/new.txt".into(),
|
||||
old_path: Some("nested/old.txt".into()),
|
||||
status: FileStatus::Renamed,
|
||||
@@ -4350,6 +4356,7 @@ fn lazy_lsp_target(editor: &mut Editor) -> crate::diff::ChangedFile {
|
||||
));
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "nested/new.txt".into(),
|
||||
old_path: Some("nested/old.txt".into()),
|
||||
status: FileStatus::Renamed,
|
||||
|
||||
@@ -3730,6 +3730,7 @@ fn async_responses_edit_only_current_bound_working_after_and_refresh_projection(
|
||||
editable_paths: [PathBuf::from("buffer.txt")].into_iter().collect(),
|
||||
files: vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: PathBuf::from("buffer.txt"),
|
||||
old_path: None,
|
||||
status: FileStatus::Modified,
|
||||
|
||||
+65
-17
@@ -1985,6 +1985,7 @@ fn syntax_diff_file(path: &str, before: &str, after: &str) -> ChangedFile {
|
||||
let after: Vec<String> = after.split('\n').map(str::to_owned).collect();
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -2608,6 +2609,7 @@ fn diff_comparison(files: Vec<ChangedFile>) -> DiffState {
|
||||
fn deletion_file() -> ChangedFile {
|
||||
ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -3559,6 +3561,7 @@ fn diff_excerpts_render_original_lines_and_expand_without_losing_changes() {
|
||||
after[60] = "let second_change = 901;".into();
|
||||
let mut diff = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -3699,6 +3702,7 @@ fn diff_row_tint_covers_blank_lines_and_wrapped_gutters() {
|
||||
fn diff_added_rows_hatch_missing_before_but_tint_real_empty_after_lines() {
|
||||
let mut diff = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -3757,6 +3761,7 @@ fn diff_added_rows_hatch_missing_before_but_tint_real_empty_after_lines() {
|
||||
fn diff_changed_backgrounds_preserve_syntax_and_clipped_source_cells() {
|
||||
let mut diff = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -3887,6 +3892,7 @@ fn diff_changed_backgrounds_preserve_syntax_and_clipped_source_cells() {
|
||||
fn diff_view_changes_files_focus_and_keeps_horizontal_offsets_independent() {
|
||||
let added = ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -4649,6 +4655,7 @@ fn large_generated_additions_render_first_scroll_and_final_rows_without_reparsin
|
||||
let hunks = crate::diff::line_hunks(&[], false, &after, true);
|
||||
let mut diff = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
path: "parser.c".into(),
|
||||
old_path: None,
|
||||
status: FileStatus::Added,
|
||||
@@ -4699,6 +4706,7 @@ fn diff_notices_empty_comparisons_and_tiny_layouts_remain_renderable() {
|
||||
assert!(screen_text(&terminal).contains("Explorer · Tree"));
|
||||
let binary = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -4714,6 +4722,7 @@ fn diff_notices_empty_comparisons_and_tiny_layouts_remain_renderable() {
|
||||
assert!(screen_text(&terminal).contains("Binary file"));
|
||||
let blank = diff_comparison(vec![ChangedFile {
|
||||
review_revisions: None,
|
||||
stats: None,
|
||||
loaded: true,
|
||||
before_eof: false,
|
||||
after_eof: false,
|
||||
@@ -5664,17 +5673,13 @@ fn comparison_titles_follow_loaded_counts_and_each_tabs_context() {
|
||||
})),
|
||||
);
|
||||
}
|
||||
let view = if phase == "view" {
|
||||
"Diff · +3 -2 · "
|
||||
} else {
|
||||
"Diff · "
|
||||
};
|
||||
let changes = if phase == "view" { " +3 -2" } else { "" };
|
||||
let default_tabs = editor.top_bar_config().segment("tabs").clone();
|
||||
for (template, ordinary, prefix, uses_view) in [
|
||||
(None, "1 source.rs", "2 ", true),
|
||||
(Some("{index} {name}{modified}"), "1 source.rs", "2 ", false),
|
||||
(
|
||||
Some("T{index}:{view}{name}{modified}"),
|
||||
Some("T{index}:{view}{name}{changes}{modified}"),
|
||||
"T1:source.rs",
|
||||
"T2:",
|
||||
true,
|
||||
@@ -5688,7 +5693,8 @@ fn comparison_titles_follow_loaded_counts_and_each_tabs_context() {
|
||||
bottom.left = vec!["mode".into()];
|
||||
bottom.center.clear();
|
||||
bottom.right.clear();
|
||||
bottom.segments.get_mut("mode").unwrap().title = "Current:{view}{name}".into();
|
||||
bottom.segments.get_mut("mode").unwrap().title =
|
||||
"Current:{view}{name}{changes}".into();
|
||||
});
|
||||
for comparison_active in [true, false] {
|
||||
let mut terminal =
|
||||
@@ -5709,16 +5715,33 @@ fn comparison_titles_follow_loaded_counts_and_each_tabs_context() {
|
||||
.unwrap();
|
||||
let titles = pane_screen(&terminal, Rect::new(0, 0, 160, 1));
|
||||
assert!(titles.contains(ordinary), "{phase}: {titles}");
|
||||
let comparison = format!("{prefix}{}source.rs", if uses_view { view } else { "" });
|
||||
let comparison = if uses_view {
|
||||
format!("{prefix}Diff · source.rs{changes}")
|
||||
} else {
|
||||
format!("{prefix}source.rs")
|
||||
};
|
||||
assert!(titles.contains(&comparison), "{phase}: {titles}");
|
||||
assert_eq!(
|
||||
titles.matches("Diff · ").count(),
|
||||
usize::from(uses_view),
|
||||
"{phase}: {titles}"
|
||||
);
|
||||
if matches!(phase, "view" | "unloaded") && comparison_active {
|
||||
let total = if phase == "view" {
|
||||
"Diff +3 -2"
|
||||
} else {
|
||||
"Diff …"
|
||||
};
|
||||
assert!(titles.contains(total), "{phase}: {titles}");
|
||||
} else {
|
||||
assert!(
|
||||
!titles.contains("Diff +") && !titles.contains("Diff …"),
|
||||
"{phase}: {titles}"
|
||||
);
|
||||
}
|
||||
let current = pane_screen(&terminal, Rect::new(0, 1, 160, 1));
|
||||
let expected = if comparison_active {
|
||||
format!("Current:{view}source.rs")
|
||||
format!("Current:Diff · source.rs{changes}")
|
||||
} else {
|
||||
"Current:source.rs".into()
|
||||
};
|
||||
@@ -5745,6 +5768,12 @@ fn comparison_title_counts_follow_live_edits_and_undo_in_hidden_tabs() {
|
||||
editor.handle(Input::Enter);
|
||||
editor.handle(Input::Enter);
|
||||
let (id, _) = editor.take_diff_request().unwrap();
|
||||
let mut unopened = syntax_diff_file("unopened.rs", "", "");
|
||||
unopened.loaded = false;
|
||||
unopened.before.clear();
|
||||
unopened.after.clear();
|
||||
unopened.hunks.clear();
|
||||
unopened.stats = Some((7, 4));
|
||||
editor.apply_diff_result(
|
||||
id,
|
||||
Ok(crate::diff::Outcome::Comparison(crate::diff::Comparison {
|
||||
@@ -5754,17 +5783,25 @@ fn comparison_title_counts_follow_live_edits_and_undo_in_hidden_tabs() {
|
||||
before: "baseline".into(),
|
||||
after: "Working checkout".into(),
|
||||
revisions: ["before-snapshot".into(), "after-snapshot".into()],
|
||||
files: vec![syntax_diff_file("live.rs", "old", "new")],
|
||||
files: vec![syntax_diff_file("live.rs", "old", "new"), unopened],
|
||||
})),
|
||||
);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(120, 14)).unwrap();
|
||||
let mut views = BufferViewports::default();
|
||||
for input in [Input::Down, Input::Char('l'), Input::Ctrl('u'), Input::Home] {
|
||||
editor.handle(input);
|
||||
terminal
|
||||
.draw(|frame| views.draw(frame, &mut editor))
|
||||
.unwrap();
|
||||
let titles = pane_screen(&terminal, Rect::new(0, 0, 120, 1));
|
||||
assert!(titles.contains("Diff +8 -5"), "{titles}");
|
||||
}
|
||||
editor.handle(Input::Char('\t'));
|
||||
editor.handle(Input::Char('\t'));
|
||||
assert!(editor.diff_editing());
|
||||
editor.execute("tab.new");
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(120, 14)).unwrap();
|
||||
let mut views = BufferViewports::default();
|
||||
for (inputs, counts) in [
|
||||
(vec![], "+1 -1"),
|
||||
for (inputs, counts, total) in [
|
||||
(vec![], "+1 -1", "+8 -5"),
|
||||
(
|
||||
vec![
|
||||
Input::Char('i'),
|
||||
@@ -5772,9 +5809,10 @@ fn comparison_title_counts_follow_live_edits_and_undo_in_hidden_tabs() {
|
||||
Input::Escape,
|
||||
],
|
||||
"+2 -1",
|
||||
"+9 -5",
|
||||
),
|
||||
(vec![Input::Char('u')], "+1 -1"),
|
||||
(vec![Input::Char('U')], "+2 -1"),
|
||||
(vec![Input::Char('u')], "+1 -1", "+8 -5"),
|
||||
(vec![Input::Char('U')], "+2 -1", "+9 -5"),
|
||||
] {
|
||||
for input in inputs {
|
||||
editor.handle(input);
|
||||
@@ -5785,10 +5823,18 @@ fn comparison_title_counts_follow_live_edits_and_undo_in_hidden_tabs() {
|
||||
.unwrap();
|
||||
let titles = pane_screen(&terminal, Rect::new(0, 0, 120, 1));
|
||||
assert!(
|
||||
titles.contains(&format!("1 Diff · {counts} · live.rs")),
|
||||
titles.contains(&format!("1 Diff · live.rs {counts}")),
|
||||
"{titles}"
|
||||
);
|
||||
assert!(titles.contains("2 live.rs"), "{titles}");
|
||||
assert!(!titles.contains("Diff +"), "{titles}");
|
||||
editor.execute("tab.previous");
|
||||
terminal
|
||||
.draw(|frame| views.draw(frame, &mut editor))
|
||||
.unwrap();
|
||||
let titles = pane_screen(&terminal, Rect::new(0, 0, 120, 1));
|
||||
assert!(titles.contains(&format!("Diff {total}")), "{titles}");
|
||||
editor.execute("tab.next");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7049,6 +7095,7 @@ fn custom_value_stays_above_split_overlays_and_diff_geometry() {
|
||||
assert_eq!(pane_screen(&terminal, Rect::new(0, 0, 120, 1)), title);
|
||||
|
||||
let mut editor = readonly_diff_editor(deletion_file());
|
||||
configure_chrome(&mut editor, |top, _| top.right = vec!["battery".into()]);
|
||||
terminal
|
||||
.draw(|frame| views.draw(frame, &mut editor))
|
||||
.unwrap();
|
||||
@@ -7234,6 +7281,7 @@ fn native_diff_dock_and_panes_fill_the_workspace_below_only_configured_chrome()
|
||||
for (width, height) in [(120, 30), (32, 9)] {
|
||||
for chrome in [false, true] {
|
||||
let mut editor = readonly_diff_editor(deletion_file());
|
||||
configure_chrome(&mut editor, |top, _| top.right = vec!["battery".into()]);
|
||||
if chrome {
|
||||
editor.set_label("battery".into(), "live".into()).unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user