Skip to content

Commit

Permalink
chore: upgrade to gods v2
Browse files Browse the repository at this point in the history
gods v2 uses go generics rather than interfaces which simplifies the
code considerably
  • Loading branch information
mxyng committed Dec 21, 2024
1 parent d8bab8e commit cb40d60
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 132 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.23.4

require (
github.com/containerd/console v1.0.3
github.com/emirpasic/gods v1.18.1
github.com/gin-gonic/gin v1.10.0
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0
Expand All @@ -18,6 +17,7 @@ require (
require (
github.com/agnivade/levenshtein v1.1.1
github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1
github.com/emirpasic/gods/v2 v2.0.0-alpha
github.com/google/go-cmp v0.6.0
github.com/mattn/go-runewidth v0.0.14
github.com/nlpodyssey/gopickle v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down
199 changes: 92 additions & 107 deletions readline/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import (
"fmt"
"os"

"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/v2/lists/arraylist"
"github.com/mattn/go-runewidth"
"golang.org/x/term"
)

type Buffer struct {
DisplayPos int
Pos int
Buf *arraylist.List
Buf *arraylist.List[rune]
// LineHasSpace is an arraylist of bools to keep track of whether a line has a space at the end
LineHasSpace *arraylist.List
LineHasSpace *arraylist.List[bool]
Prompt *Prompt
LineWidth int
Width int
Expand All @@ -33,8 +33,8 @@ func NewBuffer(prompt *Prompt) (*Buffer, error) {
b := &Buffer{
DisplayPos: 0,
Pos: 0,
Buf: arraylist.New(),
LineHasSpace: arraylist.New(),
Buf: arraylist.New[rune](),
LineHasSpace: arraylist.New[bool](),
Prompt: prompt,
Width: width,
Height: height,
Expand All @@ -46,40 +46,33 @@ func NewBuffer(prompt *Prompt) (*Buffer, error) {

func (b *Buffer) GetLineSpacing(line int) bool {
hasSpace, _ := b.LineHasSpace.Get(line)

if hasSpace == nil {
return false
}

return hasSpace.(bool)
return hasSpace
}

func (b *Buffer) MoveLeft() {
if b.Pos > 0 {
// asserts that we retrieve a rune
if e, ok := b.Buf.Get(b.Pos - 1); ok {
if r, ok := e.(rune); ok {
rLength := runewidth.RuneWidth(r)

if b.DisplayPos%b.LineWidth == 0 {
fmt.Print(CursorUp + CursorBOL + CursorRightN(b.Width))
if rLength == 2 {
fmt.Print(CursorLeft)
}
if r, ok := b.Buf.Get(b.Pos - 1); ok {
rLength := runewidth.RuneWidth(r)

line := b.DisplayPos/b.LineWidth - 1
hasSpace := b.GetLineSpacing(line)
if hasSpace {
b.DisplayPos -= 1
fmt.Print(CursorLeft)
}
} else {
fmt.Print(CursorLeftN(rLength))
if b.DisplayPos%b.LineWidth == 0 {
fmt.Print(CursorUp + CursorBOL + CursorRightN(b.Width))
if rLength == 2 {
fmt.Print(CursorLeft)
}

b.Pos -= 1
b.DisplayPos -= rLength
line := b.DisplayPos/b.LineWidth - 1
hasSpace := b.GetLineSpacing(line)
if hasSpace {
b.DisplayPos -= 1
fmt.Print(CursorLeft)
}
} else {
fmt.Print(CursorLeftN(rLength))
}

b.Pos -= 1
b.DisplayPos -= rLength
}
}
}
Expand Down Expand Up @@ -107,24 +100,22 @@ func (b *Buffer) MoveLeftWord() {

func (b *Buffer) MoveRight() {
if b.Pos < b.Buf.Size() {
if e, ok := b.Buf.Get(b.Pos); ok {
if r, ok := e.(rune); ok {
rLength := runewidth.RuneWidth(r)
b.Pos += 1
hasSpace := b.GetLineSpacing(b.DisplayPos / b.LineWidth)
b.DisplayPos += rLength

if b.DisplayPos%b.LineWidth == 0 {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())))
} else if (b.DisplayPos-rLength)%b.LineWidth == b.LineWidth-1 && hasSpace {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())+rLength))
b.DisplayPos += 1
} else if b.LineHasSpace.Size() > 0 && b.DisplayPos%b.LineWidth == b.LineWidth-1 && hasSpace {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())))
b.DisplayPos += 1
} else {
fmt.Print(CursorRightN(rLength))
}
if r, ok := b.Buf.Get(b.Pos); ok {
rLength := runewidth.RuneWidth(r)
b.Pos += 1
hasSpace := b.GetLineSpacing(b.DisplayPos / b.LineWidth)
b.DisplayPos += rLength

if b.DisplayPos%b.LineWidth == 0 {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())))
} else if (b.DisplayPos-rLength)%b.LineWidth == b.LineWidth-1 && hasSpace {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())+rLength))
b.DisplayPos += 1
} else if b.LineHasSpace.Size() > 0 && b.DisplayPos%b.LineWidth == b.LineWidth-1 && hasSpace {
fmt.Print(CursorDown + CursorBOL + CursorRightN(len(b.Prompt.prompt())))
b.DisplayPos += 1
} else {
fmt.Print(CursorRightN(rLength))
}
}
}
Expand Down Expand Up @@ -182,10 +173,8 @@ func (b *Buffer) MoveToEnd() {
func (b *Buffer) DisplaySize() int {
sum := 0
for i := range b.Buf.Size() {
if e, ok := b.Buf.Get(i); ok {
if r, ok := e.(rune); ok {
sum += runewidth.RuneWidth(r)
}
if r, ok := b.Buf.Get(i); ok {
sum += runewidth.RuneWidth(r)
}
}

Expand Down Expand Up @@ -257,11 +246,9 @@ func (b *Buffer) countRemainingLineWidth(place int) int {
for place <= b.LineWidth {
counter += 1
sum += prevLen
if e, ok := b.Buf.Get(b.Pos + counter); ok {
if r, ok := e.(rune); ok {
place += runewidth.RuneWidth(r)
prevLen = len(string(r))
}
if r, ok := b.Buf.Get(b.Pos + counter); ok {
place += runewidth.RuneWidth(r)
prevLen = len(string(r))
} else {
break
}
Expand Down Expand Up @@ -346,64 +333,62 @@ func (b *Buffer) drawRemaining() {

func (b *Buffer) Remove() {
if b.Buf.Size() > 0 && b.Pos > 0 {
if e, ok := b.Buf.Get(b.Pos - 1); ok {
if r, ok := e.(rune); ok {
rLength := runewidth.RuneWidth(r)
hasSpace := b.GetLineSpacing(b.DisplayPos/b.LineWidth - 1)

if b.DisplayPos%b.LineWidth == 0 {
// if the user backspaces over the word boundary, do this magic to clear the line
// and move to the end of the previous line
fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width))

if b.DisplaySize()%b.LineWidth < (b.DisplaySize()-rLength)%b.LineWidth {
b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1)
}
if r, ok := b.Buf.Get(b.Pos - 1); ok {
rLength := runewidth.RuneWidth(r)
hasSpace := b.GetLineSpacing(b.DisplayPos/b.LineWidth - 1)

if hasSpace {
b.DisplayPos -= 1
fmt.Print(CursorLeft)
}
if b.DisplayPos%b.LineWidth == 0 {
// if the user backspaces over the word boundary, do this magic to clear the line
// and move to the end of the previous line
fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width))

if rLength == 2 {
fmt.Print(CursorLeft + " " + CursorLeftN(2))
} else {
fmt.Print(" " + CursorLeft)
}
} else if (b.DisplayPos-rLength)%b.LineWidth == 0 && hasSpace {
fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width))
if b.DisplaySize()%b.LineWidth < (b.DisplaySize()-rLength)%b.LineWidth {
b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1)
}

if b.Pos == b.Buf.Size() {
b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1)
}
if hasSpace {
b.DisplayPos -= 1
fmt.Print(CursorLeft)
}

if rLength == 2 {
fmt.Print(CursorLeft + " " + CursorLeftN(2))
} else {
fmt.Print(CursorLeftN(rLength))
for range rLength {
fmt.Print(" ")
}
fmt.Print(CursorLeftN(rLength))
fmt.Print(" " + CursorLeft)
}
} else if (b.DisplayPos-rLength)%b.LineWidth == 0 && hasSpace {
fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width))

var eraseExtraLine bool
if (b.DisplaySize()-1)%b.LineWidth == 0 || (rLength == 2 && ((b.DisplaySize()-2)%b.LineWidth == 0)) || b.DisplaySize()%b.LineWidth == 0 {
eraseExtraLine = true
if b.Pos == b.Buf.Size() {
b.LineHasSpace.Remove(b.DisplayPos/b.LineWidth - 1)
}
b.DisplayPos -= 1
} else {
fmt.Print(CursorLeftN(rLength))
for range rLength {
fmt.Print(" ")
}
fmt.Print(CursorLeftN(rLength))
}

b.Pos -= 1
b.DisplayPos -= rLength
b.Buf.Remove(b.Pos)

if b.Pos < b.Buf.Size() {
b.drawRemaining()
// this erases a line which is left over when backspacing in the middle of a line and there
// are trailing characters which go over the line width boundary
if eraseExtraLine {
remainingLines := (b.DisplaySize() - b.DisplayPos) / b.LineWidth
fmt.Print(CursorDownN(remainingLines+1) + CursorBOL + ClearToEOL)
place := b.DisplayPos % b.LineWidth
fmt.Print(CursorUpN(remainingLines+1) + CursorRightN(place+len(b.Prompt.prompt())))
}
var eraseExtraLine bool
if (b.DisplaySize()-1)%b.LineWidth == 0 || (rLength == 2 && ((b.DisplaySize()-2)%b.LineWidth == 0)) || b.DisplaySize()%b.LineWidth == 0 {
eraseExtraLine = true
}

b.Pos -= 1
b.DisplayPos -= rLength
b.Buf.Remove(b.Pos)

if b.Pos < b.Buf.Size() {
b.drawRemaining()
// this erases a line which is left over when backspacing in the middle of a line and there
// are trailing characters which go over the line width boundary
if eraseExtraLine {
remainingLines := (b.DisplaySize() - b.DisplayPos) / b.LineWidth
fmt.Print(CursorDownN(remainingLines+1) + CursorBOL + ClearToEOL)
place := b.DisplayPos % b.LineWidth
fmt.Print(CursorUpN(remainingLines+1) + CursorRightN(place+len(b.Prompt.prompt())))
}
}
}
Expand Down Expand Up @@ -536,7 +521,7 @@ func (b *Buffer) StringNM(n, m int) string {
}
for cnt := n; cnt < m; cnt++ {
c, _ := b.Buf.Get(cnt)
s += string(c.(rune))
s += string(c)
}
return s
}
32 changes: 13 additions & 19 deletions readline/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package readline
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/v2/lists/arraylist"
)

type History struct {
Buf *arraylist.List
Buf *arraylist.List[string]
Autosave bool
Pos int
Limit int
Expand All @@ -22,7 +23,7 @@ type History struct {

func NewHistory() (*History, error) {
h := &History{
Buf: arraylist.New(),
Buf: arraylist.New[string](),
Limit: 100, // resizeme
Autosave: true,
Enabled: true,
Expand Down Expand Up @@ -73,14 +74,14 @@ func (h *History) Init() error {
continue
}

h.Add([]rune(line))
h.Add(line)
}

return nil
}

func (h *History) Add(l []rune) {
h.Buf.Add(l)
func (h *History) Add(s string) {
h.Buf.Add(s)
h.Compact()
h.Pos = h.Size()
if h.Autosave {
Expand All @@ -101,22 +102,18 @@ func (h *History) Clear() {
h.Buf.Clear()
}

func (h *History) Prev() []rune {
var line []rune
func (h *History) Prev() (line string) {
if h.Pos > 0 {
h.Pos -= 1
}
v, _ := h.Buf.Get(h.Pos)
line, _ = v.([]rune)
line, _ = h.Buf.Get(h.Pos)
return line
}

func (h *History) Next() []rune {
var line []rune
func (h *History) Next() (line string) {
if h.Pos < h.Buf.Size() {
h.Pos += 1
v, _ := h.Buf.Get(h.Pos)
line, _ = v.([]rune)
line, _ = h.Buf.Get(h.Pos)
}
return line
}
Expand All @@ -140,11 +137,8 @@ func (h *History) Save() error {

buf := bufio.NewWriter(f)
for cnt := range h.Size() {
v, _ := h.Buf.Get(cnt)
line, _ := v.([]rune)
if _, err := buf.WriteString(string(line) + "\n"); err != nil {
return err
}
line, _ := h.Buf.Get(cnt)
fmt.Fprintln(buf, line)
}
buf.Flush()
f.Close()
Expand Down
Loading

0 comments on commit cb40d60

Please sign in to comment.