Customizable vim mode text color (#46639)

everdrone created

Release Notes:
- Added ability to customize vim mode foreground

---

<video
src="https://github.com/user-attachments/assets/776ecfcd-9600-4a04-b3cf-e78af439aab2"
/>

Change summary

crates/settings/src/settings_content/theme.rs | 28 +++++++++++++++--
crates/theme/src/default_colors.rs            | 18 ++++++++++-
crates/theme/src/fallback_themes.rs           |  9 +++++
crates/theme/src/schema.rs                    | 32 +++++++++++++++++++-
crates/theme/src/styles/colors.rs             | 18 ++++++++++-
crates/vim/src/mode_indicator.rs              | 11 ++++++
6 files changed, 104 insertions(+), 12 deletions(-)

Detailed changes

crates/settings/src/settings_content/theme.rs 🔗

@@ -961,10 +961,30 @@ pub struct ThemeColorsContent {
     /// Background color for Vim Helix Select mode indicator.
     #[serde(rename = "vim.helix_select.background")]
     pub vim_helix_select_background: Option<String>,
-
-    /// Text color for Vim mode indicator label.
-    #[serde(rename = "vim.mode.text")]
-    pub vim_mode_text: Option<String>,
+    /// Background color for Vim Normal mode indicator.
+    #[serde(rename = "vim.normal.foreground")]
+    pub vim_normal_foreground: Option<String>,
+    /// Foreground color for Vim Insert mode indicator.
+    #[serde(rename = "vim.insert.foreground")]
+    pub vim_insert_foreground: Option<String>,
+    /// Foreground color for Vim Replace mode indicator.
+    #[serde(rename = "vim.replace.foreground")]
+    pub vim_replace_foreground: Option<String>,
+    /// Foreground color for Vim Visual mode indicator.
+    #[serde(rename = "vim.visual.foreground")]
+    pub vim_visual_foreground: Option<String>,
+    /// Foreground color for Vim Visual Line mode indicator.
+    #[serde(rename = "vim.visual_line.foreground")]
+    pub vim_visual_line_foreground: Option<String>,
+    /// Foreground color for Vim Visual Block mode indicator.
+    #[serde(rename = "vim.visual_block.foreground")]
+    pub vim_visual_block_foreground: Option<String>,
+    /// Foreground color for Vim Helix Normal mode indicator.
+    #[serde(rename = "vim.helix_normal.foreground")]
+    pub vim_helix_normal_foreground: Option<String>,
+    /// Foreground color for Vim Helix Select mode indicator.
+    #[serde(rename = "vim.helix_select.foreground")]
+    pub vim_helix_select_foreground: Option<String>,
 }
 
 #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]

crates/theme/src/default_colors.rs 🔗

@@ -177,7 +177,14 @@ impl ThemeColors {
             vim_visual_block_background: system.transparent,
             vim_helix_normal_background: system.transparent,
             vim_helix_select_background: system.transparent,
-            vim_mode_text: system.transparent,
+            vim_normal_foreground: system.transparent,
+            vim_insert_foreground: system.transparent,
+            vim_replace_foreground: system.transparent,
+            vim_visual_foreground: system.transparent,
+            vim_visual_line_foreground: system.transparent,
+            vim_visual_block_foreground: system.transparent,
+            vim_helix_normal_foreground: system.transparent,
+            vim_helix_select_foreground: system.transparent,
         }
     }
 
@@ -315,7 +322,14 @@ impl ThemeColors {
             vim_visual_block_background: system.transparent,
             vim_helix_normal_background: system.transparent,
             vim_helix_select_background: system.transparent,
-            vim_mode_text: system.transparent,
+            vim_normal_foreground: system.transparent,
+            vim_insert_foreground: system.transparent,
+            vim_replace_foreground: system.transparent,
+            vim_visual_foreground: system.transparent,
+            vim_visual_line_foreground: system.transparent,
+            vim_visual_block_foreground: system.transparent,
+            vim_helix_normal_foreground: system.transparent,
+            vim_helix_select_foreground: system.transparent,
         }
     }
 }

crates/theme/src/fallback_themes.rs 🔗

