Support copying permalink in multibuffer (#12435)

Bennet Bo Fenner created

Closes #11392 

Release Notes:

- Added support for copying permalinks inside multi-buffers
([#11392](https://github.com/zed-industries/zed/issues/11392))

Change summary

crates/editor/src/editor.rs | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -9957,10 +9957,33 @@ impl Editor {
     }
 
     fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
-        let (path, repo) = maybe!({
+        let (path, selection, repo) = maybe!({
             let project_handle = self.project.as_ref()?.clone();
             let project = project_handle.read(cx);
-            let buffer = self.buffer().read(cx).as_singleton()?;
+
+            let selection = self.selections.newest::<Point>(cx);
+            let selection_range = selection.range();
+
+            let (buffer, selection) = if let Some(buffer) = self.buffer().read(cx).as_singleton() {
+                (buffer, selection_range.start.row..selection_range.end.row)
+            } else {
+                let buffer_ranges = self
+                    .buffer()
+                    .read(cx)
+                    .range_to_buffer_ranges(selection_range, cx);
+
+                let (buffer, range, _) = if selection.reversed {
+                    buffer_ranges.first()
+                } else {
+                    buffer_ranges.last()
+                }?;
+
+                let snapshot = buffer.read(cx).snapshot();
+                let selection = text::ToPoint::to_point(&range.start, &snapshot).row
+                    ..text::ToPoint::to_point(&range.end, &snapshot).row;
+                (buffer.clone(), selection)
+            };
+
             let path = buffer
                 .read(cx)
                 .file()?
@@ -9969,7 +9992,7 @@ impl Editor {
                 .to_str()?
                 .to_string();
             let repo = project.get_repo(&buffer.read(cx).project_path(cx)?, cx)?;
-            Some((path, repo))
+            Some((path, selection, repo))
         })
         .ok_or_else(|| anyhow!("unable to open git repository"))?;
 
@@ -9982,8 +10005,6 @@ impl Editor {
             .lock()
             .head_sha()
             .ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
-        let selections = self.selections.all::<Point>(cx);
-        let selection = selections.iter().peekable().next();
 
         let (provider, remote) =
             parse_git_remote_url(GitHostingProviderRegistry::default_global(cx), &origin_url)
@@ -9994,12 +10015,7 @@ impl Editor {
             BuildPermalinkParams {
                 sha: &sha,
                 path: &path,
-                selection: selection.map(|selection| {
-                    let range = selection.range();
-                    let start = range.start.row;
-                    let end = range.end.row;
-                    start..end
-                }),
+                selection: Some(selection),
             },
         ))
     }