Cargo.lock 🔗
@@ -8523,6 +8523,7 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
+ "theme",
"tokio",
"util",
"workspace",
Conrad Irwin created
This is the second most common remaining complaint (after :w not
working).
Fixes: zed-industries/community#409
Cargo.lock | 1
crates/theme/src/theme.rs | 1
crates/vim/Cargo.toml | 2
crates/vim/src/mode_indicator.rs | 68 +++++++++++++++++++++++++++++++
crates/vim/src/vim.rs | 2
crates/zed/src/zed.rs | 2
styles/src/style_tree/status_bar.ts | 1
7 files changed, 77 insertions(+)
@@ -8523,6 +8523,7 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
+ "theme",
"tokio",
"util",
"workspace",
@@ -402,6 +402,7 @@ pub struct StatusBar {
pub height: f32,
pub item_spacing: f32,
pub cursor_position: TextStyle,
+ pub vim_mode: TextStyle,
pub active_language: Interactive<ContainedText>,
pub auto_update_progress_message: TextStyle,
pub auto_update_done_message: TextStyle,
@@ -32,6 +32,7 @@ language = { path = "../language" }
search = { path = "../search" }
settings = { path = "../settings" }
workspace = { path = "../workspace" }
+theme = { path = "../theme" }
[dev-dependencies]
indoc.workspace = true
@@ -44,3 +45,4 @@ project = { path = "../project", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }
settings = { path = "../settings" }
workspace = { path = "../workspace", features = ["test-support"] }
+theme = { path = "../theme", features = ["test-support"] }
@@ -0,0 +1,68 @@
+use gpui::{
+ elements::{Empty, Label},
+ AnyElement, Element, Entity, View, ViewContext,
+};
+use workspace::{item::ItemHandle, StatusItemView};
+
+use crate::{state::Mode, Vim};
+
+pub struct ModeIndicator {
+ mode: Option<Mode>,
+}
+
+impl ModeIndicator {
+ pub fn new(cx: &mut ViewContext<Self>) -> Self {
+ cx.observe_global::<Vim, _>(|this, cx| {
+ let vim = Vim::read(cx);
+ if vim.enabled {
+ this.set_mode(Some(Vim::read(cx).state.mode), cx)
+ } else {
+ this.set_mode(None, cx)
+ }
+ })
+ .detach();
+ Self { mode: None }
+ }
+
+ pub fn set_mode(&mut self, mode: Option<Mode>, cx: &mut ViewContext<Self>) {
+ if mode != self.mode {
+ self.mode = mode;
+ cx.notify();
+ }
+ }
+}
+
+impl Entity for ModeIndicator {
+ type Event = ();
+}
+
+impl View for ModeIndicator {
+ fn ui_name() -> &'static str {
+ "ModeIndicator"
+ }
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
+ if let Some(mode) = self.mode {
+ let theme = &theme::current(cx).workspace.status_bar;
+ let text = match mode {
+ Mode::Normal => "",
+ Mode::Insert => "--- INSERT ---",
+ Mode::Visual { line: false } => "--- VISUAL ---",
+ Mode::Visual { line: true } => "--- VISUAL LINE ---",
+ };
+ Label::new(text, theme.vim_mode.clone()).into_any()
+ } else {
+ Empty::new().into_any()
+ }
+ }
+}
+
+impl StatusItemView for ModeIndicator {
+ fn set_active_pane_item(
+ &mut self,
+ _active_pane_item: Option<&dyn ItemHandle>,
+ _cx: &mut ViewContext<Self>,
+ ) {
+ // nothing to do.
+ }
+}
@@ -3,6 +3,7 @@ mod test;
mod editor_events;
mod insert;
+mod mode_indicator;
mod motion;
mod normal;
mod object;
@@ -18,6 +19,7 @@ use gpui::{
ViewHandle, WeakViewHandle, WindowContext,
};
use language::CursorShape;
+pub use mode_indicator::ModeIndicator;
use motion::Motion;
use normal::normal_replace;
use serde::Deserialize;
@@ -312,8 +312,10 @@ pub fn initialize_workspace(
feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
});
let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new());
+ let vim_mode = cx.add_view(|cx| vim::ModeIndicator::new(cx));
workspace.status_bar().update(cx, |status_bar, cx| {
status_bar.add_left_item(diagnostic_summary, cx);
+ status_bar.add_left_item(vim_mode, cx);
status_bar.add_left_item(activity_indicator, cx);
status_bar.add_right_item(feedback_button, cx);
status_bar.add_right_item(copilot, cx);
@@ -27,6 +27,7 @@ export default function status_bar(): any {
},
border: border(layer, { top: true, overlay: true }),
cursor_position: text(layer, "sans", "variant"),
+ vim_mode: text(layer, "sans", "variant"),
active_language: interactive({
base: {
padding: { left: 6, right: 6 },