Select the closest outline item when the outline view's query is empty

Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-01-13 18:43:49 +01:00
parent 2660d37ad8
commit 055d48cfb2
3 changed files with 43 additions and 7 deletions

View file

@ -28,8 +28,10 @@ use language::{
BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point, Selection, SelectionGoal,
TransactionId,
};
pub use multi_buffer::{Anchor, ExcerptId, ExcerptProperties, MultiBuffer, ToOffset, ToPoint};
use multi_buffer::{AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot};
pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, ExcerptProperties, MultiBuffer, ToOffset, ToPoint,
};
use multi_buffer::{MultiBufferChunks, MultiBufferSnapshot};
use postage::watch;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;

View file

@ -1917,7 +1917,11 @@ impl BufferSnapshot {
})
.collect::<Vec<_>>();
Some(Outline::new(items))
if items.is_empty() {
None
} else {
Some(Outline::new(items))
}
}
pub fn enclosing_bracket_ranges<T: ToOffset>(

View file

@ -1,4 +1,4 @@
use editor::{Anchor, Editor, EditorSettings};
use editor::{Anchor, AnchorRangeExt, Editor, EditorSettings};
use fuzzy::StringMatch;
use gpui::{
action,
@ -14,7 +14,10 @@ use gpui::{
use language::Outline;
use ordered_float::OrderedFloat;
use postage::watch;
use std::{cmp, sync::Arc};
use std::{
cmp::{self, Reverse},
sync::Arc,
};
use workspace::{Settings, Workspace};
action!(Toggle);
@ -34,6 +37,7 @@ pub fn init(cx: &mut MutableAppContext) {
struct OutlineView {
handle: WeakViewHandle<Self>,
editor: ViewHandle<Editor>,
outline: Outline<Anchor>,
selected_match_index: usize,
matches: Vec<StringMatch>,
@ -91,6 +95,7 @@ impl View for OutlineView {
impl OutlineView {
fn new(
outline: Outline<Anchor>,
editor: ViewHandle<Editor>,
settings: watch::Receiver<Settings>,
cx: &mut ViewContext<Self>,
) -> Self {
@ -114,6 +119,7 @@ impl OutlineView {
.detach();
let mut this = Self {
handle: cx.weak_handle(),
editor,
matches: Default::default(),
selected_match_index: 0,
outline,
@ -135,7 +141,7 @@ impl OutlineView {
let buffer = editor.read(cx).buffer().read(cx).read(cx).outline();
if let Some(outline) = buffer {
workspace.toggle_modal(cx, |cx, workspace| {
cx.add_view(|cx| OutlineView::new(outline, workspace.settings(), cx))
cx.add_view(|cx| OutlineView::new(outline, editor, workspace.settings(), cx))
})
}
}
@ -185,7 +191,31 @@ impl OutlineView {
string: Default::default(),
})
.collect();
self.selected_match_index = 0;
let editor = self.editor.read(cx);
let buffer = editor.buffer().read(cx).read(cx);
let cursor_offset = editor.newest_selection::<usize>(&buffer).head();
self.selected_match_index = self
.outline
.items
.iter()
.enumerate()
.map(|(ix, item)| {
let range = item.range.to_offset(&buffer);
let distance_to_closest_endpoint = cmp::min(
(range.start as isize - cursor_offset as isize).abs() as usize,
(range.end as isize - cursor_offset as isize).abs() as usize,
);
let depth = if range.contains(&cursor_offset) {
Some(item.depth)
} else {
None
};
(ix, depth, distance_to_closest_endpoint)
})
.max_by_key(|(_, depth, distance)| (*depth, Reverse(*distance)))
.unwrap()
.0;
} else {
self.matches = self.outline.search(&query, cx);
self.selected_match_index = self