Skip to content

Commit 0144c92

Browse files
committed
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.
1 parent e01126e commit 0144c92

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

helix-term/src/commands.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -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

5962
use crate::job::{self, Jobs};
@@ -4200,6 +4203,20 @@ pub fn completion(cx: &mut Context) {
42004203
let trigger_doc = doc.id();
42014204
let trigger_view = view.id;
42024205

4206+
// FIXME: The commands Context can only have a single callback
4207+
// which means it gets overwritten when executing keybindings
4208+
// with multiple commands or macros. This would mean that completion
4209+
// might be incorrectly applied when repeating the insertmode action
4210+
//
4211+
// TODO: to solve this either make cx.callback a Vec of callbacks or
4212+
// alternatively move `last_insert` to `helix_view::Editor`
4213+
cx.callback = Some(Box::new(
4214+
move |compositor: &mut Compositor, _cx: &mut compositor::Context| {
4215+
let ui = compositor.find::<ui::EditorView>().unwrap();
4216+
ui.last_insert.1.push(InsertEvent::RequestCompletion);
4217+
},
4218+
));
4219+
42034220
cx.callback(
42044221
future,
42054222
move |editor, compositor, response: Option<lsp::CompletionResponse>| {

helix-term/src/ui/editor.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ use helix_core::{
2121
visual_offset_from_block, Position, Range, Selection, Transaction,
2222
};
2323
use 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

3333
use 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

5455
impl Default for EditorView {
@@ -891,14 +892,18 @@ 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 {
897900
InsertEvent::Key(key) => self.insert_mode(cxt, key),
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
}

0 commit comments

Comments
 (0)