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