diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-07-02 19:06:40 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-07-02 19:09:35 +0200 |
| commit | 3ab19185093d7709f824b95b979060ce125389d8 (patch) | |
| tree | fd30251c025f3cb4921d89795c8eed4b9764c4e3 /cli/src/watch.rs | |
| parent | 46fb49aed3832c2838f6668669f131d05f081b88 (diff) | |
Move more watching code into `watch.rs`
Diffstat (limited to 'cli/src/watch.rs')
| -rw-r--r-- | cli/src/watch.rs | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/cli/src/watch.rs b/cli/src/watch.rs index e70b6910..2ad73f85 100644 --- a/cli/src/watch.rs +++ b/cli/src/watch.rs @@ -1,12 +1,13 @@ use std::collections::HashSet; use std::io::{self, IsTerminal, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; use codespan_reporting::term::{self, termcolor}; -use notify::{RecommendedWatcher, Watcher}; +use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use same_file::is_same_file; use termcolor::WriteColor; use typst::diag::StrResult; +use typst::eval::eco_format; use crate::args::CompileCommand; use crate::color_stream; @@ -27,7 +28,7 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> { .map_err(|_| "failed to setup file watching")?; // Watch all the files that are used by the input file and its dependencies. - world.watch(&mut watcher, HashSet::new())?; + watch_dependencies(&mut world, &mut watcher, HashSet::new())?; // Handle events. let timeout = std::time::Duration::from_millis(100); @@ -45,18 +46,47 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> { if recompile { // Retrieve the dependencies of the last compilation. - let dependencies = world.dependencies(); + let previous: HashSet<PathBuf> = + world.dependencies().map(ToOwned::to_owned).collect(); // Recompile. compile_once(&mut world, &mut command, true)?; comemo::evict(10); // Adjust the watching. - world.watch(&mut watcher, dependencies)?; + watch_dependencies(&mut world, &mut watcher, previous)?; } } } +/// Adjust the file watching. Watches all new dependencies and unwatches +/// all `previous` dependencies that are not relevant anymore. +#[tracing::instrument(skip_all)] +fn watch_dependencies( + world: &mut SystemWorld, + watcher: &mut dyn Watcher, + mut previous: HashSet<PathBuf>, +) -> StrResult<()> { + // Watch new paths that weren't watched yet. + for path in world.dependencies() { + let watched = previous.remove(path); + if path.exists() && !watched { + tracing::info!("Watching {}", path.display()); + watcher + .watch(path, RecursiveMode::NonRecursive) + .map_err(|_| eco_format!("failed to watch {path:?}"))?; + } + } + + // Unwatch old paths that don't need to be watched anymore. + for path in previous { + tracing::info!("Unwatching {}", path.display()); + watcher.unwatch(&path).ok(); + } + + Ok(()) +} + /// Whether a watch event is relevant for compilation. fn is_event_relevant(event: ¬ify::Event, output: &Path) -> bool { // Never recompile because the output file changed. |
