editor mode in editor.rs

Smit Barmase and Oleksiy Syvokon created

Co-authored-by: Oleksiy Syvokon <oleksiy.syvokon@gmail.com>

Change summary

Cargo.lock                                      |  2 
crates/agent_ui/Cargo.toml                      |  1 
crates/agent_ui/src/message_editor.rs           | 13 +++++
crates/editor/Cargo.toml                        |  1 
crates/editor/src/editor.rs                     | 45 ++++++++++++++++--
crates/onboarding/src/basics_page.rs            |  5 +
crates/vim/src/vim.rs                           | 32 +++++++++----
crates/vim_mode_setting/src/vim_mode_setting.rs |  1 
crates/zed/src/zed.rs                           |  2 
crates/zed/src/zed/quick_action_bar.rs          |  5 +
10 files changed, 89 insertions(+), 18 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -415,6 +415,7 @@ dependencies = [
  "urlencoding",
  "util",
  "uuid",
+ "vim_mode_setting",
  "watch",
  "workspace",
  "workspace-hack",
@@ -5115,6 +5116,7 @@ dependencies = [
  "url",
  "util",
  "uuid",
+ "vim_mode_setting",
  "workspace",
  "workspace-hack",
  "zed_actions",

crates/agent_ui/Cargo.toml 🔗

@@ -100,6 +100,7 @@ watch.workspace = true
 workspace-hack.workspace = true
 workspace.workspace = true
 zed_actions.workspace = true
+vim_mode_setting.workspace = true
 
 [dev-dependencies]
 acp_thread = { workspace = true, features = ["test-support"] }

crates/agent_ui/src/message_editor.rs 🔗

@@ -114,6 +114,18 @@ pub(crate) fn create_editor(
     let editor = cx.new(|cx| {
         let buffer = cx.new(|cx| Buffer::local("", cx).with_language(Arc::new(language), cx));
         let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
+        let settings = agent_settings::AgentSettings::get_global(cx);
+
+        let editor_mode = match settings.editor_mode {
+            agent_settings::AgentEditorMode::Vim => vim_mode_setting::EditorMode::Vim,
+            agent_settings::AgentEditorMode::VimInsert => vim_mode_setting::EditorMode::VimInsert,
+            agent_settings::AgentEditorMode::Helix => vim_mode_setting::EditorMode::Helix,
+            agent_settings::AgentEditorMode::Default => vim_mode_setting::EditorMode::Default,
+            agent_settings::AgentEditorMode::Inherit => {
+                vim_mode_setting::EditorModeSetting::get_global(cx).0
+            }
+        };
+
         let mut editor = Editor::new(
             editor::EditorMode::AutoHeight {
                 min_lines,
@@ -128,6 +140,7 @@ pub(crate) fn create_editor(
         editor.set_show_indent_guides(false, cx);
         editor.set_soft_wrap();
         editor.set_use_modal_editing(true);
+        editor.set_default_editor_mode(editor_mode);
         editor.set_context_menu_options(ContextMenuOptions {
             min_entries_visible: 12,
             max_entries_visible: 12,

crates/editor/Cargo.toml 🔗

@@ -92,6 +92,7 @@ uuid.workspace = true
 workspace.workspace = true
 zed_actions.workspace = true
 workspace-hack.workspace = true
+vim_mode_setting.workspace = true
 
 [dev-dependencies]
 ctor.workspace = true

crates/editor/src/editor.rs 🔗

@@ -165,6 +165,7 @@ use project::{
 };
 use rand::{seq::SliceRandom, thread_rng};
 use rpc::{ErrorCode, ErrorExt, proto::PeerId};
+use schemars::JsonSchema;
 use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
 use selections_collection::{
     MutableSelectionsCollection, SelectionsCollection, resolve_selections,
@@ -201,6 +202,7 @@ use ui::{
     IconSize, Indicator, Key, Tooltip, h_flex, prelude::*,
 };
 use util::{RangeExt, ResultExt, TryFutureExt, maybe, post_inc};
+use vim_mode_setting::EditorModeSetting;
 use workspace::{
     CollaboratorId, Item as WorkspaceItem, ItemId, ItemNavHistory, OpenInTerminal, OpenTerminal,
     RestoreOnStartupBehavior, SERIALIZATION_THROTTLE_TIME, SplitDirection, TabBarSettings, Toast,
@@ -1092,7 +1094,6 @@ pub struct Editor {
     autoindent_mode: Option<AutoindentMode>,
     workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
     input_enabled: bool,
-    use_modal_editing: bool,
     read_only: bool,
     leader_id: Option<CollaboratorId>,
     remote_id: Option<ViewId>,
@@ -1180,6 +1181,39 @@ pub struct Editor {
     next_color_inlay_id: usize,
     colors: Option<LspColorData>,
     folding_newlines: Task<()>,
+    default_editor_mode: vim_mode_setting::EditorMode,
+    // editor_mode: EditorMode, <-- while init define which editor,
+
+    // agenty subscribe to agen settings
+    //
+    // editor <- agent
+    //
+    // settings listent to event emitted by editor,
+    //
+
+    // agent will set_editor_mode(AgentPanelSettings::read("editor_mode")) on init
+    // vim.rs will get_editor_mode() on init / activate / register
+    //
+    // match editor_mode {
+    //      // which setting to use
+    // }
+    //
+    //
+
+    // editor_mode: EditorMode, <-- while init define which editor,
+    // pros -> jsut set enum
+    // cons -> actual setting check lives in either editor.rs or vim.rs??
+    //
+    // set_edutr();
+    //
+    // Fn () -> weather mode this editor is, and what;s the default value?
+    //  pros -> all setting lives in agent, git.
+    // cons -> if someone wants to use agent setting in their editor, they need to copy paste code
+    //
+    // // agent.rs
+    // set_vim_setting_fn(|| {
+    //     // edito seting agnet
+    // });
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@@ -2258,6 +2292,7 @@ impl Editor {
             mode,
             selection_drag_state: SelectionDragState::None,
             folding_newlines: Task::ready(()),
+            default_editor_mode: vim_mode_setting::EditorMode::default(),
         };
 
         if is_minimap {
@@ -2994,12 +3029,12 @@ impl Editor {
         })
     }
 
-    pub fn set_use_modal_editing(&mut self, to: bool) {
-        self.use_modal_editing = to;
+    pub fn set_default_editor_mode(&mut self, to: vim_mode_setting::EditorMode) {
+        self.default_editor_mode = to;
     }
 
-    pub fn use_modal_editing(&self) -> bool {
-        self.use_modal_editing
+    pub fn default_editor_mode(&self) -> vim_mode_setting::EditorMode {
+        self.default_editor_mode
     }
 
     fn selections_did_change(

crates/onboarding/src/basics_page.rs 🔗

@@ -332,7 +332,10 @@ fn render_base_keymap_section(tab_index: &mut isize, cx: &mut App) -> impl IntoE
 
 fn render_vim_mode_switch(tab_index: &mut isize, cx: &mut App) -> impl IntoElement {
     let editor_mode = EditorModeSetting::get_global(cx).0;
-    let toggle_state = if matches!(editor_mode, EditorMode::Vim | EditorMode::Helix) {
+    let toggle_state = if matches!(
+        editor_mode,
+        EditorMode::Vim | EditorMode::Helix | EditorMode::VimInsert
+    ) {
         ui::ToggleState::Selected
     } else {
         ui::ToggleState::Unselected

crates/vim/src/vim.rs 🔗

@@ -454,6 +454,10 @@ impl Vim {
             return;
         }
 
+        if editor.default_editor_mode() == EditorMode::Default {
+            return;
+        }
+
         let mut was_enabled = Vim::enabled(cx);
         let mut was_toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
         cx.observe_global_in::<SettingsStore>(window, move |editor, window, cx| {
@@ -489,7 +493,9 @@ impl Vim {
     fn activate(editor: &mut Editor, window: &mut Window, cx: &mut Context<Editor>) {
         let vim = Vim::new(window, cx);
 
-        if !editor.mode().is_full() {
+        let default_editor_mode = editor.default_editor_mode();
+
+        if default_editor_mode == EditorMode::VimInsert {
             vim.update(cx, |vim, _| {
                 vim.mode = Mode::Insert;
             });
@@ -499,14 +505,18 @@ impl Vim {
             entity: vim.clone(),
         });
 
-        vim.update(cx, |_, cx| {
-            Vim::action(editor, cx, |vim, _: &SwitchToNormalMode, window, cx| {
-                if matches!(EditorModeSetting::get_global(cx).0, EditorMode::Helix) {
-                    vim.switch_mode(Mode::HelixNormal, false, window, cx)
-                } else {
-                    vim.switch_mode(Mode::Normal, false, window, cx)
-                }
-            });
+        vim.update(cx, move |_, cx| {
+            Vim::action(
+                editor,
+                cx,
+                move |vim, _: &SwitchToNormalMode, window, cx| {
+                    if matches!(default_editor_mode, EditorMode::Helix) {
+                        vim.switch_mode(Mode::HelixNormal, false, window, cx)
+                    } else {
+                        vim.switch_mode(Mode::Normal, false, window, cx)
+                    }
+                },
+            );
 
             Vim::action(editor, cx, |vim, _: &SwitchToInsertMode, window, cx| {
                 vim.switch_mode(Mode::Insert, false, window, cx)
@@ -827,8 +837,10 @@ impl Vim {
         if EditorModeSetting::get_global(cx).0 == EditorMode::Default {
             return false;
         }
+
+        // check for agent.editor_mode
+        //
         return true;
-        // VimModeSetting::get_global(cx).0 || HelixModeSetting::get_global(cx).0
     }
 
     /// Called whenever an keystroke is typed so vim can observe all actions

crates/vim_mode_setting/src/vim_mode_setting.rs 🔗

@@ -23,6 +23,7 @@ pub struct EditorModeSetting(pub EditorMode);
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
 pub enum EditorMode {
     Vim,
+    VimInsert,
     Helix,
     #[default]
     Default,

crates/zed/src/zed.rs 🔗

@@ -1495,7 +1495,7 @@ pub fn load_default_keymap(cx: &mut App) {
 
     if matches!(
         EditorModeSetting::get_global(cx).0,
-        EditorMode::Vim | EditorMode::Helix
+        EditorMode::Vim | EditorMode::Helix | EditorMode::VimInsert
     ) {
         cx.bind_keys(
             KeymapFile::load_asset(VIM_KEYMAP_PATH, Some(KeybindSource::Vim), cx).unwrap(),

crates/zed/src/zed/quick_action_bar.rs 🔗

@@ -302,7 +302,10 @@ impl Render for QuickActionBar {
         let editor = editor.downgrade();
         let editor_settings_dropdown = {
             let editor_mode = EditorModeSetting::get_global(cx).0;
-            let vim_mode_enabled = matches!(editor_mode, EditorMode::Vim | EditorMode::Helix);
+            let vim_mode_enabled = matches!(
+                editor_mode,
+                EditorMode::Vim | EditorMode::Helix | EditorMode::VimInsert
+            );
 
             PopoverMenu::new("editor-settings")
                 .trigger_with_tooltip(