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