use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
pub struct FileWatch {
_watcher: RecommendedWatcher,
}
pub fn watch_file(path: &Path, on_change: impl Fn(PathBuf) + Send + 'static) -> Result<FileWatch> {
let path = path.to_path_buf();
let dir = path
.parent()
.filter(|p| !p.as_os_str().is_empty())
.map(Path::to_path_buf)
.unwrap_or_else(|| PathBuf::from("."));
let name = path
.file_name()
.context("watching a path with no file name")?
.to_os_string();
let reported = path.clone();
let mut watcher = notify::recommended_watcher(move |event: notify::Result<notify::Event>| {
let Ok(event) = event else { return };
if !(event.kind.is_create() || event.kind.is_modify() || event.kind.is_remove()) {
return;
}
if event.paths.iter().any(|p| p.file_name() == Some(&name)) {
on_change(reported.clone());
}
})
.context("creating a file watcher")?;
watcher
.watch(&dir, RecursiveMode::NonRecursive)
.with_context(|| format!("watching {}", dir.display()))?;
Ok(FileWatch { _watcher: watcher })
}