aboutsummaryrefslogtreecommitdiff
path: root/testfiles/text.txt
diff options
context:
space:
mode:
Diffstat (limited to 'testfiles/text.txt')
-rw-r--r--testfiles/text.txt229
1 files changed, 0 insertions, 229 deletions
diff --git a/testfiles/text.txt b/testfiles/text.txt
deleted file mode 100644
index c2dc4af..0000000
--- a/testfiles/text.txt
+++ /dev/null
@@ -1,229 +0,0 @@
-package main
-
-import (
- "unicode"
-
- "github.com/pkg/errors"
- "github.com/prodhe/poe/gapbuffer"
-)
-
-type Text struct {
- buf *gapbuffer.Buffer
- cursorpos int
- p0, p1 int // not implemented
- history History
-}
-
-// Sync synchronizes the underlying buffer with the cursor position. This should be called before every call that manipulates data in the buffer.
-func (t *Text) Sync() {
- t.buf.Seek(t.cursorpos)
-}
-
-func (t *Text) Write(p []byte) (int, error) {
- c := Change{t.cursorpos, ActionInsert, p}
- n, err := t.commit(c)
- if err != nil {
- return n, err
- }
- t.history.Do(c)
- return n, nil
-}
-
-func (t *Text) Delete() (int, error) {
- if t.cursorpos <= 0 {
- return 0, errors.New("out of range")
- }
- b, _ := t.buf.ByteAt(t.cursorpos - 1)
- c := Change{t.cursorpos, ActionDelete, []byte{b}}
- n, err := t.commit(c)
- if err != nil {
- return n, err
- }
- t.history.Do(c)
- return n, nil
-}
-
-func (t *Text) Undo() error {
- change, err := t.history.Undo()
- if err != nil {
- return errors.Wrap(err, "undo")
- }
- t.commit(change)
- return nil
-}
-
-func (t *Text) Redo() error {
- change, err := t.history.Redo()
- if err != nil {
- return errors.Wrap(err, "redo")
- }
- t.commit(change)
- return nil
-}
-
-func (t *Text) commit(c Change) (int, error) {
- switch c.action {
- case ActionInsert:
- t.SetCursor(c.offset, 0)
- t.Sync()
- n, err := t.buf.Write(c.content)
- if err != nil {
- return 0, err
- }
- t.SetCursor(n, 1)
- return n, err
- case ActionDelete:
- t.SetCursor(c.offset, 0)
- t.Sync()
- var ds []byte
- for i := c.offset; i <= c.offset; i++ {
- ds = append(ds, t.buf.Delete())
- }
- t.SetCursor(len(ds), -1)
- return len(ds), nil
- default:
- return 0, errors.New("invalid action in change")
- }
-}
-
-// WordOffset returns the absolute offset for the beginning of the word and the end. A word is a letter/digit sequence of bytes separated by anything else. It scans from the current cursor position.
-func (t *Text) WordOffset() (start, end int) {
- start, end = t.cursorpos, t.cursorpos
- c, _ := t.buf.ByteAt(start)
- for unicode.IsLetter(rune(c)) || unicode.IsDigit(rune(c)) {
- start--
- c, _ = t.buf.ByteAt(start)
- }
- if start < t.cursorpos {
- start++
- }
- c, _ = t.buf.ByteAt(end)
- for unicode.IsLetter(rune(c)) || unicode.IsDigit(rune(c)) {
- end++
- c, _ = t.buf.ByteAt(end)
- }
- return start, end
-}
-
-// NextNL returns number of bytes from given position to the nearest next new line.
-func (t *Text) NextNL(start int) int {
- if start >= t.buf.Len() {
- return 0
- }
- n := start
- offset := 0
- if c, _ := t.buf.ByteAt(n); c == '\n' {
- n++
- offset++
- }
- for {
- c, _ := t.buf.ByteAt(n)
- if c == '\n' || n >= t.buf.Len() {
- break
- }
- n++
- offset++
- }
- return offset
-}
-
-// PrevNL returns number of bytes from given position to the nearest new line backwards.
-func (t *Text) PrevNL(start int) int {
- if start == 0 {
- return 0
- }
- if start > t.buf.Len() {
- start = t.buf.Len() - 1
- }
- n := start - 1
- offset := 1
- if c, _ := t.buf.ByteAt(n); c == '\n' {
- return offset
- }
- for {
- c, _ := t.buf.ByteAt(n)
- if c == '\n' || n == 0 {
- break
- }
- n--
- offset++
- }
- return offset
-}
-
-// SetCursor moves the cursor to different offsets in the text buffer.
-//
-// A negative whence is backwards from current position, a positive whence is forward and a zero whence sets the absolute position from the start of the buffer.
-func (t *Text) SetCursor(pos, whence int) {
- switch whence {
- case -1:
- t.cursorpos -= pos
- case 0:
- t.cursorpos = pos
- case 1:
- t.cursorpos += pos
- }
-
- // check out of range
- if t.cursorpos < 0 {
- t.cursorpos = 0
- }
- if t.cursorpos >= t.buf.Len() {
- t.cursorpos = t.buf.Len()
- }
-}
-
-/* History */
-type Action int
-
-const (
- ActionInsert Action = iota
- ActionDelete
-)
-
-type Change struct {
- offset int
- action Action
- content []byte
-}
-
-type History struct {
- done []Change
- recall []Change
-}
-
-func (h *History) Do(c Change) {
- h.done = append(h.done, c)
- h.recall = nil // clear old recall stack on new do
-}
-
-func (h *History) Undo() (Change, error) {
- if len(h.done) == 0 {
- return Change{}, errors.New("no history")
- }
- lastdone := h.done[len(h.done)-1]
- h.recall = append(h.recall, lastdone)
- h.done = h.done[:len(h.done)-1] // remove last one
-
- // Reverse the done action so the returned change can be applied directly.
- switch lastdone.action {
- case ActionInsert:
- lastdone.action = ActionDelete
- lastdone.offset += len(lastdone.content)
- case ActionDelete:
- lastdone.action = ActionInsert
- lastdone.offset -= len(lastdone.content)
- }
-
- return lastdone, nil
-}
-
-func (h *History) Redo() (Change, error) {
- if len(h.recall) == 0 {
- return Change{}, errors.New("no recall history")
- }
- lastrecall := h.recall[len(h.recall)-1]
- h.done = append(h.done, lastrecall)
- h.recall = h.recall[:len(h.recall)-1] //remove last one
- return lastrecall, nil
-}