Cargo.lock π
@@ -7180,6 +7180,7 @@ dependencies = [
"ordered-float 2.10.0",
"picker",
"project",
+ "serde",
"serde_json",
"smol",
"ui",
Kirill Bulatov created
Follow-up of
https://github.com/zed-industries/zed/issues/8651#issuecomment-1973411072
Zed current default is still to reuse the current window, but now it's
possible to do
```json
"alt-cmd-o": [
"projects::OpenRecent",
{
"create_new_window": true
}
]
```
and change this.
menu::Secondary confirm does the action with opposite window creation
strategy.
Release Notes:
- Improved open recent projects flexibility: settings can change whether
`menu::Confirm` opens a new window or reuses the old one
Cargo.lock | 1
assets/keymaps/default-linux.json | 7 ++
assets/keymaps/default-macos.json | 7 ++
crates/recent_projects/Cargo.toml | 1
crates/recent_projects/src/recent_projects.rs | 62 ++++++++++++++++----
crates/zed/src/app_menus.rs | 7 ++
6 files changed, 72 insertions(+), 13 deletions(-)
@@ -7180,6 +7180,7 @@ dependencies = [
"ordered-float 2.10.0",
"picker",
"project",
+ "serde",
"serde_json",
"smol",
"ui",
@@ -343,6 +343,13 @@
{
"context": "Workspace",
"bindings": {
+ // Change the default action on `menu::Confirm` by setting the parameter
+ // "alt-cmd-o": [
+ // "projects::OpenRecent",
+ // {
+ // "create_new_window": true
+ // }
+ // ]
"ctrl-alt-o": "projects::OpenRecent",
"ctrl-alt-b": "branches::OpenRecent",
"ctrl-~": "workspace::NewTerminal",
@@ -386,6 +386,13 @@
{
"context": "Workspace",
"bindings": {
+ // Change the default action on `menu::Confirm` by setting the parameter
+ // "alt-cmd-o": [
+ // "projects::OpenRecent",
+ // {
+ // "create_new_window": true
+ // }
+ // ]
"alt-cmd-o": "projects::OpenRecent",
"alt-cmd-b": "branches::OpenRecent",
"ctrl-~": "workspace::NewTerminal",
@@ -15,6 +15,7 @@ gpui.workspace = true
menu.workspace = true
ordered-float.workspace = true
picker.workspace = true
+serde.workspace = true
smol.workspace = true
ui.workspace = true
util.workspace = true
@@ -8,12 +8,19 @@ use picker::{
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
Picker, PickerDelegate,
};
+use serde::Deserialize;
use std::{path::Path, sync::Arc};
use ui::{prelude::*, tooltip_container, ListItem, ListItemSpacing, Tooltip};
use util::paths::PathExt;
use workspace::{ModalView, Workspace, WorkspaceId, WorkspaceLocation, WORKSPACE_DB};
-gpui::actions!(projects, [OpenRecent]);
+#[derive(PartialEq, Clone, Deserialize, Default)]
+pub struct OpenRecent {
+ #[serde(default)]
+ pub create_new_window: bool,
+}
+
+gpui::impl_actions!(projects, [OpenRecent]);
pub fn init(cx: &mut AppContext) {
cx.observe_new_views(RecentProjects::register).detach();
@@ -63,9 +70,9 @@ impl RecentProjects {
}
fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
- workspace.register_action(|workspace, _: &OpenRecent, cx| {
+ workspace.register_action(|workspace, open_recent: &OpenRecent, cx| {
let Some(recent_projects) = workspace.active_modal::<Self>(cx) else {
- if let Some(handler) = Self::open(workspace, cx) {
+ if let Some(handler) = Self::open(workspace, open_recent.create_new_window, cx) {
handler.detach_and_log_err(cx);
}
return;
@@ -79,12 +86,17 @@ impl RecentProjects {
});
}
- fn open(_: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<Task<Result<()>>> {
+ fn open(
+ _: &mut Workspace,
+ create_new_window: bool,
+ cx: &mut ViewContext<Workspace>,
+ ) -> Option<Task<Result<()>>> {
Some(cx.spawn(|workspace, mut cx| async move {
workspace.update(&mut cx, |workspace, cx| {
let weak_workspace = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| {
- let delegate = RecentProjectsDelegate::new(weak_workspace, true);
+ let delegate =
+ RecentProjectsDelegate::new(weak_workspace, create_new_window, true);
let modal = Self::new(delegate, 34., cx);
modal
@@ -95,7 +107,13 @@ impl RecentProjects {
}
pub fn open_popover(workspace: WeakView<Workspace>, cx: &mut WindowContext<'_>) -> View<Self> {
- cx.new_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx))
+ cx.new_view(|cx| {
+ Self::new(
+ RecentProjectsDelegate::new(workspace, false, false),
+ 20.,
+ cx,
+ )
+ })
}
}
@@ -127,17 +145,19 @@ pub struct RecentProjectsDelegate {
selected_match_index: usize,
matches: Vec<StringMatch>,
render_paths: bool,
+ create_new_window: bool,
// Flag to reset index when there is a new query vs not reset index when user delete an item
reset_selected_match_index: bool,
}
impl RecentProjectsDelegate {
- fn new(workspace: WeakView<Workspace>, render_paths: bool) -> Self {
+ fn new(workspace: WeakView<Workspace>, create_new_window: bool, render_paths: bool) -> Self {
Self {
workspace,
workspaces: vec![],
selected_match_index: 0,
matches: Default::default(),
+ create_new_window,
render_paths,
reset_selected_match_index: true,
}
@@ -148,10 +168,19 @@ impl PickerDelegate for RecentProjectsDelegate {
type ListItem = ListItem;
fn placeholder_text(&self, cx: &mut WindowContext) -> Arc<str> {
+ let (create_window, reuse_window) = if self.create_new_window {
+ (
+ cx.keystroke_text_for(&menu::Confirm),
+ cx.keystroke_text_for(&menu::SecondaryConfirm),
+ )
+ } else {
+ (
+ cx.keystroke_text_for(&menu::SecondaryConfirm),
+ cx.keystroke_text_for(&menu::Confirm),
+ )
+ };
Arc::from(format!(
- "{} reuses the window, {} opens a new one",
- cx.keystroke_text_for(&menu::Confirm),
- cx.keystroke_text_for(&menu::SecondaryConfirm),
+ "{reuse_window} reuses the window, {create_window} opens a new one",
))
}
@@ -220,7 +249,11 @@ impl PickerDelegate for RecentProjectsDelegate {
{
let (candidate_workspace_id, candidate_workspace_location) =
&self.workspaces[selected_match.candidate_id];
- let replace_current_window = !secondary;
+ let replace_current_window = if self.create_new_window {
+ secondary
+ } else {
+ !secondary
+ };
workspace
.update(cx, |workspace, cx| {
if workspace.database_id() != *candidate_workspace_id {
@@ -539,7 +572,12 @@ mod tests {
workspace: &WindowHandle<Workspace>,
cx: &mut TestAppContext,
) -> View<Picker<RecentProjectsDelegate>> {
- cx.dispatch_action((*workspace).into(), OpenRecent);
+ cx.dispatch_action(
+ (*workspace).into(),
+ OpenRecent {
+ create_new_window: false,
+ },
+ );
workspace
.update(cx, |workspace, cx| {
workspace
@@ -37,7 +37,12 @@ pub fn app_menus() -> Vec<Menu<'static>> {
MenuItem::action("New Window", workspace::NewWindow),
MenuItem::separator(),
MenuItem::action("Openβ¦", workspace::Open),
- MenuItem::action("Open Recent...", recent_projects::OpenRecent),
+ MenuItem::action(
+ "Open Recent...",
+ recent_projects::OpenRecent {
+ create_new_window: false,
+ },
+ ),
MenuItem::separator(),
MenuItem::action("Add Folder to Projectβ¦", workspace::AddFolderToProject),
MenuItem::action("Save", workspace::Save { save_intent: None }),