diff --git a/projects/code-span/src/view/iter.rs b/projects/code-span/src/view/iter.rs index 4e2bb5e..5be1bff 100644 --- a/projects/code-span/src/view/iter.rs +++ b/projects/code-span/src/view/iter.rs @@ -1,6 +1,6 @@ -use std::{collections::BTreeSet, ops::Range}; +use std::ops::Range; -use crate::view::{CodeRender, CodeView, InnerSpan}; +use crate::view::{CodeRender, CodeView, IntervalRepr}; /// # Arguments /// @@ -17,7 +17,7 @@ use crate::view::{CodeRender, CodeView, InnerSpan}; #[derive(Debug)] pub struct CodeRendered<'r, 'i, 's> { text: &'i str, - iter: std::collections::btree_map::Iter<'r, usize, InnerSpan<'s>>, + iter: std::collections::btree_map::Iter<'r, usize, IntervalRepr<'s>>, } impl<'r, 'i, 's> IntoIterator for &'r CodeRender<'i, 's> { @@ -25,7 +25,7 @@ impl<'r, 'i, 's> IntoIterator for &'r CodeRender<'i, 's> { type IntoIter = CodeRendered<'r, 'i, 's>; fn into_iter(self) -> Self::IntoIter { - CodeRendered { text: self.text, iter: self.interval.iter() } + CodeRendered { text: self.text, iter: self.intervals.iter() } } } diff --git a/projects/code-span/src/view/mod.rs b/projects/code-span/src/view/mod.rs index 4bc83bf..d435ca1 100644 --- a/projects/code-span/src/view/mod.rs +++ b/projects/code-span/src/view/mod.rs @@ -11,62 +11,78 @@ pub struct CodeRender<'i, 's> { /// raw text text: &'i str, /// start -> (styles , end) - interval: BTreeMap>, + intervals: BTreeMap>, } #[derive(Clone, Debug)] -struct InnerSpan<'s> { +struct IntervalRepr<'s> { styles: BTreeSet<&'s str>, end: usize, } -#[derive(Copy, Clone, Debug)] -pub struct CodeView<'r, 'i, 's> { - pub text: &'i str, - pub kind: &'r BTreeSet<&'s str>, -} - impl<'i, 's> CodeRender<'i, 's> { pub fn new(text: &'i str) -> Self { let mut interval = BTreeMap::new(); - interval.insert(0, InnerSpan { styles: Default::default(), end: text.len() }); - Self { text, interval } + interval.insert(0, IntervalRepr { styles: Default::default(), end: text.len() }); + Self { text, intervals: interval } } pub fn get_span<'r>(&'r mut self, offset: usize) -> Option> { - let (start, span) = self.interval.range(offset..).next()?; + let (start, span) = self.intervals.range(offset..).next()?; let range = Range { start: *start, end: span.end }; let text = self.text.get(range.clone())?; Some(CodeView { text, kind: &span.styles }) } pub fn mark_span(&mut self, span: Range, style: &'s str) { - match self.interval.get(&span.start) { + match self.intervals.get(&span.start) { Some(_) => { - match self.interval.get(&span.end) { - // easy case, no need modifier old interval - Some(_) => self.interval.range_mut(span).for_each(|(_, inner)| { - inner.styles.insert(style); - }), + match self.intervals.get(&span.end) { + // simple case, no need change old interval + Some(_) => self.mark_span_unchecked(span, style), + // remark end position None => { - todo!() + let (_, last_span) = self.intervals.range(span.end..).next().unwrap(); + let new_end = last_span.end; + let new_styles = last_span.styles.clone(); + self.intervals.remove(&span.end); + self.intervals.entry(span.end).or_insert(IntervalRepr { styles: new_styles, end: new_end }); + self.mark_span_unchecked(span, style) } } } None => { - // 修改前一个区间的结束位置 - self.interval.range_mut(..span.start).next_back().map(|(_, v)| { - v.end = span.start; - }); - todo!() + // truncate the previous span + let prev_span = self.intervals.range_mut(..span.start).next_back(); + if let Some((_, prev_inner)) = prev_span { + prev_inner.end = span.start; + } + // insert start position + let (_, next_span) = self.intervals.range(span.start..).next().unwrap(); + let new_end = next_span.end; + let new_styles = next_span.styles.clone(); + self.intervals.remove(&span.start); + self.intervals.entry(span.start).or_insert(IntervalRepr { styles: new_styles, end: new_end }); + self.mark_span_unchecked(span, style) } } } + fn mark_span_unchecked(&mut self, span: Range, style: &'s str) { + for (_, inner) in self.intervals.range_mut(span) { + inner.styles.insert(style); + } + } } #[test] fn main() { let mut code_render = CodeRender::new("public class Main {}"); - code_render.mark_span(0..17, "class"); - code_render.mark_span(0..3, "keyword"); + code_render.mark_span(0..6, "keyword"); code_render.mark_span(7..12, "keyword"); + code_render.mark_span(13..17, "class"); println!("{:#?}", code_render); } + +#[derive(Copy, Clone, Debug)] +pub struct CodeView<'r, 'i, 's> { + pub text: &'i str, + pub kind: &'r BTreeSet<&'s str>, +}