mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 19:10:24 +00:00
Display buffer/project search entries in the outline panel (#16589)
Prototypes a way to display new entities in the outline panel, making it less outline. The design is not final and might be adjusted, but the workflow seems to be solid enough to keep and iron it out. * Now, when any project search buffer is activated (multi buffer mode), or buffer search is open (singleton buffer mode, but is available for search usages multi buffer too — in that case buffer search overrides multi buffer's contents display), outline panel displays all search matches instead of the outline items. Outline items are not displayed at all during those cases, unless the buffer search is closed, or a new buffer gets opened, of an active buffer search matches zero items. https://github.com/user-attachments/assets/4a3e4faa-7f75-4522-96bb-3761872c753a * For the multi buffer mode, search matches are grouped under directories and files, same as outline items ![Screenshot 2024-08-21 at 14 55 01](https://github.com/user-attachments/assets/6dac75e4-be4e-4338-917b-37a32c285b71) * For buffer search , search matches are displayed one under another ![image](https://github.com/user-attachments/assets/9efcff85-d4c7-4462-9ef5-f76b08e59f20) For both cases, the entire match line is taken and rendered, with the hover tooltip showing the line number. So far it does not look very bad, but I am certain there are bad cases with long lines and bad indents where it looks not optimal — this part most probably will be redesigned after some trial. Or, maybe, it's ok to leave the current state if the horizontal scrollbar is added? Clicking the item navigates to the item's position in the editor. Search item lines are also possible to filter with the outline panel's filter input. * Inline panel is now possible to "pin" to track a currently active editor, to display outlines/search results for that editor even if another item is activated afterwards: ![image](https://github.com/user-attachments/assets/75fb78c3-0e5f-47b4-ba3a-485c71d7e342) This is useful in combination with project search results display: now it's possible to leave the search results pinned in the outline panel and jump to every search result and back. If the item the panel was pinned to gets closed, the panel gets back to its regular state, showing outlines/search results for a currently active editor. Release Notes: - Added a way to display buffer/project search entries in the outline panel
This commit is contained in:
parent
dd8d52f4f4
commit
28271a9a36
12 changed files with 1328 additions and 605 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -7387,9 +7387,11 @@ dependencies = [
|
|||
"menu",
|
||||
"project",
|
||||
"schemars",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"theme",
|
||||
"util",
|
||||
"workspace",
|
||||
"worktree",
|
||||
|
|
1
assets/icons/pin.svg
Normal file
1
assets/icons/pin.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-pin"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>
|
After Width: | Height: | Size: 447 B |
1
assets/icons/unpin.svg
Normal file
1
assets/icons/unpin.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-pin-off"><path d="M12 17v5"/><path d="M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89"/><path d="m2 2 20 20"/><path d="M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11"/></svg>
|
After Width: | Height: | Size: 401 B |
|
@ -524,7 +524,7 @@
|
|||
"ctrl-alt-c": "outline_panel::CopyPath",
|
||||
"alt-ctrl-shift-c": "outline_panel::CopyRelativePath",
|
||||
"alt-ctrl-r": "outline_panel::RevealInFileManager",
|
||||
"space": "outline_panel::Open",
|
||||
"space": ["outline_panel::Open", { "change_selection": false }],
|
||||
"shift-down": "menu::SelectNext",
|
||||
"shift-up": "menu::SelectPrev"
|
||||
}
|
||||
|
|
|
@ -536,7 +536,7 @@
|
|||
"cmd-alt-c": "outline_panel::CopyPath",
|
||||
"alt-cmd-shift-c": "outline_panel::CopyRelativePath",
|
||||
"alt-cmd-r": "outline_panel::RevealInFileManager",
|
||||
"space": "outline_panel::Open",
|
||||
"space": ["outline_panel::Open", { "change_selection": false }],
|
||||
"shift-down": "menu::SelectNext",
|
||||
"shift-up": "menu::SelectPrev"
|
||||
}
|
||||
|
|
|
@ -1144,16 +1144,37 @@ pub(crate) enum BufferSearchHighlights {}
|
|||
impl SearchableItem for Editor {
|
||||
type Match = Range<Anchor>;
|
||||
|
||||
fn get_matches(&self, _: &mut WindowContext) -> Vec<Range<Anchor>> {
|
||||
self.background_highlights
|
||||
.get(&TypeId::of::<BufferSearchHighlights>())
|
||||
.map_or(Vec::new(), |(_color, ranges)| {
|
||||
ranges.iter().map(|range| range.clone()).collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.clear_background_highlights::<BufferSearchHighlights>(cx);
|
||||
if self
|
||||
.clear_background_highlights::<BufferSearchHighlights>(cx)
|
||||
.is_some()
|
||||
{
|
||||
cx.emit(SearchEvent::MatchesInvalidated);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_matches(&mut self, matches: &[Range<Anchor>], cx: &mut ViewContext<Self>) {
|
||||
let existing_range = self
|
||||
.background_highlights
|
||||
.get(&TypeId::of::<BufferSearchHighlights>())
|
||||
.map(|(_, range)| range.as_ref());
|
||||
let updated = existing_range != Some(matches);
|
||||
self.highlight_background::<BufferSearchHighlights>(
|
||||
matches,
|
||||
|theme| theme.search_match_background,
|
||||
cx,
|
||||
);
|
||||
if updated {
|
||||
cx.emit(SearchEvent::MatchesInvalidated);
|
||||
}
|
||||
}
|
||||
|
||||
fn has_filtered_search_ranges(&mut self) -> bool {
|
||||
|
|
|
@ -26,9 +26,11 @@ log.workspace = true
|
|||
menu.workspace = true
|
||||
project.workspace = true
|
||||
schemars.workspace = true
|
||||
search.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
theme.workspace = true
|
||||
util.workspace = true
|
||||
worktree.workspace = true
|
||||
workspace.workspace = true
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -988,7 +988,11 @@ impl BufferSearchBar {
|
|||
.searchable_items_with_matches
|
||||
.get(&active_searchable_item.downgrade())
|
||||
.unwrap();
|
||||
active_searchable_item.update_matches(matches, cx);
|
||||
if matches.is_empty() {
|
||||
active_searchable_item.clear_matches(cx);
|
||||
} else {
|
||||
active_searchable_item.update_matches(matches, cx);
|
||||
}
|
||||
let _ = done_tx.send(());
|
||||
}
|
||||
cx.notify();
|
||||
|
|
|
@ -503,6 +503,10 @@ impl Item for ProjectSearchView {
|
|||
}
|
||||
|
||||
impl ProjectSearchView {
|
||||
pub fn get_matches(&self, cx: &AppContext) -> Vec<Range<Anchor>> {
|
||||
self.model.read(cx).match_ranges.clone()
|
||||
}
|
||||
|
||||
fn toggle_filters(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.filters_enabled = !self.filters_enabled;
|
||||
ActiveSettings::update_global(cx, |settings, cx| {
|
||||
|
@ -836,6 +840,10 @@ impl ProjectSearchView {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn search_query_text(&self, cx: &WindowContext) -> String {
|
||||
self.query_editor.read(cx).text(cx)
|
||||
}
|
||||
|
||||
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
|
||||
// Do not bail early in this function, as we want to fill out `self.panels_with_errors`.
|
||||
let text = self.query_editor.read(cx).text(cx);
|
||||
|
|
|
@ -212,6 +212,7 @@ pub enum IconName {
|
|||
PageUp,
|
||||
Pencil,
|
||||
Person,
|
||||
Pin,
|
||||
Play,
|
||||
Plus,
|
||||
Public,
|
||||
|
@ -263,6 +264,7 @@ pub enum IconName {
|
|||
Trash,
|
||||
TriangleRight,
|
||||
Undo,
|
||||
Unpin,
|
||||
Update,
|
||||
WholeWord,
|
||||
XCircle,
|
||||
|
@ -381,6 +383,7 @@ impl IconName {
|
|||
IconName::PageUp => "icons/page_up.svg",
|
||||
IconName::Pencil => "icons/pencil.svg",
|
||||
IconName::Person => "icons/person.svg",
|
||||
IconName::Pin => "icons/pin.svg",
|
||||
IconName::Play => "icons/play.svg",
|
||||
IconName::Plus => "icons/plus.svg",
|
||||
IconName::Public => "icons/public.svg",
|
||||
|
@ -431,6 +434,7 @@ impl IconName {
|
|||
IconName::TextSelect => "icons/text_select.svg",
|
||||
IconName::Trash => "icons/trash.svg",
|
||||
IconName::TriangleRight => "icons/triangle_right.svg",
|
||||
IconName::Unpin => "icons/unpin.svg",
|
||||
IconName::Update => "icons/update.svg",
|
||||
IconName::Undo => "icons/undo.svg",
|
||||
IconName::WholeWord => "icons/word_search.svg",
|
||||
|
|
|
@ -65,6 +65,9 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
|
|||
|
||||
fn toggle_filtered_search_ranges(&mut self, _enabled: bool, _cx: &mut ViewContext<Self>) {}
|
||||
|
||||
fn get_matches(&self, _: &mut WindowContext) -> Vec<Self::Match> {
|
||||
Vec::new()
|
||||
}
|
||||
fn clear_matches(&mut self, cx: &mut ViewContext<Self>);
|
||||
fn update_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>);
|
||||
fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String;
|
||||
|
|
Loading…
Reference in a new issue