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