Add `open permalink to line` action (#7562)

Daniel Schmidt and Marshall Bowers created

Release Notes:

- Added `open permalink to line` action.

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

crates/editor/src/actions.rs |  1 +
crates/editor/src/editor.rs  | 28 +++++++++++++++++++++++++++-
crates/editor/src/element.rs |  1 +
3 files changed, 29 insertions(+), 1 deletion(-)

Detailed changes

crates/editor/src/actions.rs 🔗

@@ -194,6 +194,7 @@ gpui::actions!(
         NewlineBelow,
         NextScreen,
         OpenExcerpts,
+        OpenPermalinkToLine,
         Outdent,
         PageDown,
         PageUp,

crates/editor/src/editor.rs 🔗

@@ -8393,7 +8393,7 @@ impl Editor {
         }
     }
 
-    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
+    fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
         use git::permalink::{build_permalink, BuildPermalinkParams};
 
         let permalink = maybe!({
@@ -8439,6 +8439,11 @@ impl Editor {
                 selection: selection.map(|selection| selection.range()),
             })
         });
+        permalink
+    }
+
+    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
+        let permalink = self.get_permalink_to_line(cx);
 
         match permalink {
             Ok(permalink) => {
@@ -8458,6 +8463,27 @@ impl Editor {
         }
     }
 
+    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
+        let permalink = self.get_permalink_to_line(cx);
+
+        match permalink {
+            Ok(permalink) => {
+                cx.open_url(&permalink.to_string());
+            }
+            Err(err) => {
+                let message = format!("Failed to open permalink: {err}");
+
+                Err::<(), anyhow::Error>(err).log_err();
+
+                if let Some(workspace) = self.workspace() {
+                    workspace.update(cx, |workspace, cx| {
+                        workspace.show_toast(Toast::new(0x45a8978, message), cx)
+                    })
+                }
+            }
+        }
+    }
+
     pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
         self.highlighted_rows = rows;
     }

crates/editor/src/element.rs 🔗

@@ -278,6 +278,7 @@ impl EditorElement {
         register_action(view, cx, Editor::copy_relative_path);
         register_action(view, cx, Editor::copy_highlight_json);
         register_action(view, cx, Editor::copy_permalink_to_line);
+        register_action(view, cx, Editor::open_permalink_to_line);
         register_action(view, cx, |editor, action, cx| {
             if let Some(task) = editor.format(action, cx) {
                 task.detach_and_log_err(cx);