base_keymap_setting.rs

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