on master help sign in
correctly store snapshots when repeating insert-mode actions
aabc8afPascal Kuthe
helix-term/src/commands.rs+18−1
@@ -53,7 +53,10 @@ use crate::{
53 filter_picker_entry,
53 filter_picker_entry,
54 job::Callback,
54 job::Callback,
55 keymap::ReverseKeymap,
55 keymap::ReverseKeymap,
56+ ui::{
56− ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent},
57+ self, editor::InsertEvent, overlay::overlayed, FilePicker, Picker, Popup, Prompt,
58+ PromptEvent,
59+ },
57};
60};
58
61
59use crate::job::{self, Jobs};
62use crate::job::{self, Jobs};
@@ -4205,6 +4208,20 @@ pub fn completion(cx: &mut Context) {
4205 let trigger_doc = doc.id();
4208 let trigger_doc = doc.id();
4206 let trigger_view = view.id;
4209 let trigger_view = view.id;
4207
4210
4211+ // FIXME: The commands Context can only have a single callback
4212+ // which means it gets overwritten when executing keybindings
4213+ // with multiple commands or macros. This would mean that completion
4214+ // might be incorrectly applied when repeating the insertmode action
4215+ //
4216+ // TODO: to solve this either make cx.callback a Vec of callbacks or
4217+ // alternatively move `last_insert` to `helix_view::Editor`
4218+ cx.callback = Some(Box::new(
4219+ move |compositor: &mut Compositor, _cx: &mut compositor::Context| {
4220+ let ui = compositor.find::<ui::EditorView>().unwrap();
4221+ ui.last_insert.1.push(InsertEvent::RequestCompletion);
4222+ },
4223+ ));
4224+
4208 cx.callback(
4225 cx.callback(
4209 future,
4226 future,
4210 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
4227 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
helix-term/src/ui/editor.rs+13−5
@@ -21,14 +21,14 @@ use helix_core::{
21 visual_offset_from_block, Position, Range, Selection, Transaction,
21 visual_offset_from_block, Position, Range, Selection, Transaction,
22};
22};
23use helix_view::{
23use helix_view::{
24− document::{Mode, SCRATCH_BUFFER_NAME},
24+ document::{Mode, SavePoint, SCRATCH_BUFFER_NAME},
25 editor::{CompleteAction, CursorShapeConfig},
25 editor::{CompleteAction, CursorShapeConfig},
26 graphics::{Color, CursorKind, Modifier, Rect, Style},
26 graphics::{Color, CursorKind, Modifier, Rect, Style},
27 input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
27 input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
28 keyboard::{KeyCode, KeyModifiers},
28 keyboard::{KeyCode, KeyModifiers},
29 Document, Editor, Theme, View,
29 Document, Editor, Theme, View,
30};
30};
31−use std::{num::NonZeroUsize, path::PathBuf, rc::Rc};
31+use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};
32
32
33use tui::buffer::Buffer as Surface;
33use tui::buffer::Buffer as Surface;
34
34
@@ -39,7 +39,7 @@ pub struct EditorView {
39 pub keymaps: Keymaps,
39 pub keymaps: Keymaps,
40 on_next_key: Option<OnKeyCallback>,
40 on_next_key: Option<OnKeyCallback>,
41 pseudo_pending: Vec<KeyEvent>,
41 pseudo_pending: Vec<KeyEvent>,
42− last_insert: (commands::MappableCommand, Vec<InsertEvent>),
42+ pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
43 pub(crate) completion: Option<Completion>,
43 pub(crate) completion: Option<Completion>,
44 spinners: ProgressSpinners,
44 spinners: ProgressSpinners,
45}
45}
@@ -49,6 +49,7 @@ pub enum InsertEvent {
49 Key(KeyEvent),
49 Key(KeyEvent),
50 CompletionApply(CompleteAction),
50 CompletionApply(CompleteAction),
51 TriggerCompletion,
51 TriggerCompletion,
52+ RequestCompletion,
52}
53}
53
54
54impl Default for EditorView {
55impl Default for EditorView {
@@ -891,6 +892,8 @@ impl EditorView {
891 for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) {
892 for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) {
892 // first execute whatever put us into insert mode
893 // first execute whatever put us into insert mode
893 self.last_insert.0.execute(cxt);
894 self.last_insert.0.execute(cxt);
895+ let mut last_savepoint = None;
896+ let mut last_request_savepoint = None;
894 // then replay the inputs
897 // then replay the inputs
895 for key in self.last_insert.1.clone() {
898 for key in self.last_insert.1.clone() {
896 match key {
899 match key {
@@ -898,7 +901,9 @@ impl EditorView {
898 InsertEvent::CompletionApply(compl) => {
901 InsertEvent::CompletionApply(compl) => {
899 let (view, doc) = current!(cxt.editor);
902 let (view, doc) = current!(cxt.editor);
900
903
904+ if let Some(last_savepoint) = last_savepoint.as_deref() {
901− doc.restore(view);
905+ doc.restore(view, last_savepoint);
906+ }
902
907
903 let text = doc.text().slice(..);
908 let text = doc.text().slice(..);
904 let cursor = doc.selection(view.id).primary().cursor(text);
909 let cursor = doc.selection(view.id).primary().cursor(text);
@@ -915,8 +920,11 @@ impl EditorView {
915 doc.apply(&tx, view.id);
920 doc.apply(&tx, view.id);
916 }
921 }
917 InsertEvent::TriggerCompletion => {
922 InsertEvent::TriggerCompletion => {
923+ last_savepoint = take(&mut last_request_savepoint);
924+ }
925+ InsertEvent::RequestCompletion => {
918 let (view, doc) = current!(cxt.editor);
926 let (view, doc) = current!(cxt.editor);
919− doc.savepoint(view);
927+ last_request_savepoint = Some(doc.savepoint(view));
920 }
928 }
921 }
929 }
922 }
930 }