replace LineCache with RangeCache trait
2 files changed, 41 insertions(+), 62 deletions(-)

M cursive/src/views/editor.rs
M src/cache.rs
M cursive/src/views/editor.rs +28 -27
@@ 17,6 17,7 @@ use {
             Duration
         },
         collections::{
+            BTreeMap,
             BTreeSet,
             BinaryHeap
         }

          
@@ 55,7 56,7 @@ use {
             History
         },
         cache::{
-            LineCache,
+            RangeCache,
             CharCache
         },
         trie::{

          
@@ 88,13 89,13 @@ pub struct EditorView {
     click: (Instant, u8),
 
     // rendering
-    lines: LineCache<String>,
-    spans: LineCache<Vec<StyledIndexedSpan>>,
+    lines: BTreeMap<usize, String>,
+    spans: BTreeMap<usize, Vec<StyledIndexedSpan>>,
     highlight_heap: BinaryHeap<LineHighlightState>,
 
     lines_to_highlight: BTreeSet<usize>,
     /// Draw this instead of `spans` if a cursor is on the line.
-    spans_highlight: LineCache<Vec<StyledIndexedSpan>>,
+    spans_highlight: BTreeMap<usize, Vec<StyledIndexedSpan>>,
     /// To draw the empty space after the line.
     line_highlight: Style,
     /// To borrow a `str` of only spaces for drawing behind the line.

          
@@ 264,8 265,8 @@ impl Builder {
             view_width: 0,
             click: (Instant::now(), 0),
 
-            lines: LineCache::new(),
-            spans: LineCache::new(),
+            lines: BTreeMap::new(),
+            spans: BTreeMap::new(),
             highlight_heap: BinaryHeap::new(),
             lines_to_highlight: BTreeSet::new(),
             line_highlight: {

          
@@ 273,7 274,7 @@ impl Builder {
                 self.highlighting.cursor_line(&mut style);
                 style
             },
-            spans_highlight: LineCache::new(),
+            spans_highlight: BTreeMap::new(),
             space: CharCache::new(' '),
             selections: Vec::new(),
             cursors:    Vec::new(),

          
@@ 386,8 387,8 @@ impl View for EditorView {
 
         // Cache the line strings.
         for line_idx in line_idc.clone() {
-            if let None = self.lines.get(line_idx) {
-                self.lines.cache(line_idx,
+            if let None = self.lines.get(&line_idx) {
+                self.lines.insert(line_idx,
                     // allocate owned string
                     self.buf.text().line(line_idx).to_string()
                 );

          
@@ 397,7 398,7 @@ impl View for EditorView {
         { // Cache the line styles.
             let mut current_highlight = None;
             for line_idx in line_idc.clone() {
-                if let None = self.spans.get(line_idx) {
+                if let None = self.spans.get(&line_idx) {
                     let mut highlight = current_highlight.take()
                         .unwrap_or_else(|| {
                             let (start_line_idx, mut highlight) = self.highlight_heap.peek()

          
@@ 406,15 407,15 @@ impl View for EditorView {
 
                             for line_idx in start_line_idx..line_idx {
                                 highlight.parse(
-                                    self.lines.get(line_idx).expect("line not allocated").as_str()
+                                    self.lines.get(&line_idx).expect("line not allocated").as_str()
                                 );
                             }
 
                             highlight
                         });
 
-                    let line = self.lines.get(line_idx).expect("line not allocated").as_str();
-                    self.spans.cache(line_idx,
+                    let line = self.lines.get(&line_idx).expect("line not allocated").as_str();
+                    self.spans.insert(line_idx,
                         // highlight syntax
                         highlight.highlight(line)
                     );

          
@@ 465,8 466,8 @@ impl View for EditorView {
 
                 // highlight lines
                 for line_idx in self.lines_to_highlight.iter() {
-                    if let None = self.spans_highlight.get(*line_idx) {
-                        let spans = self.spans.get(*line_idx)
+                    if let None = self.spans_highlight.get(line_idx) {
+                        let spans = self.spans.get(line_idx)
                             .map(|spans| spans.iter()
                                 .cloned()
                                 .map(|mut span| {

          
@@ 477,7 478,7 @@ impl View for EditorView {
                                 .collect())
                             .unwrap_or_else(|| vec![]);
 
-                        self.spans_highlight.cache(*line_idx, spans);
+                        self.spans_highlight.insert(*line_idx, spans);
                     }
                 }
             } else {

          
@@ 540,8 541,8 @@ impl View for EditorView {
 
                     let mut style: Style = ColorStyle::primary().into(); // fallback
                     // find style at span under cursor
-                    if let Some(spans) = self.spans.get(line_idx) {
-                        let line = self.lines.get(line_idx).expect("line not cached");
+                    if let Some(spans) = self.spans.get(&line_idx) {
+                        let line = self.lines.get(&line_idx).expect("line not cached");
 
                         let mut x_acc = 0;
                         for span in spans.iter() {

          
@@ 606,13 607,13 @@ impl View for EditorView {
          * Since line highlighting always affects the whole line,
          * we can also do that here before rendering other stuff … */
         self.scrollbase.draw(printer, |printer, line_idx| {
-            let line = self.lines.get(line_idx).expect("line not allocated in draw()").as_str();
+            let line = self.lines.get(&line_idx).expect("line not allocated in draw()").as_str();
 
             let highlight_line = self.lines_to_highlight.contains(&line_idx);
             let spans = if highlight_line {
-                self.spans_highlight.get(line_idx).expect("line not highlighted in draw()")
+                self.spans_highlight.get(&line_idx).expect("line not highlighted in draw()")
             } else {
-                self.spans          .get(line_idx).expect("line not styled in draw()")
+                self.spans          .get(&line_idx).expect("line not styled in draw()")
             };
 
             let mut x = 0;

          
@@ 662,7 663,7 @@ impl View for EditorView {
         // `span`: (x_range, line_idx)
         let print_span_text = |printer: &Printer, span: (Range<usize>, usize)| {
             let (x_range, line_idx) = span;
-            let line = self.lines.get(line_idx)
+            let line = self.lines.get(&line_idx)
                 .map(|s| s.as_str())
                 .unwrap_or(" ");
 

          
@@ 742,14 743,14 @@ impl View for EditorView {
                             for event in tx.0.iter() {
                                 self.buf.handle((**event).clone());
                             }
-                            self.cur.handle_cur(&self.buf, cursor::CursorEvent::Jump(tx.1.to_vec()));
+                            self.cur.handle_cur(&self.buf, CursorEvent::Jump(tx.1.to_vec()));
                             EventResult::Consumed(None)
                         }
                         Err(_) => EventResult::Ignored
                     }
                     HistoryCmd::Redo => match self.hist.redo() {
                         Ok(ref tx) => {
-                            self.cur.handle_cur(&self.buf, cursor::CursorEvent::Jump(tx.1.to_vec()));
+                            self.cur.handle_cur(&self.buf, CursorEvent::Jump(tx.1.to_vec()));
                             for event in tx.0.iter() {
                                 self.buf.handle((**event).clone());
                             }

          
@@ 902,9 903,9 @@ impl View for EditorView {
                         .min(self.buf.text().len_lines().saturating_sub(1))
                 )
                 .unwrap();
-            self.lines          .invalidate_lines_from(first_damage..);
-            self.spans          .invalidate_lines_from(first_damage..);
-            self.spans_highlight.invalidate_lines_from(first_damage..);
+            self.lines          .invalidate_from(first_damage..);
+            self.spans          .invalidate_from(first_damage..);
+            self.spans_highlight.invalidate_from(first_damage..);
             while self.highlight_heap.peek()
                 .map(|x| x.line_idx >= first_damage)
                 .unwrap_or(false)

          
M src/cache.rs +13 -35
@@ 1,46 1,24 @@ 
 use std::ops::RangeFrom;
 use std::collections::BTreeMap;
 
-pub struct LineCache<T> {
-    lines: BTreeMap<usize, T>
+pub trait RangeCache {
+    /// Returns whether the index was cached.
+    fn invalidate(&mut self, idx: usize) -> bool;
+
+    /// Returns whether at least one index was cached.
+    // TODO name invalidate_range() instead with RangeArgument once stable
+    fn invalidate_from(&mut self, idc: RangeFrom<usize>) -> bool;
 }
 
-impl<T> LineCache<T> {
-    pub fn new() -> Self {
-        Self {
-            lines: BTreeMap::new()
-        }
-    }
-
-    #[allow(dead_code)]
-    pub fn len(&self) -> usize {
-        self.lines.len()
+impl<T> RangeCache for BTreeMap<usize, T> {
+    fn invalidate(&mut self, idx: usize) -> bool {
+        self.remove(&idx).is_some()
     }
 
-    #[allow(dead_code)]
-    pub fn is_empty(&self) -> bool {
-        self.lines.len() == 0
-    }
-
-    pub fn cache(&mut self, line_idx: usize, line: T) {
-        self.lines.insert(line_idx, line);
-    }
-
-    pub fn get(&self, line_idx: usize) -> Option<&T> {
-        self.lines.get(&line_idx)
-    }
-
-    /// Returns whether the line was cached.
-    pub fn invalidate_line(&mut self, line_idx: usize) -> bool {
-        self.lines.remove(&line_idx).is_some()
-    }
-
-    /// Returns whether at least one line was cached.
-    // TODO name invalidate_lines() instead with RangeArgument once stable
-    pub fn invalidate_lines_from(&mut self, line_idc: RangeFrom<usize>) -> bool {
+    fn invalidate_from(&mut self, idc: RangeFrom<usize>) -> bool {
         let mut changed = false;
-        for line_idx in line_idc.start..=*self.lines.keys().max().unwrap_or(&line_idc.start) {
-            changed |= self.invalidate_line(line_idx);
+        for line_idx in idc.start..=*self.keys().max().unwrap_or(&idc.start) {
+            changed |= self.invalidate(line_idx);
         }
         changed
     }