k9s/internal/model/fish_buff.go

142 lines
3.0 KiB
Go

package model
import (
"sort"
)
// SuggestionListener listens for suggestions.
type SuggestionListener interface {
BuffWatcher
// SuggestionChanged notifies suggestion changes.
SuggestionChanged(text, sugg string)
}
// SuggestionFunc produces suggestions.
type SuggestionFunc func(text string) sort.StringSlice
// FishBuff represents a suggestion buffer.
type FishBuff struct {
*CmdBuff
suggestionFn SuggestionFunc
suggestions []string
suggestionIndex int
}
// NewFishBuff returns a new command buffer.
func NewFishBuff(key rune, kind BufferKind) *FishBuff {
return &FishBuff{
CmdBuff: NewCmdBuff(key, kind),
suggestionIndex: -1,
}
}
// PrevSuggestion returns the prev suggestion.
func (f *FishBuff) PrevSuggestion() (string, bool) {
if len(f.suggestions) == 0 {
return "", false
}
if f.suggestionIndex < 0 {
f.suggestionIndex = 0
} else {
f.suggestionIndex--
}
if f.suggestionIndex < 0 {
f.suggestionIndex = len(f.suggestions) - 1
}
return f.suggestions[f.suggestionIndex], true
}
// NextSuggestion returns the next suggestion.
func (f *FishBuff) NextSuggestion() (string, bool) {
if len(f.suggestions) == 0 {
return "", false
}
if f.suggestionIndex < 0 {
f.suggestionIndex = 0
} else {
f.suggestionIndex++
}
if f.suggestionIndex >= len(f.suggestions) {
f.suggestionIndex = 0
}
return f.suggestions[f.suggestionIndex], true
}
// ClearSuggestions clear out all suggestions.
func (f *FishBuff) ClearSuggestions() {
f.suggestionIndex = -1
}
// CurrentSuggestion returns the current suggestion.
func (f *FishBuff) CurrentSuggestion() (string, bool) {
if len(f.suggestions) == 0 || f.suggestionIndex < 0 || f.suggestionIndex >= len(f.suggestions) {
return "", false
}
return f.suggestions[f.suggestionIndex], true
}
// AutoSuggests returns true if model implements auto suggestions.
func (f *FishBuff) AutoSuggests() bool {
return true
}
// Suggestions returns suggestions.
func (f *FishBuff) Suggestions() []string {
if f.suggestionFn != nil {
return f.suggestionFn(string(f.buff))
}
return nil
}
// SetSuggestionFn sets up suggestions.
func (f *FishBuff) SetSuggestionFn(fn SuggestionFunc) {
f.suggestionFn = fn
}
// Notify publish suggestions to all listeners.
func (f *FishBuff) Notify(delete bool) {
if f.suggestionFn == nil {
return
}
ss := f.suggestionFn(string(f.buff))
if len(ss) == 1 && !delete {
f.SetText(string(string(f.buff) + ss[0]))
return
}
f.fireSuggestionChanged(f.suggestionFn(string(f.buff)))
}
// Add adds a new character to the buffer.
func (f *FishBuff) Add(r rune) {
f.CmdBuff.Add(r)
f.Notify(false)
}
// Delete removes the last character from the buffer.
func (f *FishBuff) Delete() {
f.CmdBuff.Delete()
f.Notify(true)
}
func (f *FishBuff) fireSuggestionChanged(ss []string) {
f.suggestions, f.suggestionIndex = ss, 0
if len(ss) == 0 {
f.suggestionIndex = -1
return
}
text, sug := f.GetText(), ss[f.suggestionIndex]
for _, l := range f.listeners {
if listener, ok := l.(SuggestionListener); ok {
listener.SuggestionChanged(text, sug)
}
}
}