@@ -257,7 +257,14 @@ pub(crate) fn zed_default_dark() -> Theme {
                 vim_visual_block_background: SystemColors::default().transparent,
                 vim_helix_normal_background: SystemColors::default().transparent,
                 vim_helix_select_background: SystemColors::default().transparent,
-                vim_mode_text: SystemColors::default().transparent,
+                vim_normal_foreground: SystemColors::default().transparent,
+                vim_insert_foreground: SystemColors::default().transparent,
+                vim_replace_foreground: SystemColors::default().transparent,
+                vim_visual_foreground: SystemColors::default().transparent,
+                vim_visual_line_foreground: SystemColors::default().transparent,
+                vim_visual_block_foreground: SystemColors::default().transparent,
+                vim_helix_normal_foreground: SystemColors::default().transparent,
+                vim_helix_select_foreground: SystemColors::default().transparent,
             },
             status: StatusColors {
                 conflict: yellow,

crates/theme/src/schema.rs 🔗

@@ -803,8 +803,36 @@ pub fn theme_colors_refinement(
             .vim_helix_select_background
             .as_ref()
             .and_then(|color| try_parse_color(color).ok()),
-        vim_mode_text: this
-            .vim_mode_text
+        vim_normal_foreground: this
+            .vim_normal_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_insert_foreground: this
+            .vim_insert_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_replace_foreground: this
+            .vim_replace_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_visual_foreground: this
+            .vim_visual_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_visual_line_foreground: this
+            .vim_visual_line_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_visual_block_foreground: this
+            .vim_visual_block_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_helix_normal_foreground: this
+            .vim_helix_normal_foreground
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok()),
+        vim_helix_select_foreground: this
+            .vim_helix_select_foreground
             .as_ref()
             .and_then(|color| try_parse_color(color).ok()),
     }

crates/theme/src/styles/colors.rs 🔗

@@ -179,8 +179,22 @@ pub struct ThemeColors {
     pub vim_helix_normal_background: Hsla,
     /// Background color for Vim Helix Select mode indicator.
     pub vim_helix_select_background: Hsla,
-    /// Text color for Vim mode indicator label.
-    pub vim_mode_text: Hsla,
+    /// Foreground color for Vim Normal mode indicator.
+    pub vim_normal_foreground: Hsla,
+    /// Foreground color for Vim Insert mode indicator.
+    pub vim_insert_foreground: Hsla,
+    /// Foreground color for Vim Replace mode indicator.
+    pub vim_replace_foreground: Hsla,
+    /// Foreground color for Vim Visual mode indicator.
+    pub vim_visual_foreground: Hsla,
+    /// Foreground color for Vim Visual Line mode indicator.
+    pub vim_visual_line_foreground: Hsla,
+    /// Foreground color for Vim Visual Block mode indicator.
+    pub vim_visual_block_foreground: Hsla,
+    /// Foreground color for Vim Helix Normal mode indicator.
+    pub vim_helix_normal_foreground: Hsla,
+    /// Foreground color for Vim Helix Select mode indicator.
+    pub vim_helix_select_foreground: Hsla,
 
     // ===
     // Editor

crates/vim/src/mode_indicator.rs 🔗

@@ -100,7 +100,16 @@ impl Render for ModeIndicator {
         let theme = cx.theme();
         let colors = theme.colors();
         let system_transparent = gpui::hsla(0.0, 0.0, 0.0, 0.0);
-        let vim_mode_text = colors.vim_mode_text;
+        let vim_mode_text = match mode {
+            crate::state::Mode::Normal => colors.vim_normal_foreground,
+            crate::state::Mode::Insert => colors.vim_insert_foreground,
+            crate::state::Mode::Replace => colors.vim_replace_foreground,
+            crate::state::Mode::Visual => colors.vim_visual_foreground,
+            crate::state::Mode::VisualLine => colors.vim_visual_line_foreground,
+            crate::state::Mode::VisualBlock => colors.vim_visual_block_foreground,
+            crate::state::Mode::HelixNormal => colors.vim_helix_normal_foreground,
+            crate::state::Mode::HelixSelect => colors.vim_helix_select_foreground,
+        };
         let bg_color = match mode {
             crate::state::Mode::Normal => colors.vim_normal_background,
             crate::state::Mode::Insert => colors.vim_insert_background,