diff --git a/go.mod b/go.mod index 2ec5ad26d..1a1fdb408 100644 --- a/go.mod +++ b/go.mod @@ -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 @@ -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 diff --git a/go.sum b/go.sum index 4ba022611..6a2c91896 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/readline/buffer.go b/readline/buffer.go index d91fe0a99..52dc70526 100644 --- a/readline/buffer.go +++ b/readline/buffer.go @@ -4,7 +4,7 @@ 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" ) @@ -12,9 +12,9 @@ import ( 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 @@ -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, @@ -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 r, ok := b.Buf.Get(b.Pos - 1); ok { + rLength := runewidth.RuneWidth(r) - if b.DisplayPos%b.LineWidth == 0 { - fmt.Print(CursorUp + CursorBOL + CursorRightN(b.Width)) - if rLength == 2 { - fmt.Print(CursorLeft) - } - - 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 } } } @@ -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 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)) - } + 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)) } } } @@ -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) } } @@ -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 } @@ -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 r, ok := b.Buf.Get(b.Pos - 1); 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.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 b.DisplaySize()%b.LineWidth < (b.DisplaySize()-rLength)%b.LineWidth { + 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(" " + CursorLeft) - } - } else if (b.DisplayPos-rLength)%b.LineWidth == 0 && hasSpace { - fmt.Print(CursorBOL + ClearToEOL + CursorUp + CursorBOL + CursorRightN(b.Width)) - - 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) + 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.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()))) - } + 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()))) } } } @@ -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 } diff --git a/readline/history.go b/readline/history.go index 9c6b930b3..bf3cafe25 100644 --- a/readline/history.go +++ b/readline/history.go @@ -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 @@ -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, @@ -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 { @@ -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 } @@ -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() diff --git a/readline/readline.go b/readline/readline.go index 1c14fe103..f7b694eb2 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -120,11 +120,11 @@ func (i *Instance) Readline() (string, error) { if i.History.Pos == i.History.Size() { currentLineBuf = []rune(buf.String()) } - buf.Replace(i.History.Prev()) + buf.Replace([]rune(i.History.Prev())) } case KeyDown: if i.History.Pos < i.History.Size() { - buf.Replace(i.History.Next()) + buf.Replace([]rune(i.History.Next())) if i.History.Pos == i.History.Size() { buf.Replace(currentLineBuf) } @@ -220,7 +220,7 @@ func (i *Instance) Readline() (string, error) { case CharEnter, CharCtrlJ: output := buf.String() if output != "" { - i.History.Add([]rune(output)) + i.History.Add(output) } buf.MoveToEnd() fmt.Println()