mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-18 14:40:26 +01:00
69 lines
1.1 KiB
Go
69 lines
1.1 KiB
Go
|
package readline
|
||
|
|
||
|
import (
|
||
|
"github.com/ergochat/readline/internal/ringbuf"
|
||
|
)
|
||
|
|
||
|
type undoEntry struct {
|
||
|
pos int
|
||
|
buf []rune
|
||
|
}
|
||
|
|
||
|
// nil receiver is a valid no-op object
|
||
|
type opUndo struct {
|
||
|
op *operation
|
||
|
stack ringbuf.Buffer[undoEntry]
|
||
|
}
|
||
|
|
||
|
func newOpUndo(op *operation) *opUndo {
|
||
|
o := &opUndo{op: op}
|
||
|
o.stack.Initialize(32, 64)
|
||
|
o.init()
|
||
|
return o
|
||
|
}
|
||
|
|
||
|
func (o *opUndo) add() {
|
||
|
if o == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
top, success := o.stack.Pop()
|
||
|
buf, pos, changed := o.op.buf.CopyForUndo(top.buf) // if !success, top.buf is nil
|
||
|
newEntry := undoEntry{pos: pos, buf: buf}
|
||
|
if !success {
|
||
|
o.stack.Add(newEntry)
|
||
|
} else if !changed {
|
||
|
o.stack.Add(newEntry) // update cursor position
|
||
|
} else {
|
||
|
o.stack.Add(top)
|
||
|
o.stack.Add(newEntry)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (o *opUndo) undo() {
|
||
|
if o == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
top, success := o.stack.Pop()
|
||
|
if !success {
|
||
|
return
|
||
|
}
|
||
|
o.op.buf.Restore(top.buf, top.pos)
|
||
|
o.op.buf.Refresh(nil)
|
||
|
}
|
||
|
|
||
|
func (o *opUndo) init() {
|
||
|
if o == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
buf, pos, _ := o.op.buf.CopyForUndo(nil)
|
||
|
initialEntry := undoEntry{
|
||
|
pos: pos,
|
||
|
buf: buf,
|
||
|
}
|
||
|
o.stack.Clear()
|
||
|
o.stack.Add(initialEntry)
|
||
|
}
|