1use std::fmt::{Display, Formatter};
2
3use crate::{self as settings};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use settings::{Settings, SettingsSources, VsCodeSettings};
7use settings_ui_macros::{SettingsKey, SettingsUi};
8
9/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
10///
11/// Default: VSCode
12#[derive(
13 Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default, SettingsUi,
14)]
15pub enum BaseKeymap {
16 #[default]
17 VSCode,
18 JetBrains,
19 SublimeText,
20 Atom,
21 TextMate,
22 Emacs,
23 Cursor,
24 None,
25}
26
27impl Display for BaseKeymap {
28 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29 match self {
30 BaseKeymap::VSCode => write!(f, "VSCode"),
31 BaseKeymap::JetBrains => write!(f, "JetBrains"),
32 BaseKeymap::SublimeText => write!(f, "Sublime Text"),
33 BaseKeymap::Atom => write!(f, "Atom"),
34 BaseKeymap::TextMate => write!(f, "TextMate"),
35 BaseKeymap::Emacs => write!(f, "Emacs (beta)"),
36 BaseKeymap::Cursor => write!(f, "Cursor (beta)"),
37 BaseKeymap::None => write!(f, "None"),
38 }
39 }
40}
41
42impl BaseKeymap {
43 #[cfg(target_os = "macos")]
44 pub const OPTIONS: [(&'static str, Self); 7] = [
45 ("VSCode (Default)", Self::VSCode),
46 ("Atom", Self::Atom),
47 ("JetBrains", Self::JetBrains),
48 ("Sublime Text", Self::SublimeText),
49 ("Emacs (beta)", Self::Emacs),
50 ("TextMate", Self::TextMate),
51 ("Cursor", Self::Cursor),
52 ];
53
54 #[cfg(not(target_os = "macos"))]
55 pub const OPTIONS: [(&'static str, Self); 6] = [
56 ("VSCode (Default)", Self::VSCode),
57 ("Atom", Self::Atom),
58 ("JetBrains", Self::JetBrains),
59 ("Sublime Text", Self::SublimeText),
60 ("Emacs (beta)", Self::Emacs),
61 ("Cursor", Self::Cursor),
62 ];
63
64 pub fn asset_path(&self) -> Option<&'static str> {
65 #[cfg(target_os = "macos")]
66 match self {
67 BaseKeymap::JetBrains => Some("keymaps/macos/jetbrains.json"),
68 BaseKeymap::SublimeText => Some("keymaps/macos/sublime_text.json"),
69 BaseKeymap::Atom => Some("keymaps/macos/atom.json"),
70 BaseKeymap::TextMate => Some("keymaps/macos/textmate.json"),
71 BaseKeymap::Emacs => Some("keymaps/macos/emacs.json"),
72 BaseKeymap::Cursor => Some("keymaps/macos/cursor.json"),
73 BaseKeymap::VSCode => None,
74 BaseKeymap::None => None,
75 }
76
77 #[cfg(not(target_os = "macos"))]
78 match self {
79 BaseKeymap::JetBrains => Some("keymaps/linux/jetbrains.json"),
80 BaseKeymap::SublimeText => Some("keymaps/linux/sublime_text.json"),
81 BaseKeymap::Atom => Some("keymaps/linux/atom.json"),
82 BaseKeymap::Emacs => Some("keymaps/linux/emacs.json"),
83 BaseKeymap::Cursor => Some("keymaps/linux/cursor.json"),
84 BaseKeymap::TextMate => None,
85 BaseKeymap::VSCode => None,
86 BaseKeymap::None => None,
87 }
88 }
89
90 pub fn names() -> impl Iterator<Item = &'static str> {
91 Self::OPTIONS.iter().map(|(name, _)| *name)
92 }
93
94 pub fn from_names(option: &str) -> BaseKeymap {
95 Self::OPTIONS
96 .iter()
97 .copied()
98 .find_map(|(name, value)| (name == option).then_some(value))
99 .unwrap_or_default()
100 }
101}
102
103#[derive(
104 Copy,
105 Clone,
106 Debug,
107 Serialize,
108 Deserialize,
109 JsonSchema,
110 PartialEq,
111 Eq,
112 Default,
113 SettingsUi,
114 SettingsKey,
115)]
116// extracted so that it can be an option, and still work with derive(SettingsUi)
117#[settings_key(None)]
118pub struct BaseKeymapSetting {
119 pub base_keymap: Option<BaseKeymap>,
120}
121
122impl Settings for BaseKeymap {
123 type FileContent = BaseKeymapSetting;
124
125 fn load(
126 sources: SettingsSources<Self::FileContent>,
127 _: &mut gpui::App,
128 ) -> anyhow::Result<Self> {
129 if let Some(Some(user_value)) = sources.user.map(|setting| setting.base_keymap) {
130 return Ok(user_value);
131 }
132 if let Some(Some(server_value)) = sources.server.map(|setting| setting.base_keymap) {
133 return Ok(server_value);
134 }
135 sources
136 .default
137 .base_keymap
138 .ok_or_else(Self::missing_default)
139 }
140
141 fn import_from_vscode(_vscode: &VsCodeSettings, current: &mut Self::FileContent) {
142 current.base_keymap = Some(BaseKeymap::VSCode);
143 }
144}