diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 0821214895df..19f08f855311 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -111,11 +111,9 @@ impl Application { })), ); - let keymaps = Box::new(Map::new(Arc::clone(&config), |config: &Config| { - &config.keys - })); - - let editor_view = Box::new(ui::EditorView::new(keymaps)); + let editor_view = Box::new(ui::EditorView::new(std::mem::take( + &mut config.load().keys.clone(), + ))); compositor.push(editor_view); if args.load_tutor { @@ -266,7 +264,7 @@ impl Application { ConfigEvent::Update(editor_config) => { let mut app_config = (*self.config.load().clone()).clone(); app_config.editor = editor_config; - self.config.store(Arc::new(app_config)); + self.config.swap(Arc::new(app_config)); } } } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c168e5580666..813b4b2ea640 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1586,8 +1586,8 @@ fn rsearch(cx: &mut Context) { } fn searcher(cx: &mut Context, direction: Direction) { - let config = cx.editor.config(); let reg = cx.register.unwrap_or('/'); + let config = cx.editor.config(); let scrolloff = config.scrolloff; let wrap_around = config.search.wrap_around; @@ -2110,7 +2110,7 @@ pub fn command_palette(cx: &mut Context) { move |compositor: &mut Compositor, cx: &mut compositor::Context| { let doc = doc_mut!(cx.editor); let keymap = - compositor.find::().unwrap().keymaps()[&doc.mode].reverse_map(); + compositor.find::().unwrap().keymaps[&doc.mode].reverse_map(); let mut commands: Vec = MappableCommand::STATIC_COMMAND_LIST.into(); commands.extend(typed::TYPABLE_COMMAND_LIST.iter().map(|cmd| { diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 24ec7facaed6..1059feaea473 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -315,7 +315,7 @@ pub enum KeymapResultKind { /// Returned after looking up a key in [`Keymap`]. The `sticky` field has a /// reference to the sticky node if one is currently active. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug)] pub struct KeymapResult<'a> { pub kind: KeymapResultKind, pub sticky: Option<&'a KeyTrieNode>, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index f1c9aae7ab90..6b7455d70cee 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -6,7 +6,6 @@ use crate::{ ui::{Completion, ProgressSpinners}, }; -use arc_swap::access::{DynAccess, DynGuard}; use helix_core::{ coords_at_pos, encoding, graphemes::{ @@ -32,7 +31,7 @@ use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind}; use tui::buffer::Buffer as Surface; pub struct EditorView { - pub keymaps: Box>, + pub keymaps: Keymaps, on_next_key: Option>, last_insert: (commands::MappableCommand, Vec), pub(crate) completion: Option, @@ -46,8 +45,14 @@ pub enum InsertEvent { TriggerCompletion, } +impl Default for EditorView { + fn default() -> Self { + Self::new(Keymaps::default()) + } +} + impl EditorView { - pub fn new(keymaps: Box>) -> Self { + pub fn new(keymaps: Keymaps) -> Self { Self { keymaps, on_next_key: None, @@ -57,10 +62,6 @@ impl EditorView { } } - pub fn keymaps(&self) -> DynGuard { - self.keymaps.load() - } - pub fn spinners_mut(&mut self) -> &mut ProgressSpinners { &mut self.spinners } @@ -697,51 +698,51 @@ impl EditorView { /// otherwise. fn handle_keymap_event( &mut self, - cx: &mut commands::Context, - key_result: &KeymapResult, - ) -> Option { - cx.editor.autoinfo = key_result.sticky.map(|node| node.infobox()); + mode: Mode, + cxt: &mut commands::Context, + event: KeyEvent, + ) -> Option { + cxt.editor.autoinfo = None; + let key_result = self.keymaps.get_mut(&mode).unwrap().get(event); + cxt.editor.autoinfo = key_result.sticky.map(|node| node.infobox()); match &key_result.kind { - KeymapResultKind::Matched(command) => command.execute(cx), - KeymapResultKind::Pending(node) => cx.editor.autoinfo = Some(node.infobox()), + KeymapResultKind::Matched(command) => command.execute(cxt), + KeymapResultKind::Pending(node) => cxt.editor.autoinfo = Some(node.infobox()), KeymapResultKind::MatchedSequence(commands) => { for command in commands { - command.execute(cx); + command.execute(cxt); } } - KeymapResultKind::NotFound => return Some(KeymapResultKind::NotFound), - KeymapResultKind::Cancelled(evs) => { - return Some(KeymapResultKind::Cancelled(evs.to_vec())) - } + KeymapResultKind::NotFound | KeymapResultKind::Cancelled(_) => return Some(key_result), } None } fn insert_mode(&mut self, cx: &mut commands::Context, event: KeyEvent) { - let mut keymaps = self.keymaps().clone(); - let insert_keys = keymaps.get_mut(&Mode::Insert).unwrap(); - - match self.handle_keymap_event(cx, &insert_keys.get(event)) { - Some(KeymapResultKind::NotFound) => { - if let Some(ch) = event.char() { - commands::insert::insert_char(cx, ch) + if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) { + match keyresult.kind { + KeymapResultKind::NotFound => { + if let Some(ch) = event.char() { + commands::insert::insert_char(cx, ch) + } } - } - Some(KeymapResultKind::Cancelled(pending)) => { - for ev in pending { - match ev.char() { - Some(ch) => commands::insert::insert_char(cx, ch), - None => { - if let KeymapResultKind::Matched(command) = insert_keys.get(ev).kind { - command.execute(cx); + KeymapResultKind::Cancelled(pending) => { + for ev in pending { + match ev.char() { + Some(ch) => commands::insert::insert_char(cx, ch), + None => { + if let KeymapResultKind::Matched(command) = + self.keymaps.get_mut(&Mode::Insert).unwrap().get(ev).kind + { + command.execute(cx); + } } } } } + _ => unreachable!(), } - None => {} - _ => unreachable!(), } } @@ -754,7 +755,7 @@ impl EditorView { 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 self.keymaps.pending().is_empty() => { // first execute whatever put us into insert mode self.last_insert.0.execute(cxt); // then replay the inputs @@ -796,10 +797,9 @@ impl EditorView { // set the register cxt.register = cxt.editor.selected_register.take(); - let mut keymaps = self.keymaps().clone(); - let key_result = keymaps.get_mut(&mode).unwrap().get(event); - self.handle_keymap_event(cxt, &key_result); - if keymaps.pending().is_empty() { + + self.handle_keymap_event(mode, cxt, event); + if self.keymaps.pending().is_empty() { cxt.editor.count = None } } @@ -1183,19 +1183,12 @@ impl Component for EditorView { // how we entered insert mode is important, and we should track that so // we can repeat the side effect. - self.last_insert.0 = match self - .keymaps - .load() - .clone() - .get_mut(&mode) - .unwrap() - .get(key) - .kind - { - KeymapResultKind::Matched(command) => command, - // FIXME: insert mode can only be entered through single KeyCodes - _ => unimplemented!(), - }; + self.last_insert.0 = + match self.keymaps.get_mut(&mode).unwrap().get(key).kind { + KeymapResultKind::Matched(command) => command, + // FIXME: insert mode can only be entered through single KeyCodes + _ => unimplemented!(), + }; self.last_insert.1.clear(); } (Mode::Insert, Mode::Normal) => { @@ -1215,7 +1208,7 @@ impl Component for EditorView { fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { // clear with background color surface.set_style(area, cx.editor.theme.get("ui.background")); - + let config = cx.editor.config(); // if the terminal size suddenly changed, we need to trigger a resize cx.editor.resize(area.clip_bottom(1)); // -1 from bottom for commandline @@ -1224,7 +1217,7 @@ impl Component for EditorView { self.render_view(cx.editor, doc, view, area, surface, is_focused); } - if cx.editor.config().auto_info { + if config.auto_info { if let Some(mut info) = cx.editor.autoinfo.take() { info.render(area, surface, cx); cx.editor.autoinfo = Some(info) @@ -1257,7 +1250,7 @@ impl Component for EditorView { if let Some(count) = cx.editor.count { disp.push_str(&count.to_string()) } - for key in self.keymaps().pending() { + for key in self.keymaps.pending() { let s = key.to_string(); if s.graphemes(true).count() > 1 { disp.push_str(&format!("<{}>", s)); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 88bdd93c0311..8220deb7f761 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -42,8 +42,8 @@ use helix_dap as dap; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; -use arc_swap::access::DynAccess; -use arc_swap::access::DynGuard; +use arc_swap::access::{DynAccess, DynGuard}; + fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -770,6 +770,7 @@ impl Editor { } pub fn cursor(&self) -> (Option, CursorKind) { + let config = self.config(); let (view, doc) = current_ref!(self); let cursor = doc .selection(view.id) @@ -779,7 +780,6 @@ impl Editor { let inner = view.inner_area(); pos.col += inner.x as usize; pos.row += inner.y as usize; - let config = self.config(); let cursorkind = config.cursor_shape.from_mode(doc.mode()); (Some(pos), cursorkind) } else {