From 9999ef643ffe3ee953c675aa05b62705a2f45266 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 15 Aug 2020 18:17:57 -0400 Subject: [PATCH] Use delta instead of textedit --- internal/buffer/autocomplete.go | 33 ++++++++++++++++----------------- internal/buffer/buffer.go | 16 ++++++++++++++++ internal/buffer/eventhandler.go | 6 ++++++ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/internal/buffer/autocomplete.go b/internal/buffer/autocomplete.go index 135637a5..4a5817ed 100644 --- a/internal/buffer/autocomplete.go +++ b/internal/buffer/autocomplete.go @@ -9,7 +9,6 @@ import ( "github.com/zyedidia/micro/v2/internal/lsp" "github.com/zyedidia/micro/v2/internal/util" - "go.lsp.dev/protocol" ) // A Completer is a function that takes a buffer and returns info @@ -22,7 +21,7 @@ import ( type Completer func(*Buffer) []Completion type Completion struct { - Edits []protocol.TextEdit + Edits []Delta Label string CommitChars []rune Kind int @@ -67,7 +66,7 @@ func (b *Buffer) CycleAutocomplete(forward bool) { // apply current completion comp := b.Completions[b.CurCompletion] - b.ApplyEdits(comp.Edits) + b.ApplyDeltas(comp.Edits) if len(b.Completions) > 1 { b.HasSuggestions = true } @@ -234,7 +233,11 @@ func LSPComplete(b *Buffer) []Completion { } if item.TextEdit != nil && len(item.TextEdit.NewText) > 0 { - completions[i].Edits = []protocol.TextEdit{*item.TextEdit} + completions[i].Edits = []Delta{Delta{ + Text: []byte(item.TextEdit.NewText), + Start: toLoc(item.TextEdit.Range.Start), + End: toLoc(item.TextEdit.Range.End), + }} } else { var t string if len(item.InsertText) > 0 { @@ -243,13 +246,11 @@ func LSPComplete(b *Buffer) []Completion { t = item.Label } _, argstart := GetWord(b) - str := util.SliceEndStr(t, c.X-argstart) - completions[i].Edits = []protocol.TextEdit{protocol.TextEdit{ - NewText: str, - Range: protocol.Range{ - Start: lsp.Position(c.X, c.Y), - End: lsp.Position(c.X, c.Y), - }, + str := util.SliceEnd([]byte(t), c.X-argstart) + completions[i].Edits = []Delta{Delta{ + Text: str, + Start: Loc{c.X, c.Y}, + End: Loc{c.X, c.Y}, }} } } @@ -266,12 +267,10 @@ func ConvertCompletions(completions, suggestions []string, c *Cursor) []Completi comp[i] = Completion{ Label: suggestions[i], } - comp[i].Edits = []protocol.TextEdit{protocol.TextEdit{ - NewText: completions[i], - Range: protocol.Range{ - Start: lsp.Position(c.X, c.Y), - End: lsp.Position(c.X, c.Y), - }, + comp[i].Edits = []Delta{Delta{ + Text: []byte(completions[i]), + Start: Loc{c.X, c.Y}, + End: Loc{c.X, c.Y}, }} } return comp diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 9de39d95..bd0285e1 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -553,6 +553,22 @@ func (b *Buffer) ApplyEdits(edits []lspt.TextEdit) { } } +func (b *Buffer) ApplyDeltas(deltas []Delta) { + if !b.Type.Readonly { + sort.Slice(deltas, func(i, j int) bool { + return deltas[i].Start.GreaterThan(deltas[j].Start) + }) + for _, d := range deltas { + if len(d.Text) == 0 { + b.Remove(d.Start, d.End) + } else { + b.ReplaceBytes(d.Start, d.End, d.Text) + } + } + b.RelocateCursors() + } +} + // FileType returns the buffer's filetype func (b *Buffer) FileType() string { return b.Settings["filetype"].(string) diff --git a/internal/buffer/eventhandler.go b/internal/buffer/eventhandler.go index 3862d696..94957c04 100644 --- a/internal/buffer/eventhandler.go +++ b/internal/buffer/eventhandler.go @@ -230,6 +230,12 @@ func (eh *EventHandler) Replace(start, end Loc, replace string) { eh.Insert(start, replace) } +// ReplaceBytes deletes from start to end and replaces it with the given string +func (eh *EventHandler) ReplaceBytes(start, end Loc, replace []byte) { + eh.Remove(start, end) + eh.InsertBytes(start, replace) +} + // Execute a textevent and add it to the undo stack func (eh *EventHandler) Execute(t *TextEvent) { if eh.RedoStack.Len() > 0 {