fix: restore tab and diff context through jump history

This commit is contained in:
Valdemar Lorenzen
2026-10-12 14:45:49 +02:00
parent 6b7cfdea20
commit 054225686e
8 changed files with 679 additions and 39 deletions
+105 -7
View File
@@ -1057,6 +1057,7 @@ fn chrome_title(
index: usize,
path: Option<&std::path::Path>,
dirty: bool,
is_diff: bool,
) -> String {
let name = path
.map(|path| {
@@ -1075,6 +1076,7 @@ fn chrome_title(
};
match field {
"index" => write!(title, "{index}").unwrap(),
"view" if is_diff => title.push_str("Diff · "),
"name" => title.push_str(&name),
"path" => title.push_str(&path),
"modified" if dirty => title.push_str(" [+]"),
@@ -1109,6 +1111,7 @@ fn chrome_items<'a>(
index + 1,
buffer.as_ref().and_then(|buffer| buffer.path),
buffer.is_some_and(|buffer| buffer.dirty),
editor.tab_is_diff(index),
)),
config,
tab: Some(index),
@@ -1133,6 +1136,7 @@ fn chrome_items<'a>(
editor.tab_index() + 1,
editor.path(),
editor.dirty(),
editor.tab_is_diff(editor.tab_index()),
)),
"position" => Cow::Owned(format!(
"{}:{}",
@@ -1207,6 +1211,7 @@ fn chrome_items<'a>(
editor.tab_index() + 1,
editor.path(),
editor.dirty(),
editor.tab_is_diff(editor.tab_index()),
));
} else if text.chars().any(char::is_control) {
text = Cow::Owned(display_text(&text));
@@ -5574,7 +5579,7 @@ mod tests {
let path = directory.file("λ\t{index}.rs", "source");
let editor = Editor::open(Some(path.clone()), vec![]).unwrap();
let groups = chrome_groups(&editor, editor.bottom_bar_config(), &SyntaxCache::new());
let title = chrome_title("{path}", 2, Some(&path), false);
let title = chrome_title("{path}", 2, Some(&path), false, false);
assert_eq!(title, display_text(&display_path(&path)));
assert!(groups.iter().flatten().any(|item| item.text == title));
assert_eq!(editor.path(), Some(path.as_path()));
@@ -6129,6 +6134,105 @@ mod tests {
}
}
#[test]
fn comparison_titles_distinguish_same_named_tabs_and_follow_current_context() {
let directory = Directory::new();
let path = directory.file("source.rs", "fn main() {}");
for phase in ["loading", "before", "after", "view"] {
let mut editor = Editor::open(Some(path.clone()), vec![]).unwrap();
editor.execute("tab.new");
editor.execute("diff");
if phase != "loading" {
let (id, _) = editor.take_diff_request().unwrap();
editor.apply_diff_result(id, Ok(crate::diff::Outcome::Catalog(diff_catalog())));
}
if matches!(phase, "after" | "view") {
editor.handle(Input::Down);
editor.handle(Input::Enter);
}
if phase == "view" {
editor.handle(Input::Down);
editor.handle(Input::Enter);
let (id, _) = editor.take_diff_request().unwrap();
editor.apply_diff_result(
id,
Ok(crate::diff::Outcome::Comparison(crate::diff::Comparison {
root: directory.0.clone(),
editable_paths: Default::default(),
before: "baseline".into(),
after: "historic".into(),
files: vec![syntax_diff_file("source.rs", "fn old() {}", "fn main() {}")],
})),
);
}
let default_tabs = editor.top_bar_config().segment("tabs").clone();
for (template, ordinary, comparison, marker_count) in [
(None, "1 source.rs", "2 Diff · source.rs", 1),
(
Some("{index} {name}{modified}"),
"1 source.rs",
"2 source.rs",
0,
),
(
Some("T{index}:{view}{name}{modified}"),
"T1:source.rs",
"T2:Diff · source.rs",
1,
),
] {
configure_chrome(&mut editor, |top, bottom| {
top.segments.insert("tabs".into(), default_tabs.clone());
if let Some(template) = template {
top.segments.get_mut("tabs").unwrap().title = template.into();
}
bottom.left = vec!["mode".into()];
bottom.center.clear();
bottom.right.clear();
bottom.segments.get_mut("mode").unwrap().title = "Current:{view}{name}".into();
});
for comparison_active in [true, false] {
let mut terminal =
Terminal::new(ratatui::backend::TestBackend::new(160, 2)).unwrap();
terminal
.draw(|frame| {
for (line, y) in [
(editor.top_bar_config(), 0),
(editor.bottom_bar_config(), 1),
] {
draw_chrome(
frame,
chrome_groups(&editor, line, &SyntaxCache::new()),
Rect::new(0, y, 160, 1),
);
}
})
.unwrap();
let titles = pane_screen(&terminal, Rect::new(0, 0, 160, 1));
assert!(titles.contains(ordinary), "{phase}: {titles}");
assert!(titles.contains(comparison), "{phase}: {titles}");
assert_eq!(
titles.matches("Diff · ").count(),
marker_count,
"{phase}: {titles}"
);
let current = pane_screen(&terminal, Rect::new(0, 1, 160, 1));
let expected = if comparison_active {
"Current:Diff · source.rs"
} else {
"Current:source.rs"
};
assert!(current.contains(expected), "{phase}: {current}");
editor.execute(if comparison_active {
"tab.previous"
} else {
"tab.next"
});
}
}
}
}
#[test]
fn tab_titles_update_templates_without_reinterpreting_file_names() {
let directory = Directory::new();
@@ -6158,12 +6262,6 @@ mod tests {
let titles = pane_screen(&terminal, Rect::new(0, 0, 160, 1));
assert!(titles.contains("T1:λ{index}�.rs [+]"), "{titles}");
assert!(titles.contains("T2:λ{index}�.rs [+]"), "{titles}");
let buffer = terminal.backend().buffer();
assert_eq!(buffer[(0, 0)].bg, Color::Reset);
let active = (0..159)
.find(|&x| buffer[(x, 0)].symbol() == "T" && buffer[(x + 1, 0)].symbol() == "2")
.unwrap();
assert_eq!(buffer[(active, 0)].bg, Color::Cyan);
configure_chrome(&mut editor, |top, _| {
top.segments.get_mut("tabs").unwrap().title = "{index}:{path}{modified}".into();