diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index c7f1f9b86871d499a7f90861b6d9fb1c9aef67a2..c008b10399eb94c3b34d6164fc96e20773b135e7 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -19,12 +19,21 @@ use util::TryFutureExt; use workspace::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, None)]); + cx.add_bindings([ + Binding::new("alt-shift-D", Deploy, Some("Workspace")), + Binding::new( + "alt-shift-D", + OpenExcerpts, + Some("ProjectDiagnosticsEditor"), + ), + ]); cx.add_action(ProjectDiagnosticsEditor::deploy); + cx.add_action(ProjectDiagnosticsEditor::open_excerpts); } type Event = editor::Event; @@ -155,6 +164,24 @@ impl ProjectDiagnosticsEditor { workspace.add_item(diagnostics, cx); } + fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext) { + 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, range) in excerpts.excerpted_buffers(selection.start..selection.end, cx) { + new_selections_by_buffer + .entry(buffer) + .or_insert(Vec::new()) + .push((range.start, range.end, selection.reversed)) + } + } + + for (buffer, selections) in new_selections_by_buffer { + // buffer.read(cx). + } + } + fn update_excerpts(&self, paths: HashSet, cx: &mut ViewContext) { let project = self.project.clone(); cx.spawn(|this, mut cx| { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b9c57de1308b25ec0cf9999a5d29a240179371fb..7ec1a171fed16a690b252b1459b1afda528fe93e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1105,7 +1105,7 @@ impl Editor { T: ToOffset, { let buffer = self.buffer.read(cx).snapshot(cx); - let selections = ranges + let mut selections = ranges .into_iter() .map(|range| { let mut start = range.start.to_offset(&buffer); @@ -1124,7 +1124,8 @@ impl Editor { goal: SelectionGoal::None, } }) - .collect(); + .collect::>(); + selections.sort_unstable_by_key(|s| s.start); self.update_selections(selections, autoscroll, cx); } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index ed67491e24b4e7ba82dd270272920aa07a38d828..0fe155ff1138e20693643b0009c1775809f36e5b 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -689,6 +689,33 @@ impl MultiBuffer { .map_or(Vec::new(), |state| state.excerpts.clone()) } + pub fn excerpted_buffers<'a, T: ToOffset>( + &'a self, + range: Range, + cx: &AppContext, + ) -> Vec<(ModelHandle, Range)> { + let snapshot = self.snapshot(cx); + let start = range.start.to_offset(&snapshot); + let end = range.end.to_offset(&snapshot); + + let mut result = Vec::new(); + let mut cursor = snapshot.excerpts.cursor::(); + cursor.seek(&start, Bias::Right, &()); + while let Some(excerpt) = cursor.item() { + if *cursor.start() > end { + break; + } + + let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer); + let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start()); + let end = excerpt_start + (cmp::min(end, cursor.end(&())) - *cursor.start()); + let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone(); + result.push((buffer, start..end)); + } + + result + } + pub fn remove_excerpts<'a>( &mut self, excerpt_ids: impl IntoIterator, diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index f317a189167f16eeddab18f25b47a35e5f8ee3e5..48a1acd03bff8be8cada436380c55b8d77bd0d0c 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -250,7 +250,7 @@ impl FileFinder { match event { Event::Selected(project_path) => { workspace - .open_entry(project_path.clone(), cx) + .open_path(project_path.clone(), cx) .map(|d| d.detach()); workspace.dismiss_modal(cx); } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 9ced3fbeb0062c1fc4f7a667cd7bd94c8249188d..8e3f004e8d98851745c6beaed543eacfad590fd1 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -124,7 +124,7 @@ impl ProjectPanel { if let Some(worktree) = project.read(cx).worktree_for_id(worktree_id, cx) { if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) { workspace - .open_entry( + .open_path( ProjectPath { worktree_id, path: entry.path.clone(), diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 6bb6da215778bd69eb3c98e7e1d35be776d14e06..3c60254b709d7f8068c6c6c51e429011eb77aa36 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -561,7 +561,7 @@ impl Workspace { let project_path = project_path.await.ok()?; if fs.is_file(&abs_path).await { if let Some(entry) = - this.update(&mut cx, |this, cx| this.open_entry(project_path, cx)) + this.update(&mut cx, |this, cx| this.open_path(project_path, cx)) { return Some(entry.await); } @@ -665,7 +665,7 @@ impl Workspace { } #[must_use] - pub fn open_entry( + pub fn open_path( &mut self, project_path: ProjectPath, cx: &mut ViewContext, diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 00046689398091174b771cfb297dfc72531fedb6..04e21fc58cb4e5ab17e6d9e44a51f37515834d9f 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -264,7 +264,7 @@ mod tests { // Open the first entry let entry_1 = workspace - .update(&mut cx, |w, cx| w.open_entry(file1.clone(), cx)) + .update(&mut cx, |w, cx| w.open_path(file1.clone(), cx)) .unwrap() .await .unwrap(); @@ -279,7 +279,7 @@ mod tests { // Open the second entry workspace - .update(&mut cx, |w, cx| w.open_entry(file2.clone(), cx)) + .update(&mut cx, |w, cx| w.open_path(file2.clone(), cx)) .unwrap() .await .unwrap(); @@ -294,7 +294,7 @@ mod tests { // Open the first entry again. The existing pane item is activated. let entry_1b = workspace - .update(&mut cx, |w, cx| w.open_entry(file1.clone(), cx).unwrap()) + .update(&mut cx, |w, cx| w.open_path(file1.clone(), cx).unwrap()) .await .unwrap(); assert_eq!(entry_1.id(), entry_1b.id()); @@ -312,7 +312,7 @@ mod tests { workspace .update(&mut cx, |w, cx| { w.split_pane(w.active_pane().clone(), SplitDirection::Right, cx); - w.open_entry(file2.clone(), cx).unwrap() + w.open_path(file2.clone(), cx).unwrap() }) .await .unwrap(); @@ -331,8 +331,8 @@ mod tests { // Open the third entry twice concurrently. Only one pane item is added. let (t1, t2) = workspace.update(&mut cx, |w, cx| { ( - w.open_entry(file3.clone(), cx).unwrap(), - w.open_entry(file3.clone(), cx).unwrap(), + w.open_path(file3.clone(), cx).unwrap(), + w.open_path(file3.clone(), cx).unwrap(), ) }); t1.await.unwrap(); @@ -562,7 +562,7 @@ mod tests { .update(&mut cx, |workspace, cx| { workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx); workspace - .open_entry( + .open_path( ProjectPath { worktree_id: worktree.read(cx).id(), path: Path::new("the-new-name.rs").into(), @@ -666,7 +666,7 @@ mod tests { let pane_1 = cx.read(|cx| workspace.read(cx).active_pane().clone()); workspace - .update(&mut cx, |w, cx| w.open_entry(file1.clone(), cx)) + .update(&mut cx, |w, cx| w.open_path(file1.clone(), cx)) .unwrap() .await .unwrap();