From c7e247855a99c9dcaee12737f5616b00ba51699b Mon Sep 17 00:00:00 2001 From: Charles Crete Date: Fri, 6 Jun 2025 20:34:44 -0400 Subject: [PATCH] Vim: Add color to mode status --- assets/settings/default.json | 4 ++- crates/vim/src/mode_indicator.rs | 43 ++++++++++++++++++++++++-------- crates/vim/src/state.rs | 16 ++++++++++-- crates/vim/src/vim.rs | 3 +++ 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 2759262b51a87d..ace439e3c91b23 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1681,7 +1681,9 @@ // 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": {} + "cursor_shape": {}, + // Adds color to the mode in the status bar + "colored_mode": false }, // 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/mode_indicator.rs b/crates/vim/src/mode_indicator.rs index d54b270074f192..daba59cf3aeebe 100644 --- a/crates/vim/src/mode_indicator.rs +++ b/crates/vim/src/mode_indicator.rs @@ -1,8 +1,9 @@ use gpui::{Context, Element, Entity, Render, Subscription, WeakEntity, Window, div}; +use settings::Settings; use ui::text_for_keystrokes; use workspace::{StatusItemView, item::ItemHandle, ui::prelude::*}; -use crate::{Vim, VimEvent, VimGlobals}; +use crate::{Vim, VimEvent, VimGlobals, VimSettings}; /// The ModeIndicator displays the current mode in the status bar. pub struct ModeIndicator { @@ -96,28 +97,50 @@ impl Render for ModeIndicator { return div().into_any(); }; + let mut container = h_flex().gap_2(); + let vim_readable = vim.read(cx); - let label = if let Some(label) = vim_readable.status_label.clone() { - label + if let Some(label) = vim_readable.status_label.clone() { + container = container.child( + Label::new(label) + .size(LabelSize::Small) + .line_height_style(LineHeightStyle::UiLabel), + ); } else { - let mode = if vim_readable.temp_mode { + let mode_label = if vim_readable.temp_mode { format!("(insert) {}", vim_readable.mode) } else { vim_readable.mode.to_string() }; + let mode_color = if VimSettings::get_global(cx).colored_mode { + vim_readable.mode.color() + } else { + Color::Default + }; let current_operators_description = self.current_operators_description(vim.clone(), cx); let pending = self .pending_keys .as_ref() .unwrap_or(¤t_operators_description); - format!("{} -- {} --", pending, mode).into() - }; - Label::new(label) - .size(LabelSize::Small) - .line_height_style(LineHeightStyle::UiLabel) - .into_any_element() + if !pending.is_empty() { + container = container.child( + Label::new(pending) + .size(LabelSize::Small) + .line_height_style(LineHeightStyle::UiLabel), + ); + } + + container = container.child( + Label::new(mode_label) + .size(LabelSize::Small) + .line_height_style(LineHeightStyle::UiLabel) + .color(mode_color), + ); + } + + container.into_any_element() } } diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs index 46dafdd6c80d87..bec43b6314b5c1 100644 --- a/crates/vim/src/state.rs +++ b/crates/vim/src/state.rs @@ -28,8 +28,8 @@ use std::{fmt::Display, ops::Range, sync::Arc}; use text::{Bias, ToPoint}; use theme::ThemeSettings; use ui::{ - ActiveTheme, Context, Div, FluentBuilder, KeyBinding, ParentElement, SharedString, Styled, - StyledTypography, Window, h_flex, rems, + ActiveTheme, Color, Context, Div, FluentBuilder, KeyBinding, ParentElement, SharedString, + Styled, StyledTypography, Window, h_flex, rems, }; use util::ResultExt; use workspace::searchable::Direction; @@ -67,6 +67,18 @@ impl Mode { Self::Normal | Self::Insert | Self::Replace | Self::HelixNormal => false, } } + + pub fn color(&self) -> Color { + match self { + Mode::Normal => Color::Accent, + Mode::Insert => Color::Created, + Mode::Replace => Color::Deleted, + Mode::Visual => Color::Conflict, + Mode::VisualLine => Color::Conflict, + Mode::VisualBlock => Color::Conflict, + Mode::HelixNormal => Color::Accent, + } + } } impl Default for Mode { diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 88bd2fb744e0c4..e0a3b5db50af5a 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -1731,6 +1731,7 @@ struct VimSettings { pub custom_digraphs: HashMap>, pub highlight_on_yank_duration: u64, pub cursor_shape: CursorShapeSettings, + pub colored_mode: bool, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] @@ -1743,6 +1744,7 @@ struct VimSettingsContent { pub custom_digraphs: Option>>, pub highlight_on_yank_duration: Option, pub cursor_shape: Option, + pub colored_mode: Option, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] @@ -1802,6 +1804,7 @@ impl Settings for VimSettings { .highlight_on_yank_duration .ok_or_else(Self::missing_default)?, cursor_shape: settings.cursor_shape.ok_or_else(Self::missing_default)?, + colored_mode: settings.colored_mode.ok_or_else(Self::missing_default)?, }) }