tlc: MC-style name-based cursor restoration on parent navigation

When going UP to a parent directory, find the entry whose name matches
the last component of the path being left (MC's get_parent_dir_name
approach). This is more robust than saved-index restoration because it
works even when the parent directory listing changed between visits.
Falls back to saved dir_cursors index for non-parent navigation.
This commit is contained in:
2026-07-05 09:48:16 +03:00
parent 4526853895
commit 7043a466c5
@@ -744,9 +744,16 @@ impl Panel {
/// Replace the directory contents without touching history.
fn replace_directory(&mut self, path: &Path) -> Result<()> {
if !self.path.as_os_str().is_empty() {
let old_child_name = if !self.path.as_os_str().is_empty() {
self.dir_cursors.insert(self.path.clone(), (self.cursor, self.top));
}
if self.path.parent() == Some(path) {
self.path.file_name().and_then(|n| n.to_str()).map(String::from)
} else {
None
}
} else {
None
};
let mut entries = Vec::new();
if path.parent().is_some() && path != Path::new("/") {
entries.push(Entry {
@@ -778,16 +785,22 @@ impl Panel {
} else {
self.entries.len().saturating_sub(1)
};
self.cursor = match saved {
Some((c, _)) => c.min(max_idx),
None => {
if has_parent && self.entries.len() > 1 {
1
} else {
0
if let Some(ref name) = old_child_name {
self.cursor = self.entries.iter().position(|e| &e.name == name)
.unwrap_or_else(|| saved.map(|(c, _)| c.min(max_idx))
.unwrap_or(if has_parent && self.entries.len() > 1 { 1 } else { 0 }));
} else {
self.cursor = match saved {
Some((c, _)) => c.min(max_idx),
None => {
if has_parent && self.entries.len() > 1 {
1
} else {
0
}
}
}
};
};
}
self.top = saved.map(|(_, t)| t).unwrap_or(0);
self.path = path.to_path_buf();
self.unmark_all();