diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 1dbfbea61f..14e3056e6a 100644 --- a/assets/keymaps/default.json +++ b/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" diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 933d76613b..0c3d5d1854 100644 --- a/crates/editor/src/editor.rs +++ b/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) { + 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) { + 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>) { self.highlighted_rows = rows; } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index dd08d68f71..822e730d0c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/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| { 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("Copy", Copy)); - menu_entries.push(ContextMenuItem::item("Copy Path", CopyPath)); 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( + "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) { 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) { + if let Some((_, entry)) = self.selected_entry(cx) { + cx.write_to_clipboard(ClipboardItem::new(entry.path.to_string_lossy().to_string())); } }