diff --git a/cli/src/highlight.rs b/cli/src/highlight.rs index 6cd19392..55ef4bc2 100644 --- a/cli/src/highlight.rs +++ b/cli/src/highlight.rs @@ -209,7 +209,7 @@ pub fn ansi( HighlightEvent::ScopeStart(s) => { scope_stack.push(s); } - HighlightEvent::ScopeEnd(_) => { + HighlightEvent::ScopeEnd => { scope_stack.pop(); } } diff --git a/cli/src/tests/highlight_test.rs b/cli/src/tests/highlight_test.rs index 6e07ab4a..57f61e16 100644 --- a/cli/src/tests/highlight_test.rs +++ b/cli/src/tests/highlight_test.rs @@ -162,8 +162,7 @@ fn to_token_vector<'a>( )? { match event { HighlightEvent::ScopeStart(s) => scopes.push(s), - HighlightEvent::ScopeEnd(s) => { - assert_eq!(*scopes.last().unwrap(), s); + HighlightEvent::ScopeEnd => { scopes.pop(); } HighlightEvent::Source(s) => { diff --git a/highlight/src/lib.rs b/highlight/src/lib.rs index bbe0b424..7ec186d8 100644 --- a/highlight/src/lib.rs +++ b/highlight/src/lib.rs @@ -96,7 +96,7 @@ where pub enum HighlightEvent<'a> { Source(&'a str), ScopeStart(Scope), - ScopeEnd(Scope), + ScopeEnd, } #[derive(Debug, Deserialize)] @@ -565,10 +565,7 @@ where .parse(self.source, None) .expect("Failed to parse"); let layer = Layer::new(self.source, tree, property_sheet, ranges); - match self - .layers - .binary_search_by_key(&(layer.offset(), 1), |l| (l.offset(), 0)) - { + match self.layers.binary_search_by(|l| l.cmp(&layer)) { Ok(i) | Err(i) => self.layers.insert(i, layer), }; } @@ -625,7 +622,7 @@ impl<'a, T: Fn(&str) -> Option<(Language, &'a PropertySheet)>> Itera } scope_event = if self.layers[0].at_node_end { - Some(HighlightEvent::ScopeEnd(scope)) + Some(HighlightEvent::ScopeEnd) } else { Some(HighlightEvent::ScopeStart(scope)) }; @@ -638,7 +635,7 @@ impl<'a, T: Fn(&str) -> Option<(Language, &'a PropertySheet)>> Itera // to re-sort the layers. If the cursor is already at the end of its syntax tree, // remove it. if self.layers[0].advance() { - self.layers.sort_unstable_by_key(|layer| layer.offset()); + self.layers.sort_unstable_by(|a, b| a.cmp(&b)); } else { self.layers.remove(0); } @@ -676,6 +673,15 @@ impl<'a> Layer<'a> { } } + fn cmp(&self, other: &Layer) -> cmp::Ordering { + // Events are ordered primarily by their position in the document. But if + // one scope starts at a given position and another scope ends at that + // same position, return the scope end event before the scope start event. + self.offset() + .cmp(&other.offset()) + .then_with(|| other.at_node_end.cmp(&self.at_node_end)) + } + fn offset(&self) -> usize { if self.at_node_end { self.cursor.node().end_byte() @@ -770,8 +776,8 @@ where scopes.push(s); renderer.start_scope(s); } - HighlightEvent::ScopeEnd(s) => { - assert_eq!(scopes.pop(), Some(s)); + HighlightEvent::ScopeEnd => { + scopes.pop(); renderer.end_scope(); } HighlightEvent::Source(src) => {