165 lines
2.5 KiB
Go
165 lines
2.5 KiB
Go
package views
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/derailed/k9s/resource"
|
|
"github.com/gdamore/tcell"
|
|
"github.com/k8sland/tview"
|
|
)
|
|
|
|
const (
|
|
menuFmt = " [dodgerblue::b]%s[white::d]%s "
|
|
menuSepFmt = " [dodgerblue::b]<%s> [white::d]%s "
|
|
menuIndexFmt = " [dodgerblue::b]<%d> [white::d]%s "
|
|
maxRows = 5
|
|
colLen = 20
|
|
)
|
|
|
|
// Defines numeric keys for container actions
|
|
const (
|
|
Key0 int32 = iota + 48
|
|
Key1
|
|
Key2
|
|
Key3
|
|
Key4
|
|
Key5
|
|
Key6
|
|
Key7
|
|
Key8
|
|
Key9
|
|
)
|
|
|
|
// Defines char keystrokes
|
|
const (
|
|
KeyA int32 = iota + 97
|
|
KeyB
|
|
KeyC
|
|
KeyD
|
|
KeyE
|
|
KeyF
|
|
KeyG
|
|
KeyH
|
|
KeyI
|
|
KeyJ
|
|
KeyK
|
|
KeyL
|
|
KeyM
|
|
KeyN
|
|
KeyO
|
|
KeyP
|
|
KeyQ
|
|
KeyR
|
|
KeyS
|
|
KeyT
|
|
KeyU
|
|
KeyV
|
|
KeyW
|
|
KeyX
|
|
KeyY
|
|
KeyZ
|
|
)
|
|
|
|
var numKeys = map[int]int32{
|
|
0: Key0,
|
|
1: Key1,
|
|
2: Key2,
|
|
3: Key3,
|
|
4: Key4,
|
|
5: Key5,
|
|
6: Key6,
|
|
7: Key7,
|
|
8: Key8,
|
|
9: Key9,
|
|
}
|
|
|
|
type (
|
|
keyboardHandler func(*tcell.EventKey)
|
|
|
|
hint struct {
|
|
mnemonic, display string
|
|
}
|
|
hints []hint
|
|
|
|
hinter interface {
|
|
hints() hints
|
|
}
|
|
|
|
keyAction struct {
|
|
description string
|
|
action keyboardHandler
|
|
}
|
|
keyActions map[tcell.Key]keyAction
|
|
|
|
menuView struct {
|
|
*tview.Grid
|
|
}
|
|
)
|
|
|
|
func newKeyHandler(d string, a keyboardHandler) keyAction {
|
|
return keyAction{description: d, action: a}
|
|
}
|
|
|
|
func newMenuView() *menuView {
|
|
v := menuView{tview.NewGrid()}
|
|
v.SetGap(0, 1)
|
|
return &v
|
|
}
|
|
|
|
func (v *menuView) setMenu(hh hints) {
|
|
v.Clear()
|
|
v.SetRows(1, 1, 1, 1)
|
|
v.SetColumns(colLen, colLen)
|
|
isNS := true
|
|
var row, col int
|
|
for _, h := range hh {
|
|
// Reset cols for namespace menus...
|
|
if len(h.mnemonic) == 1 && isNS {
|
|
col++
|
|
row = 0
|
|
isNS = false
|
|
}
|
|
v.AddItem(v.item(h), row, col, 1, 1, 1, 1, false)
|
|
row++
|
|
if row > maxRows {
|
|
col++
|
|
row = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *menuView) item(h hint) tview.Primitive {
|
|
c := tview.NewTextView()
|
|
c.SetDynamicColors(true)
|
|
var s string
|
|
if i, err := strconv.Atoi(h.mnemonic); err != nil {
|
|
if strings.ToLower(h.display)[0] == h.mnemonic[0] {
|
|
s = fmt.Sprintf(menuFmt, strings.ToUpper(h.mnemonic), h.display[1:])
|
|
} else {
|
|
s = fmt.Sprintf(menuSepFmt, strings.ToUpper(h.mnemonic), h.display)
|
|
}
|
|
} else {
|
|
s = fmt.Sprintf(menuIndexFmt, i, resource.Truncate(h.display, 14))
|
|
}
|
|
c.SetText(s)
|
|
return c
|
|
}
|
|
|
|
func (a keyActions) toHints() hints {
|
|
kk := make([]int, 0, len(a))
|
|
for k := range a {
|
|
kk = append(kk, int(k))
|
|
}
|
|
sort.Ints(kk)
|
|
hh := make(hints, 0, len(a))
|
|
for _, k := range kk {
|
|
hh = append(hh, hint{
|
|
mnemonic: tcell.KeyNames[tcell.Key(k)],
|
|
display: a[tcell.Key(k)].description})
|
|
}
|
|
return hh
|
|
}
|