mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 08:55:35 +00:00
widget: refactoring to prep for editor selection
- Move caret from editBuffer.caret to Editor.caret.pos.ofs and related refactoring. Move other fields in Editor.caret into Editor.caret.pos. - Refactor several functions to change a position passed into them, rather than changing e.rr.caret directly. - Add editBuffer.Seek(). - Remove editBuffer.dump(). - Change Editor.Move to MoveCaret. - Add Editor.SetCaret. - Updated tests. Signed-off-by: Larry Clapp <larry@theclapp.org>
This commit is contained in:
+37
-32
@@ -3,18 +3,13 @@
|
||||
package widget
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const bufferDebug = false
|
||||
|
||||
// editBuffer implements a gap buffer for text editing.
|
||||
type editBuffer struct {
|
||||
// caret is the caret position in bytes.
|
||||
caret int
|
||||
// pos is the byte position for Read and ReadRune.
|
||||
pos int
|
||||
|
||||
@@ -35,12 +30,12 @@ func (e *editBuffer) Changed() bool {
|
||||
return c
|
||||
}
|
||||
|
||||
func (e *editBuffer) deleteRunes(runes int) {
|
||||
e.moveGap(0)
|
||||
func (e *editBuffer) deleteRunes(caret, runes int) int {
|
||||
e.moveGap(caret, 0)
|
||||
for ; runes < 0 && e.gapstart > 0; runes++ {
|
||||
_, s := utf8.DecodeLastRune(e.text[:e.gapstart])
|
||||
e.gapstart -= s
|
||||
e.caret -= s
|
||||
caret -= s
|
||||
e.changed = e.changed || s > 0
|
||||
}
|
||||
for ; runes > 0 && e.gapend < len(e.text); runes-- {
|
||||
@@ -48,12 +43,12 @@ func (e *editBuffer) deleteRunes(runes int) {
|
||||
e.gapend += s
|
||||
e.changed = e.changed || s > 0
|
||||
}
|
||||
e.dump()
|
||||
return caret
|
||||
}
|
||||
|
||||
// moveGap moves the gap to the caret position. After returning,
|
||||
// the gap is guaranteed to be at least space bytes long.
|
||||
func (e *editBuffer) moveGap(space int) {
|
||||
func (e *editBuffer) moveGap(caret, space int) {
|
||||
if e.gapLen() < space {
|
||||
if space < minSpace {
|
||||
space = minSpace
|
||||
@@ -62,29 +57,28 @@ func (e *editBuffer) moveGap(space int) {
|
||||
// Expand to capacity.
|
||||
txt = txt[:cap(txt)]
|
||||
gaplen := len(txt) - e.len()
|
||||
if e.caret > e.gapstart {
|
||||
if caret > e.gapstart {
|
||||
copy(txt, e.text[:e.gapstart])
|
||||
copy(txt[e.caret+gaplen:], e.text[e.caret:])
|
||||
copy(txt[e.gapstart:], e.text[e.gapend:e.caret+e.gapLen()])
|
||||
copy(txt[caret+gaplen:], e.text[caret:])
|
||||
copy(txt[e.gapstart:], e.text[e.gapend:caret+e.gapLen()])
|
||||
} else {
|
||||
copy(txt, e.text[:e.caret])
|
||||
copy(txt, e.text[:caret])
|
||||
copy(txt[e.gapstart+gaplen:], e.text[e.gapend:])
|
||||
copy(txt[e.caret+gaplen:], e.text[e.caret:e.gapstart])
|
||||
copy(txt[caret+gaplen:], e.text[caret:e.gapstart])
|
||||
}
|
||||
e.text = txt
|
||||
e.gapstart = e.caret
|
||||
e.gapstart = caret
|
||||
e.gapend = e.gapstart + gaplen
|
||||
} else {
|
||||
if e.caret > e.gapstart {
|
||||
copy(e.text[e.gapstart:], e.text[e.gapend:e.caret+e.gapLen()])
|
||||
if caret > e.gapstart {
|
||||
copy(e.text[e.gapstart:], e.text[e.gapend:caret+e.gapLen()])
|
||||
} else {
|
||||
copy(e.text[e.caret+e.gapLen():], e.text[e.caret:e.gapstart])
|
||||
copy(e.text[caret+e.gapLen():], e.text[caret:e.gapstart])
|
||||
}
|
||||
l := e.gapLen()
|
||||
e.gapstart = e.caret
|
||||
e.gapstart = caret
|
||||
e.gapend = e.gapstart + l
|
||||
}
|
||||
e.dump()
|
||||
}
|
||||
|
||||
func (e *editBuffer) len() int {
|
||||
@@ -96,7 +90,25 @@ func (e *editBuffer) gapLen() int {
|
||||
}
|
||||
|
||||
func (e *editBuffer) Reset() {
|
||||
e.pos = 0
|
||||
e.Seek(0, io.SeekStart)
|
||||
}
|
||||
|
||||
// Seek implements io.Seeker
|
||||
func (e *editBuffer) Seek(offset int64, whence int) (ret int64, err error) {
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
e.pos = int(offset)
|
||||
case io.SeekCurrent:
|
||||
e.pos += int(offset)
|
||||
case io.SeekEnd:
|
||||
e.pos = e.len() - int(offset)
|
||||
}
|
||||
if e.pos < 0 {
|
||||
e.pos = 0
|
||||
} else if e.pos > e.len() {
|
||||
e.pos = e.len()
|
||||
}
|
||||
return int64(e.pos), nil
|
||||
}
|
||||
|
||||
func (e *editBuffer) Read(p []byte) (int, error) {
|
||||
@@ -138,18 +150,11 @@ func (e *editBuffer) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (e *editBuffer) prepend(s string) {
|
||||
e.moveGap(len(s))
|
||||
copy(e.text[e.caret:], s)
|
||||
func (e *editBuffer) prepend(caret int, s string) {
|
||||
e.moveGap(caret, len(s))
|
||||
copy(e.text[caret:], s)
|
||||
e.gapstart += len(s)
|
||||
e.changed = e.changed || len(s) > 0
|
||||
e.dump()
|
||||
}
|
||||
|
||||
func (e *editBuffer) dump() {
|
||||
if bufferDebug {
|
||||
fmt.Printf("len(e.text) %d e.len() %d e.gapstart %d e.gapend %d e.caret %d txt:\n'%+x'<-%d->'%+x'\n", len(e.text), e.len(), e.gapstart, e.gapend, e.caret, e.text[:e.gapstart], e.gapLen(), e.text[e.gapend:])
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editBuffer) runeBefore(idx int) (rune, int) {
|
||||
|
||||
Reference in New Issue
Block a user