1use std::collections::{BTreeMap, HashMap, HashSet};
22use syntect::highlighting::StyleModifier;
23use syntect::parsing::Scope;
24
25use xi_rope::spans::{Spans, SpansBuilder};
26use xi_rope::{Interval, RopeDelta};
27use xi_trace::trace_block;
28
29use crate::plugins::PluginPid;
30use crate::styles::{Style, ThemeStyleMap};
31
32#[derive(Default)]
34pub struct Layers {
35 layers: BTreeMap<PluginPid, ScopeLayer>,
36 deleted: HashSet<PluginPid>,
37 merged: Spans<Style>,
38}
39
40pub struct ScopeLayer {
42 stack_lookup: Vec<Vec<Scope>>,
43 style_lookup: Vec<Style>,
44 style_cache: HashMap<Vec<Scope>, StyleModifier>,
49 scope_spans: Spans<u32>,
51 style_spans: Spans<Style>,
52}
53
54impl Layers {
55 pub fn get_merged(&self) -> &Spans<Style> {
56 &self.merged
57 }
58
59 pub fn add_scopes(
61 &mut self,
62 layer: PluginPid,
63 scopes: Vec<Vec<String>>,
64 style_map: &ThemeStyleMap,
65 ) {
66 let _t = trace_block("Layers::AddScopes", &["core"]);
67 if self.create_if_missing(layer).is_err() {
68 return;
69 }
70 self.layers.get_mut(&layer).unwrap().add_scopes(scopes, style_map);
71 }
72
73 pub fn update_all(&mut self, delta: &RopeDelta) {
79 self.merged.apply_shape(delta);
80
81 for layer in self.layers.values_mut() {
82 layer.blank_scopes(delta);
83 }
84 let (iv, _len) = delta.summary();
85 self.resolve_styles(iv);
86 }
87
88 pub fn update_layer(&mut self, layer: PluginPid, iv: Interval, spans: Spans<u32>) {
90 if self.create_if_missing(layer).is_err() {
91 return;
92 }
93 self.layers.get_mut(&layer).unwrap().update_scopes(iv, &spans);
94 self.resolve_styles(iv);
95 }
96
97 pub fn remove_layer(&mut self, layer: PluginPid) -> Option<ScopeLayer> {
100 self.deleted.insert(layer);
101 let layer = self.layers.remove(&layer);
102 if layer.is_some() {
103 let iv_all = Interval::new(0, self.merged.len());
104 self.merged = SpansBuilder::new(self.merged.len()).build();
106 self.resolve_styles(iv_all);
107 }
108 layer
109 }
110
111 pub fn theme_changed(&mut self, style_map: &ThemeStyleMap) {
112 for layer in self.layers.values_mut() {
113 layer.theme_changed(style_map);
114 }
115 self.merged = SpansBuilder::new(self.merged.len()).build();
116 let iv_all = Interval::new(0, self.merged.len());
117 self.resolve_styles(iv_all);
118 }
119
120 fn resolve_styles(&mut self, iv: Interval) {
123 if self.layers.is_empty() {
124 return;
125 }
126 let mut layer_iter = self.layers.values();
127 let mut resolved = layer_iter.next().unwrap().style_spans.subseq(iv);
128
129 for other in layer_iter {
130 let spans = other.style_spans.subseq(iv);
131 assert_eq!(resolved.len(), spans.len());
132 resolved = resolved.merge(&spans, |a, b| match b {
133 Some(b) => a.merge(b),
134 None => a.to_owned(),
135 });
136 }
137 self.merged.edit(iv, resolved);
138 }
139
140 pub fn debug_print_spans(&self, iv: Interval) {
142 for (id, layer) in &self.layers {
143 let spans = layer.scope_spans.subseq(iv);
144 let styles = layer.style_spans.subseq(iv);
145 if spans.iter().next().is_some() {
146 info!("scopes for layer {:?}:", id);
147 for (iv, val) in spans.iter() {
148 info!("{}: {:?}", iv, layer.stack_lookup[*val as usize]);
149 }
150 info!("styles:");
151 for (iv, val) in styles.iter() {
152 info!("{}: {:?}", iv, val);
153 }
154 }
155 }
156 }
157
158 fn create_if_missing(&mut self, layer_id: PluginPid) -> Result<(), ()> {
160 if self.deleted.contains(&layer_id) {
161 return Err(());
162 }
163 if !self.layers.contains_key(&layer_id) {
164 self.layers.insert(layer_id, ScopeLayer::new(self.merged.len()));
165 }
166 Ok(())
167 }
168}
169
170impl Default for ScopeLayer {
171 fn default() -> Self {
172 ScopeLayer {
173 stack_lookup: Vec::new(),
174 style_lookup: Vec::new(),
175 style_cache: HashMap::new(),
176 scope_spans: Spans::default(),
177 style_spans: Spans::default(),
178 }
179 }
180}
181
182impl ScopeLayer {
183 pub fn new(len: usize) -> Self {
184 ScopeLayer {
185 stack_lookup: Vec::new(),
186 style_lookup: Vec::new(),
187 style_cache: HashMap::new(),
188 scope_spans: SpansBuilder::new(len).build(),
189 style_spans: SpansBuilder::new(len).build(),
190 }
191 }
192
193 fn theme_changed(&mut self, style_map: &ThemeStyleMap) {
194 let cur_stacks = self.stack_lookup.clone();
196 self.style_lookup = self.styles_for_stacks(&cur_stacks, style_map);
197 let iv_all = Interval::new(0, self.style_spans.len());
198 self.style_spans = SpansBuilder::new(self.style_spans.len()).build();
199 let scopes = self.scope_spans.clone();
202 self.update_styles(iv_all, &scopes)
203 }
204
205 fn add_scopes(&mut self, scopes: Vec<Vec<String>>, style_map: &ThemeStyleMap) {
206 let mut stacks = Vec::with_capacity(scopes.len());
207 for stack in scopes {
208 let scopes = stack
209 .iter()
210 .map(|s| Scope::new(&s))
211 .filter(|result| match *result {
212 Err(ref err) => {
213 warn!("failed to resolve scope {}\nErr: {:?}", &stack.join(" "), err);
214 false
215 }
216 _ => true,
217 })
218 .map(|s| s.unwrap())
219 .collect::<Vec<_>>();
220 stacks.push(scopes);
221 }
222
223 let mut new_styles = self.styles_for_stacks(stacks.as_slice(), style_map);
224 self.stack_lookup.append(&mut stacks);
225 self.style_lookup.append(&mut new_styles);
226 }
227
228 fn styles_for_stacks(
229 &mut self,
230 stacks: &[Vec<Scope>],
231 style_map: &ThemeStyleMap,
232 ) -> Vec<Style> {
233 let highlighter = style_map.get_highlighter();
235 let mut new_styles = Vec::new();
236
237 for stack in stacks {
238 let mut last_style: Option<StyleModifier> = None;
239 let mut upper_bound_of_last = stack.len() as usize;
240
241 for i in 0..stack.len() - 1 {
244 let prev_range = 0..stack.len() - (i + 1);
245 if let Some(s) = self.style_cache.get(&stack[prev_range]) {
246 last_style = Some(*s);
247 upper_bound_of_last = stack.len() - (i + 1);
248 break;
249 }
250 }
251 let mut base_style_mod = last_style.unwrap_or_default();
252
253 for i in upper_bound_of_last..stack.len() {
255 let style_mod = highlighter.style_mod_for_stack(&stack[0..=i]);
256 base_style_mod = base_style_mod.apply(style_mod);
257 }
258
259 let style = Style::from_syntect_style_mod(&base_style_mod);
260 self.style_cache.insert(stack.clone(), base_style_mod);
261
262 new_styles.push(style);
263 }
264 new_styles
265 }
266
267 fn update_scopes(&mut self, iv: Interval, spans: &Spans<u32>) {
268 self.scope_spans.edit(iv, spans.to_owned());
269 self.update_styles(iv, spans);
270 }
271
272 fn blank_scopes(&mut self, delta: &RopeDelta) {
276 self.style_spans.apply_shape(delta);
277 self.scope_spans.apply_shape(delta);
278 }
279
280 fn update_styles(&mut self, iv: Interval, spans: &Spans<u32>) {
283 let mut sb = SpansBuilder::new(spans.len());
288 let mut spans_iter = spans.iter();
289 let mut prev = spans_iter.next();
290 {
291 let style_eq = |i1: &u32, i2: &u32| {
294 self.style_lookup[*i1 as usize] == self.style_lookup[*i2 as usize]
295 };
296
297 while let Some((p_iv, p_val)) = prev {
298 match spans_iter.next() {
299 Some((n_iv, n_val)) if n_iv.start() == p_iv.end() && style_eq(p_val, n_val) => {
300 prev = Some((p_iv.union(n_iv), p_val));
301 }
302 other => {
303 sb.add_span(p_iv, self.style_lookup[*p_val as usize].to_owned());
304 prev = other;
305 }
306 }
307 }
308 }
309 self.style_spans.edit(iv, sb.build());
310 }
311}