keymap_ui: Add open keymap JSON button (#36182)

Ben Kunkle created

Closes #ISSUE

Release Notes:

- Keymap Editor: Added a button in the top left to allow opening the
keymap JSON file. Right clicking the button provides shortcuts to
opening the default Zed and Vim keymaps as well.

Change summary

Cargo.lock                            |  2 ++
assets/icons/json.svg                 |  4 ++++
crates/icons/src/icons.rs             |  1 +
crates/settings_ui/Cargo.toml         |  2 ++
crates/settings_ui/src/keybindings.rs | 29 ++++++++++++++++++++++++++++-
5 files changed, 37 insertions(+), 1 deletion(-)

Detailed changes

Cargo.lock 🔗

@@ -15054,8 +15054,10 @@ dependencies = [
  "ui",
  "ui_input",
  "util",
+ "vim",
  "workspace",
  "workspace-hack",
+ "zed_actions",
 ]
 
 [[package]]

assets/icons/json.svg 🔗

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.78125 3C3.90625 3 3.90625 4.5 3.90625 5.5C3.90625 6.5 3.40625 7.50106 2.40625 8C3.40625 8.50106 3.90625 9.5 3.90625 10.5C3.90625 11.5 3.90625 13 5.78125 13" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M10.2422 3C12.1172 3 12.1172 4.5 12.1172 5.5C12.1172 6.5 12.6172 7.50106 13.6172 8C12.6172 8.50106 12.1172 9.5 12.1172 10.5C12.1172 11.5 12.1172 13 10.2422 13" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

crates/settings_ui/Cargo.toml 🔗

@@ -42,8 +42,10 @@ tree-sitter-rust.workspace = true
 ui.workspace = true
 ui_input.workspace = true
 util.workspace = true
+vim.workspace = true
 workspace-hack.workspace = true
 workspace.workspace = true
+zed_actions.workspace = true
 
 [dev-dependencies]
 db = {"workspace"= true, "features" = ["test-support"]}

crates/settings_ui/src/keybindings.rs 🔗

@@ -23,7 +23,7 @@ use settings::{BaseKeymap, KeybindSource, KeymapFile, Settings as _, SettingsAss
 use ui::{
     ActiveTheme as _, App, Banner, BorrowAppContext, ContextMenu, IconButtonShape, Indicator,
     Modal, ModalFooter, ModalHeader, ParentElement as _, Render, Section, SharedString,
-    Styled as _, Tooltip, Window, prelude::*,
+    Styled as _, Tooltip, Window, prelude::*, right_click_menu,
 };
 use ui_input::SingleLineInput;
 use util::ResultExt;
@@ -1536,6 +1536,33 @@ impl Render for KeymapEditor {
                     .child(
                         h_flex()
                             .gap_2()
+                            .child(
+                                right_click_menu("open-keymap-menu")
+                                    .menu(|window, cx| {
+                                        ContextMenu::build(window, cx, |menu, _, _| {
+                                            menu.header("Open Keymap JSON")
+                                                .action("User", zed_actions::OpenKeymap.boxed_clone())
+                                                .action("Zed Default", zed_actions::OpenDefaultKeymap.boxed_clone())
+                                                .action("Vim Default", vim::OpenDefaultKeymap.boxed_clone())
+                                        })
+                                    })
+                                    .anchor(gpui::Corner::TopLeft)
+                                    .trigger(|open, _, _|
+                                        IconButton::new(
+                                            "OpenKeymapJsonButton",
+                                            IconName::Json
+                                        )
+                                        .shape(ui::IconButtonShape::Square)
+                                        .when(!open, |this|
+                                            this.tooltip(move |window, cx| {
+                                                Tooltip::with_meta("Open Keymap JSON", Some(&zed_actions::OpenKeymap),"Right click to view more options", window, cx)
+                                            })
+                                        )
+                                        .on_click(|_, window, cx| {
+                                            window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
+                                        })
+                                    )
+                            )
                             .child(
                                 div()
                                     .key_context({