outline: Add preview pane to buffer symbols (#61069)

# Objective

- Implement preview pane for buffer symbols, similar to #59863 

## Showcase
### Before 
<img width="4512" height="2980" alt="CleanShot 2026-07-15 at 23 25
19@2x"
src="https://github.com/user-attachments/assets/443f150a-bb67-4bac-ba4a-f8f299554470"
/>

### After
<img width="4512" height="2980" alt="CleanShot 2026-07-15 at 23 19
09@2x"
src="https://github.com/user-attachments/assets/0fd4be89-d25e-4052-8de0-3a9a5a5908f9"
/>


---

Release Notes:

- Added a preview pane to the buffer symbols picker
This commit is contained in:
d0 authored and GitHub committed 2026-07-17 11:41:08 +00:00
1 parent fc11498fb4
commit ec06066302
3 files changed
+36 -3

No files matched your search

Generated
+1
View File
@@ -12560,6 +12560,7 @@ dependencies = [
"lsp",
"menu",
"picker",
"picker_preview",
"project",
"rope",
"serde_json",
+1
View File
@@ -18,6 +18,7 @@ fuzzy_nucleo.workspace = true
gpui.workspace = true
language.workspace = true
picker.workspace = true
picker_preview.workspace = true
settings.workspace = true
theme.workspace = true
theme_settings.workspace = true
+34 -3
View File
@@ -10,8 +10,8 @@ use gpui::{
ParentElement, Point, Rems, Render, Styled, StyledText, Task, TextStyle, WeakEntity, Window,
div, rems,
};
use language::{Outline, OutlineItem, OutlineSearchEntry};
use picker::{Picker, PickerDelegate};
use language::{OffsetRangeExt, Outline, OutlineItem, OutlineSearchEntry};
use picker::{MatchLocation, Picker, PickerDelegate, PreviewUpdate};
use settings::Settings;
use theme::ActiveTheme;
use theme_settings::ThemeSettings;
@@ -176,9 +176,16 @@ impl OutlineView {
window: &mut Window,
cx: &mut Context<Self>,
) -> OutlineView {
let project = editor.read(cx).project().cloned();
let delegate = OutlineViewDelegate::new(cx.entity().downgrade(), outline, editor, cx);
let picker = cx.new(|cx| {
Picker::uniform_list(delegate, window, cx)
let picker = if let Some(project) = project {
let preview = picker_preview::editor_preview(project, window, cx);
Picker::uniform_list_with_preview(delegate, preview, window, cx)
} else {
Picker::uniform_list(delegate, window, cx)
};
picker
.max_height(Rems::from_pixels(
window.viewport_size().height * 0.75,
window,
@@ -293,6 +300,30 @@ impl PickerDelegate for OutlineViewDelegate {
self.set_selected_index(ix, true, cx);
}
fn try_get_preview_data_for_match(&self, cx: &App) -> Option<PreviewUpdate> {
let selected_match = self.matches.get(self.selected_match_index)?;
let outline_item = self.outline.items.get(selected_match.candidate_id())?;
let multi_buffer = self.active_editor.read(cx).buffer().clone();
let (buffer, start) = multi_buffer
.read(cx)
.text_anchor_for_position(outline_item.selection_range.start, cx)?;
let (end_buffer, end) = multi_buffer
.read(cx)
.text_anchor_for_position(outline_item.selection_range.end, cx)?;
if buffer != end_buffer {
return None;
}
let range = (start..end).to_offset(&buffer.read(cx).text_snapshot());
Some(PreviewUpdate::from_buffer(
buffer,
MatchLocation {
anchor_range: start..end,
range,
},
))
}
fn update_matches(
&mut self,
query: String,