Merge pull request #2363 from zed-industries/add-copy-path-commands

Joseph T. Lyons created

Update copy path commands

Change summary

assets/keymaps/default.json               |  1 
crates/editor/src/editor.rs               | 24 ++++++++++++++++++
crates/project_panel/src/project_panel.rs | 32 ++++++++++++++++++------
3 files changed, 49 insertions(+), 8 deletions(-)

Detailed changes

assets/keymaps/default.json 🔗

@@ -477,6 +477,7 @@
             "cmd-c": "project_panel::Copy",
             "cmd-v": "project_panel::Paste",
             "cmd-alt-c": "project_panel::CopyPath",
+            "alt-cmd-shift-c": "project_panel::CopyRelativePath",
             "f2": "project_panel::Rename",
             "backspace": "project_panel::Delete",
             "alt-cmd-r": "project_panel::RevealInFinder"

crates/editor/src/editor.rs 🔗

@@ -261,6 +261,8 @@ actions!(
         Format,
         ToggleSoftWrap,
         RevealInFinder,
+        CopyPath,
+        CopyRelativePath,
         CopyHighlightJson
     ]
 );
@@ -381,6 +383,8 @@ pub fn init(cx: &mut AppContext) {
     cx.add_action(Editor::jump);
     cx.add_action(Editor::toggle_soft_wrap);
     cx.add_action(Editor::reveal_in_finder);
+    cx.add_action(Editor::copy_path);
+    cx.add_action(Editor::copy_relative_path);
     cx.add_action(Editor::copy_highlight_json);
     cx.add_async_action(Editor::format);
     cx.add_action(Editor::restart_language_server);
@@ -6252,6 +6256,26 @@ impl Editor {
         }
     }
 
+    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
+        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
+            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
+                if let Some(path) = file.abs_path(cx).to_str() {
+                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
+                }
+            }
+        }
+    }
+
+    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
+        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
+            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
+                if let Some(path) = file.path().to_str() {
+                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
+                }
+            }
+        }
+    }
+
     pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
         self.highlighted_rows = rows;
     }

crates/project_panel/src/project_panel.rs 🔗

@@ -24,7 +24,7 @@ use std::{
     collections::{hash_map, HashMap},
     ffi::OsStr,
     ops::Range,
-    path::{Path, PathBuf},
+    path::Path,
     sync::Arc,
 };
 use theme::ProjectPanelEntry;
@@ -119,6 +119,7 @@ actions!(
         NewFile,
         Copy,
         CopyPath,
+        CopyRelativePath,
         RevealInFinder,
         Cut,
         Paste,
@@ -146,10 +147,11 @@ pub fn init(cx: &mut AppContext) {
     cx.add_async_action(ProjectPanel::delete);
     cx.add_async_action(ProjectPanel::confirm);
     cx.add_action(ProjectPanel::cancel);
+    cx.add_action(ProjectPanel::cut);
     cx.add_action(ProjectPanel::copy);
     cx.add_action(ProjectPanel::copy_path);
+    cx.add_action(ProjectPanel::copy_relative_path);
     cx.add_action(ProjectPanel::reveal_in_finder);
-    cx.add_action(ProjectPanel::cut);
     cx.add_action(
         |this: &mut ProjectPanel, action: &Paste, cx: &mut ViewContext<ProjectPanel>| {
             this.paste(action, cx);
@@ -307,11 +309,16 @@ impl ProjectPanel {
             }
             menu_entries.push(ContextMenuItem::item("New File", NewFile));
             menu_entries.push(ContextMenuItem::item("New Folder", NewDirectory));
-            menu_entries.push(ContextMenuItem::item("Reveal in Finder", RevealInFinder));
             menu_entries.push(ContextMenuItem::Separator);
+            menu_entries.push(ContextMenuItem::item("Cut", Cut));
             menu_entries.push(ContextMenuItem::item("Copy", Copy));
+            menu_entries.push(ContextMenuItem::Separator);
             menu_entries.push(ContextMenuItem::item("Copy Path", CopyPath));
-            menu_entries.push(ContextMenuItem::item("Cut", Cut));
+            menu_entries.push(ContextMenuItem::item(
+                "Copy Relative Path",
+                CopyRelativePath,
+            ));
+            menu_entries.push(ContextMenuItem::item("Reveal in Finder", RevealInFinder));
             if let Some(clipboard_entry) = self.clipboard_entry {
                 if clipboard_entry.worktree_id() == worktree.id() {
                     menu_entries.push(ContextMenuItem::item("Paste", Paste));
@@ -785,10 +792,19 @@ impl ProjectPanel {
 
     fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
         if let Some((worktree, entry)) = self.selected_entry(cx) {
-            let mut path = PathBuf::new();
-            path.push(worktree.root_name());
-            path.push(&entry.path);
-            cx.write_to_clipboard(ClipboardItem::new(path.to_string_lossy().to_string()));
+            cx.write_to_clipboard(ClipboardItem::new(
+                worktree
+                    .abs_path()
+                    .join(&entry.path)
+                    .to_string_lossy()
+                    .to_string(),
+            ));
+        }
+    }
+
+    fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
+        if let Some((_, entry)) = self.selected_entry(cx) {
+            cx.write_to_clipboard(ClipboardItem::new(entry.path.to_string_lossy().to_string()));
         }
     }