summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/src/watch.rs40
-rw-r--r--cli/src/world.rs47
2 files changed, 41 insertions, 46 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: &notify::Event, output: &Path) -> bool {
// Never recompile because the output file changed.
diff --git a/cli/src/world.rs b/cli/src/world.rs
index f3dfaa42..f09a3f6c 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<Self> {
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<PathBuf>,
- ) -> 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<Item = &Path> {
+ 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<PathBuf> {
- 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();