diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index e668ce326f..bb269fdbab 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1,13 +1,11 @@ pub mod items; use anyhow::Result; -use collections::{BTreeSet, HashMap, HashSet}; +use collections::{BTreeSet, HashSet}; use editor::{ diagnostic_block_renderer, display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock}, - highlight_diagnostic_message, - items::BufferItemHandle, - Autoscroll, Editor, ExcerptId, MultiBuffer, ToOffset, + highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset, }; use gpui::{ action, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity, @@ -31,21 +29,12 @@ use util::TryFutureExt; use workspace::{ItemHandle, ItemNavHistory, ItemViewHandle as _, Workspace}; action!(Deploy); -action!(OpenExcerpts); const CONTEXT_LINE_COUNT: u32 = 1; pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("alt-shift-D", Deploy, Some("Workspace")), - Binding::new( - "alt-shift-D", - OpenExcerpts, - Some("ProjectDiagnosticsEditor"), - ), - ]); + cx.add_bindings([Binding::new("alt-shift-D", Deploy, Some("Workspace"))]); cx.add_action(ProjectDiagnosticsEditor::deploy); - cx.add_action(ProjectDiagnosticsEditor::open_excerpts); } type Event = editor::Event; @@ -180,47 +169,6 @@ impl ProjectDiagnosticsEditor { } } - fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext) { - if let Some(workspace) = self.workspace.upgrade(cx) { - let editor = self.editor.read(cx); - let excerpts = self.excerpts.read(cx); - let mut new_selections_by_buffer = HashMap::default(); - - for selection in editor.local_selections::(cx) { - for (buffer, mut range) in - excerpts.range_to_buffer_ranges(selection.start..selection.end, cx) - { - if selection.reversed { - mem::swap(&mut range.start, &mut range.end); - } - new_selections_by_buffer - .entry(buffer) - .or_insert(Vec::new()) - .push(range) - } - } - - // We defer the pane interaction because we ourselves are a workspace item - // and activating a new item causes the pane to call a method on us reentrantly, - // which panics if we're on the stack. - workspace.defer(cx, |workspace, cx| { - for (buffer, ranges) in new_selections_by_buffer { - let buffer = BufferItemHandle(buffer); - if !workspace.activate_pane_for_item(&buffer, cx) { - workspace.activate_next_pane(cx); - } - let editor = workspace - .open_item(buffer, cx) - .downcast::() - .unwrap(); - editor.update(cx, |editor, cx| { - editor.select_ranges(ranges, Some(Autoscroll::Center), cx) - }); - } - }); - } - } - fn update_excerpts(&mut self, cx: &mut ViewContext) { let paths = mem::take(&mut self.paths_to_update); let project = self.model.read(cx).project.clone(); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 21f1d9a4ad..6919a85c55 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -132,6 +132,7 @@ action!(ShowCompletions); action!(ToggleCodeActions, bool); action!(ConfirmCompletion, Option); action!(ConfirmCodeAction, Option); +action!(OpenExcerpts); pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec>) { path_openers.push(Box::new(items::BufferOpener)); @@ -259,6 +260,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec bool { self.searchable } + + fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext) { + let active_item = workspace.active_item(cx); + let editor_handle = if let Some(editor) = active_item + .as_ref() + .and_then(|item| item.act_as::(cx)) + { + editor + } else { + cx.propagate_action(); + return; + }; + + let editor = editor_handle.read(cx); + let buffer = editor.buffer.read(cx); + if buffer.is_singleton() { + cx.propagate_action(); + return; + } + + let mut new_selections_by_buffer = HashMap::default(); + for selection in editor.local_selections::(cx) { + for (buffer, mut range) in + buffer.range_to_buffer_ranges(selection.start..selection.end, cx) + { + if selection.reversed { + mem::swap(&mut range.start, &mut range.end); + } + new_selections_by_buffer + .entry(buffer) + .or_insert(Vec::new()) + .push(range) + } + } + + // We defer the pane interaction because we ourselves are a workspace item + // and activating a new item causes the pane to call a method on us reentrantly, + // which panics if we're on the stack. + cx.defer(|workspace, cx| { + for (buffer, ranges) in new_selections_by_buffer { + let buffer = BufferItemHandle(buffer); + if !workspace.activate_pane_for_item(&buffer, cx) { + workspace.activate_next_pane(cx); + } + let editor = workspace + .open_item(buffer, cx) + .downcast::() + .unwrap(); + editor.update(cx, |editor, cx| { + let prev_nav_history_len = + editor.nav_history().map_or(0, |history| history.len()); + editor.select_ranges(ranges, Some(Autoscroll::Newest), cx); + if let Some(history) = editor.nav_history() { + history.truncate(prev_nav_history_len); + } + }); + } + }); + } } impl EditorSnapshot { diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index beafd0eb8c..c650a0240f 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -649,6 +649,14 @@ impl ToolbarHandle for ViewHandle { } impl ItemNavHistory { + pub fn len(&self) -> usize { + self.history.borrow().len() + } + + pub fn truncate(&self, len: usize) { + self.history.borrow_mut().truncate(len) + } + pub fn new(history: Rc>, item_view: &ViewHandle) -> Self { Self { history, @@ -666,6 +674,14 @@ impl ItemNavHistory { } impl NavHistory { + pub fn len(&self) -> usize { + self.backward_stack.len() + } + + pub fn truncate(&mut self, len: usize) { + self.backward_stack.truncate(len); + } + pub fn pop_backward(&mut self) -> Option { self.backward_stack.pop_back() }