mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +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::collections::HashSet;
|
||||||
use std::io::{self, IsTerminal, Write};
|
use std::io::{self, IsTerminal, Write};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use codespan_reporting::term::{self, termcolor};
|
use codespan_reporting::term::{self, termcolor};
|
||||||
use notify::{RecommendedWatcher, Watcher};
|
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use same_file::is_same_file;
|
use same_file::is_same_file;
|
||||||
use termcolor::WriteColor;
|
use termcolor::WriteColor;
|
||||||
use typst::diag::StrResult;
|
use typst::diag::StrResult;
|
||||||
|
use typst::eval::eco_format;
|
||||||
|
|
||||||
use crate::args::CompileCommand;
|
use crate::args::CompileCommand;
|
||||||
use crate::color_stream;
|
use crate::color_stream;
|
||||||
@ -27,7 +28,7 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> {
|
|||||||
.map_err(|_| "failed to setup file watching")?;
|
.map_err(|_| "failed to setup file watching")?;
|
||||||
|
|
||||||
// Watch all the files that are used by the input file and its dependencies.
|
// 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.
|
// Handle events.
|
||||||
let timeout = std::time::Duration::from_millis(100);
|
let timeout = std::time::Duration::from_millis(100);
|
||||||
@ -45,18 +46,47 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> {
|
|||||||
|
|
||||||
if recompile {
|
if recompile {
|
||||||
// Retrieve the dependencies of the last compilation.
|
// Retrieve the dependencies of the last compilation.
|
||||||
let dependencies = world.dependencies();
|
let previous: HashSet<PathBuf> =
|
||||||
|
world.dependencies().map(ToOwned::to_owned).collect();
|
||||||
|
|
||||||
// Recompile.
|
// Recompile.
|
||||||
compile_once(&mut world, &mut command, true)?;
|
compile_once(&mut world, &mut command, true)?;
|
||||||
comemo::evict(10);
|
comemo::evict(10);
|
||||||
|
|
||||||
// Adjust the watching.
|
// 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.
|
/// Whether a watch event is relevant for compilation.
|
||||||
fn is_event_relevant(event: ¬ify::Event, output: &Path) -> bool {
|
fn is_event_relevant(event: ¬ify::Event, output: &Path) -> bool {
|
||||||
// Never recompile because the output file changed.
|
// Never recompile because the output file changed.
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use std::cell::{OnceCell, RefCell, RefMut};
|
use std::cell::{OnceCell, RefCell, RefMut};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use chrono::Datelike;
|
use chrono::Datelike;
|
||||||
use comemo::Prehashed;
|
use comemo::Prehashed;
|
||||||
use notify::{RecursiveMode, Watcher};
|
|
||||||
use same_file::Handle;
|
use same_file::Handle;
|
||||||
use siphasher::sip128::{Hasher128, SipHasher13};
|
use siphasher::sip128::{Hasher128, SipHasher13};
|
||||||
use typst::diag::{FileError, FileResult, StrResult};
|
use typst::diag::{FileError, FileResult, StrResult};
|
||||||
@ -45,6 +44,7 @@ pub struct SystemWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SystemWorld {
|
impl SystemWorld {
|
||||||
|
/// Create a new system world.
|
||||||
pub fn new(command: &CompileCommand) -> StrResult<Self> {
|
pub fn new(command: &CompileCommand) -> StrResult<Self> {
|
||||||
let mut searcher = FontSearcher::new();
|
let mut searcher = FontSearcher::new();
|
||||||
searcher.search(&command.font_paths);
|
searcher.search(&command.font_paths);
|
||||||
@ -89,47 +89,12 @@ impl SystemWorld {
|
|||||||
self.main
|
self.main
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adjust the file watching. Watches all new dependencies and unwatches
|
/// Return all paths the last compilation depended on.
|
||||||
/// all `previous` dependencies that are not relevant anymore.
|
pub fn dependencies(&mut self) -> impl Iterator<Item = &Path> {
|
||||||
#[tracing::instrument(skip_all)]
|
self.paths.get_mut().values().map(|slot| slot.system_path.as_path())
|
||||||
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(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect all paths the last compilation depended on.
|
/// Reset the compilation state in preparation of a new compilation.
|
||||||
#[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)]
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.hashes.borrow_mut().clear();
|
self.hashes.borrow_mut().clear();
|
||||||
self.paths.borrow_mut().clear();
|
self.paths.borrow_mut().clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user