tinymist_world/
snapshot.rsuse core::fmt;
use crate::{args::TaskWhen, CompilerFeat, CompilerWorld, EntryReader, TaskInputs};
use ecow::EcoString;
use tinymist_std::typst::TypstDocument;
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ProjectInsId(pub EcoString);
impl fmt::Display for ProjectInsId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl ProjectInsId {
pub const PRIMARY: ProjectInsId = ProjectInsId(EcoString::inline("primary"));
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ExportSignal {
pub by_mem_events: bool,
pub by_fs_events: bool,
pub by_entry_update: bool,
}
impl ExportSignal {
pub fn merge(&mut self, other: ExportSignal) {
self.by_mem_events |= other.by_mem_events;
self.by_fs_events |= other.by_fs_events;
self.by_entry_update |= other.by_entry_update;
}
pub fn should_run_task_dyn(
&self,
when: TaskWhen,
docs: Option<&TypstDocument>,
) -> Option<bool> {
match docs {
Some(TypstDocument::Paged(doc)) => self.should_run_task(when, Some(doc.as_ref())),
Some(TypstDocument::Html(doc)) => self.should_run_task(when, Some(doc.as_ref())),
None => self.should_run_task::<typst::layout::PagedDocument>(when, None),
}
}
pub fn should_run_task<D: typst::Document>(
&self,
when: TaskWhen,
docs: Option<&D>,
) -> Option<bool> {
if !matches!(when, TaskWhen::Never) && self.by_entry_update {
return Some(true);
}
match when {
TaskWhen::Never => Some(false),
TaskWhen::OnType => Some(self.by_mem_events),
TaskWhen::OnSave => Some(self.by_fs_events),
TaskWhen::OnDocumentHasTitle if self.by_fs_events => {
docs.map(|doc| doc.info().title.is_some())
}
TaskWhen::OnDocumentHasTitle => Some(false),
}
}
}
pub struct CompileSnapshot<F: CompilerFeat> {
pub id: ProjectInsId,
pub signal: ExportSignal,
pub world: CompilerWorld<F>,
pub success_doc: Option<TypstDocument>,
}
impl<F: CompilerFeat + 'static> CompileSnapshot<F> {
pub fn from_world(world: CompilerWorld<F>) -> Self {
Self {
id: ProjectInsId("primary".into()),
signal: ExportSignal::default(),
world,
success_doc: None,
}
}
pub fn task(mut self, inputs: TaskInputs) -> Self {
'check_changed: {
if let Some(entry) = &inputs.entry {
if *entry != self.world.entry_state() {
break 'check_changed;
}
}
if let Some(inputs) = &inputs.inputs {
if inputs.clone() != self.world.inputs() {
break 'check_changed;
}
}
return self;
};
self.world = self.world.task(inputs);
self
}
}
impl<F: CompilerFeat> Clone for CompileSnapshot<F> {
fn clone(&self) -> Self {
Self {
id: self.id.clone(),
signal: self.signal,
world: self.world.clone(),
success_doc: self.success_doc.clone(),
}
}
}