mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 23:31:05 +00:00
fix(mgr): restore hovered fallback for %s/%d shell-formatting when nothing is selected
The Splatable impl for Mgr used to fall back to the hovered item via Tab::selected_or_hovered_urls() when the selection was empty, the same convention used everywhere else (yank, copy, remove, open). PR #4108 rewrote this into MgrSnap/TabSnap but only ported the plain "selected" list, dropping the hovered fallback. This made %s and %d expand to nothing when hovering a file without an explicit selection. Restore the fallback in MgrSnap::selected(), which both %s/%S and %d/%D read from. Resolves #4132 Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: nabsei <nsahrane@hotmail.com>
This commit is contained in:
parent
52640fcece
commit
f6e7473db9
1 changed files with 51 additions and 8 deletions
|
|
@ -1,3 +1,5 @@
|
|||
use std::iter;
|
||||
|
||||
use yazi_fs::Splatable;
|
||||
use yazi_shared::url::{AsUrl, Url, UrlBuf};
|
||||
|
||||
|
|
@ -24,14 +26,15 @@ impl Splatable for MgrSnap {
|
|||
|
||||
fn selected(&self, tab: usize, mut idx: Option<usize>) -> impl Iterator<Item = Url<'_>> {
|
||||
idx = idx.and_then(|i| i.checked_sub(1));
|
||||
tab
|
||||
.checked_sub(1)
|
||||
.and_then(|tab| self.tabs.get(tab))
|
||||
.map_or_else(|| &[][..], |s| &s.selected)
|
||||
.iter()
|
||||
.skip(idx.unwrap_or(0))
|
||||
.take(if idx.is_some() { 1 } else { usize::MAX })
|
||||
.map(AsUrl::as_url)
|
||||
// Fall back to the hovered item when nothing is explicitly selected, same
|
||||
// as `Tab::selected_or_hovered_urls()` used for file operations elsewhere.
|
||||
let urls: Box<dyn Iterator<Item = &UrlBuf>> =
|
||||
match tab.checked_sub(1).and_then(|tab| self.tabs.get(tab)) {
|
||||
Some(s) if !s.selected.is_empty() => Box::new(s.selected.iter()),
|
||||
Some(s) => Box::new(s.hovered.iter()),
|
||||
None => Box::new(iter::empty()),
|
||||
};
|
||||
urls.skip(idx.unwrap_or(0)).take(if idx.is_some() { 1 } else { usize::MAX }).map(AsUrl::as_url)
|
||||
}
|
||||
|
||||
fn hovered(&self, tab: usize) -> Option<Url<'_>> {
|
||||
|
|
@ -52,3 +55,43 @@ impl Splatable for MgrSnap {
|
|||
.map(AsUrl::as_url)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn url(s: &str) -> UrlBuf { UrlBuf::from(PathBuf::from(s)) }
|
||||
|
||||
fn snap(selected: &[&str], hovered: Option<&str>) -> MgrSnap {
|
||||
MgrSnap {
|
||||
tab: 0,
|
||||
tabs: vec![TabSnap {
|
||||
hovered: hovered.map(url),
|
||||
selected: selected.iter().map(|s| url(s)).collect(),
|
||||
}],
|
||||
yanked: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_falls_back_to_hovered_when_nothing_selected() {
|
||||
let s = snap(&[], Some("hovered/file"));
|
||||
let urls: Vec<_> = s.selected(1, None).collect();
|
||||
assert_eq!(urls, [url("hovered/file")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_prefers_actual_selection_over_hovered() {
|
||||
let s = snap(&["a", "b"], Some("hovered/file"));
|
||||
let urls: Vec<_> = s.selected(1, None).collect();
|
||||
assert_eq!(urls, [url("a"), url("b")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_is_empty_when_nothing_selected_or_hovered() {
|
||||
let s = snap(&[], None);
|
||||
assert_eq!(s.selected(1, None).count(), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue