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