yazi_core/tab/
finder.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
66
67
68
69
use std::collections::HashMap;

use anyhow::Result;
use yazi_fs::{Files, Filter, FilterCase};
use yazi_shared::url::Url;

pub struct Finder {
	pub filter: Filter,
	matched:    HashMap<Url, u8>,
	revision:   u64,
}

impl Finder {
	pub(super) fn new(s: &str, case: FilterCase) -> Result<Self> {
		Ok(Self { filter: Filter::new(s, case)?, matched: Default::default(), revision: 0 })
	}

	pub(super) fn prev(&self, files: &Files, cursor: usize, include: bool) -> Option<isize> {
		for i in !include as usize..files.len() {
			let idx = (cursor + files.len() - i) % files.len();
			if self.filter.matches(files[idx].name()) {
				return Some(idx as isize - cursor as isize);
			}
		}
		None
	}

	pub(super) fn next(&self, files: &Files, cursor: usize, include: bool) -> Option<isize> {
		for i in !include as usize..files.len() {
			let idx = (cursor + i) % files.len();
			if self.filter.matches(files[idx].name()) {
				return Some(idx as isize - cursor as isize);
			}
		}
		None
	}

	pub(super) fn catchup(&mut self, files: &Files) -> bool {
		if self.revision == files.revision {
			return false;
		}
		self.matched.clear();

		let mut i = 0u8;
		for file in files.iter() {
			if !self.filter.matches(file.name()) {
				continue;
			}

			self.matched.insert(file.url_owned(), i);
			if self.matched.len() > 99 {
				break;
			}

			i += 1;
		}

		self.revision = files.revision;
		true
	}
}

impl Finder {
	#[inline]
	pub fn matched(&self) -> &HashMap<Url, u8> { &self.matched }

	#[inline]
	pub fn matched_idx(&self, url: &Url) -> Option<u8> { self.matched.get(url).copied() }
}