From b3b71a6e5cd5202fb85980bcb97a241f55e70113 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Wed, 17 Sep 2025 10:57:30 -0500 Subject: [PATCH] wip --- crates/collab_ui/src/panel_settings.rs | 1 + .../file_finder/src/file_finder_settings.rs | 42 ++++- crates/git_ui/src/git_panel_settings.rs | 2 +- crates/go_to_line/src/cursor_position.rs | 2 +- crates/journal/src/journal.rs | 42 ++++- .../src/outline_panel_settings.rs | 158 +++++++--------- crates/settings/src/settings_content.rs | 178 +++++++++++++++++- crates/vim/src/vim.rs | 118 ++++-------- 8 files changed, 345 insertions(+), 198 deletions(-) diff --git a/crates/collab_ui/src/panel_settings.rs b/crates/collab_ui/src/panel_settings.rs index c99f299e2c03c0b152221c849134613bceb9132d..9e9a2e185bd9c24d62b075344e8fb0e61692cc46 100644 --- a/crates/collab_ui/src/panel_settings.rs +++ b/crates/collab_ui/src/panel_settings.rs @@ -19,6 +19,7 @@ pub struct NotificationPanelSettings { } #[derive(Clone, Default, Debug)] +// todo! are these settings even relevant any more? pub struct MessageEditorSettings { /// Whether to automatically replace emoji shortcodes with emoji characters. /// For example: typing `:wave:` gets replaced with `👋`. diff --git a/crates/file_finder/src/file_finder_settings.rs b/crates/file_finder/src/file_finder_settings.rs index f24b1bf2bed9e103dce2afda3daa80cca8fba26b..0ebdaa6f25612f6f79f465b38d8ea6d6dc7cf59d 100644 --- a/crates/file_finder/src/file_finder_settings.rs +++ b/crates/file_finder/src/file_finder_settings.rs @@ -1,21 +1,41 @@ use anyhow::Result; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsKey, SettingsSources, SettingsUi}; +use settings::Settings; +use util::MergeFrom; #[derive(Deserialize, Debug, Clone, Copy, PartialEq)] pub struct FileFinderSettings { pub file_icons: bool, - pub modal_max_width: Option, + pub modal_max_width: FileFinderWidth, pub skip_focus_for_active_in_search: bool, pub include_ignored: Option, } impl Settings for FileFinderSettings { - type FileContent = FileFinderSettingsContent; + fn from_defaults(content: &settings::SettingsContent, cx: &mut ui::App) -> Self { + let file_finder = content.file_finder.as_ref().unwrap(); - fn load(sources: SettingsSources, _: &mut gpui::App) -> Result { - sources.json_merge() + Self { + file_icons: file_finder.file_icons.unwrap(), + modal_max_width: file_finder.modal_max_width.unwrap().into(), + skip_focus_for_active_in_search: file_finder.skip_focus_for_active_in_search.unwrap(), + include_ignored: file_finder.include_ignored.unwrap(), + } + } + + fn refine(&mut self, content: &settings::SettingsContent, _cx: &mut ui::App) { + let Some(file_finder) = content.file_finder.as_ref() else { + return; + }; + + self.file_icons.merge_from(&file_finder.file_icons); + self.modal_max_width + .merge_from(&file_finder.modal_max_width.map(Into::into)); + self.skip_focus_for_active_in_search + .merge_from(&file_finder.skip_focus_for_active_in_search); + self.include_ignored + .merge_from(&file_finder.include_ignored); } fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {} @@ -31,3 +51,15 @@ pub enum FileFinderWidth { XLarge, Full, } + +impl From for FileFinderWidth { + fn from(content: settings::FileFinderWidthContent) -> Self { + match content { + settings::FileFinderWidthContent::Small => FileFinderWidth::Small, + settings::FileFinderWidthContent::Medium => FileFinderWidth::Medium, + settings::FileFinderWidthContent::Large => FileFinderWidth::Large, + settings::FileFinderWidthContent::XLarge => FileFinderWidth::XLarge, + settings::FileFinderWidthContent::Full => FileFinderWidth::Full, + } + } +} diff --git a/crates/git_ui/src/git_panel_settings.rs b/crates/git_ui/src/git_panel_settings.rs index 9b389945b90fbae5e2ada0a64ee7b3d463c98a5f..c82ff469857f084ce59201b359a79883056fee43 100644 --- a/crates/git_ui/src/git_panel_settings.rs +++ b/crates/git_ui/src/git_panel_settings.rs @@ -2,7 +2,7 @@ use editor::EditorSettings; use gpui::Pixels; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsContent, SettingsKey, SettingsSources, SettingsUi, StatusStyle}; +use settings::{Settings, SettingsContent, StatusStyle}; use ui::{ px, scrollbars::{ScrollbarVisibility, ShowScrollbar}, diff --git a/crates/go_to_line/src/cursor_position.rs b/crates/go_to_line/src/cursor_position.rs index 5d7e0d27d362f8b6245d8ce25774342495a90427..49ab6013478ee0fa623e051ce927fde5921fa977 100644 --- a/crates/go_to_line/src/cursor_position.rs +++ b/crates/go_to_line/src/cursor_position.rs @@ -2,7 +2,7 @@ use editor::{Editor, EditorSettings, MultiBufferSnapshot}; use gpui::{App, Entity, FocusHandle, Focusable, Subscription, Task, WeakEntity}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsKey, SettingsSources, SettingsUi}; +use settings::Settings; use std::{fmt::Write, num::NonZeroU32, time::Duration}; use text::{Point, Selection}; use ui::{ diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index 5cdfa6c1df034deaf06e1c99ea99415757b84c29..740cc2d2d8ad7149d1615995f2e3ac6b5a216f80 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -22,17 +22,16 @@ actions!( ); /// Settings specific to journaling -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)] -#[settings_key(key = "journal")] +#[derive(Clone, Debug)] pub struct JournalSettings { /// The path of the directory where journal entries are stored. /// /// Default: `~` - pub path: Option, + pub path: String, /// What format to display the hours in. /// /// Default: hour12 - pub hour_format: Option, + pub hour_format: HourFormat, } impl Default for JournalSettings { @@ -44,19 +43,44 @@ impl Default for JournalSettings { } } -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] +#[derive(Clone, Debug, Default)] pub enum HourFormat { #[default] Hour12, Hour24, } +impl From for HourFormat { + fn from(content: settings::HourFormatContent) -> Self { + match content { + settings::HourFormatContent::Hour12 => HourFormat::Hour12, + settings::HourFormatContent::Hour24 => HourFormat::Hour24, + } + } +} + impl settings::Settings for JournalSettings { - type FileContent = Self; + fn from_defaults(content: &settings::SettingsContent, cx: &mut App) -> Self { + let journal = content.journal.as_ref().unwrap(); - fn load(sources: SettingsSources, _: &mut App) -> Result { - sources.json_merge() + Self { + path: journal.path.unwrap(), + hour_format: journal.hour_format.unwrap().into(), + } + } + + fn refine(&mut self, content: &settings::SettingsContent, cx: &mut App) { + let Some(journal) = content.journal.as_ref() else { + return; + }; + + if let Some(path) = journal.path { + self.path = path; + } + + if let Some(hour_format) = journal.hour_format { + self.hour_format = hour_format.into(); + } } fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {} diff --git a/crates/outline_panel/src/outline_panel_settings.rs b/crates/outline_panel/src/outline_panel_settings.rs index db34a318188fc10b100b88f959b1c7a77b1161cb..9cbac56e891c9d081c50cf558f00308ce777e96e 100644 --- a/crates/outline_panel/src/outline_panel_settings.rs +++ b/crates/outline_panel/src/outline_panel_settings.rs @@ -1,25 +1,10 @@ use editor::EditorSettings; use gpui::{App, Pixels}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsKey, SettingsSources, SettingsUi}; +pub use settings::{OutlinePanelDockPosition, Settings, ShowIndentGuides}; use ui::scrollbars::{ScrollbarVisibility, ShowScrollbar}; +use util::MergeFrom; -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)] -#[serde(rename_all = "snake_case")] -pub enum OutlinePanelDockPosition { - Left, - Right, -} - -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(rename_all = "snake_case")] -pub enum ShowIndentGuides { - Always, - Never, -} - -#[derive(Deserialize, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct OutlinePanelSettings { pub button: bool, pub default_width: Pixels, @@ -35,7 +20,7 @@ pub struct OutlinePanelSettings { pub expand_outlines_with_depth: usize, } -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct ScrollbarSettings { /// When to show the scrollbar in the project panel. /// @@ -43,80 +28,17 @@ pub struct ScrollbarSettings { pub show: Option, } -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -pub struct ScrollbarSettingsContent { - /// When to show the scrollbar in the project panel. - /// - /// Default: inherits editor scrollbar settings - pub show: Option>, -} - -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct IndentGuidesSettings { pub show: ShowIndentGuides, } -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct IndentGuidesSettingsContent { /// When to show the scrollbar in the outline panel. pub show: Option, } -#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUi, SettingsKey)] -#[settings_key(key = "outline_panel")] -pub struct OutlinePanelSettingsContent { - /// Whether to show the outline panel button in the status bar. - /// - /// Default: true - pub button: Option, - /// Customize default width (in pixels) taken by outline panel - /// - /// Default: 240 - pub default_width: Option, - /// The position of outline panel - /// - /// Default: left - pub dock: Option, - /// Whether to show file icons in the outline panel. - /// - /// Default: true - pub file_icons: Option, - /// Whether to show folder icons or chevrons for directories in the outline panel. - /// - /// Default: true - pub folder_icons: Option, - /// Whether to show the git status in the outline panel. - /// - /// Default: true - pub git_status: Option, - /// Amount of indentation (in pixels) for nested items. - /// - /// Default: 20 - pub indent_size: Option, - /// Whether to reveal it in the outline panel automatically, - /// when a corresponding project entry becomes active. - /// Gitignored entries are never auto revealed. - /// - /// Default: true - pub auto_reveal_entries: Option, - /// Whether to fold directories automatically - /// when directory has only one directory inside. - /// - /// Default: true - pub auto_fold_dirs: Option, - /// Settings related to indent guides in the outline panel. - pub indent_guides: Option, - /// Scrollbar-related settings - pub scrollbar: Option, - /// Default depth to expand outline items in the current file. - /// The default depth to which outline entries are expanded on reveal. - /// - Set to 0 to collapse all items that have children - /// - Set to 1 or higher to collapse items at that depth or deeper - /// - /// Default: 100 - pub expand_outlines_with_depth: Option, -} - impl ScrollbarVisibility for OutlinePanelSettings { fn visibility(&self, cx: &App) -> ShowScrollbar { self.scrollbar @@ -126,21 +48,67 @@ impl ScrollbarVisibility for OutlinePanelSettings { } impl Settings for OutlinePanelSettings { - type FileContent = OutlinePanelSettingsContent; - - fn load( - sources: SettingsSources, - _: &mut gpui::App, - ) -> anyhow::Result { - sources.json_merge() + fn from_defaults(content: &settings::SettingsContent, cx: &mut App) -> Self { + let panel = content.outline_panel.as_ref().unwrap(); + Self { + button: panel.button.unwrap(), + default_width: panel.default_width.map(gpui::px).unwrap(), + dock: panel.dock.unwrap(), + file_icons: panel.file_icons.unwrap(), + folder_icons: panel.folder_icons.unwrap(), + git_status: panel.git_status.unwrap(), + indent_size: panel.indent_size.unwrap(), + indent_guides: IndentGuidesSettings { + show: panel.indent_guides.unwrap().show.unwrap(), + }, + auto_reveal_entries: panel.auto_reveal_entries.unwrap(), + auto_fold_dirs: panel.auto_fold_dirs.unwrap(), + scrollbar: ScrollbarSettings { + show: panel.scrollbar.unwrap().show.unwrap(), + }, + expand_outlines_with_depth: panel.expand_outlines_with_depth.unwrap(), + } } - fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut Self::FileContent) { + fn refine(&mut self, content: &settings::SettingsContent, cx: &mut App) { + let Some(panel) = content.outline_panel.as_ref() else { + return; + }; + + self.button.merge_from(&panel.button); + self.default_width + .merge_from(&panel.default_width.map(Pixels::from)); + self.dock.merge_from(&panel.dock.map(Into::into)); + self.file_icons.merge_from(&panel.file_icons); + self.folder_icons.merge_from(&panel.folder_icons); + self.git_status.merge_from(&panel.git_status); + self.indent_size.merge_from(&panel.indent_size); + + if let Some(indent_guides) = panel.indent_guides.as_ref() { + self.indent_guides.show.merge_from(&indent_guides.show); + } + + self.auto_reveal_entries + .merge_from(&panel.auto_reveal_entries); + self.auto_fold_dirs.merge_from(&panel.auto_fold_dirs); + + if let Some(scrollbar) = panel.scrollbar.as_ref() { + self.scrollbar.show.merge_from(&scrollbar.show); + } + } + fn import_from_vscode( + vscode: &settings::VsCodeSettings, + current: &mut settings::SettingsContent, + ) { if let Some(b) = vscode.read_bool("outline.icons") { - current.file_icons = Some(b); - current.folder_icons = Some(b); + let outline_panel = current.outline_panel.get_or_insert_default(); + outline_panel.file_icons = Some(b); + outline_panel.folder_icons = Some(b); } - vscode.bool_setting("git.decorations.enabled", &mut current.git_status); + if let Some(b) = vscode.read_bool("git.decorations.enabled") { + let outline_panel = current.outline_panel.get_or_insert_default(); + outline_panel.git_status = Some(b); + } } } diff --git a/crates/settings/src/settings_content.rs b/crates/settings/src/settings_content.rs index a9765e99debd78463b6ff8dde11ba386cd34329c..1a7a643c6b5b287f56a66373391494a3248d15f2 100644 --- a/crates/settings/src/settings_content.rs +++ b/crates/settings/src/settings_content.rs @@ -41,6 +41,9 @@ pub struct SettingsContent { #[serde(flatten)] pub editor: EditorSettingsContent, + /// Settings related to the file finder. + pub file_finder: Option, + pub git_panel: Option, pub tabs: Option, @@ -81,12 +84,16 @@ pub struct SettingsContent { /// Default: false pub helix_mode: Option, + pub journal: Option, + /// A map of log scopes to the desired log level. /// Useful for filtering out noisy logs or enabling more verbose logging. /// /// Example: {"log": {"client": "warn"}} pub log: Option>, + pub outline_panel: Option, + /// Configuration for the Message Editor pub message_editor: Option, @@ -123,6 +130,9 @@ pub struct SettingsContent { /// /// Default: false pub disable_ai: Option, + + /// Settings related to Vim mode in Zed. + pub vim: Option, } impl SettingsContent { @@ -472,7 +482,7 @@ pub struct MessageEditorSettings { pub auto_replace_emoji_shortcode: Option, } -#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] pub struct FileFinderSettingsContent { /// Whether to show file icons in the file finder. /// @@ -481,7 +491,7 @@ pub struct FileFinderSettingsContent { /// Determines how much space the file finder can take up in relation to the available window width. /// /// Default: small - pub modal_max_width: Option, + pub modal_max_width: Option, /// Determines whether the file finder should skip focus for the active file in search results. /// /// Default: true @@ -499,5 +509,169 @@ pub struct FileFinderSettingsContent { /// * `None`: Be smart and search for ignored when called from a gitignored worktree /// /// Default: None + /// todo!() -> Change this type to an enum pub include_ignored: Option>, } + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum FileFinderWidthContent { + #[default] + Small, + Medium, + Large, + XLarge, + Full, +} + +#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema)] +pub struct VimSettingsContent { + pub default_mode: Option, + pub toggle_relative_line_numbers: Option, + pub use_system_clipboard: Option, + pub use_smartcase_find: Option, + pub custom_digraphs: Option>>, + pub highlight_on_yank_duration: Option, + pub cursor_shape: Option, +} + +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ModeContent { + #[default] + Normal, + Insert, + Replace, + Visual, + VisualLine, + VisualBlock, + HelixNormal, +} + +/// Controls when to use system clipboard. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum UseSystemClipboard { + /// Don't use system clipboard. + Never, + /// Use system clipboard. + Always, + /// Use system clipboard for yank operations. + OnYank, +} + +/// The settings for cursor shape. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +pub struct CursorShapeSettings { + /// Cursor shape for the normal mode. + /// + /// Default: block + pub normal: Option, + /// Cursor shape for the replace mode. + /// + /// Default: underline + pub replace: Option, + /// Cursor shape for the visual mode. + /// + /// Default: block + pub visual: Option, + /// Cursor shape for the insert mode. + /// + /// The default value follows the primary cursor_shape. + pub insert: Option, +} + +/// Settings specific to journaling +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct JournalSettingsContent { + /// The path of the directory where journal entries are stored. + /// + /// Default: `~` + pub path: Option, + /// What format to display the hours in. + /// + /// Default: hour12 + pub hour_format: Option, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum HourFormatContent { + #[default] + Hour12, + Hour24, +} + +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] +pub struct OutlinePanelSettingsContent { + /// Whether to show the outline panel button in the status bar. + /// + /// Default: true + pub button: Option, + /// Customize default width (in pixels) taken by outline panel + /// + /// Default: 240 + pub default_width: Option, + /// The position of outline panel + /// + /// Default: left + pub dock: Option, + /// Whether to show file icons in the outline panel. + /// + /// Default: true + pub file_icons: Option, + /// Whether to show folder icons or chevrons for directories in the outline panel. + /// + /// Default: true + pub folder_icons: Option, + /// Whether to show the git status in the outline panel. + /// + /// Default: true + pub git_status: Option, + /// Amount of indentation (in pixels) for nested items. + /// + /// Default: 20 + pub indent_size: Option, + /// Whether to reveal it in the outline panel automatically, + /// when a corresponding project entry becomes active. + /// Gitignored entries are never auto revealed. + /// + /// Default: true + pub auto_reveal_entries: Option, + /// Whether to fold directories automatically + /// when directory has only one directory inside. + /// + /// Default: true + pub auto_fold_dirs: Option, + /// Settings related to indent guides in the outline panel. + pub indent_guides: Option, + /// Scrollbar-related settings + pub scrollbar: Option, + /// Default depth to expand outline items in the current file. + /// The default depth to which outline entries are expanded on reveal. + /// - Set to 0 to collapse all items that have children + /// - Set to 1 or higher to collapse items at that depth or deeper + /// + /// Default: 100 + pub expand_outlines_with_depth: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum OutlinePanelDockPosition { + Left, + Right, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ShowIndentGuides { + Always, + Never, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct IndentGuidesSettingsContent { + /// When to show the scrollbar in the outline panel. + pub show: Option, +} diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 7faff54e73b179bdfa944798a9c87fafa245f732..8bffc45b7e1cdf30781e2d685404b8fb5526f2af 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -1793,39 +1793,6 @@ impl Vim { } } -/// Controls when to use system clipboard. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum UseSystemClipboard { - /// Don't use system clipboard. - Never, - /// Use system clipboard. - Always, - /// Use system clipboard for yank operations. - OnYank, -} - -/// The settings for cursor shape. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -struct CursorShapeSettings { - /// Cursor shape for the normal mode. - /// - /// Default: block - pub normal: Option, - /// Cursor shape for the replace mode. - /// - /// Default: underline - pub replace: Option, - /// Cursor shape for the visual mode. - /// - /// Default: block - pub visual: Option, - /// Cursor shape for the insert mode. - /// - /// The default value follows the primary cursor_shape. - pub insert: Option, -} - #[derive(Deserialize)] struct VimSettings { pub default_mode: Mode, @@ -1837,32 +1804,7 @@ struct VimSettings { pub cursor_shape: CursorShapeSettings, } -#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)] -#[settings_key(key = "vim")] -struct VimSettingsContent { - pub default_mode: Option, - pub toggle_relative_line_numbers: Option, - pub use_system_clipboard: Option, - pub use_smartcase_find: Option, - pub custom_digraphs: Option>>, - pub highlight_on_yank_duration: Option, - pub cursor_shape: Option, -} - -#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ModeContent { - #[default] - Normal, - Insert, - Replace, - Visual, - VisualLine, - VisualBlock, - HelixNormal, -} - -impl From for Mode { +impl From for Mode { fn from(mode: ModeContent) -> Self { match mode { ModeContent::Normal => Self::Normal, @@ -1877,34 +1819,40 @@ impl From for Mode { } impl Settings for VimSettings { - type FileContent = VimSettingsContent; - - fn load(sources: SettingsSources, _: &mut App) -> Result { - let settings: VimSettingsContent = sources.json_merge()?; - - Ok(Self { - default_mode: settings - .default_mode - .ok_or_else(Self::missing_default)? - .into(), - toggle_relative_line_numbers: settings - .toggle_relative_line_numbers - .ok_or_else(Self::missing_default)?, - use_system_clipboard: settings - .use_system_clipboard - .ok_or_else(Self::missing_default)?, - use_smartcase_find: settings - .use_smartcase_find - .ok_or_else(Self::missing_default)?, - custom_digraphs: settings.custom_digraphs.ok_or_else(Self::missing_default)?, - highlight_on_yank_duration: settings - .highlight_on_yank_duration - .ok_or_else(Self::missing_default)?, - cursor_shape: settings.cursor_shape.ok_or_else(Self::missing_default)?, - }) + fn from_defaults(content: &settings::SettingsContent, cx: &mut App) -> Self { + let vim = content.vim.as_ref().unwrap(); + Self { + default_mode: vim.default_mode.unwrap().into(), + toggle_relative_line_numbers: vim.toggle_relative_line_numbers.unwrap(), + use_system_clipboard: vim.use_system_clipboard.unwrap(), + use_smartcase_find: vim.use_smartcase_find.unwrap(), + custom_digraphs: vim.custom_digraphs.unwrap(), + highlight_on_yank_duration: vim.highlight_on_yank_duration.unwrap(), + cursor_shape: vim.cursor_shape.unwrap(), + } } - fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) { + fn refine(&mut self, content: &settings::SettingsContent, cx: &mut App) { + let Some(vim) = content.vim.as_ref() else { + return; + }; + self.default_mode + .merge_from(&vim.default_mode.map(Into::into)); + self.toggle_relative_line_numbers + .merge_from(&vim.toggle_relative_line_numbers); + self.use_system_clipboard + .merge_from(&vim.use_system_clipboard); + self.use_smartcase_find.merge_from(&vim.use_smartcase_find); + self.custom_digraphs.merge_from(&vim.custom_digraphs); + self.highlight_on_yank_duration + .merge_from(&vim.highlight_on_yank_duration); + self.cursor_shape.merge_from(&vim.cursor_shape); + } + + fn import_from_vscode( + _vscode: &settings::VsCodeSettings, + _current: &mut settings::SettingsContent, + ) { // TODO: translate vim extension settings } }