Include highlighting runs in Outline

This commit is contained in:
Max Brunsfeld 2022-01-13 14:46:15 -08:00
parent 3e1c559b2d
commit 7913a1ea22
5 changed files with 36 additions and 10 deletions

View file

@ -1698,9 +1698,9 @@ impl MultiBufferSnapshot {
}) })
} }
pub fn outline(&self) -> Option<Outline<Anchor>> { pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
let buffer = self.as_singleton()?; let buffer = self.as_singleton()?;
let outline = buffer.outline()?; let outline = buffer.outline(theme)?;
let excerpt_id = &self.excerpts.iter().next().unwrap().id; let excerpt_id = &self.excerpts.iter().next().unwrap().id;
Some(Outline::new( Some(Outline::new(
outline outline
@ -1711,6 +1711,7 @@ impl MultiBufferSnapshot {
range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start) range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end), ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
text: item.text, text: item.text,
text_runs: item.text_runs,
name_ranges: item.name_ranges, name_ranges: item.name_ranges,
}) })
.collect(), .collect(),

View file

@ -1835,7 +1835,7 @@ impl BufferSnapshot {
} }
} }
pub fn outline(&self) -> Option<Outline<Anchor>> { pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
let tree = self.tree.as_ref()?; let tree = self.tree.as_ref()?;
let grammar = self let grammar = self
.language .language
@ -1849,6 +1849,8 @@ impl BufferSnapshot {
TextProvider(self.as_rope()), TextProvider(self.as_rope()),
); );
let mut chunks = self.chunks(0..self.len(), theme);
let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?; let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?;
let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?; let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?;
let context_capture_ix = grammar let context_capture_ix = grammar
@ -1863,6 +1865,7 @@ impl BufferSnapshot {
let range = item_node.start_byte()..item_node.end_byte(); let range = item_node.start_byte()..item_node.end_byte();
let mut text = String::new(); let mut text = String::new();
let mut name_ranges = Vec::new(); let mut name_ranges = Vec::new();
let mut text_runs = Vec::new();
for capture in mat.captures { for capture in mat.captures {
let node_is_name; let node_is_name;
@ -1890,7 +1893,22 @@ impl BufferSnapshot {
name_ranges.push(start..end); name_ranges.push(start..end);
} }
text.extend(self.text_for_range(range));
let mut offset = range.start;
chunks.seek(offset);
while let Some(mut chunk) = chunks.next() {
if chunk.text.len() > range.end - offset {
chunk.text = &chunk.text[0..(range.end - offset)];
offset = range.end;
} else {
offset += chunk.text.len();
}
text_runs.push((chunk.text.len(), chunk.highlight_style));
text.push_str(chunk.text);
if offset >= range.end {
break;
}
}
} }
while stack.last().map_or(false, |prev_range| { while stack.last().map_or(false, |prev_range| {
@ -1905,6 +1923,7 @@ impl BufferSnapshot {
range: self.anchor_after(range.start)..self.anchor_before(range.end), range: self.anchor_after(range.start)..self.anchor_before(range.end),
text, text,
name_ranges: name_ranges.into_boxed_slice(), name_ranges: name_ranges.into_boxed_slice(),
text_runs,
}) })
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -1,5 +1,5 @@
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::executor::Background; use gpui::{executor::Background, fonts::HighlightStyle};
use std::{ops::Range, sync::Arc}; use std::{ops::Range, sync::Arc};
#[derive(Debug)] #[derive(Debug)]
@ -14,6 +14,7 @@ pub struct OutlineItem<T> {
pub range: Range<T>, pub range: Range<T>,
pub text: String, pub text: String,
pub name_ranges: Box<[Range<u32>]>, pub name_ranges: Box<[Range<u32>]>,
pub text_runs: Vec<(usize, Option<HighlightStyle>)>,
} }
impl<T> Outline<T> { impl<T> Outline<T> {

View file

@ -332,7 +332,7 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx)); let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
let outline = buffer let outline = buffer
.read_with(&cx, |buffer, _| buffer.snapshot().outline()) .read_with(&cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap(); .unwrap();
assert_eq!( assert_eq!(

View file

@ -167,11 +167,16 @@ impl OutlineView {
.to_any() .to_any()
.downcast::<Editor>() .downcast::<Editor>()
.unwrap(); .unwrap();
let buffer = editor.read(cx).buffer().read(cx).read(cx).outline(); let settings = workspace.settings();
let buffer = editor
.read(cx)
.buffer()
.read(cx)
.read(cx)
.outline(Some(settings.borrow().theme.editor.syntax.as_ref()));
if let Some(outline) = buffer { if let Some(outline) = buffer {
workspace.toggle_modal(cx, |cx, workspace| { workspace.toggle_modal(cx, |cx, _| {
let view = let view = cx.add_view(|cx| OutlineView::new(outline, editor, settings, cx));
cx.add_view(|cx| OutlineView::new(outline, editor, workspace.settings(), cx));
cx.subscribe(&view, Self::on_event).detach(); cx.subscribe(&view, Self::on_event).detach();
view view
}) })