Skip to content

Commit

Permalink
correctly store snapshots when repeating insert-mode actions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pascalkuthe authored and archseer committed Mar 9, 2023
1 parent 8cb7cdf commit aabc8af
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
19 changes: 18 additions & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ use crate::{
filter_picker_entry,
job::Callback,
keymap::ReverseKeymap,
ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent},
ui::{
self, editor::InsertEvent, overlay::overlayed, FilePicker, Picker, Popup, Prompt,
PromptEvent,
},
};

use crate::job::{self, Jobs};
Expand Down Expand Up @@ -4205,6 +4208,20 @@ pub fn completion(cx: &mut Context) {
let trigger_doc = doc.id();
let trigger_view = view.id;

// FIXME: The commands Context can only have a single callback
// which means it gets overwritten when executing keybindings
// with multiple commands or macros. This would mean that completion
// might be incorrectly applied when repeating the insertmode action
//
// TODO: to solve this either make cx.callback a Vec of callbacks or
// alternatively move `last_insert` to `helix_view::Editor`
cx.callback = Some(Box::new(
move |compositor: &mut Compositor, _cx: &mut compositor::Context| {
let ui = compositor.find::<ui::EditorView>().unwrap();
ui.last_insert.1.push(InsertEvent::RequestCompletion);
},
));

cx.callback(
future,
move |editor, compositor, response: Option<lsp::CompletionResponse>| {
Expand Down
18 changes: 13 additions & 5 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ use helix_core::{
visual_offset_from_block, Position, Range, Selection, Transaction,
};
use helix_view::{
document::{Mode, SCRATCH_BUFFER_NAME},
document::{Mode, SavePoint, SCRATCH_BUFFER_NAME},
editor::{CompleteAction, CursorShapeConfig},
graphics::{Color, CursorKind, Modifier, Rect, Style},
input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
keyboard::{KeyCode, KeyModifiers},
Document, Editor, Theme, View,
};
use std::{num::NonZeroUsize, path::PathBuf, rc::Rc};
use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};

use tui::buffer::Buffer as Surface;

Expand All @@ -39,7 +39,7 @@ pub struct EditorView {
pub keymaps: Keymaps,
on_next_key: Option<OnKeyCallback>,
pseudo_pending: Vec<KeyEvent>,
last_insert: (commands::MappableCommand, Vec<InsertEvent>),
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
pub(crate) completion: Option<Completion>,
spinners: ProgressSpinners,
}
Expand All @@ -49,6 +49,7 @@ pub enum InsertEvent {
Key(KeyEvent),
CompletionApply(CompleteAction),
TriggerCompletion,
RequestCompletion,
}

impl Default for EditorView {
Expand Down Expand Up @@ -891,14 +892,18 @@ impl EditorView {
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);
let mut last_savepoint = None;
let mut last_request_savepoint = None;
// then replay the inputs
for key in self.last_insert.1.clone() {
match key {
InsertEvent::Key(key) => self.insert_mode(cxt, key),
InsertEvent::CompletionApply(compl) => {
let (view, doc) = current!(cxt.editor);

doc.restore(view);
if let Some(last_savepoint) = last_savepoint.as_deref() {
doc.restore(view, last_savepoint);
}

let text = doc.text().slice(..);
let cursor = doc.selection(view.id).primary().cursor(text);
Expand All @@ -915,8 +920,11 @@ impl EditorView {
doc.apply(&tx, view.id);
}
InsertEvent::TriggerCompletion => {
last_savepoint = take(&mut last_request_savepoint);
}
InsertEvent::RequestCompletion => {
let (view, doc) = current!(cxt.editor);
doc.savepoint(view);
last_request_savepoint = Some(doc.savepoint(view));
}
}
}
Expand Down

0 comments on commit aabc8af

Please sign in to comment.