mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Move more watching code into watch.rs
This commit is contained in:
parent
46fb49aed3
commit
3ab1918509
@ -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.
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user