tinymist_world/
snapshot.rs1use core::fmt;
4
5use crate::{args::TaskWhen, CompilerFeat, CompilerWorld, EntryReader, TaskInputs};
6use ecow::EcoString;
7use tinymist_std::typst::TypstDocument;
8
9#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct ProjectInsId(pub EcoString);
13
14impl fmt::Display for ProjectInsId {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 self.0.fmt(f)
17 }
18}
19
20impl ProjectInsId {
21 pub const PRIMARY: ProjectInsId = ProjectInsId(EcoString::inline("primary"));
23}
24
25#[derive(Debug, Clone, Copy, Default)]
30pub struct ExportSignal {
31 pub by_mem_events: bool,
33 pub by_fs_events: bool,
35 pub by_entry_update: bool,
37}
38
39impl ExportSignal {
40 pub fn merge(&mut self, other: ExportSignal) {
42 self.by_mem_events |= other.by_mem_events;
43 self.by_fs_events |= other.by_fs_events;
44 self.by_entry_update |= other.by_entry_update;
45 }
46
47 pub fn should_run_task_dyn(
48 &self,
49 when: TaskWhen,
50 docs: Option<&TypstDocument>,
51 ) -> Option<bool> {
52 match docs {
53 Some(TypstDocument::Paged(doc)) => self.should_run_task(when, Some(doc.as_ref())),
54 Some(TypstDocument::Html(doc)) => self.should_run_task(when, Some(doc.as_ref())),
55 None => self.should_run_task::<typst::layout::PagedDocument>(when, None),
56 }
57 }
58
59 pub fn should_run_task<D: typst::Document>(
60 &self,
61 when: TaskWhen,
62 docs: Option<&D>,
63 ) -> Option<bool> {
64 if !matches!(when, TaskWhen::Never) && self.by_entry_update {
65 return Some(true);
66 }
67
68 match when {
69 TaskWhen::Never => Some(false),
70 TaskWhen::OnType => Some(self.by_mem_events),
71 TaskWhen::OnSave => Some(self.by_fs_events),
72 TaskWhen::OnDocumentHasTitle if self.by_fs_events => {
73 docs.map(|doc| doc.info().title.is_some())
74 }
75 TaskWhen::OnDocumentHasTitle => Some(false),
76 }
77 }
78}
79
80pub struct CompileSnapshot<F: CompilerFeat> {
82 pub id: ProjectInsId,
84 pub signal: ExportSignal,
86 pub world: CompilerWorld<F>,
88 pub success_doc: Option<TypstDocument>,
90}
91
92impl<F: CompilerFeat + 'static> CompileSnapshot<F> {
93 pub fn from_world(world: CompilerWorld<F>) -> Self {
95 Self {
96 id: ProjectInsId("primary".into()),
97 signal: ExportSignal::default(),
98 world,
99 success_doc: None,
100 }
101 }
102
103 pub fn task(mut self, inputs: TaskInputs) -> Self {
109 'check_changed: {
110 if let Some(entry) = &inputs.entry {
111 if *entry != self.world.entry_state() {
112 break 'check_changed;
113 }
114 }
115 if let Some(inputs) = &inputs.inputs {
116 if inputs.clone() != self.world.inputs() {
117 break 'check_changed;
118 }
119 }
120
121 return self;
122 };
123
124 self.world = self.world.task(inputs);
125
126 self
127 }
128}
129
130impl<F: CompilerFeat> Clone for CompileSnapshot<F> {
131 fn clone(&self) -> Self {
132 Self {
133 id: self.id.clone(),
134 signal: self.signal,
135 world: self.world.clone(),
136 success_doc: self.success_doc.clone(),
137 }
138 }
139}