yazi_core/manager/commands/
hover.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::collections::HashSet;

use yazi_dds::Pubsub;
use yazi_macro::render;
use yazi_shared::{Id, event::{CmdCow, Data}, url::{Url, Urn}};

use crate::manager::Manager;

struct Opt {
	url: Option<Url>,
	tab: Option<Id>,
}

impl From<CmdCow> for Opt {
	fn from(mut c: CmdCow) -> Self {
		Self { url: c.take_first_url(), tab: c.get("tab").and_then(Data::as_id) }
	}
}
impl From<Option<Url>> for Opt {
	fn from(url: Option<Url>) -> Self { Self { url, tab: None } }
}

impl Manager {
	#[yazi_codegen::command]
	pub fn hover(&mut self, opt: Opt) {
		if let Some(u) = opt.url {
			self.hover_do(u, opt.tab);
		} else {
			self.current_or_mut(opt.tab).arrow(0);
		}

		// Repeek
		self.peek(false);

		// Refresh watcher
		let mut to_watch = HashSet::with_capacity(3 * self.tabs.len());
		for tab in self.tabs.iter() {
			to_watch.insert(tab.cwd());
			if let Some(ref p) = tab.parent {
				to_watch.insert(&p.url);
			}
			if let Some(h) = tab.hovered().filter(|&h| h.is_dir()) {
				to_watch.insert(&h.url);
			}
		}
		self.watcher.watch(to_watch);

		// Publish through DDS
		Pubsub::pub_from_hover(self.active().id, self.hovered().map(|h| &h.url));
	}

	fn hover_do(&mut self, url: Url, tab: Option<Id>) {
		// Hover on the file
		if let Ok(p) = url.strip_prefix(&self.current_or(tab).url) {
			render!(self.current_or_mut(tab).hover(Urn::new(p)));
		}

		// Turn on tracing
		if self.current_or(tab).hovered().is_some_and(|h| h.url == url) {
			// `hover(Some)` occurs after user actions, such as create, rename, reveal, etc.
			// At this point, it's intuitive to track the location of the file regardless.
			self.current_or_mut(tab).trace = Some(url.urn_owned());
		}
	}
}