pitchfork_cli/
watch_files.rs

1use crate::Result;
2use itertools::Itertools;
3use miette::IntoDiagnostic;
4use notify::{Config, EventKind, RecommendedWatcher, RecursiveMode};
5use notify_debouncer_full::{DebounceEventResult, Debouncer, FileIdMap, new_debouncer_opt};
6use std::path::{Path, PathBuf};
7use std::time::Duration;
8
9pub struct WatchFiles {
10    pub rx: tokio::sync::mpsc::Receiver<Vec<PathBuf>>,
11    debouncer: Debouncer<RecommendedWatcher, FileIdMap>,
12}
13
14impl WatchFiles {
15    pub fn new(duration: Duration) -> Result<Self> {
16        let h = tokio::runtime::Handle::current();
17        let (tx, rx) = tokio::sync::mpsc::channel(1);
18        let debouncer = new_debouncer_opt(
19            duration,
20            None,
21            move |res: DebounceEventResult| {
22                let tx = tx.clone();
23                h.spawn(async move {
24                    if let Ok(ev) = res {
25                        let paths = ev
26                            .into_iter()
27                            .filter(|e| {
28                                matches!(
29                                    e.kind,
30                                    EventKind::Modify(_)
31                                        | EventKind::Create(_)
32                                        | EventKind::Remove(_)
33                                )
34                            })
35                            .flat_map(|e| e.paths.clone())
36                            .unique()
37                            .collect_vec();
38                        if !paths.is_empty() {
39                            tx.send(paths).await.unwrap();
40                        }
41                    }
42                });
43            },
44            FileIdMap::new(),
45            Config::default(),
46        )
47        .into_diagnostic()?;
48
49        Ok(Self { debouncer, rx })
50    }
51
52    pub fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()> {
53        self.debouncer.watch(path, recursive_mode).into_diagnostic()
54    }
55}