mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-21 03:18:47 +03:00
Add keyboard shortcut to suppress prompt while deleting files/dirs (#9452)
Completes #7228. Adds back Backspace as the main delete key binding and makes Linux bindings consistent with macOS Release Notes: - ⌘-Delete/⌘-Backspace will now suppress deletion confirmation prompts in project panel ([#7228](https://github.com/zed-industries/zed/issues/7228)).
This commit is contained in:
parent
e22d31b52d
commit
7c0a0e21ab
@ -514,6 +514,9 @@
|
|||||||
"f2": "project_panel::Rename",
|
"f2": "project_panel::Rename",
|
||||||
"enter": "project_panel::Rename",
|
"enter": "project_panel::Rename",
|
||||||
"backspace": "project_panel::Delete",
|
"backspace": "project_panel::Delete",
|
||||||
|
"delete": "project_panel::Delete",
|
||||||
|
"ctrl-backspace": ["project_panel::Delete", { "skip_prompt": true }],
|
||||||
|
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": true }],
|
||||||
"ctrl-alt-r": "project_panel::RevealInFinder",
|
"ctrl-alt-r": "project_panel::RevealInFinder",
|
||||||
"alt-shift-f": "project_panel::NewSearchInDirectory"
|
"alt-shift-f": "project_panel::NewSearchInDirectory"
|
||||||
}
|
}
|
||||||
|
@ -561,8 +561,10 @@
|
|||||||
"alt-cmd-shift-c": "project_panel::CopyRelativePath",
|
"alt-cmd-shift-c": "project_panel::CopyRelativePath",
|
||||||
"f2": "project_panel::Rename",
|
"f2": "project_panel::Rename",
|
||||||
"enter": "project_panel::Rename",
|
"enter": "project_panel::Rename",
|
||||||
|
"backspace": "project_panel::Delete",
|
||||||
"delete": "project_panel::Delete",
|
"delete": "project_panel::Delete",
|
||||||
"cmd-backspace": "project_panel::Delete",
|
"cmd-backspace": ["project_panel::Delete", { "skip_prompt": true }],
|
||||||
|
"cmd-delete": ["project_panel::Delete", { "skip_prompt": true }],
|
||||||
"alt-cmd-r": "project_panel::RevealInFinder",
|
"alt-cmd-r": "project_panel::RevealInFinder",
|
||||||
"alt-shift-f": "project_panel::NewSearchInDirectory"
|
"alt-shift-f": "project_panel::NewSearchInDirectory"
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,7 @@ impl<T: 'static> Model<T> {
|
|||||||
///
|
///
|
||||||
/// The update function receives a context appropriate for its environment.
|
/// The update function receives a context appropriate for its environment.
|
||||||
/// When updating in an `AppContext`, it receives a `ModelContext`.
|
/// When updating in an `AppContext`, it receives a `ModelContext`.
|
||||||
/// When updating an a `WindowContext`, it receives a `ViewContext`.
|
/// When updating in a `WindowContext`, it receives a `ViewContext`.
|
||||||
pub fn update<C, R>(
|
pub fn update<C, R>(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut C,
|
cx: &mut C,
|
||||||
|
@ -10,11 +10,11 @@ use file_associations::FileAssociations;
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use collections::{hash_map, HashMap};
|
use collections::{hash_map, HashMap};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, overlay, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
|
actions, div, impl_actions, overlay, px, uniform_list, Action, AppContext, AssetSource,
|
||||||
ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
|
AsyncWindowContext, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||||
KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel,
|
InteractiveElement, KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels,
|
||||||
Render, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext,
|
Point, PromptLevel, Render, Stateful, Styled, Subscription, Task, UniformListScrollHandle,
|
||||||
VisualContext as _, WeakView, WindowContext,
|
View, ViewContext, VisualContext as _, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use menu::{Confirm, SelectNext, SelectPrev};
|
use menu::{Confirm, SelectNext, SelectPrev};
|
||||||
use project::{
|
use project::{
|
||||||
@ -106,6 +106,13 @@ pub struct EntryDetails {
|
|||||||
is_dotenv: bool,
|
is_dotenv: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize)]
|
||||||
|
pub struct Delete {
|
||||||
|
pub skip_prompt: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_actions!(project_panel, [Delete]);
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
project_panel,
|
project_panel,
|
||||||
[
|
[
|
||||||
@ -121,7 +128,6 @@ actions!(
|
|||||||
OpenInTerminal,
|
OpenInTerminal,
|
||||||
Cut,
|
Cut,
|
||||||
Paste,
|
Paste,
|
||||||
Delete,
|
|
||||||
Rename,
|
Rename,
|
||||||
Open,
|
Open,
|
||||||
ToggleFocus,
|
ToggleFocus,
|
||||||
@ -448,7 +454,9 @@ impl ProjectPanel {
|
|||||||
})
|
})
|
||||||
.separator()
|
.separator()
|
||||||
.action("Rename", Box::new(Rename))
|
.action("Rename", Box::new(Rename))
|
||||||
.when(!is_root, |menu| menu.action("Delete", Box::new(Delete)))
|
.when(!is_root, |menu| {
|
||||||
|
menu.action("Delete", Box::new(Delete { skip_prompt: false }))
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -793,23 +801,27 @@ impl ProjectPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
|
fn delete(&mut self, action: &Delete, cx: &mut ViewContext<Self>) {
|
||||||
maybe!({
|
maybe!({
|
||||||
let Selection { entry_id, .. } = self.selection?;
|
let Selection { entry_id, .. } = self.selection?;
|
||||||
let path = self.project.read(cx).path_for_entry(entry_id, cx)?.path;
|
let path = self.project.read(cx).path_for_entry(entry_id, cx)?.path;
|
||||||
let file_name = path.file_name()?;
|
let file_name = path.file_name()?;
|
||||||
|
|
||||||
let answer = cx.prompt(
|
let answer = (!action.skip_prompt).then(|| {
|
||||||
|
cx.prompt(
|
||||||
PromptLevel::Info,
|
PromptLevel::Info,
|
||||||
&format!("Delete {file_name:?}?"),
|
&format!("Delete {file_name:?}?"),
|
||||||
None,
|
None,
|
||||||
&["Delete", "Cancel"],
|
&["Delete", "Cancel"],
|
||||||
);
|
)
|
||||||
|
});
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
if let Some(answer) = answer {
|
||||||
if answer.await != Ok(0) {
|
if answer.await != Ok(0) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.project
|
this.project
|
||||||
.update(cx, |project, cx| project.delete_entry(entry_id, cx))
|
.update(cx, |project, cx| project.delete_entry(entry_id, cx))
|
||||||
@ -2691,7 +2703,7 @@ mod tests {
|
|||||||
open_editor.update(cx, |editor, cx| editor.set_text("Another text!", cx));
|
open_editor.update(cx, |editor, cx| editor.set_text("Another text!", cx));
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
submit_deletion(&panel, cx);
|
submit_deletion_skipping_prompt(&panel, cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
visible_entries_as_strings(&panel, 0..10, cx),
|
visible_entries_as_strings(&panel, 0..10, cx),
|
||||||
&["v src", " v test", " third.rs"],
|
&["v src", " v test", " third.rs"],
|
||||||
@ -3652,7 +3664,9 @@ mod tests {
|
|||||||
!cx.has_pending_prompt(),
|
!cx.has_pending_prompt(),
|
||||||
"Should have no prompts before the deletion"
|
"Should have no prompts before the deletion"
|
||||||
);
|
);
|
||||||
panel.update(cx, |panel, cx| panel.delete(&Delete, cx));
|
panel.update(cx, |panel, cx| {
|
||||||
|
panel.delete(&Delete { skip_prompt: false }, cx)
|
||||||
|
});
|
||||||
assert!(
|
assert!(
|
||||||
cx.has_pending_prompt(),
|
cx.has_pending_prompt(),
|
||||||
"Should have a prompt after the deletion"
|
"Should have a prompt after the deletion"
|
||||||
@ -3665,6 +3679,18 @@ mod tests {
|
|||||||
cx.executor().run_until_parked();
|
cx.executor().run_until_parked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn submit_deletion_skipping_prompt(panel: &View<ProjectPanel>, cx: &mut VisualTestContext) {
|
||||||
|
assert!(
|
||||||
|
!cx.has_pending_prompt(),
|
||||||
|
"Should have no prompts before the deletion"
|
||||||
|
);
|
||||||
|
panel.update(cx, |panel, cx| {
|
||||||
|
panel.delete(&Delete { skip_prompt: true }, cx)
|
||||||
|
});
|
||||||
|
assert!(!cx.has_pending_prompt(), "Should have received no prompts");
|
||||||
|
cx.executor().run_until_parked();
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_no_open_items_and_panes(
|
fn ensure_no_open_items_and_panes(
|
||||||
workspace: &WindowHandle<Workspace>,
|
workspace: &WindowHandle<Workspace>,
|
||||||
cx: &mut VisualTestContext,
|
cx: &mut VisualTestContext,
|
||||||
|
@ -378,6 +378,7 @@ But, it was impossible to take into account the `{` and `}` when he was typing s
|
|||||||
| Copy relative path | Project Panel | `Alt` + `⌘` + `Shift` + `C` |
|
| Copy relative path | Project Panel | `Alt` + `⌘` + `Shift` + `C` |
|
||||||
| Cut | Project Panel | `⌘` + `X` |
|
| Cut | Project Panel | `⌘` + `X` |
|
||||||
| Delete | Project Panel | `Backspace` |
|
| Delete | Project Panel | `Backspace` |
|
||||||
|
| Delete (no prompt) | Project Panel | `⌘` + `Backspace` |
|
||||||
| Expand selected entry | Project Panel | `Right` |
|
| Expand selected entry | Project Panel | `Right` |
|
||||||
| New directory | Project Panel | `Alt` + `⌘` + `N` |
|
| New directory | Project Panel | `Alt` + `⌘` + `N` |
|
||||||
| New file | Project Panel | `Command + N` |
|
| New file | Project Panel | `Command + N` |
|
||||||
|
Loading…
Reference in New Issue
Block a user