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}
 45impl Into<BaseKeymapContent> for BaseKeymap {
 46    fn into(self) -> BaseKeymapContent {
 47        match self {
 48            BaseKeymap::VSCode => BaseKeymapContent::VSCode,
 49            BaseKeymap::JetBrains => BaseKeymapContent::JetBrains,
 50            BaseKeymap::SublimeText => BaseKeymapContent::SublimeText,
 51            BaseKeymap::Atom => BaseKeymapContent::Atom,
 52            BaseKeymap::TextMate => BaseKeymapContent::TextMate,
 53            BaseKeymap::Emacs => BaseKeymapContent::Emacs,
 54            BaseKeymap::Cursor => BaseKeymapContent::Cursor,
 55            BaseKeymap::None => BaseKeymapContent::None,
 56        }
 57    }
 58}
 59
 60impl Display for BaseKeymap {
 61    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 62        match self {
 63            BaseKeymap::VSCode => write!(f, "VSCode"),
 64            BaseKeymap::JetBrains => write!(f, "JetBrains"),
 65            BaseKeymap::SublimeText => write!(f, "Sublime Text"),
 66            BaseKeymap::Atom => write!(f, "Atom"),
 67            BaseKeymap::TextMate => write!(f, "TextMate"),
 68            BaseKeymap::Emacs => write!(f, "Emacs (beta)"),
 69            BaseKeymap::Cursor => write!(f, "Cursor (beta)"),
 70            BaseKeymap::None => write!(f, "None"),
 71        }
 72    }
 73}
 74
 75impl BaseKeymap {
 76    #[cfg(target_os = "macos")]
 77    pub const OPTIONS: [(&'static str, Self); 7] = [
 78        ("VSCode (Default)", Self::VSCode),
 79        ("Atom", Self::Atom),
 80        ("JetBrains", Self::JetBrains),
 81        ("Sublime Text", Self::SublimeText),
 82        ("Emacs (beta)", Self::Emacs),
 83        ("TextMate", Self::TextMate),
 84        ("Cursor", Self::Cursor),
 85    ];
 86
 87    #[cfg(not(target_os = "macos"))]
 88    pub const OPTIONS: [(&'static str, Self); 6] = [
 89        ("VSCode (Default)", Self::VSCode),
 90        ("Atom", Self::Atom),
 91        ("JetBrains", Self::JetBrains),
 92        ("Sublime Text", Self::SublimeText),
 93        ("Emacs (beta)", Self::Emacs),
 94        ("Cursor", Self::Cursor),
 95    ];
 96
 97    pub fn asset_path(&self) -> Option<&'static str> {
 98        #[cfg(target_os = "macos")]
 99        match self {
100            BaseKeymap::JetBrains => Some("keymaps/macos/jetbrains.json"),
101            BaseKeymap::SublimeText => Some("keymaps/macos/sublime_text.json"),
102            BaseKeymap::Atom => Some("keymaps/macos/atom.json"),
103            BaseKeymap::TextMate => Some("keymaps/macos/textmate.json"),
104            BaseKeymap::Emacs => Some("keymaps/macos/emacs.json"),
105            BaseKeymap::Cursor => Some("keymaps/macos/cursor.json"),
106            BaseKeymap::VSCode => None,
107            BaseKeymap::None => None,
108        }
109
110        #[cfg(not(target_os = "macos"))]
111        match self {
112            BaseKeymap::JetBrains => Some("keymaps/linux/jetbrains.json"),
113            BaseKeymap::SublimeText => Some("keymaps/linux/sublime_text.json"),
114            BaseKeymap::Atom => Some("keymaps/linux/atom.json"),
115            BaseKeymap::Emacs => Some("keymaps/linux/emacs.json"),
116            BaseKeymap::Cursor => Some("keymaps/linux/cursor.json"),
117            BaseKeymap::TextMate => None,
118            BaseKeymap::VSCode => None,
119            BaseKeymap::None => None,
120        }
121    }
122
123    pub fn names() -> impl Iterator<Item = &'static str> {
124        Self::OPTIONS.iter().map(|(name, _)| *name)
125    }
126
127    pub fn from_names(option: &str) -> BaseKeymap {
128        Self::OPTIONS
129            .iter()
130            .copied()
131            .find_map(|(name, value)| (name == option).then_some(value))
132            .unwrap_or_default()
133    }
134}
135
136#[derive(
137    Copy,
138    Clone,
139    Debug,
140    Serialize,
141    Deserialize,
142    JsonSchema,
143    PartialEq,
144    Eq,
145    Default,
146    SettingsUi,
147    SettingsKey,
148)]
149// extracted so that it can be an option, and still work with derive(SettingsUi)
150#[settings_key(None)]
151pub struct BaseKeymapSetting {
152    pub base_keymap: Option<BaseKeymap>,
153}
154
155impl Settings for BaseKeymap {
156    fn from_defaults(s: &crate::settings_content::SettingsContent, _cx: &mut App) -> Self {
157        s.base_keymap.unwrap().into()
158    }
159
160    fn refine(&mut self, s: &settings_content::SettingsContent, _cx: &mut App) {
161        if let Some(base_keymap) = s.base_keymap {
162            *self = base_keymap.into();
163        };
164    }
165
166    fn import_from_vscode(_vscode: &VsCodeSettings, current: &mut SettingsContent) {
167        current.base_keymap = Some(BaseKeymapContent::VSCode);
168    }
169}