Closes https://github.com/zed-industries/zed/issues/4461 This PR improves the coding experience by hiding the mouse while the user is typing so it does not accidentally get in their way, making it challenging to ready characters in the editor. Release Notes: - The following PR hides the cursor when the user is typing by adding a new cursor style called `None`. - Assuming the user does not move the mouse, it will stay hidden until it is moved again. https://github.com/user-attachments/assets/6ba9f2ee-b9f3-4595-81e4-e9d986da4a39 --------- Co-authored-by: Agus <agus@zed.dev> Co-authored-by: Peter Tripp <peter@zed.dev> Co-authored-by: Kirill Bulatov <kirill@zed.dev>
493 lines
16 KiB
Rust
493 lines
16 KiB
Rust
use gpui::App;
|
|
use language::CursorShape;
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
use settings::{Settings, SettingsSources};
|
|
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct EditorSettings {
|
|
pub cursor_blink: bool,
|
|
pub cursor_shape: Option<CursorShape>,
|
|
pub current_line_highlight: CurrentLineHighlight,
|
|
pub selection_highlight: bool,
|
|
pub selection_highlight_debounce: u64,
|
|
pub lsp_highlight_debounce: u64,
|
|
pub hover_popover_enabled: bool,
|
|
pub hover_popover_delay: u64,
|
|
pub toolbar: Toolbar,
|
|
pub scrollbar: Scrollbar,
|
|
pub gutter: Gutter,
|
|
pub scroll_beyond_last_line: ScrollBeyondLastLine,
|
|
pub vertical_scroll_margin: f32,
|
|
pub autoscroll_on_clicks: bool,
|
|
pub horizontal_scroll_margin: f32,
|
|
pub scroll_sensitivity: f32,
|
|
pub relative_line_numbers: bool,
|
|
pub seed_search_query_from_cursor: SeedQuerySetting,
|
|
pub use_smartcase_search: bool,
|
|
pub multi_cursor_modifier: MultiCursorModifier,
|
|
pub redact_private_values: bool,
|
|
pub expand_excerpt_lines: u32,
|
|
pub middle_click_paste: bool,
|
|
#[serde(default)]
|
|
pub double_click_in_multibuffer: DoubleClickInMultibuffer,
|
|
pub search_wrap: bool,
|
|
#[serde(default)]
|
|
pub search: SearchSettings,
|
|
pub auto_signature_help: bool,
|
|
pub show_signature_help_after_edits: bool,
|
|
pub jupyter: Jupyter,
|
|
pub hide_mouse_while_typing: Option<bool>,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum CurrentLineHighlight {
|
|
// Don't highlight the current line.
|
|
None,
|
|
// Highlight the gutter area.
|
|
Gutter,
|
|
// Highlight the editor area.
|
|
Line,
|
|
// Highlight the full line.
|
|
All,
|
|
}
|
|
|
|
/// When to populate a new search's query based on the text under the cursor.
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum SeedQuerySetting {
|
|
/// Always populate the search query with the word under the cursor.
|
|
Always,
|
|
/// Only populate the search query when there is text selected.
|
|
Selection,
|
|
/// Never populate the search query
|
|
Never,
|
|
}
|
|
|
|
/// What to do when multibuffer is double clicked in some of its excerpts (parts of singleton buffers).
|
|
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum DoubleClickInMultibuffer {
|
|
/// Behave as a regular buffer and select the whole word.
|
|
#[default]
|
|
Select,
|
|
/// Open the excerpt clicked as a new buffer in the new tab, if no `alt` modifier was pressed during double click.
|
|
/// Otherwise, behave as a regular buffer and select the whole word.
|
|
Open,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct Jupyter {
|
|
/// Whether the Jupyter feature is enabled.
|
|
///
|
|
/// Default: true
|
|
pub enabled: bool,
|
|
}
|
|
|
|
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub struct JupyterContent {
|
|
/// Whether the Jupyter feature is enabled.
|
|
///
|
|
/// Default: true
|
|
pub enabled: Option<bool>,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct Toolbar {
|
|
pub breadcrumbs: bool,
|
|
pub quick_actions: bool,
|
|
pub selections_menu: bool,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct Scrollbar {
|
|
pub show: ShowScrollbar,
|
|
pub git_diff: bool,
|
|
pub selected_text: bool,
|
|
pub selected_symbol: bool,
|
|
pub search_results: bool,
|
|
pub diagnostics: ScrollbarDiagnostics,
|
|
pub cursors: bool,
|
|
pub axes: ScrollbarAxes,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct Gutter {
|
|
pub line_numbers: bool,
|
|
pub code_actions: bool,
|
|
pub runnables: bool,
|
|
pub folds: bool,
|
|
}
|
|
|
|
/// When to show the scrollbar in the editor.
|
|
///
|
|
/// Default: auto
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ShowScrollbar {
|
|
/// Show the scrollbar if there's important information or
|
|
/// follow the system's configured behavior.
|
|
Auto,
|
|
/// Match the system's configured behavior.
|
|
System,
|
|
/// Always show the scrollbar.
|
|
Always,
|
|
/// Never show the scrollbar.
|
|
Never,
|
|
}
|
|
|
|
/// Forcefully enable or disable the scrollbar for each axis
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub struct ScrollbarAxes {
|
|
/// When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
|
|
///
|
|
/// Default: true
|
|
pub horizontal: bool,
|
|
|
|
/// When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
|
|
///
|
|
/// Default: true
|
|
pub vertical: bool,
|
|
}
|
|
|
|
/// Which diagnostic indicators to show in the scrollbar.
|
|
///
|
|
/// Default: all
|
|
#[derive(Copy, Clone, Debug, Serialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum ScrollbarDiagnostics {
|
|
/// Show all diagnostic levels: hint, information, warnings, error.
|
|
All,
|
|
/// Show only the following diagnostic levels: information, warning, error.
|
|
Information,
|
|
/// Show only the following diagnostic levels: warning, error.
|
|
Warning,
|
|
/// Show only the following diagnostic level: error.
|
|
Error,
|
|
/// Do not show diagnostics.
|
|
None,
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for ScrollbarDiagnostics {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
struct Visitor;
|
|
|
|
impl<'de> serde::de::Visitor<'de> for Visitor {
|
|
type Value = ScrollbarDiagnostics;
|
|
|
|
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
r#"a boolean or one of "all", "information", "warning", "error", "none""#
|
|
)
|
|
}
|
|
|
|
fn visit_bool<E>(self, b: bool) -> Result<Self::Value, E>
|
|
where
|
|
E: serde::de::Error,
|
|
{
|
|
match b {
|
|
false => Ok(ScrollbarDiagnostics::None),
|
|
true => Ok(ScrollbarDiagnostics::All),
|
|
}
|
|
}
|
|
|
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: serde::de::Error,
|
|
{
|
|
match s {
|
|
"all" => Ok(ScrollbarDiagnostics::All),
|
|
"information" => Ok(ScrollbarDiagnostics::Information),
|
|
"warning" => Ok(ScrollbarDiagnostics::Warning),
|
|
"error" => Ok(ScrollbarDiagnostics::Error),
|
|
"none" => Ok(ScrollbarDiagnostics::None),
|
|
_ => Err(E::unknown_variant(
|
|
s,
|
|
&["all", "information", "warning", "error", "none"],
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_any(Visitor)
|
|
}
|
|
}
|
|
|
|
/// The key to use for adding multiple cursors
|
|
///
|
|
/// Default: alt
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum MultiCursorModifier {
|
|
Alt,
|
|
#[serde(alias = "cmd", alias = "ctrl")]
|
|
CmdOrCtrl,
|
|
}
|
|
|
|
/// Whether the editor will scroll beyond the last line.
|
|
///
|
|
/// Default: one_page
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ScrollBeyondLastLine {
|
|
/// The editor will not scroll beyond the last line.
|
|
Off,
|
|
|
|
/// The editor will scroll beyond the last line by one page.
|
|
OnePage,
|
|
|
|
/// The editor will scroll beyond the last line by the same number of lines as vertical_scroll_margin.
|
|
VerticalScrollMargin,
|
|
}
|
|
|
|
/// Default options for buffer and project search items.
|
|
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct SearchSettings {
|
|
#[serde(default)]
|
|
pub whole_word: bool,
|
|
#[serde(default)]
|
|
pub case_sensitive: bool,
|
|
#[serde(default)]
|
|
pub include_ignored: bool,
|
|
#[serde(default)]
|
|
pub regex: bool,
|
|
}
|
|
|
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
|
pub struct EditorSettingsContent {
|
|
/// Whether the cursor blinks in the editor.
|
|
///
|
|
/// Default: true
|
|
pub cursor_blink: Option<bool>,
|
|
/// Cursor shape for the default editor.
|
|
/// Can be "bar", "block", "underline", or "hollow".
|
|
///
|
|
/// Default: None
|
|
pub cursor_shape: Option<CursorShape>,
|
|
/// Determines whether the mouse cursor should be hidden while typing in an editor or input box.
|
|
///
|
|
/// Default: true
|
|
pub hide_mouse_while_typing: Option<bool>,
|
|
/// How to highlight the current line in the editor.
|
|
///
|
|
/// Default: all
|
|
pub current_line_highlight: Option<CurrentLineHighlight>,
|
|
/// Whether to highlight all occurrences of the selected text in an editor.
|
|
///
|
|
/// Default: true
|
|
pub selection_highlight: Option<bool>,
|
|
/// The debounce delay before querying highlights based on the selected text.
|
|
///
|
|
/// Default: 75
|
|
pub selection_highlight_debounce: Option<u64>,
|
|
/// The debounce delay before querying highlights from the language
|
|
/// server based on the current cursor location.
|
|
///
|
|
/// Default: 75
|
|
pub lsp_highlight_debounce: Option<u64>,
|
|
/// Whether to show the informational hover box when moving the mouse
|
|
/// over symbols in the editor.
|
|
///
|
|
/// Default: true
|
|
pub hover_popover_enabled: Option<bool>,
|
|
/// Time to wait before showing the informational hover box
|
|
///
|
|
/// Default: 350
|
|
pub hover_popover_delay: Option<u64>,
|
|
/// Toolbar related settings
|
|
pub toolbar: Option<ToolbarContent>,
|
|
/// Scrollbar related settings
|
|
pub scrollbar: Option<ScrollbarContent>,
|
|
/// Gutter related settings
|
|
pub gutter: Option<GutterContent>,
|
|
/// Whether the editor will scroll beyond the last line.
|
|
///
|
|
/// Default: one_page
|
|
pub scroll_beyond_last_line: Option<ScrollBeyondLastLine>,
|
|
/// The number of lines to keep above/below the cursor when auto-scrolling.
|
|
///
|
|
/// Default: 3.
|
|
pub vertical_scroll_margin: Option<f32>,
|
|
/// Whether to scroll when clicking near the edge of the visible text area.
|
|
///
|
|
/// Default: false
|
|
pub autoscroll_on_clicks: Option<bool>,
|
|
/// The number of characters to keep on either side when scrolling with the mouse.
|
|
///
|
|
/// Default: 5.
|
|
pub horizontal_scroll_margin: Option<f32>,
|
|
/// Scroll sensitivity multiplier. This multiplier is applied
|
|
/// to both the horizontal and vertical delta values while scrolling.
|
|
///
|
|
/// Default: 1.0
|
|
pub scroll_sensitivity: Option<f32>,
|
|
/// Whether the line numbers on editors gutter are relative or not.
|
|
///
|
|
/// Default: false
|
|
pub relative_line_numbers: Option<bool>,
|
|
/// When to populate a new search's query based on the text under the cursor.
|
|
///
|
|
/// Default: always
|
|
pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
|
|
pub use_smartcase_search: Option<bool>,
|
|
/// The key to use for adding multiple cursors
|
|
///
|
|
/// Default: alt
|
|
pub multi_cursor_modifier: Option<MultiCursorModifier>,
|
|
/// Hide the values of variables in `private` files, as defined by the
|
|
/// private_files setting. This only changes the visual representation,
|
|
/// the values are still present in the file and can be selected / copied / pasted
|
|
///
|
|
/// Default: false
|
|
pub redact_private_values: Option<bool>,
|
|
|
|
/// How many lines to expand the multibuffer excerpts by default
|
|
///
|
|
/// Default: 3
|
|
pub expand_excerpt_lines: Option<u32>,
|
|
|
|
/// Whether to enable middle-click paste on Linux
|
|
///
|
|
/// Default: true
|
|
pub middle_click_paste: Option<bool>,
|
|
|
|
/// What to do when multibuffer is double clicked in some of its excerpts
|
|
/// (parts of singleton buffers).
|
|
///
|
|
/// Default: select
|
|
pub double_click_in_multibuffer: Option<DoubleClickInMultibuffer>,
|
|
/// Whether the editor search results will loop
|
|
///
|
|
/// Default: true
|
|
pub search_wrap: Option<bool>,
|
|
|
|
/// Defaults to use when opening a new buffer and project search items.
|
|
///
|
|
/// Default: nothing is enabled
|
|
pub search: Option<SearchSettings>,
|
|
|
|
/// Whether to automatically show a signature help pop-up or not.
|
|
///
|
|
/// Default: false
|
|
pub auto_signature_help: Option<bool>,
|
|
|
|
/// Whether to show the signature help pop-up after completions or bracket pairs inserted.
|
|
///
|
|
/// Default: false
|
|
pub show_signature_help_after_edits: Option<bool>,
|
|
|
|
/// Jupyter REPL settings.
|
|
pub jupyter: Option<JupyterContent>,
|
|
}
|
|
|
|
// Toolbar related settings
|
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct ToolbarContent {
|
|
/// Whether to display breadcrumbs in the editor toolbar.
|
|
///
|
|
/// Default: true
|
|
pub breadcrumbs: Option<bool>,
|
|
/// Whether to display quick action buttons in the editor toolbar.
|
|
///
|
|
/// Default: true
|
|
pub quick_actions: Option<bool>,
|
|
|
|
/// Whether to show the selections menu in the editor toolbar
|
|
///
|
|
/// Default: true
|
|
pub selections_menu: Option<bool>,
|
|
}
|
|
|
|
/// Scrollbar related settings
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
|
|
pub struct ScrollbarContent {
|
|
/// When to show the scrollbar in the editor.
|
|
///
|
|
/// Default: auto
|
|
pub show: Option<ShowScrollbar>,
|
|
/// Whether to show git diff indicators in the scrollbar.
|
|
///
|
|
/// Default: true
|
|
pub git_diff: Option<bool>,
|
|
/// Whether to show buffer search result indicators in the scrollbar.
|
|
///
|
|
/// Default: true
|
|
pub search_results: Option<bool>,
|
|
/// Whether to show selected text occurrences in the scrollbar.
|
|
///
|
|
/// Default: true
|
|
pub selected_text: Option<bool>,
|
|
/// Whether to show selected symbol occurrences in the scrollbar.
|
|
///
|
|
/// Default: true
|
|
pub selected_symbol: Option<bool>,
|
|
/// Which diagnostic indicators to show in the scrollbar:
|
|
///
|
|
/// Default: all
|
|
pub diagnostics: Option<ScrollbarDiagnostics>,
|
|
/// Whether to show cursor positions in the scrollbar.
|
|
///
|
|
/// Default: true
|
|
pub cursors: Option<bool>,
|
|
/// Forcefully enable or disable the scrollbar for each axis
|
|
pub axes: Option<ScrollbarAxesContent>,
|
|
}
|
|
|
|
/// Forcefully enable or disable the scrollbar for each axis
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
|
|
pub struct ScrollbarAxesContent {
|
|
/// When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
|
|
///
|
|
/// Default: true
|
|
horizontal: Option<bool>,
|
|
|
|
/// When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
|
|
///
|
|
/// Default: true
|
|
vertical: Option<bool>,
|
|
}
|
|
|
|
/// Gutter related settings
|
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
pub struct GutterContent {
|
|
/// Whether to show line numbers in the gutter.
|
|
///
|
|
/// Default: true
|
|
pub line_numbers: Option<bool>,
|
|
/// Whether to show code action buttons in the gutter.
|
|
///
|
|
/// Default: true
|
|
pub code_actions: Option<bool>,
|
|
/// Whether to show runnable buttons in the gutter.
|
|
///
|
|
/// Default: true
|
|
pub runnables: Option<bool>,
|
|
/// Whether to show fold buttons in the gutter.
|
|
///
|
|
/// Default: true
|
|
pub folds: Option<bool>,
|
|
}
|
|
|
|
impl EditorSettings {
|
|
pub fn jupyter_enabled(cx: &App) -> bool {
|
|
EditorSettings::get_global(cx).jupyter.enabled
|
|
}
|
|
}
|
|
|
|
impl Settings for EditorSettings {
|
|
const KEY: Option<&'static str> = None;
|
|
|
|
type FileContent = EditorSettingsContent;
|
|
|
|
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
|
|
sources.json_merge()
|
|
}
|
|
}
|