merman_editor_core/
workspace.rs1use crate::snapshot::{DocumentSnapshot, FenceSnapshot};
2use crate::types::{DocumentKind, DocumentUri};
3use merman_analysis::{
4 AnalyzedDiagram, Analyzer, SourceDescriptor, SourceKind, analyze_document_result_shared,
5};
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[derive(Debug)]
10pub struct DocumentWorkspace {
11 documents: HashMap<DocumentUri, DocumentSnapshot>,
12 analyzer: Analyzer,
13}
14
15impl Default for DocumentWorkspace {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl DocumentWorkspace {
22 pub fn new() -> Self {
23 Self::with_analyzer(Analyzer::new())
24 }
25
26 pub fn with_analyzer(analyzer: Analyzer) -> Self {
27 Self {
28 documents: HashMap::new(),
29 analyzer,
30 }
31 }
32
33 pub fn replace_analyzer(&mut self, analyzer: Analyzer) {
34 self.analyzer = analyzer;
35 self.documents.clear();
36 }
37
38 pub fn upsert(
39 &mut self,
40 uri: impl Into<DocumentUri>,
41 version: i32,
42 text: String,
43 kind: DocumentKind,
44 ) -> DocumentSnapshot {
45 let uri = uri.into();
46 let snapshot = self.build_snapshot(uri.clone(), version, text, kind);
47 self.documents.insert(uri, snapshot.clone());
48 snapshot
49 }
50
51 pub fn build_snapshot(
52 &self,
53 uri: impl Into<DocumentUri>,
54 version: i32,
55 text: String,
56 kind: DocumentKind,
57 ) -> DocumentSnapshot {
58 Self::build_snapshot_with_analyzer(&self.analyzer, uri, version, text, kind)
59 }
60
61 pub fn build_snapshot_with_analyzer(
62 analyzer: &Analyzer,
63 uri: impl Into<DocumentUri>,
64 version: i32,
65 text: String,
66 kind: DocumentKind,
67 ) -> DocumentSnapshot {
68 Self::build_snapshot_with_shared_text(analyzer, uri, version, Arc::from(text), kind)
69 }
70
71 pub fn build_snapshot_with_shared_text(
72 analyzer: &Analyzer,
73 uri: impl Into<DocumentUri>,
74 version: i32,
75 text: Arc<str>,
76 kind: DocumentKind,
77 ) -> DocumentSnapshot {
78 let uri = uri.into();
79 let source = source_descriptor_for_document(&uri, kind);
80 let analysis = analyze_document_result_shared(Arc::clone(&text), analyzer, source.clone());
81 let fences = analysis
82 .diagrams()
83 .iter()
84 .map(Self::fence_snapshot)
85 .collect::<Vec<_>>();
86 let source_map = analysis.source_map().clone();
87 DocumentSnapshot {
88 uri,
89 version,
90 kind,
91 source,
92 text,
93 source_map,
94 fences,
95 }
96 }
97
98 pub fn get(&self, uri: &DocumentUri) -> Option<&DocumentSnapshot> {
99 self.documents.get(uri)
100 }
101
102 pub fn remove(&mut self, uri: &DocumentUri) {
103 self.documents.remove(uri);
104 }
105
106 pub fn snapshots(&self) -> Vec<DocumentSnapshot> {
107 self.documents.values().cloned().collect()
108 }
109
110 fn fence_snapshot(diagram: &AnalyzedDiagram) -> FenceSnapshot {
111 FenceSnapshot {
112 source_id: diagram.source_id.clone(),
113 index: diagram.index,
114 source: diagram.source.clone(),
115 start: diagram.start,
116 body_start: diagram.body_start,
117 body_end: diagram.body_end,
118 end: diagram.end,
119 text: diagram.text.clone(),
120 fence_delimiter: diagram.fence_delimiter,
121 diagram_type: diagram.syntax.diagram_type.clone(),
122 text_index: diagram.syntax.text_index.clone(),
123 }
124 }
125}
126
127fn source_descriptor_for_document(uri: &DocumentUri, kind: DocumentKind) -> SourceDescriptor {
128 let source_kind = match kind {
129 DocumentKind::Diagram => SourceKind::Diagram,
130 DocumentKind::Markdown => SourceKind::Markdown,
131 DocumentKind::Mdx => SourceKind::Mdx,
132 };
133 merman_analysis::source_descriptor_for_kind(Some(uri.as_str()), source_kind)
134}