diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 05294c1419..70a3ad82f4 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1698,9 +1698,9 @@ impl MultiBufferSnapshot { }) } - pub fn outline(&self) -> Option> { + pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option> { let buffer = self.as_singleton()?; - let outline = buffer.outline()?; + let outline = buffer.outline(theme)?; let excerpt_id = &self.excerpts.iter().next().unwrap().id; Some(Outline::new( outline @@ -1711,6 +1711,7 @@ impl MultiBufferSnapshot { range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start) ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end), text: item.text, + text_runs: item.text_runs, name_ranges: item.name_ranges, }) .collect(), diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index e699023d84..6a4f3bebd8 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1835,7 +1835,7 @@ impl BufferSnapshot { } } - pub fn outline(&self) -> Option> { + pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option> { let tree = self.tree.as_ref()?; let grammar = self .language @@ -1849,6 +1849,8 @@ impl BufferSnapshot { 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 name_capture_ix = grammar.outline_query.capture_index_for_name("name")?; let context_capture_ix = grammar @@ -1863,6 +1865,7 @@ impl BufferSnapshot { let range = item_node.start_byte()..item_node.end_byte(); let mut text = String::new(); let mut name_ranges = Vec::new(); + let mut text_runs = Vec::new(); for capture in mat.captures { let node_is_name; @@ -1890,7 +1893,22 @@ impl BufferSnapshot { 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| { @@ -1905,6 +1923,7 @@ impl BufferSnapshot { range: self.anchor_after(range.start)..self.anchor_before(range.end), text, name_ranges: name_ranges.into_boxed_slice(), + text_runs, }) }) .collect::>(); diff --git a/crates/language/src/outline.rs b/crates/language/src/outline.rs index 76b7462a97..c0b12b1210 100644 --- a/crates/language/src/outline.rs +++ b/crates/language/src/outline.rs @@ -1,5 +1,5 @@ use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::executor::Background; +use gpui::{executor::Background, fonts::HighlightStyle}; use std::{ops::Range, sync::Arc}; #[derive(Debug)] @@ -14,6 +14,7 @@ pub struct OutlineItem { pub range: Range, pub text: String, pub name_ranges: Box<[Range]>, + pub text_runs: Vec<(usize, Option)>, } impl Outline { diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 1622ca92a9..2c3b0e62c8 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -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 outline = buffer - .read_with(&cx, |buffer, _| buffer.snapshot().outline()) + .read_with(&cx, |buffer, _| buffer.snapshot().outline(None)) .unwrap(); assert_eq!( diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 3eb8374a77..36fe071b45 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -167,11 +167,16 @@ impl OutlineView { .to_any() .downcast::() .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 { - workspace.toggle_modal(cx, |cx, workspace| { - let view = - cx.add_view(|cx| OutlineView::new(outline, editor, workspace.settings(), cx)); + workspace.toggle_modal(cx, |cx, _| { + let view = cx.add_view(|cx| OutlineView::new(outline, editor, settings, cx)); cx.subscribe(&view, Self::on_event).detach(); view })