Support highlighted_text_for_range for buffers without a language

This commit is contained in:
Antonio Scandurra 2021-05-24 16:47:13 +02:00
parent 4b8805bad2
commit d1788c69ab

View file

@ -753,16 +753,18 @@ impl Buffer {
} }
pub fn highlighted_text_for_range<T: ToOffset>(&self, range: Range<T>) -> HighlightedChunks { pub fn highlighted_text_for_range<T: ToOffset>(&self, range: Range<T>) -> HighlightedChunks {
let start = range.start.to_offset(self);
let end = range.end.to_offset(self);
let chunks = self.visible_text.chunks_in_range(start..end);
if let (Some(language), Some((tree, _))) = (&self.language, self.tree.as_ref()) { if let (Some(language), Some((tree, _))) = (&self.language, self.tree.as_ref()) {
let mut cursor = self let mut cursor = self
.query_cursor .query_cursor
.lock() .lock()
.take() .take()
.unwrap_or_else(|| QueryCursor::new()); .unwrap_or_else(|| QueryCursor::new());
let start = range.start.to_offset(self);
let end = range.end.to_offset(self);
cursor.set_byte_range(start, end); cursor.set_byte_range(start, end);
let chunks = self.visible_text.chunks_in_range(start..end);
let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) }; let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
let captures = cursor_ref.captures( let captures = cursor_ref.captures(
&language.highlight_query, &language.highlight_query,
@ -771,15 +773,22 @@ impl Buffer {
); );
HighlightedChunks { HighlightedChunks {
captures: captures.peekable(),
chunks,
stack: Default::default(),
range: start..end, range: start..end,
query_cursor: Some(cursor), chunks,
highlights: Some(Highlights {
captures: captures.peekable(),
stack: Default::default(),
cursor,
}),
buffer: self, buffer: self,
} }
} else { } else {
todo!() HighlightedChunks {
range: start..end,
chunks,
highlights: None,
buffer: self,
}
} }
} }
@ -2189,27 +2198,33 @@ impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
} }
} }
pub struct HighlightedChunks<'a> { struct Highlights<'a> {
chunks: Chunks<'a>,
captures: iter::Peekable<tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>>, captures: iter::Peekable<tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>>,
stack: Vec<(usize, usize)>, stack: Vec<(usize, usize)>,
cursor: QueryCursor,
}
pub struct HighlightedChunks<'a> {
range: Range<usize>, range: Range<usize>,
query_cursor: Option<QueryCursor>, chunks: Chunks<'a>,
highlights: Option<Highlights<'a>>,
buffer: &'a Buffer, buffer: &'a Buffer,
} }
impl<'a> HighlightedChunks<'a> { impl<'a> HighlightedChunks<'a> {
pub fn seek(&mut self, offset: usize) { pub fn seek(&mut self, offset: usize) {
self.range.start = offset;
self.chunks.seek(self.range.start);
if let Some(highlights) = self.highlights.as_mut() {
let language = self.buffer.language.as_ref().unwrap(); let language = self.buffer.language.as_ref().unwrap();
let tree = &self.buffer.tree.as_ref().unwrap().0; let tree = &self.buffer.tree.as_ref().unwrap().0;
let mut cursor = self.query_cursor.as_mut().unwrap(); let cursor_ref =
let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) }; unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut highlights.cursor) };
highlights
self.stack.clear(); .cursor
self.range.start = offset; .set_byte_range(self.range.start, self.range.end);
self.chunks.seek(offset); highlights.stack.clear();
cursor.set_byte_range(self.range.start, self.range.end); highlights.captures = cursor_ref
self.captures = cursor_ref
.captures( .captures(
&language.highlight_query, &language.highlight_query,
tree.root_node(), tree.root_node(),
@ -2217,6 +2232,7 @@ impl<'a> HighlightedChunks<'a> {
) )
.peekable(); .peekable();
} }
}
pub fn offset(&self) -> usize { pub fn offset(&self) -> usize {
self.range.start self.range.start
@ -2227,24 +2243,28 @@ impl<'a> Iterator for HighlightedChunks<'a> {
type Item = (&'a str, Option<usize>); type Item = (&'a str, Option<usize>);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some((parent_capture_end, _)) = self.stack.last() { let mut next_capture_start = usize::MAX;
if let Some(highlights) = self.highlights.as_mut() {
while let Some((parent_capture_end, _)) = highlights.stack.last() {
if *parent_capture_end <= self.range.start { if *parent_capture_end <= self.range.start {
self.stack.pop(); highlights.stack.pop();
} else { } else {
break; break;
} }
} }
let mut next_capture_start = usize::MAX; while let Some((mat, capture_ix)) = highlights.captures.peek() {
while let Some((mat, capture_ix)) = self.captures.peek() {
let capture = mat.captures[*capture_ix as usize]; let capture = mat.captures[*capture_ix as usize];
if self.range.start < capture.node.start_byte() { if self.range.start < capture.node.start_byte() {
next_capture_start = capture.node.start_byte(); next_capture_start = capture.node.start_byte();
break; break;
} else { } else {
self.stack highlights
.stack
.push((capture.node.end_byte(), capture.index as usize)); .push((capture.node.end_byte(), capture.index as usize));
self.captures.next().unwrap(); highlights.captures.next().unwrap();
}
} }
} }
@ -2252,7 +2272,9 @@ impl<'a> Iterator for HighlightedChunks<'a> {
let chunk_start = self.range.start; let chunk_start = self.range.start;
let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start); let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
let mut capture_ix = None; let mut capture_ix = None;
if let Some((parent_capture_end, parent_capture_ix)) = self.stack.last() { if let Some((parent_capture_end, parent_capture_ix)) =
self.highlights.as_ref().and_then(|h| h.stack.last())
{
chunk_end = chunk_end.min(*parent_capture_end); chunk_end = chunk_end.min(*parent_capture_end);
capture_ix = Some(*parent_capture_ix); capture_ix = Some(*parent_capture_ix);
} }
@ -2273,10 +2295,11 @@ impl<'a> Iterator for HighlightedChunks<'a> {
impl<'a> Drop for HighlightedChunks<'a> { impl<'a> Drop for HighlightedChunks<'a> {
fn drop(&mut self) { fn drop(&mut self) {
let query_cursor = self.query_cursor.take().unwrap(); if let Some(highlights) = self.highlights.take() {
let mut buffer_cursor = self.buffer.query_cursor.lock(); let mut buffer_cursor = self.buffer.query_cursor.lock();
if buffer_cursor.is_none() { if buffer_cursor.is_none() {
*buffer_cursor = Some(query_cursor); *buffer_cursor = Some(highlights.cursor);
}
} }
} }
} }