From c15382c4d816a4d9c8aacb240c50aa3c8848d750 Mon Sep 17 00:00:00 2001 From: Gaku Kanematsu <67619348+kanematsugaku@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:42:04 +0900 Subject: [PATCH] vim: Add cursor shape settings for each vim mode (#28636) Closes #4495 Release Notes: - vim: add cursor shape settings for each vim mode --- Add cursor shape settings for each vim mode to enable users to specify them. Example of `settings.json`: ```json { "vim_mode": true, "vim": { "cursor_shape": { "normal": "hollow", "insert": "bar", "replace": "block", "visual": "underline" } } } ``` After this change is applied, - The cursor shape specified by the user for each mode is used. - In insert mode, the `vim > cursor_shape > insert` setting takes precedence over the primary `cursor_shape` setting. - If `vim > cursor_shape > insert` is not set, the primary `cursor_shape` will be used in insert mode. - The cursor shape will remain unchanged before and after this update when the user does not set the `vim > cursor_shape` setting. Video: [screen-record.webm](https://github.com/user-attachments/assets/b87461a1-6b3a-4a77-a607-a340f106def5) --- assets/settings/default.json | 7 ++++++- crates/vim/src/vim.rs | 39 +++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index d93a6d39fc..60c8708e23 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1489,7 +1489,12 @@ "use_multiline_find": false, "use_smartcase_find": false, "highlight_on_yank_duration": 200, - "custom_digraphs": {} + "custom_digraphs": {}, + // Cursor shape for the each mode. + // Specify the mode as the key and the shape as the value. + // The mode can be one of the following: "normal", "replace", "insert", "visual". + // The shape can be one of the following: "block", "bar", "underline", "hollow". + "cursor_shape": {} }, // The server to connect to. If the environment variable // ZED_SERVER_URL is set, it will override this setting. diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 0320ded826..dc2a0edc17 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -1023,6 +1023,7 @@ impl Vim { } pub fn cursor_shape(&self, cx: &mut App) -> CursorShape { + let cursor_shape = VimSettings::get_global(cx).cursor_shape; match self.mode { Mode::Normal => { if let Some(operator) = self.operator_stack.last() { @@ -1040,18 +1041,18 @@ impl Vim { _ => CursorShape::Underline, } } else { - // No operator active -> Block cursor - CursorShape::Block + cursor_shape.normal.unwrap_or(CursorShape::Block) } } - Mode::Replace => CursorShape::Underline, - Mode::HelixNormal | Mode::Visual | Mode::VisualLine | Mode::VisualBlock => { - CursorShape::Block + Mode::HelixNormal => cursor_shape.normal.unwrap_or(CursorShape::Block), + Mode::Replace => cursor_shape.replace.unwrap_or(CursorShape::Underline), + Mode::Visual | Mode::VisualLine | Mode::VisualBlock => { + cursor_shape.visual.unwrap_or(CursorShape::Block) } - Mode::Insert => { + Mode::Insert => cursor_shape.insert.unwrap_or({ let editor_settings = EditorSettings::get_global(cx); editor_settings.cursor_shape.unwrap_or_default() - } + }), } } @@ -1693,6 +1694,27 @@ pub enum UseSystemClipboard { 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, @@ -1702,6 +1724,7 @@ struct VimSettings { pub use_smartcase_find: bool, pub custom_digraphs: HashMap>, pub highlight_on_yank_duration: u64, + pub cursor_shape: CursorShapeSettings, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] @@ -1713,6 +1736,7 @@ struct VimSettingsContent { 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)] @@ -1771,6 +1795,7 @@ impl Settings for VimSettings { 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)?, }) } }