diff --git a/assets/keymaps/atom.json b/assets/keymaps/atom.json new file mode 100644 index 0000000000..766c46c133 --- /dev/null +++ b/assets/keymaps/atom.json @@ -0,0 +1,68 @@ +[ + { + "bindings": { + "cmd-k cmd-p": "workspace::ActivatePreviousPane", + "cmd-k cmd-n": "workspace::ActivateNextPane" + } + }, + { + "context": "Editor", + "bindings": { + "cmd-b": "editor::GoToDefinition", + "cmd-<": "editor::ScrollCursorCenter", + "cmd-g": [ + "editor::SelectNext", + { + "replace_newest": true + } + ], + "ctrl-shift-down": "editor::AddSelectionBelow", + "ctrl-shift-up": "editor::AddSelectionAbove", + "cmd-shift-backspace": "editor::DeleteToBeginningOfLine" + } + }, + { + "context": "Editor && mode == full", + "bindings": { + "cmd-r": "outline::Toggle" + } + }, + { + "context": "BufferSearchBar", + "bindings": { + "cmd-f3": "search::SelectNextMatch", + "cmd-shift-f3": "search::SelectPrevMatch" + } + }, + { + "context": "Workspace", + "bindings": { + "cmd-\\": "workspace::ToggleLeftSidebar", + "cmd-k cmd-b": "workspace::ToggleLeftSidebar", + "cmd-t": "file_finder::Toggle", + "cmd-shift-r": "project_symbols::Toggle" + } + }, + { + "context": "Pane", + "bindings": { + "alt-cmd-/": "search::ToggleRegex", + "ctrl-0": "project_panel::ToggleFocus" + } + }, + { + "context": "ProjectPanel", + "bindings": { + "ctrl-[": "project_panel::CollapseSelectedEntry", + "ctrl-b": "project_panel::CollapseSelectedEntry", + "h": "project_panel::CollapseSelectedEntry", + "ctrl-]": "project_panel::ExpandSelectedEntry", + "ctrl-f": "project_panel::ExpandSelectedEntry", + "ctrl-shift-c": "project_panel::CopyPath" + } + }, + { + "context": "Dock", + "bindings": {} + } +] \ No newline at end of file diff --git a/assets/keymaps/jetbrains.json b/assets/keymaps/jetbrains.json new file mode 100644 index 0000000000..2e6e5e77e6 --- /dev/null +++ b/assets/keymaps/jetbrains.json @@ -0,0 +1,78 @@ +[ + { + "bindings": { + "cmd-shift-[": "pane::ActivatePrevItem", + "cmd-shift-]": "pane::ActivateNextItem" + } + }, + { + "context": "Editor", + "bindings": { + "ctrl->": "zed::IncreaseBufferFontSize", + "ctrl-<": "zed::DecreaseBufferFontSize", + "cmd-d": "editor::DuplicateLine", + "cmd-pagedown": "editor::MovePageDown", + "cmd-pageup": "editor::MovePageUp", + "ctrl-alt-shift-b": "editor::SelectToPreviousWordStart", + "shift-enter": "editor::NewlineBelow", + "cmd--": "editor::Fold", + "cmd-=": "editor::UnfoldLines", + "alt-shift-g": "editor::SplitSelectionIntoLines", + "ctrl-g": [ + "editor::SelectNext", + { + "replace_newest": false + } + ], + "cmd-/": [ + "editor::ToggleComments", + { + "advance_downwards": true + } + ], + "shift-alt-up": "editor::MoveLineUp", + "shift-alt-down": "editor::MoveLineDown", + "cmd-[": "pane::GoBack", + "cmd-]": "pane::GoForward", + "alt-f7": "editor::FindAllReferences", + "cmd-alt-f7": "editor::FindAllReferences", + "cmd-b": "editor::GoToDefinition", + "cmd-alt-b": "editor::GoToDefinition", + "cmd-shift-b": "editor::GoToTypeDefinition", + "alt-enter": "editor::ToggleCodeActions", + "f2": "editor::GoToDiagnostic", + "cmd-f2": "editor::GoToPrevDiagnostic", + "ctrl-alt-shift-down": "editor::GoToHunk", + "ctrl-alt-shift-up": "editor::GoToPrevHunk", + "cmd-home": "editor::MoveToBeginning", + "cmd-end": "editor::MoveToEnd", + "cmd-shift-home": "editor::SelectToBeginning", + "cmd-shift-end": "editor::SelectToEnd" + } + }, + { + "context": "Editor && mode == full", + "bindings": { + "cmd-f12": "outline::Toggle", + "cmd-7": "outline::Toggle", + "cmd-shift-o": "file_finder::Toggle", + "cmd-l": "go_to_line::Toggle" + } + }, + { + "context": "Workspace", + "bindings": { + "cmd-shift-a": "command_palette::Toggle", + "cmd-alt-o": "project_symbols::Toggle", + "cmd-1": "workspace::ToggleLeftSidebar", + "cmd-6": "diagnostics::Deploy", + "alt-f12": "dock::FocusDock" + } + }, + { + "context": "Dock", + "bindings": { + "alt-f12": "dock::HideDock" + } + } +] \ No newline at end of file diff --git a/assets/keymaps/sublime_text.json b/assets/keymaps/sublime_text.json new file mode 100644 index 0000000000..1d3dd887d7 --- /dev/null +++ b/assets/keymaps/sublime_text.json @@ -0,0 +1,60 @@ +[ + { + "bindings": { + "cmd-shift-[": "pane::ActivatePrevItem", + "cmd-shift-]": "pane::ActivateNextItem", + "ctrl-pagedown": "pane::ActivatePrevItem", + "ctrl-pageup": "pane::ActivateNextItem", + "ctrl-shift-tab": "pane::ActivateNextItem", + "ctrl-tab": "pane::ActivatePrevItem", + "cmd-+": "zed::IncreaseBufferFontSize" + } + }, + { + "context": "Editor", + "bindings": { + "ctrl-shift-up": "editor::AddSelectionAbove", + "ctrl-shift-down": "editor::AddSelectionBelow", + "cmd-shift-space": "editor::SelectAll", + "ctrl-shift-m": "editor::SelectLargerSyntaxNode", + "cmd-shift-a": "editor::SelectLargerSyntaxNode", + "shift-f12": "editor::FindAllReferences", + "alt-cmd-down": "editor::GoToDefinition", + "alt-shift-cmd-down": "editor::FindAllReferences", + "ctrl-.": "editor::GoToHunk", + "ctrl-,": "editor::GoToPrevHunk", + "ctrl-backspace": "editor::DeleteToPreviousWordStart", + "ctrl-delete": "editor::DeleteToNextWordEnd" + } + }, + { + "context": "Editor && mode == full", + "bindings": { + "cmd-r": "outline::Toggle" + } + }, + { + "context": "Pane", + "bindings": { + "f4": "search::SelectNextMatch", + "shift-f4": "search::SelectPrevMatch" + } + }, + { + "context": "Workspace", + "bindings": { + "ctrl-`": "dock::FocusDock", + "cmd-k cmd-b": "workspace::ToggleLeftSidebar", + "cmd-t": "file_finder::Toggle", + "shift-cmd-r": "project_symbols::Toggle", + // Currently busted: https://github.com/zed-industries/feedback/issues/898 + "ctrl-0": "project_panel::ToggleFocus" + } + }, + { + "context": "Dock", + "bindings": { + "ctrl-`": "dock::HideDock" + } + } +] \ No newline at end of file diff --git a/crates/install_cli/src/install_cli.rs b/crates/install_cli/src/install_cli.rs index 06561a28f8..adf50586d7 100644 --- a/crates/install_cli/src/install_cli.rs +++ b/crates/install_cli/src/install_cli.rs @@ -1,11 +1,10 @@ use std::path::Path; -use anyhow::{Result, anyhow}; -use gpui::{AsyncAppContext, actions}; +use anyhow::{anyhow, Result}; +use gpui::{actions, AsyncAppContext}; use util::ResultExt; -actions!(cli, [ Install ]); - +actions!(cli, [Install]); pub async fn install_cli(cx: &AsyncAppContext) -> Result<()> { let cli_path = cx.platform().path_for_auxiliary_executable("cli")?; @@ -53,4 +52,4 @@ pub async fn install_cli(cx: &AsyncAppContext) -> Result<()> { } else { Err(anyhow!("error running osascript")) } -} \ No newline at end of file +} diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 01992d9431..9048719d3f 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -1,4 +1,4 @@ -use crate::parse_json_with_comments; +use crate::{parse_json_with_comments, Settings}; use anyhow::{Context, Result}; use assets::Assets; use collections::BTreeMap; @@ -45,6 +45,10 @@ impl KeymapFileContent { for path in ["keymaps/default.json", "keymaps/vim.json"] { Self::load(path, cx).unwrap(); } + + if let Some(base_keymap) = cx.global::().base_keymap { + Self::load(base_keymap.asset_path(), cx).log_err(); + } } pub fn load(asset_path: &str, cx: &mut MutableAppContext) -> Result<()> { diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 501a88c42e..ae67428948 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -24,6 +24,7 @@ use tree_sitter::Query; use util::ResultExt as _; pub use keymap_file::{keymap_file_json_schema, KeymapFileContent}; +pub use watched_json::watch_files; #[derive(Clone)] pub struct Settings { @@ -54,6 +55,24 @@ pub struct Settings { pub telemetry_defaults: TelemetrySettings, pub telemetry_overrides: TelemetrySettings, pub auto_update: bool, + pub base_keymap: Option, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub enum BaseKeymap { + JetBrains, + Sublime, + Atom, +} + +impl BaseKeymap { + pub fn asset_path(&self) -> &str { + match self { + BaseKeymap::JetBrains => "keymaps/jetbrains.json", + BaseKeymap::Sublime => "keymaps/sublime_text.json", + BaseKeymap::Atom => "keymaps/atom.json", + } + } } #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] @@ -326,6 +345,8 @@ pub struct SettingsFileContent { pub telemetry: TelemetrySettings, #[serde(default)] pub auto_update: Option, + #[serde(default)] + pub base_keymap: Option, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] @@ -396,6 +417,7 @@ impl Settings { telemetry_defaults: defaults.telemetry, telemetry_overrides: Default::default(), auto_update: defaults.auto_update.unwrap(), + base_keymap: Default::default(), } } @@ -433,6 +455,7 @@ impl Settings { merge(&mut self.vim_mode, data.vim_mode); merge(&mut self.autosave, data.autosave); merge(&mut self.default_dock_anchor, data.default_dock_anchor); + merge(&mut self.base_keymap, Some(data.base_keymap)); // Ensure terminal font is loaded, so we can request it in terminal_element layout if let Some(terminal_font) = &data.terminal.font_family { @@ -610,6 +633,7 @@ impl Settings { }, telemetry_overrides: Default::default(), auto_update: true, + base_keymap: None, } } diff --git a/crates/settings/src/watched_json.rs b/crates/settings/src/watched_json.rs index e304842aa2..c4cc64cd62 100644 --- a/crates/settings/src/watched_json.rs +++ b/crates/settings/src/watched_json.rs @@ -62,7 +62,18 @@ where } } -pub fn watch_settings_file( +pub fn watch_files( + defaults: Settings, + settings_file: WatchedJsonFile, + theme_registry: Arc, + keymap_file: WatchedJsonFile, + cx: &mut MutableAppContext, +) { + watch_settings_file(defaults, settings_file, theme_registry, cx); + watch_keymap_file(keymap_file, cx); +} + +pub(crate) fn watch_settings_file( defaults: Settings, mut file: WatchedJsonFile, theme_registry: Arc, @@ -77,13 +88,13 @@ pub fn watch_settings_file( .detach(); } -pub fn keymap_updated(content: KeymapFileContent, cx: &mut MutableAppContext) { +fn keymap_updated(content: KeymapFileContent, cx: &mut MutableAppContext) { cx.clear_bindings(); KeymapFileContent::load_defaults(cx); content.add_to_cx(cx).log_err(); } -pub fn settings_updated( +fn settings_updated( defaults: &Settings, content: SettingsFileContent, theme_registry: &Arc, @@ -95,10 +106,20 @@ pub fn settings_updated( cx.refresh_windows(); } -pub fn watch_keymap_file(mut file: WatchedJsonFile, cx: &mut MutableAppContext) { +fn watch_keymap_file(mut file: WatchedJsonFile, cx: &mut MutableAppContext) { cx.spawn(|mut cx| async move { + let mut settings_subscription = None; while let Some(content) = file.0.recv().await { - cx.update(|cx| keymap_updated(content, cx)); + cx.update(|cx| { + let old_base_keymap = cx.global::().base_keymap; + keymap_updated(content.clone(), cx); + settings_subscription = Some(cx.observe_global::(move |cx| { + let settings = cx.global::(); + if settings.base_keymap != old_base_keymap { + keymap_updated(content.clone(), cx); + } + })); + }); } }) .detach(); diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 0930bf0484..ae3278b711 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -47,11 +47,7 @@ impl ThemeSelector { let mut theme_names = registry .list(**cx.default_global::()) .collect::>(); - theme_names.sort_unstable_by(|a, b| { - a.is_light - .cmp(&b.is_light) - .then(a.name.cmp(&b.name)) - }); + theme_names.sort_unstable_by(|a, b| a.is_light.cmp(&b.is_light).then(a.name.cmp(&b.name))); let matches = theme_names .iter() .map(|meta| StringMatch { diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index dc864a3ad1..8bb055dad0 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -84,7 +84,8 @@ impl View for WelcomePage { ]) .constrained() .with_max_width(width) - .contained().with_uniform_padding(10.) + .contained() + .with_uniform_padding(10.) .aligned() .boxed(), ) @@ -174,7 +175,10 @@ impl WelcomePage { } }) .boxed(), - Label::new(label, style.label.text.clone()).contained().with_style(style.label.container).boxed(), + Label::new(label, style.label.text.clone()) + .contained() + .with_style(style.label.container) + .boxed(), ]) .align_children_center() .boxed() diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 234c40c69d..e74bcdc177 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -17,7 +17,7 @@ mod toolbar; pub use smallvec; -use anyhow::{anyhow, Result, Context}; +use anyhow::{anyhow, Context, Result}; use call::ActiveCall; use client::{ proto::{self, PeerId}, @@ -267,27 +267,30 @@ pub fn init(app_state: Arc, cx: &mut MutableAppContext) { }) }, ); - + cx.add_action(|_: &mut Workspace, _: &install_cli::Install, cx| { cx.spawn(|workspace, mut cx| async move { - let err = install_cli::install_cli(&cx).await.context("Failed to create CLI symlink"); - + let err = install_cli::install_cli(&cx) + .await + .context("Failed to create CLI symlink"); + cx.update(|cx| { workspace.update(cx, |workspace, cx| { if matches!(err, Err(_)) { err.notify_err(workspace, cx); } else { workspace.show_notification(1, cx, |cx| { - cx.add_view(|_| MessageNotification::new_message("Successfully installed the 'zed' binary")) + cx.add_view(|_| { + MessageNotification::new_message( + "Successfully installed the `zed` binary", + ) + }) }); } }) }) - - }).detach(); - - - + }) + .detach(); }); let client = &app_state.client; diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index a9625bf78e..8407bd4516 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -38,7 +38,7 @@ use std::{ use terminal_view::{get_working_directory, TerminalView}; use fs::RealFs; -use settings::watched_json::{watch_keymap_file, watch_settings_file, WatchedJsonFile}; +use settings::watched_json::WatchedJsonFile; use theme::ThemeRegistry; #[cfg(debug_assertions)] use util::StaffMode; @@ -123,7 +123,14 @@ fn main() { fs.clone(), )); - watch_settings_file(default_settings, settings_file_content, themes.clone(), cx); + settings::watch_files( + default_settings, + settings_file_content, + themes.clone(), + keymap_file, + cx, + ); + if !stdout_is_a_pty() { upload_previous_panics(http.clone(), cx); } @@ -136,8 +143,6 @@ fn main() { languages::init(languages.clone()); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx)); - watch_keymap_file(keymap_file, cx); - cx.set_global(client.clone()); context_menu::init(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 71e4b48db3..2fb956f5b6 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -21,7 +21,7 @@ use gpui::{ geometry::vector::vec2f, impl_actions, platform::{WindowBounds, WindowOptions}, - AssetSource, Platform, PromptLevel, TitlebarOptions, ViewContext, WindowKind, + AssetSource, Platform, PromptLevel, TitlebarOptions, ViewContext, WindowKind, }; use language::Rope; pub use lsp; @@ -144,8 +144,12 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { }); }); cx.add_global_action(move |_: &install_cli::Install, cx| { - cx.spawn(|cx| async move { install_cli::install_cli(&cx).await.context("error creating CLI symlink") }) - .detach_and_log_err(cx); + cx.spawn(|cx| async move { + install_cli::install_cli(&cx) + .await + .context("error creating CLI symlink") + }) + .detach_and_log_err(cx); }); cx.add_action({ let app_state = app_state.clone();