diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 7e9684827..25875d457 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -63,6 +63,7 @@ pub struct Application { compositor: Compositor, + keymaps: Keymaps, terminal: Terminal, pub editor: Editor, @@ -156,7 +157,8 @@ pub fn new( let keys = Box::new(Map::new(Arc::clone(&config), |config: &Config| { &config.keys })); - let editor_view = Box::new(ui::EditorView::new(Keymaps::new(keys))); + let keymaps = Keymaps::new(keys); + let editor_view = Box::new(ui::EditorView::default()); compositor.push(editor_view); if args.load_tutor { @@ -241,6 +243,7 @@ pub fn new( .context("build signal handler")?; let app = Self { + keymaps, compositor, terminal, editor, @@ -261,6 +264,7 @@ pub fn new( async fn render(&mut self) { let mut cx = crate::compositor::Context { + keymaps: &mut self.keymaps, editor: &mut self.editor, jobs: &mut self.jobs, scroll: None, @@ -521,6 +525,7 @@ pub async fn handle_signals(&mut self, signal: i32) -> bool { pub async fn handle_idle_timeout(&mut self) { let mut cx = crate::compositor::Context { + keymaps: &mut self.keymaps, editor: &mut self.editor, jobs: &mut self.jobs, scroll: None, @@ -641,6 +646,7 @@ pub async fn handle_terminal_events( event: Result, ) { let mut cx = crate::compositor::Context { + keymaps: &mut self.keymaps, editor: &mut self.editor, jobs: &mut self.jobs, scroll: None, diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 1bd736523..f77e27a25 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -53,7 +53,7 @@ compositor::{self, Component, Compositor}, filter_picker_entry, job::Callback, - keymap::ReverseKeymap, + keymap::{Keymaps, ReverseKeymap}, ui::{ self, editor::InsertEvent, lsp::SignatureHelp, overlay::overlaid, CompletionItem, Picker, Popup, Prompt, PromptEvent, @@ -81,6 +81,8 @@ pub type OnKeyCallback = Box; pub struct Context<'a> { + pub keymaps: &'a mut Keymaps, + pub register: Option, pub count: Option, pub editor: &'a mut Editor, @@ -196,6 +198,7 @@ pub fn execute(&self, cx: &mut Context) { let args: Vec> = args.iter().map(Cow::from).collect(); if let Some(command) = typed::TYPABLE_COMMAND_MAP.get(name.as_str()) { let mut cx = compositor::Context { + keymaps: cx.keymaps, editor: cx.editor, jobs: cx.jobs, scroll: None, @@ -2716,9 +2719,8 @@ pub fn command_palette(cx: &mut Context) { cx.callback = Some(Box::new( move |compositor: &mut Compositor, cx: &mut compositor::Context| { - let keymap = compositor.find::().unwrap().keymaps.map() - [&cx.editor.mode] - .reverse_map(); + let keymap = + cx.keymaps.map()[&crate::keymap::Domain::Mode(cx.editor.mode)].reverse_map(); let mut commands: Vec = MappableCommand::STATIC_COMMAND_LIST.into(); commands.extend(typed::TYPABLE_COMMAND_LIST.iter().map(|cmd| { @@ -2733,6 +2735,7 @@ pub fn command_palette(cx: &mut Context) { let mut ctx = Context { register, count, + keymaps: cx.keymaps, editor: cx.editor, callback: None, on_next_key_callback: None, diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs index bcb3e4490..904d22baa 100644 --- a/helix-term/src/compositor.rs +++ b/helix-term/src/compositor.rs @@ -15,12 +15,13 @@ pub enum EventResult { Consumed(Option), } -use crate::job::Jobs; +use crate::{job::Jobs, keymap::Keymaps}; use helix_view::Editor; pub use helix_view::input::Event; pub struct Context<'a> { + pub keymaps: &'a mut Keymaps, pub editor: &'a mut Editor, pub scroll: Option, pub jobs: &'a mut Jobs, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 5b5cda935..515297c39 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -3,7 +3,7 @@ compositor::{Component, Context, Event, EventResult}, job::{self, Callback}, key, - keymap::{KeymapResult, Keymaps}, + keymap::KeymapResult, ui::{ document::{render_document, LinePos, TextRenderer, TranslatedPosition}, Completion, ProgressSpinners, @@ -37,7 +37,6 @@ use super::{document::LineDecoration, lsp::SignatureHelp}; pub struct EditorView { - pub keymaps: Keymaps, on_next_key: Option, pseudo_pending: Vec, pub(crate) last_insert: (commands::MappableCommand, Vec), @@ -58,14 +57,7 @@ pub enum InsertEvent { impl Default for EditorView { fn default() -> Self { - Self::new(Keymaps::default()) - } -} - -impl EditorView { - pub fn new(keymaps: Keymaps) -> Self { Self { - keymaps, on_next_key: None, pseudo_pending: Vec::new(), last_insert: (commands::MappableCommand::normal_mode, Vec::new()), @@ -73,7 +65,9 @@ pub fn new(keymaps: Keymaps) -> Self { spinners: ProgressSpinners::default(), } } +} +impl EditorView { pub fn spinners_mut(&mut self) -> &mut ProgressSpinners { &mut self.spinners } @@ -786,7 +780,7 @@ pub fn highlight_cursorcolumn( } } - /// Handle events by looking them up in `self.keymaps`. Returns None + /// Handle events by looking them up in `cxt.keymaps`. Returns None /// if event was handled (a command was executed or a subkeymap was /// activated). Only KeymapResult::{NotFound, Cancelled} is returned /// otherwise. @@ -797,9 +791,9 @@ fn handle_keymap_event( event: KeyEvent, ) -> Option { let mut last_mode = mode; - self.pseudo_pending.extend(self.keymaps.pending()); - let key_result = self.keymaps.get(mode, event); - cxt.editor.autoinfo = self.keymaps.sticky().map(|node| node.infobox()); + self.pseudo_pending.extend(cxt.keymaps.pending()); + let key_result = cxt.keymaps.get(mode, event); + cxt.editor.autoinfo = cxt.keymaps.sticky().map(|node| node.infobox()); let mut execute_command = |command: &commands::MappableCommand| { command.execute(cxt); @@ -864,7 +858,7 @@ fn insert_mode(&mut self, cx: &mut commands::Context, event: KeyEvent) { Some(ch) => commands::insert::insert_char(cx, ch), None => { if let KeymapResult::Matched(command) = - self.keymaps.get(Mode::Insert, ev) + cx.keymaps.get_by_mode(Mode::Insert, ev) { command.execute(cx); } @@ -886,7 +880,7 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv std::num::NonZeroUsize::new(cxt.editor.count.map_or(i, |c| c.get() * 10 + i)); } // special handling for repeat operator - (key!('.'), _) if self.keymaps.pending().is_empty() => { + (key!('.'), _) if cxt.keymaps.pending().is_empty() => { for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) { // first execute whatever put us into insert mode self.last_insert.0.execute(cxt); @@ -944,7 +938,7 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv cxt.register = cxt.editor.selected_register.take(); self.handle_keymap_event(mode, cxt, event); - if self.keymaps.pending().is_empty() { + if cxt.keymaps.pending().is_empty() { cxt.editor.count = None } else { cxt.editor.selected_register = cxt.register.take(); @@ -1225,6 +1219,7 @@ fn handle_event( context: &mut crate::compositor::Context, ) -> EventResult { let mut cx = commands::Context { + keymaps: context.keymaps, editor: context.editor, count: None, register: None, @@ -1280,6 +1275,7 @@ fn handle_event( let res = { // use a fake context here let mut cx = Context { + keymaps: cx.keymaps, editor: cx.editor, jobs: cx.jobs, scroll: None, @@ -1445,7 +1441,7 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { if let Some(count) = cx.editor.count { disp.push_str(&count.to_string()) } - for key in self.keymaps.pending() { + for key in cx.keymaps.pending() { disp.push_str(&key.key_sequence_format()); } for key in &self.pseudo_pending {