base_keymap_setting.rs

  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}