Move open command handler to workspace global action

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

gpui/src/app.rs          |  6 +++---
zed/src/main.rs          | 24 +++---------------------
zed/src/menus.rs         |  2 +-
zed/src/workspace/mod.rs | 24 ++++++++++++++++++++++--
4 files changed, 29 insertions(+), 27 deletions(-)

Detailed changes

gpui/src/app.rs πŸ”—

@@ -77,7 +77,7 @@ pub enum MenuItem<'a> {
         name: &'a str,
         keystroke: Option<&'a str>,
         action: &'a str,
-        arg: Option<Box<dyn Any>>,
+        arg: Option<Box<dyn Any + 'static>>,
     },
     Separator,
 }
@@ -172,7 +172,7 @@ impl App {
 
     pub fn on_menu_command<F>(self, mut callback: F) -> Self
     where
-        F: 'static + FnMut(&str, Option<&dyn Any>, &mut MutableAppContext),
+        F: 'static + FnMut(&str, Option<&(dyn Any + 'static)>, &mut MutableAppContext),
     {
         let ctx = self.0.clone();
         self.0
@@ -646,7 +646,7 @@ impl MutableAppContext {
         self.dispatch_global_action_with_dyn_arg(name, Box::new(arg).as_ref());
     }
 
-    fn dispatch_global_action_with_dyn_arg(&mut self, name: &str, arg: &dyn Any) {
+    pub fn dispatch_global_action_with_dyn_arg(&mut self, name: &str, arg: &dyn Any) {
         if let Some((name, mut handlers)) = self.global_actions.remove_entry(name) {
             self.pending_flushes += 1;
             for handler in handlers.iter_mut().rev() {

zed/src/main.rs πŸ”—

@@ -16,27 +16,9 @@ fn main() {
     let app = gpui::App::new(assets::Assets).unwrap();
     let (_, settings_rx) = settings::channel(&app.font_cache()).unwrap();
     app.set_menus(menus::menus(settings_rx.clone()));
-    app.on_menu_command(move |command, arg, ctx| match command {
-        "app:open" => {
-            if let Some(paths) = ctx.platform().prompt_for_paths(PathPromptOptions {
-                files: true,
-                directories: true,
-                multiple: true,
-            }) {
-                ctx.dispatch_global_action(
-                    "workspace:open_paths",
-                    OpenParams {
-                        paths,
-                        settings: arg
-                            .unwrap()
-                            .downcast_ref::<Receiver<Settings>>()
-                            .unwrap()
-                            .clone(),
-                    },
-                );
-            }
-        }
-        _ => ctx.dispatch_global_action(command, ()),
+    app.on_menu_command(move |command, arg, ctx| {
+        eprintln!("command: {:?} {:?}", command, arg);
+        ctx.dispatch_global_action_with_dyn_arg(command, arg.unwrap_or(&()))
     })
     .run(move |ctx| {
         workspace::init(ctx);

zed/src/menus.rs πŸ”—

@@ -27,7 +27,7 @@ pub fn menus(settings: Receiver<Settings>) -> Vec<Menu<'static>> {
             items: vec![MenuItem::Action {
                 name: "Open…",
                 keystroke: Some("cmd-o"),
-                action: "app:open",
+                action: "workspace:open",
                 arg: Some(Box::new(settings)),
             }],
         },

zed/src/workspace/mod.rs πŸ”—

@@ -8,11 +8,15 @@ pub use pane_group::*;
 pub use workspace::*;
 pub use workspace_view::*;
 
-use crate::{settings::Settings, watch};
-use gpui::MutableAppContext;
+use crate::{
+    settings::Settings,
+    watch::{self, Receiver},
+};
+use gpui::{MutableAppContext, PathPromptOptions};
 use std::path::PathBuf;
 
 pub fn init(app: &mut MutableAppContext) {
+    app.add_global_action("workspace:open", open);
     app.add_global_action("workspace:open_paths", open_paths);
     app.add_global_action("app:quit", quit);
     pane::init(app);
@@ -24,6 +28,22 @@ pub struct OpenParams {
     pub settings: watch::Receiver<Settings>,
 }
 
+fn open(settings: &Receiver<Settings>, ctx: &mut MutableAppContext) {
+    if let Some(paths) = ctx.platform().prompt_for_paths(PathPromptOptions {
+        files: true,
+        directories: true,
+        multiple: true,
+    }) {
+        ctx.dispatch_global_action(
+            "workspace:open_paths",
+            OpenParams {
+                paths,
+                settings: settings.clone(),
+            },
+        );
+    }
+}
+
 fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
     log::info!("open paths {:?}", params.paths);