workspace_settings.rs

  1use std::num::NonZeroUsize;
  2
  3use crate::DockPosition;
  4use anyhow::Result;
  5use collections::HashMap;
  6use gpui::App;
  7use schemars::JsonSchema;
  8use serde::{Deserialize, Serialize};
  9use settings::{Settings, SettingsKey, SettingsSources, SettingsUi};
 10
 11#[derive(Deserialize)]
 12pub struct WorkspaceSettings {
 13    pub active_pane_modifiers: ActivePanelModifiers,
 14    pub bottom_dock_layout: BottomDockLayout,
 15    pub pane_split_direction_horizontal: PaneSplitDirectionHorizontal,
 16    pub pane_split_direction_vertical: PaneSplitDirectionVertical,
 17    pub centered_layout: CenteredLayoutSettings,
 18    pub confirm_quit: bool,
 19    pub show_call_status_icon: bool,
 20    pub autosave: AutosaveSetting,
 21    pub restore_on_startup: RestoreOnStartupBehavior,
 22    pub restore_on_file_reopen: bool,
 23    pub drop_target_size: f32,
 24    pub use_system_path_prompts: bool,
 25    pub use_system_prompts: bool,
 26    pub command_aliases: HashMap<String, String>,
 27    pub max_tabs: Option<NonZeroUsize>,
 28    pub when_closing_with_no_tabs: CloseWindowWhenNoItems,
 29    pub on_last_window_closed: OnLastWindowClosed,
 30    pub resize_all_panels_in_dock: Vec<DockPosition>,
 31    pub close_on_file_delete: bool,
 32    pub use_system_window_tabs: bool,
 33    pub zoomed_padding: bool,
 34}
 35
 36#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)]
 37#[serde(rename_all = "snake_case")]
 38pub enum OnLastWindowClosed {
 39    /// Match platform conventions by default, so don't quit on macOS, and quit on other platforms
 40    #[default]
 41    PlatformDefault,
 42    /// Quit the application the last window is closed
 43    QuitApp,
 44}
 45
 46impl OnLastWindowClosed {
 47    pub fn is_quit_app(&self) -> bool {
 48        match self {
 49            OnLastWindowClosed::PlatformDefault => false,
 50            OnLastWindowClosed::QuitApp => true,
 51        }
 52    }
 53}
 54
 55#[derive(Deserialize)]
 56pub struct TabBarSettings {
 57    pub show: bool,
 58    pub show_nav_history_buttons: bool,
 59    pub show_tab_bar_buttons: bool,
 60}
 61impl Settings for WorkspaceSettings {
 62    type FileContent = WorkspaceSettingsContent;
 63
 64    fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
 65        sources.json_merge()
 66    }
 67
 68    fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut Self::FileContent) {
 69        if vscode
 70            .read_bool("accessibility.dimUnfocused.enabled")
 71            .unwrap_or_default()
 72            && let Some(opacity) = vscode
 73                .read_value("accessibility.dimUnfocused.opacity")
 74                .and_then(|v| v.as_f64())
 75        {
 76            if let Some(settings) = current.active_pane_modifiers.as_mut() {
 77                settings.inactive_opacity = Some(opacity as f32)
 78            } else {
 79                current.active_pane_modifiers = Some(ActivePanelModifiers {
 80                    inactive_opacity: Some(opacity as f32),
 81                    ..Default::default()
 82                })
 83            }
 84        }
 85
 86        vscode.enum_setting(
 87            "window.confirmBeforeClose",
 88            &mut current.confirm_quit,
 89            |s| match s {
 90                "always" | "keyboardOnly" => Some(true),
 91                "never" => Some(false),
 92                _ => None,
 93            },
 94        );
 95
 96        vscode.bool_setting(
 97            "workbench.editor.restoreViewState",
 98            &mut current.restore_on_file_reopen,
 99        );
100
101        if let Some(b) = vscode.read_bool("window.closeWhenEmpty") {
102            current.when_closing_with_no_tabs = Some(if b {
103                CloseWindowWhenNoItems::CloseWindow
104            } else {
105                CloseWindowWhenNoItems::KeepWindowOpen
106            })
107        }
108
109        if let Some(b) = vscode.read_bool("files.simpleDialog.enable") {
110            current.use_system_path_prompts = Some(!b);
111        }
112
113        vscode.enum_setting("files.autoSave", &mut current.autosave, |s| match s {
114            "off" => Some(AutosaveSetting::Off),
115            "afterDelay" => Some(AutosaveSetting::AfterDelay {
116                milliseconds: vscode
117                    .read_value("files.autoSaveDelay")
118                    .and_then(|v| v.as_u64())
119                    .unwrap_or(1000),
120            }),
121            "onFocusChange" => Some(AutosaveSetting::OnFocusChange),
122            "onWindowChange" => Some(AutosaveSetting::OnWindowChange),
123            _ => None,
124        });
125
126        // workbench.editor.limit contains "enabled", "value", and "perEditorGroup"
127        // our semantics match if those are set to true, some N, and true respectively.
128        // we'll ignore "perEditorGroup" for now since we only support a global max
129        if let Some(n) = vscode
130            .read_value("workbench.editor.limit.value")
131            .and_then(|v| v.as_u64())
132            .and_then(|n| NonZeroUsize::new(n as usize))
133            && vscode
134                .read_bool("workbench.editor.limit.enabled")
135                .unwrap_or_default()
136        {
137            current.max_tabs = Some(n)
138        }
139
140        vscode.bool_setting("window.nativeTabs", &mut current.use_system_window_tabs);
141
142        // some combination of "window.restoreWindows" and "workbench.startupEditor" might
143        // map to our "restore_on_startup"
144
145        // there doesn't seem to be a way to read whether the bottom dock's "justified"
146        // setting is enabled in vscode. that'd be our equivalent to "bottom_dock_layout"
147    }
148}
149
150impl Settings for TabBarSettings {
151    type FileContent = TabBarSettingsContent;
152
153    fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
154        sources.json_merge()
155    }
156
157    fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut Self::FileContent) {
158        vscode.enum_setting(
159            "workbench.editor.showTabs",
160            &mut current.show,
161            |s| match s {
162                "multiple" => Some(true),
163                "single" | "none" => Some(false),
164                _ => None,
165            },
166        );
167        if Some("hidden") == vscode.read_string("workbench.editor.editorActionsLocation") {
168            current.show_tab_bar_buttons = Some(false)
169        }
170    }
171}