From ec060663022f619b5d8db6dd2bd73bc7f7d5a749 Mon Sep 17 00:00:00 2001 From: d0 <35865489+neiii@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:41:08 +0100 Subject: [PATCH] outline: Add preview pane to buffer symbols (#61069) # Objective - Implement preview pane for buffer symbols, similar to #59863 ## Showcase ### Before CleanShot 2026-07-15 at 23 25
19@2x ### After CleanShot 2026-07-15 at 23 19
09@2x --- Release Notes: - Added a preview pane to the buffer symbols picker --- Cargo.lock | 1 + crates/outline/Cargo.toml | 1 + crates/outline/src/outline.rs | 37 ++++++++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1094fced2c..3775ab6b3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12560,6 +12560,7 @@ dependencies = [ "lsp", "menu", "picker", + "picker_preview", "project", "rope", "serde_json", diff --git a/crates/outline/Cargo.toml b/crates/outline/Cargo.toml index 8b49b5a287..ba661b36f9 100644 --- a/crates/outline/Cargo.toml +++ b/crates/outline/Cargo.toml @@ -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 diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index ffd11e3197..0f22226f89 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -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, ) -> 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 { + 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,