on master help sign in
correctly store snapshots when repeating insert-mode actions

Repeating completions currently crates a savepoint when a completion popup was triggered (so after the request completed). Just like for normal completions the savepoint must be created at the request. The occurrence of the completion request was previously not saved in `last_insert`. To that end a new `InsertEvent::RequestCompletion` variant has been added. When replayed this event creates a snapshot that is "actived" by the `TriggerCompletion` event and subsequently used during any `InsertEvent::CompletiuonApply` events.

commitaabc8af95dd1c093da4b67151f6a7026a85e9c0e authorPascal Kuthe <pascal.kuthe@semimod.de> dateFri 3 Mar 2023, 00:34 (4 years ago) parent8cb7cdf
2 files changed+31−6
helix-term/src/commands.rs+18−1 helix-term/src/ui/editor.rs+13−5
helix-term/src/commands.rs+18−1
@@ -53,7 +53,10 @@ use crate::{
5353 filter_picker_entry,
5454 job::Callback,
5555 keymap::ReverseKeymap,
56− ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent},
56+ ui::{
57+ self, editor::InsertEvent, overlay::overlayed, FilePicker, Picker, Popup, Prompt,
58+ PromptEvent,
59+ },
5760};
5861
5962use crate::job::{self, Jobs};
@@ -4205,6 +4208,20 @@ pub fn completion(cx: &mut Context) {
42054208 let trigger_doc = doc.id();
42064209 let trigger_view = view.id;
42074210
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+
42084225 cx.callback(
42094226 future,
42104227 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
helix-term/src/ui/editor.rs+13−5
@@ -21,14 +21,14 @@ use helix_core::{
2121 visual_offset_from_block, Position, Range, Selection, Transaction,
2222};
2323use helix_view::{
24− document::{Mode, SCRATCH_BUFFER_NAME},
24+ document::{Mode, SavePoint, SCRATCH_BUFFER_NAME},
2525 editor::{CompleteAction, CursorShapeConfig},
2626 graphics::{Color, CursorKind, Modifier, Rect, Style},
2727 input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
2828 keyboard::{KeyCode, KeyModifiers},
2929 Document, Editor, Theme, View,
3030};
31−use std::{num::NonZeroUsize, path::PathBuf, rc::Rc};
31+use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};
3232
3333use tui::buffer::Buffer as Surface;
3434
@@ -39,7 +39,7 @@ pub struct EditorView {
3939 pub keymaps: Keymaps,
4040 on_next_key: Option<OnKeyCallback>,
4141 pseudo_pending: Vec<KeyEvent>,
42− last_insert: (commands::MappableCommand, Vec<InsertEvent>),
42+ pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
4343 pub(crate) completion: Option<Completion>,
4444 spinners: ProgressSpinners,
4545}
@@ -49,6 +49,7 @@ pub enum InsertEvent {
4949 Key(KeyEvent),
5050 CompletionApply(CompleteAction),
5151 TriggerCompletion,
52+ RequestCompletion,
5253}
5354
5455impl Default for EditorView {
@@ -891,6 +892,8 @@ impl EditorView {
891892 for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) {
892893 // first execute whatever put us into insert mode
893894 self.last_insert.0.execute(cxt);
895+ let mut last_savepoint = None;
896+ let mut last_request_savepoint = None;
894897 // then replay the inputs
895898 for key in self.last_insert.1.clone() {
896899 match key {
@@ -898,7 +901,9 @@ impl EditorView {
898901 InsertEvent::CompletionApply(compl) => {
899902 let (view, doc) = current!(cxt.editor);
900903
901− doc.restore(view);
904+ if let Some(last_savepoint) = last_savepoint.as_deref() {
905+ doc.restore(view, last_savepoint);
906+ }
902907
903908 let text = doc.text().slice(..);
904909 let cursor = doc.selection(view.id).primary().cursor(text);
@@ -915,8 +920,11 @@ impl EditorView {
915920 doc.apply(&tx, view.id);
916921 }
917922 InsertEvent::TriggerCompletion => {
923+ last_savepoint = take(&mut last_request_savepoint);
924+ }
925+ InsertEvent::RequestCompletion => {
918926 let (view, doc) = current!(cxt.editor);
919− doc.savepoint(view);
927+ last_request_savepoint = Some(doc.savepoint(view));
920928 }
921929 }
922930 }