From 3ab19185093d7709f824b95b979060ce125389d8 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 2 Jul 2023 19:06:40 +0200 Subject: [PATCH] Move more watching code into `watch.rs` --- cli/src/watch.rs | 40 +++++++++++++++++++++++++++++++++++----- cli/src/world.rs | 47 ++++++----------------------------------------- 2 files changed, 41 insertions(+), 46 deletions(-) diff --git a/cli/src/watch.rs b/cli/src/watch.rs index e70b69100..2ad73f858 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 = + 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, +) -> 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. diff --git a/cli/src/world.rs b/cli/src/world.rs index f3dfaa429..f09a3f6c7 100644 --- a/cli/src/world.rs +++ b/cli/src/world.rs @@ -1,12 +1,11 @@ use std::cell::{OnceCell, RefCell, RefMut}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::fs; use std::hash::Hash; use std::path::{Path, PathBuf}; use chrono::Datelike; use comemo::Prehashed; -use notify::{RecursiveMode, Watcher}; use same_file::Handle; use siphasher::sip128::{Hasher128, SipHasher13}; use typst::diag::{FileError, FileResult, StrResult}; @@ -45,6 +44,7 @@ pub struct SystemWorld { } impl SystemWorld { + /// Create a new system world. pub fn new(command: &CompileCommand) -> StrResult { let mut searcher = FontSearcher::new(); searcher.search(&command.font_paths); @@ -89,47 +89,12 @@ impl SystemWorld { self.main } - /// Adjust the file watching. Watches all new dependencies and unwatches - /// all `previous` dependencies that are not relevant anymore. - #[tracing::instrument(skip_all)] - pub fn watch( - &self, - watcher: &mut dyn Watcher, - mut previous: HashSet, - ) -> StrResult<()> { - // Watch new paths that weren't watched yet. - for slot in self.paths.borrow().values() { - let path = &slot.system_path; - 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(()) + /// Return all paths the last compilation depended on. + pub fn dependencies(&mut self) -> impl Iterator { + self.paths.get_mut().values().map(|slot| slot.system_path.as_path()) } - /// Collect all paths the last compilation depended on. - #[tracing::instrument(skip_all)] - pub fn dependencies(&self) -> HashSet { - self.paths - .borrow() - .values() - .map(|slot| slot.system_path.clone()) - .collect() - } - - /// Reset th compilation state in preparation of a new compilation. - #[tracing::instrument(skip_all)] + /// Reset the compilation state in preparation of a new compilation. pub fn reset(&mut self) { self.hashes.borrow_mut().clear(); self.paths.borrow_mut().clear();