@@ -122,6 +122,7 @@ actions!(
CopyPath,
CopyRelativePath,
RevealInFinder,
+ OpenInTerminal,
Cut,
Paste,
Delete,
@@ -156,6 +157,7 @@ pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
cx.add_action(ProjectPanel::copy_path);
cx.add_action(ProjectPanel::copy_relative_path);
cx.add_action(ProjectPanel::reveal_in_finder);
+ cx.add_action(ProjectPanel::open_in_terminal);
cx.add_action(ProjectPanel::new_search_in_directory);
cx.add_action(
|this: &mut ProjectPanel, action: &Paste, cx: &mut ViewContext<ProjectPanel>| {
@@ -423,24 +425,30 @@ impl ProjectPanel {
menu_entries.push(ContextMenuItem::Separator);
menu_entries.push(ContextMenuItem::action("Cut", Cut));
menu_entries.push(ContextMenuItem::action("Copy", Copy));
+ if let Some(clipboard_entry) = self.clipboard_entry {
+ if clipboard_entry.worktree_id() == worktree.id() {
+ menu_entries.push(ContextMenuItem::action("Paste", Paste));
+ }
+ }
menu_entries.push(ContextMenuItem::Separator);
menu_entries.push(ContextMenuItem::action("Copy Path", CopyPath));
menu_entries.push(ContextMenuItem::action(
"Copy Relative Path",
CopyRelativePath,
));
+
+ if entry.is_dir() {
+ menu_entries.push(ContextMenuItem::Separator);
+ }
menu_entries.push(ContextMenuItem::action("Reveal in Finder", RevealInFinder));
if entry.is_dir() {
+ menu_entries.push(ContextMenuItem::action("Open in Terminal", OpenInTerminal));
menu_entries.push(ContextMenuItem::action(
"Search Inside",
NewSearchInDirectory,
));
}
- if let Some(clipboard_entry) = self.clipboard_entry {
- if clipboard_entry.worktree_id() == worktree.id() {
- menu_entries.push(ContextMenuItem::action("Paste", Paste));
- }
- }
+
menu_entries.push(ContextMenuItem::Separator);
menu_entries.push(ContextMenuItem::action("Rename", Rename));
if !is_root {
@@ -965,6 +973,26 @@ impl ProjectPanel {
}
}
+ fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
+ if let Some((worktree, entry)) = self.selected_entry(cx) {
+ let window = cx.window();
+ let view_id = cx.view_id();
+ let path = worktree.abs_path().join(&entry.path);
+
+ cx.app_context()
+ .spawn(|mut cx| async move {
+ window.dispatch_action(
+ view_id,
+ &workspace::OpenTerminal {
+ working_directory: path,
+ },
+ &mut cx,
+ );
+ })
+ .detach();
+ }
+ }
+
pub fn new_search_in_directory(
&mut self,
_: &NewSearchInDirectory,
@@ -1,4 +1,4 @@
-use std::sync::Arc;
+use std::{path::PathBuf, sync::Arc};
use crate::TerminalView;
use db::kvp::KEY_VALUE_STORE;
@@ -23,6 +23,7 @@ actions!(terminal_panel, [ToggleFocus]);
pub fn init(cx: &mut AppContext) {
cx.add_action(TerminalPanel::new_terminal);
+ cx.add_action(TerminalPanel::open_terminal);
}
#[derive(Debug)]
@@ -79,7 +80,7 @@ impl TerminalPanel {
cx.window_context().defer(move |cx| {
if let Some(this) = this.upgrade(cx) {
this.update(cx, |this, cx| {
- this.add_terminal(cx);
+ this.add_terminal(None, cx);
});
}
})
@@ -230,6 +231,21 @@ impl TerminalPanel {
}
}
+ pub fn open_terminal(
+ workspace: &mut Workspace,
+ action: &workspace::OpenTerminal,
+ cx: &mut ViewContext<Workspace>,
+ ) {
+ let Some(this) = workspace.focus_panel::<Self>(cx) else {
+ return;
+ };
+
+ this.update(cx, |this, cx| {
+ this.add_terminal(Some(action.working_directory.clone()), cx)
+ })
+ }
+
+ ///Create a new Terminal in the current working directory or the user's home directory
fn new_terminal(
workspace: &mut Workspace,
_: &workspace::NewTerminal,
@@ -239,19 +255,23 @@ impl TerminalPanel {
return;
};
- this.update(cx, |this, cx| this.add_terminal(cx))
+ this.update(cx, |this, cx| this.add_terminal(None, cx))
}
- fn add_terminal(&mut self, cx: &mut ViewContext<Self>) {
+ fn add_terminal(&mut self, working_directory: Option<PathBuf>, cx: &mut ViewContext<Self>) {
let workspace = self.workspace.clone();
cx.spawn(|this, mut cx| async move {
let pane = this.read_with(&cx, |this, _| this.pane.clone())?;
workspace.update(&mut cx, |workspace, cx| {
- let working_directory_strategy = settings::get::<TerminalSettings>(cx)
- .working_directory
- .clone();
- let working_directory =
- crate::get_working_directory(workspace, cx, working_directory_strategy);
+ let working_directory = if let Some(working_directory) = working_directory {
+ Some(working_directory)
+ } else {
+ let working_directory_strategy = settings::get::<TerminalSettings>(cx)
+ .working_directory
+ .clone();
+ crate::get_working_directory(workspace, cx, working_directory_strategy)
+ };
+
let window = cx.window();
if let Some(terminal) = workspace.project().update(cx, |project, cx| {
project
@@ -389,7 +409,7 @@ impl Panel for TerminalPanel {
fn set_active(&mut self, active: bool, cx: &mut ViewContext<Self>) {
if active && self.pane.read(cx).items_len() == 0 {
- self.add_terminal(cx)
+ self.add_terminal(None, cx)
}
}
@@ -203,7 +203,15 @@ impl Clone for Toast {
}
}
-impl_actions!(workspace, [ActivatePane, ActivatePaneInDirection, Toast]);
+#[derive(Clone, Deserialize, PartialEq)]
+pub struct OpenTerminal {
+ pub working_directory: PathBuf,
+}
+
+impl_actions!(
+ workspace,
+ [ActivatePane, ActivatePaneInDirection, Toast, OpenTerminal]
+);
pub type WorkspaceId = i64;