@ -15,11 +15,11 @@ use helix_core::{
syntax ::{ self , HighlightEvent } ,
syntax ::{ self , HighlightEvent } ,
unicode ::segmentation ::UnicodeSegmentation ,
unicode ::segmentation ::UnicodeSegmentation ,
unicode ::width ::UnicodeWidthStr ,
unicode ::width ::UnicodeWidthStr ,
LineEnding , Position , Range , Selection ,
LineEnding , Position , Range , Selection , Transaction ,
} ;
} ;
use helix_view ::{
use helix_view ::{
document ::{ Mode , SCRATCH_BUFFER_NAME } ,
document ::{ Mode , SCRATCH_BUFFER_NAME } ,
editor ::CursorShapeConfig ,
editor ::{ CompleteAction , CursorShapeConfig } ,
graphics ::{ CursorKind , Modifier , Rect , Style } ,
graphics ::{ CursorKind , Modifier , Rect , Style } ,
input ::KeyEvent ,
input ::KeyEvent ,
keyboard ::{ KeyCode , KeyModifiers } ,
keyboard ::{ KeyCode , KeyModifiers } ,
@ -33,11 +33,18 @@ use tui::buffer::Buffer as Surface;
pub struct EditorView {
pub struct EditorView {
pub keymaps : Keymaps ,
pub keymaps : Keymaps ,
on_next_key : Option < Box < dyn FnOnce ( & mut commands ::Context , KeyEvent ) > > ,
on_next_key : Option < Box < dyn FnOnce ( & mut commands ::Context , KeyEvent ) > > ,
last_insert : ( commands ::MappableCommand , Vec < Key Event> ) ,
last_insert : ( commands ::MappableCommand , Vec < Insert Event> ) ,
pub ( crate ) completion : Option < Completion > ,
pub ( crate ) completion : Option < Completion > ,
spinners : ProgressSpinners ,
spinners : ProgressSpinners ,
}
}
#[ derive(Debug, Clone) ]
pub enum InsertEvent {
Key ( KeyEvent ) ,
CompletionApply ( CompleteAction ) ,
TriggerCompletion ,
}
impl Default for EditorView {
impl Default for EditorView {
fn default ( ) -> Self {
fn default ( ) -> Self {
Self ::new ( Keymaps ::default ( ) )
Self ::new ( Keymaps ::default ( ) )
@ -766,8 +773,33 @@ impl EditorView {
// first execute whatever put us into insert mode
// first execute whatever put us into insert mode
self . last_insert . 0. execute ( cxt ) ;
self . last_insert . 0. execute ( cxt ) ;
// then replay the inputs
// then replay the inputs
for & key in & self . last_insert . 1. clone ( ) {
for key in self . last_insert . 1. clone ( ) {
self . insert_mode ( cxt , key )
match key {
InsertEvent ::Key ( key ) = > self . insert_mode ( cxt , key ) ,
InsertEvent ::CompletionApply ( compl ) = > {
let ( view , doc ) = current ! ( cxt . editor ) ;
doc . restore ( view . id ) ;
let text = doc . text ( ) . slice ( .. ) ;
let cursor = doc . selection ( view . id ) . primary ( ) . cursor ( text ) ;
let shift_position =
| pos : usize | -> usize { pos + cursor - compl . trigger_offset } ;
let tx = Transaction ::change (
doc . text ( ) ,
compl . changes . iter ( ) . cloned ( ) . map ( | ( start , end , t ) | {
( shift_position ( start ) , shift_position ( end ) , t )
} ) ,
) ;
doc . apply ( & tx , view . id ) ;
}
InsertEvent ::TriggerCompletion = > {
let ( _ , doc ) = current ! ( cxt . editor ) ;
doc . savepoint ( ) ;
}
}
}
}
}
}
_ = > {
_ = > {
@ -808,6 +840,9 @@ impl EditorView {
// Immediately initialize a savepoint
// Immediately initialize a savepoint
doc_mut ! ( editor ) . savepoint ( ) ;
doc_mut ! ( editor ) . savepoint ( ) ;
editor . last_completion = None ;
self . last_insert . 1. push ( InsertEvent ::TriggerCompletion ) ;
// TODO : propagate required size on resize to completion too
// TODO : propagate required size on resize to completion too
completion . required_size ( ( size . width , size . height ) ) ;
completion . required_size ( ( size . width , size . height ) ) ;
self . completion = Some ( completion ) ;
self . completion = Some ( completion ) ;
@ -1067,9 +1102,6 @@ impl Component for EditorView {
} else {
} else {
match mode {
match mode {
Mode ::Insert = > {
Mode ::Insert = > {
// record last_insert key
self . last_insert . 1. push ( key ) ;
// let completion swallow the event if necessary
// let completion swallow the event if necessary
let mut consumed = false ;
let mut consumed = false ;
if let Some ( completion ) = & mut self . completion {
if let Some ( completion ) = & mut self . completion {
@ -1093,8 +1125,15 @@ impl Component for EditorView {
// if completion didn't take the event, we pass it onto commands
// if completion didn't take the event, we pass it onto commands
if ! consumed {
if ! consumed {
if let Some ( compl ) = cx . editor . last_completion . take ( ) {
self . last_insert . 1. push ( InsertEvent ::CompletionApply ( compl ) ) ;
}
self . insert_mode ( & mut cx , key ) ;
self . insert_mode ( & mut cx , key ) ;
// record last_insert key
self . last_insert . 1. push ( InsertEvent ::Key ( key ) ) ;
// lastly we recalculate completion
// lastly we recalculate completion
if let Some ( completion ) = & mut self . completion {
if let Some ( completion ) = & mut self . completion {
completion . update ( & mut cx ) ;
completion . update ( & mut cx ) ;