Reworking Keymaps

This commit is contained in:
2025-10-26 08:47:07 -05:00
parent cf47b5a4e4
commit d63e3a414a
30 changed files with 384 additions and 715 deletions

160
keymap.go
View File

@@ -23,71 +23,119 @@ package widgets
import "github.com/gdamore/tcell"
type Key struct {
ev *tcell.EventKey
do []func(*tcell.EventKey) bool
desc string
}
func BuildEK(k tcell.Key) *tcell.EventKey { return tcell.NewEventKey(k, 0, 0) }
func BuildEKr(r rune) *tcell.EventKey { return tcell.NewEventKey(tcell.KeyRune, r, 0) }
func NewKey(ev *tcell.EventKey, do func(*tcell.EventKey) bool) *Key {
return &Key{
ev: ev,
do: []func(*tcell.EventKey) bool{do},
}
}
func (k *Key) AddBinding(do func(*tcell.EventKey) bool) *Key {
k.do = append(k.do, do)
return k
}
func (k *Key) SetDescription(d string) *Key {
k.desc = d
return k
}
func (k *Key) Matches(ev *tcell.EventKey) bool {
return k.ev.Key() == ev.Key() &&
k.ev.Rune() == ev.Rune() &&
k.ev.Modifiers() == ev.Modifiers()
}
func (k *Key) Handle(ev *tcell.EventKey) bool {
if !k.Matches(ev) {
return false
}
var cons bool
for _, d := range k.do {
cons = cons || d(ev)
}
return cons
}
type KeyMap struct {
Keys map[tcell.Key]func(*tcell.EventKey) bool
Runes map[rune]func(*tcell.EventKey) bool
Keys []*Key
}
func BlankKeyMap() KeyMap {
return KeyMap{
Keys: make(map[tcell.Key]func(*tcell.EventKey) bool),
Runes: make(map[rune]func(*tcell.EventKey) bool),
func BlankKeyMap() *KeyMap { return &KeyMap{} }
func NewKeyMap(k *Key, rest ...*Key) *KeyMap {
ret := &KeyMap{}
return ret
}
// Search through 'Keys', and return all that matches
func (m *KeyMap) Get(k *Key) *Key {
for _, key := range m.Keys {
if k.Matches(key.ev) {
return key
}
}
return nil
}
func (m *KeyMap) Merge(n *KeyMap) {
switch len(n.Keys) {
case 0:
return
case 1:
m.Add(n.Keys[0])
default:
m.Add(n.Keys[0], n.Keys[1:]...)
}
}
func NewKeyMap(m map[tcell.Key]func(*tcell.EventKey) bool) KeyMap {
return KeyMap{
Keys: m,
Runes: make(map[rune]func(*tcell.EventKey) bool),
}
}
func NewRuneMap(m map[rune]func(*tcell.EventKey) bool) KeyMap {
return KeyMap{
Keys: make(map[tcell.Key]func(*tcell.EventKey) bool),
Runes: m,
}
}
func (m KeyMap) Merge(km KeyMap) {
for k, v := range km.Keys {
m.Keys[k] = v
}
for r, v := range km.Runes {
m.Runes[r] = v
}
}
func (m KeyMap) Add(k tcell.Key, do func(*tcell.EventKey) bool) { m.Keys[k] = do }
func (m KeyMap) Remove(k tcell.Key) { delete(m.Keys, k) }
func (m KeyMap) AddAll(all map[tcell.Key]func(*tcell.EventKey) bool) {
for k, v := range all {
m.Add(k, v)
}
}
func (m KeyMap) AddRune(k rune, do func(*tcell.EventKey) bool) { m.Runes[k] = do }
func (m KeyMap) RemoveRune(k rune) { delete(m.Runes, k) }
func (m KeyMap) AddRunes(all map[rune]func(*tcell.EventKey) bool) {
for k, v := range all {
m.AddRune(k, v)
}
}
func (m KeyMap) Handle(ev *tcell.EventKey) bool {
if ev.Key() == tcell.KeyRune {
for k, v := range m.Runes {
if ev.Rune() == k {
return v(ev)
}
func (m *KeyMap) Add(k *Key, rest ...*Key) {
p := m.Get(k)
if p != nil {
for dIdx := range k.do {
p.AddBinding(k.do[dIdx])
}
if k.desc != "" {
p.SetDescription(k.desc)
}
} else {
for k, v := range m.Keys {
if ev.Key() == k {
return v(ev)
m.Keys = append(m.Keys, k)
}
}
func (m *KeyMap) Remove(k *Key, rest ...*Key) {
do := func(k *Key) {
idx := -1
for i := range m.Keys {
if m.Keys[i].Matches(k.ev) {
idx = i
break
}
}
if idx == -1 {
return
}
m.Keys = append(m.Keys[:idx], m.Keys[idx+1:]...)
}
do(k)
for i := range rest {
do(rest[i])
}
return false
}
func (m *KeyMap) Handle(ev *tcell.EventKey) bool {
var cons bool
for _, k := range m.Keys {
cons = cons || k.Handle(ev)
}
return cons
}

View File

@@ -45,7 +45,7 @@ type AbsoluteLayout struct {
visible bool
focusable bool
keyMap KeyMap
keyMap *KeyMap
cursor int
disableTab bool
@@ -80,17 +80,8 @@ func (w *AbsoluteLayout) HandleResize(ev *tcell.EventResize) {
w.updateWidgetLayouts()
}
// AbsoluteLayout doesn't have a default keymap
func (w *AbsoluteLayout) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *AbsoluteLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *AbsoluteLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *AbsoluteLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *AbsoluteLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *AbsoluteLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.disableTab && ev.Key() == tcell.KeyTab {

View File

@@ -44,7 +44,7 @@ type Alert struct {
btnLayout *LinearLayout
btnOk, btnCancel *Button
keyMap, customKeyMap KeyMap
keyMap *KeyMap
logger func(string, ...any)
}
@@ -82,15 +82,14 @@ func (w *Alert) Init(id string, style tcell.Style) {
w.btnOk.SetActive(true)
w.btnLayout.Add(w.btnOk)
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyTab: w.SelectNext,
tcell.KeyRight: w.SelectNext,
tcell.KeyDown: w.SelectNext,
tcell.KeyLeft: w.SelectNext,
tcell.KeyUp: w.SelectNext,
tcell.KeyEnter: w.Do,
})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyTab), w.SelectNext),
NewKey(BuildEK(tcell.KeyRight), w.SelectNext),
NewKey(BuildEK(tcell.KeyDown), w.SelectNext),
NewKey(BuildEK(tcell.KeyLeft), w.SelectNext),
NewKey(BuildEK(tcell.KeyUp), w.SelectNext),
NewKey(BuildEK(tcell.KeyEnter), w.Do),
)
w.focusable = true
}
func (w *Alert) Id() string { return w.id }
@@ -101,36 +100,14 @@ func (w *Alert) HandleResize(ev *tcell.EventResize) {
w.layout.HandleResize(tcell.NewEventResize(w.w-2, w.h-2))
}
func (w *Alert) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Alert) AddToKeyMap(km KeyMap) {
w.customKeyMap.Merge(km)
}
func (w *Alert) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
w.customKeyMap.RemoveRune(r)
}
}
func (w *Alert) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Alert) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Alert) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Alert) HandleTime(ev *tcell.EventTime) {

View File

@@ -44,7 +44,7 @@ type ArtWidget struct {
font string
text string
keyMap KeyMap
keyMap *KeyMap
allFonts []ArtWidgetFont
currFont ArtWidgetFont
@@ -69,18 +69,10 @@ func (w *ArtWidget) Init(id string, st tcell.Style) {
}
func (w *ArtWidget) Id() string { return w.id }
func (w *ArtWidget) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *ArtWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *ArtWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *ArtWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *ArtWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *ArtWidget) HandleTime(ev *tcell.EventTime) {}
func (w *ArtWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *ArtWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *ArtWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *ArtWidget) HandleTime(ev *tcell.EventTime) {}
func (w *ArtWidget) Draw(screen tcell.Screen) {
if !w.visible {
return

View File

@@ -27,7 +27,7 @@ import "github.com/gdamore/tcell"
type BlankWidget struct {
id string
x, y int
keyMap KeyMap
keyMap *KeyMap
wantH, wantW int
}
@@ -45,19 +45,11 @@ func NewBlankWidget(id string) *BlankWidget {
func (w *BlankWidget) Init(id string, st tcell.Style) { w.keyMap = BlankKeyMap() }
func (w *BlankWidget) Id() string { return w.id }
func (w *BlankWidget) HandleResize(ev *tcell.EventResize) {}
func (w *BlankWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *BlankWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *BlankWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *BlankWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *BlankWidget) HandleTime(ev *tcell.EventTime) {}
func (w *BlankWidget) Draw(screen tcell.Screen) {}
func (w *BlankWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *BlankWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *BlankWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *BlankWidget) HandleTime(ev *tcell.EventTime) {}
func (w *BlankWidget) Draw(screen tcell.Screen) {}
func (w *BlankWidget) Active() bool { return false }
func (w *BlankWidget) SetActive(a bool) {}

View File

@@ -69,13 +69,9 @@ func (w *BorderedWidget) HandleResize(ev *tcell.EventResize) {
w.widget.HandleResize(tcell.NewEventResize(w.w-2, w.h-2))
}
func (w *BorderedWidget) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) }
func (w *BorderedWidget) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) }
func (w *BorderedWidget) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) }
func (w *BorderedWidget) HandleKey(ev *tcell.EventKey) bool {
w.Log("BW(%s) Active(%s) Handlekey", w.Id(), w.widget.Id())
return w.widget.HandleKey(ev)
}
func (w *BorderedWidget) GetKeyMap() *KeyMap { return w.widget.GetKeyMap() }
func (w *BorderedWidget) SetKeyMap(km *KeyMap) { w.widget.SetKeyMap(km) }
func (w *BorderedWidget) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) }
func (w *BorderedWidget) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) }

View File

@@ -38,7 +38,7 @@ type BufferWidget struct {
buffer *Buffer
keyMap KeyMap
keyMap *KeyMap
timeMap *TimeMap
}
@@ -64,16 +64,8 @@ func (w *BufferWidget) Id() string { return w.id }
func (w *BufferWidget) HandleResize(ev *tcell.EventResize) {
}
func (w *BufferWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *BufferWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *BufferWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *BufferWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *BufferWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *BufferWidget) HandleKey(ev *tcell.EventKey) bool {
if !w.active {

View File

@@ -36,10 +36,10 @@ type Button struct {
x, y int
w, h int
active bool
visible bool
focusable bool
keyMap, customKeyMap KeyMap
active bool
visible bool
focusable bool
keyMap *KeyMap
onPressed func() bool
logger func(string, ...any)
@@ -57,10 +57,7 @@ func (w *Button) Init(id string, style tcell.Style) {
w.id = id
w.style = style
w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyEnter: func(ev *tcell.EventKey) bool { return w.onPressed() },
})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool { return w.onPressed() }))
w.onPressed = func() bool { return false }
w.focusable = true
}
@@ -69,30 +66,14 @@ func (w *Button) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size()
}
func (w *Button) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Button) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Button) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Button) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Button) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Button) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Button) HandleTime(ev *tcell.EventTime) {}

View File

@@ -51,7 +51,7 @@ type Chat struct {
history []ChatMsg
historyPosition int
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Chat)(nil)
@@ -74,26 +74,8 @@ func (w *Chat) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size()
}
func (w *Chat) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Chat) AddToKeyMap(km KeyMap) {
w.customKeyMap.Merge(km)
}
func (w *Chat) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Chat) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Chat) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Chat) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -111,9 +93,7 @@ func (w *Chat) HandleKey(ev *tcell.EventKey) bool {
w.value = w.value[:w.cursor] + w.value[w.cursor+1:]
}
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}
@@ -201,12 +181,12 @@ func (w *Chat) MinW() int { return 2 + 20 }
func (w *Chat) MinH() int { return 6 }
func (w *Chat) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyEsc: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyEsc), func(ev *tcell.EventKey) bool {
w.SetActive(false)
return true
},
tcell.KeyUp: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyUp), func(ev *tcell.EventKey) bool {
if w.historyPosition < len(w.history)-1 {
w.historyPosition++
w.value = w.history[w.historyPosition].Message
@@ -214,8 +194,8 @@ func (w *Chat) initKeyMap() {
return true
}
return false
},
tcell.KeyDown: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyDown), func(ev *tcell.EventKey) bool {
if w.historyPosition > -1 {
w.historyPosition--
if w.historyPosition == -1 {
@@ -227,37 +207,36 @@ func (w *Chat) initKeyMap() {
return true
}
return false
},
tcell.KeyLeft: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyLeft), func(ev *tcell.EventKey) bool {
if w.cursor > 0 {
w.cursor--
return true
}
return false
},
tcell.KeyRight: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyRight), func(ev *tcell.EventKey) bool {
if w.cursor < len(w.value) {
w.cursor++
return true
}
return false
},
tcell.KeyCtrlU: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyCtrlU), func(ev *tcell.EventKey) bool {
w.value = w.value[w.cursor:]
w.cursor = 0
return true
},
tcell.KeyTab: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
// Auto-complete
// TODO: Find best guess for current word
return false
},
tcell.KeyEnter: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
// TODO: Submit the message
return false
},
})
w.customKeyMap = BlankKeyMap()
}),
)
}
func (w *Chat) SetTitle(ttl string) { w.title = ttl }
func (w *Chat) Title() string { return w.title }

View File

@@ -45,8 +45,8 @@ type Checkbox struct {
x, y int
w, h int
keyMap, customKeyMap KeyMap
stateRunes []rune
keyMap *KeyMap
stateRunes []rune
}
var _ Widget = (*Checkbox)(nil)
@@ -63,43 +63,22 @@ func (w *Checkbox) Init(id string, style tcell.Style) {
w.visible = true
w.stateRunes = []rune{'X', ' ', '-'}
w.focusable = true
w.keyMap = KeyMap{
Keys: map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyEnter: w.ToggleState,
},
Runes: map[rune]func(ev *tcell.EventKey) bool{
' ': w.ToggleState,
},
}
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyEnter), w.ToggleState),
NewKey(BuildEKr(' '), w.ToggleState),
)
}
func (w *Checkbox) Id() string { return w.id }
func (w *Checkbox) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Checkbox) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Checkbox) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Checkbox) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Checkbox) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Checkbox) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Checkbox) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Checkbox) HandleTime(ev *tcell.EventTime) {}
func (w *Checkbox) Draw(screen tcell.Screen) {

View File

@@ -54,7 +54,7 @@ type Cli struct {
commands []*CliCommand
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
// TODO: Fix Command/SubCommand finding
@@ -81,22 +81,8 @@ func (w *Cli) HandleResize(ev *tcell.EventResize) {
}
}
func (w *Cli) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Cli) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Cli) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Cli) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Cli) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Cli) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -114,8 +100,7 @@ func (w *Cli) HandleKey(ev *tcell.EventKey) bool {
w.value = w.value[:w.cursor] + w.value[w.cursor+1:]
}
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}
@@ -216,12 +201,12 @@ func (w *Cli) MinW() int { return 20 }
func (w *Cli) MinH() int { return 6 }
func (w *Cli) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyEsc: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyEsc), func(ev *tcell.EventKey) bool {
w.SetActive(false)
return true
},
tcell.KeyUp: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyUp), func(ev *tcell.EventKey) bool {
if w.historyPosition < len(w.history)-1 {
w.historyPosition++
w.value = w.history[w.historyPosition]
@@ -229,8 +214,8 @@ func (w *Cli) initKeyMap() {
return true
}
return false
},
tcell.KeyDown: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyDown), func(ev *tcell.EventKey) bool {
if w.historyPosition > -1 {
w.historyPosition--
if w.historyPosition == -1 {
@@ -242,27 +227,27 @@ func (w *Cli) initKeyMap() {
return true
}
return false
},
tcell.KeyLeft: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyLeft), func(ev *tcell.EventKey) bool {
if w.cursor > 0 {
w.cursor--
return true
}
return false
},
tcell.KeyRight: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyRight), func(ev *tcell.EventKey) bool {
if w.cursor < len(w.value) {
w.cursor++
return true
}
return false
},
tcell.KeyCtrlU: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyCtrlU), func(ev *tcell.EventKey) bool {
w.value = w.value[w.cursor:]
w.cursor = 0
return true
},
tcell.KeyTab: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
// Auto-complete
guess := w.findBestGuess()
if guess != nil {
@@ -273,8 +258,8 @@ func (w *Cli) initKeyMap() {
return true
}
return false
},
tcell.KeyEnter: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
args := strings.Split(w.value, " ")
w.historyPosition = -1
w.value = ""
@@ -289,8 +274,8 @@ func (w *Cli) initKeyMap() {
}
w.history = append(w.history, fmt.Sprintf("%s: command not found", w.value))
return true
},
tcell.KeyPgUp: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyPgUp), func(ev *tcell.EventKey) bool {
if w.logPosition < len(w.log)-w.h-2 {
w.logPosition += (w.h - 2)
if w.logPosition > len(w.log) {
@@ -299,8 +284,8 @@ func (w *Cli) initKeyMap() {
return true
}
return false
},
tcell.KeyPgDn: func(ev *tcell.EventKey) bool {
}),
NewKey(BuildEK(tcell.KeyPgDn), func(ev *tcell.EventKey) bool {
if w.logPosition > 0 {
w.logPosition -= (w.h - 2)
if w.logPosition < 0 {
@@ -309,8 +294,8 @@ func (w *Cli) initKeyMap() {
return true
}
return false
},
})
}),
)
}
func (w *Cli) SetTitle(ttl string) { w.title = ttl }
func (w *Cli) Title() string { return w.title }

View File

@@ -45,7 +45,7 @@ type DatePicker struct {
dateFld *Field
dateNow *Button
keyMap, customKeyMap KeyMap
keyMap *KeyMap
logger func(string, ...any)
}
@@ -96,38 +96,15 @@ func (w *DatePicker) HandleResize(ev *tcell.EventResize) {
w.dateNow.SetPos(Coord{X: wd - 6, Y: 0})
}
func (w *DatePicker) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *DatePicker) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *DatePicker) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *DatePicker) GetKeyMap() *KeyMap { return w.keyMap }
func (w *DatePicker) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
if ev.Key() == tcell.KeyTab {
if w.dateFld.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(true)
return true
} else if w.dateNow.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(false)
return false
}
return false
if w.keyMap.Handle(ev) {
return true
}
if w.dateFld.Active() {
if w.dateFld.HandleKey(ev) {
@@ -140,9 +117,7 @@ func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool {
} else if w.dateNow.Active() {
return w.dateNow.HandleKey(ev)
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return false
}
func (w *DatePicker) HandleTime(ev *tcell.EventTime) {}
func (w *DatePicker) Draw(screen tcell.Screen) {
@@ -198,8 +173,20 @@ func (w *DatePicker) updateUI() {
}
func (w *DatePicker) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
if w.dateFld.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(true)
return true
} else if w.dateNow.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(false)
return true
}
return false
}),
)
}
func (w *DatePicker) Format() string { return w.format }

View File

@@ -43,7 +43,7 @@ type DebugWidget struct {
focusable bool
mTL, mBR Coord // Margins (Top-Right & Bottom Left)
keyMap KeyMap
keyMap *KeyMap
logger func(string, ...any)
}
@@ -106,16 +106,8 @@ func (w *DebugWidget) HandleResize(ev *tcell.EventResize) {
w.widget.HandleResize(tcell.NewEventResize(w.w-w.mTL.X-w.mBR.X, w.h-w.mTL.Y-w.mBR.Y))
}
func (w *DebugWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *DebugWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *DebugWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *DebugWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *DebugWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *DebugWidget) HandleKey(ev *tcell.EventKey) bool {
if ok := w.keyMap.Handle(ev); ok {

View File

@@ -47,7 +47,7 @@ type Field struct {
filter func(tcell.EventKey) bool
onChange func(prev, curr string)
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Field)(nil)
@@ -66,36 +66,21 @@ func (w *Field) Init(id string, style tcell.Style) {
return wh.IsBS(ev) ||
wh.KeyIsDisplayable(ev)
}
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyLeft: w.handleLeft,
tcell.KeyRight: w.handleRight,
tcell.KeyHome: w.handleHome,
tcell.KeyEnd: w.handleEnd,
tcell.KeyCtrlU: w.clearValueBeforeCursor,
})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyLeft), w.handleLeft),
NewKey(BuildEK(tcell.KeyRight), w.handleRight),
NewKey(BuildEK(tcell.KeyHome), w.handleHome),
NewKey(BuildEK(tcell.KeyEnd), w.handleEnd),
NewKey(BuildEK(tcell.KeyCtrlU), w.clearValueBeforeCursor),
)
w.focusable = true
}
func (w *Field) Id() string { return w.id }
func (w *Field) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Field) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Field) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Field) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Field) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Field) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Field) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -114,9 +99,7 @@ func (w *Field) HandleKey(ev *tcell.EventKey) bool {
return w.handleBackspace(ev)
}
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}
if w.filter != nil && !w.filter(*ev) {

View File

@@ -49,7 +49,7 @@ type FilePicker struct {
error error
keyMap, customKeyMap KeyMap
keyMap *KeyMap
logger func(string, ...any)
}
@@ -77,7 +77,6 @@ func (w *FilePicker) Init(id string, style tcell.Style) {
w.focusable = true
w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
w.refreshFileList()
}
@@ -96,30 +95,14 @@ func (w *FilePicker) HandleResize(ev *tcell.EventResize) {
w.Log("%s: HandleResize(%d, %d)", w.id, wd, ht)
}
func (w *FilePicker) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *FilePicker) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *FilePicker) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *FilePicker) GetKeyMap() *KeyMap { return w.keyMap }
func (w *FilePicker) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *FilePicker) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *FilePicker) HandleTime(ev *tcell.EventTime) {

View File

@@ -45,7 +45,7 @@ type Form struct {
hasSubmit bool
hasCancel bool
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Form)(nil)
@@ -64,7 +64,6 @@ func (w *Form) Init(id string, style tcell.Style) {
w.submit = NewButton(fmt.Sprintf("%s-submit", id), style)
w.cancel = NewButton(fmt.Sprintf("%s-cancel", id), style)
w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
}
func (w *Form) Id() string { return w.id }
@@ -92,22 +91,8 @@ func (w *Form) HandleResize(ev *tcell.EventResize) {
}
}
func (w *Form) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Form) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Form) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Form) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Form) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Form) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -129,9 +114,7 @@ func (w *Form) HandleKey(ev *tcell.EventKey) bool {
w.updateWidgets()
return w.cursor > pre
}
b1 := w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Form) HandleTime(ev *tcell.EventTime) {}
func (w *Form) Draw(screen tcell.Screen) {

View File

@@ -56,7 +56,7 @@ type LinearLayout struct {
disableTab bool
insetBorder bool
keyMap, customKeyMap KeyMap
keyMap *KeyMap
logger func(string, ...any)
}
@@ -84,8 +84,7 @@ func (w *LinearLayout) Init(id string, s tcell.Style) {
w.defFlags = LayoutFlag(LFAlignHCenter | LFAlignVCenter)
w.layoutFlags = make(map[Widget]LayoutFlag)
w.layoutWeights = make(map[Widget]int)
w.keyMap = BlankKeyMap()
w.keyMap.Add(tcell.KeyTab, func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
active := w.findActive()
if active == nil && len(w.widgets) > 0 {
// No widget is active, but we do have some
@@ -97,8 +96,7 @@ func (w *LinearLayout) Init(id string, s tcell.Style) {
return false
}
return w.ActivateNext()
})
w.customKeyMap = BlankKeyMap()
}))
}
func (w *LinearLayout) Id() string { return w.id }
@@ -107,22 +105,8 @@ func (w *LinearLayout) HandleResize(ev *tcell.EventResize) {
w.updateWidgetLayouts()
}
func (w *LinearLayout) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *LinearLayout) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *LinearLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *LinearLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *LinearLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.active || w.disableTab {
@@ -134,8 +118,7 @@ func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool {
return true
}
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *LinearLayout) GetActiveWidgetIdx() int { return w.findActiveIdx() }
@@ -335,6 +318,7 @@ func (w *LinearLayout) FindById(id string) Widget {
}
return nil
}
func (w *LinearLayout) Contains(n Widget) bool {
return w.IndexOf(n) >= 0
}

View File

@@ -47,7 +47,7 @@ type Menu struct {
expanded bool
vimMode bool
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
type MenuType int
@@ -69,19 +69,18 @@ func (w *Menu) Init(id string, style tcell.Style) {
w.id = id
w.style = style
w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyRight: w.MoveRight,
tcell.KeyLeft: w.MoveLeft,
tcell.KeyUp: w.MoveUp,
tcell.KeyDown: w.MoveDown,
tcell.KeyEnter: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyRight), w.MoveRight),
NewKey(BuildEK(tcell.KeyLeft), w.MoveLeft),
NewKey(BuildEK(tcell.KeyUp), w.MoveUp),
NewKey(BuildEK(tcell.KeyDown), w.MoveDown),
NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onPressed != nil {
return w.onPressed()
}
return false
},
})
w.customKeyMap = BlankKeyMap()
}),
)
w.focusable = true
}
func (w *Menu) Id() string { return w.id }
@@ -124,22 +123,8 @@ func (w *Menu) handleResizeV(_ *tcell.EventResize) {
}
}
func (w *Menu) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Menu) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Menu) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Menu) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Menu) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -152,8 +137,7 @@ func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
}
return true
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}

View File

@@ -51,7 +51,7 @@ type MenuItem struct {
expanded bool
disabled bool
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*MenuItem)(nil)
@@ -66,19 +66,18 @@ func (w *MenuItem) Init(id string, style tcell.Style) {
w.id = id
w.style = style
w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyUp: w.MoveUp,
tcell.KeyDown: w.MoveDown,
tcell.KeyEnter: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyUp), w.MoveUp),
NewKey(BuildEK(tcell.KeyDown), w.MoveDown),
NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onPressed != nil {
return w.onPressed()
} else if len(w.items) > w.cursor && w.items[w.cursor].HandleKey(ev) {
return true
}
return false
},
})
w.customKeyMap = BlankKeyMap()
}),
)
for i := range w.items {
w.items[i].SetActive(i == w.cursor)
@@ -91,22 +90,8 @@ func (w *MenuItem) HandleResize(ev *tcell.EventResize) {
// TODO: Trickle-down HandleResize
}
func (w *MenuItem) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *MenuItem) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *MenuItem) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *MenuItem) GetKeyMap() *KeyMap { return w.keyMap }
func (w *MenuItem) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -127,8 +112,7 @@ func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool {
}
}
// Look for a sub-item that's selected
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *MenuItem) HandleTime(ev *tcell.EventTime) {

View File

@@ -46,7 +46,7 @@ type Prompt struct {
btnOk, btnCancel *Button
onOk func(string) bool
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Prompt)(nil)
@@ -68,7 +68,6 @@ func (w *Prompt) Init(id string, style tcell.Style) {
w.btnCancel.SetLabel("Cancel")
w.focusable = true
w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
}
func (w *Prompt) Id() string { return w.id }
func (w *Prompt) HandleResize(ev *tcell.EventResize) {
@@ -84,29 +83,14 @@ func (w *Prompt) HandleResize(ev *tcell.EventResize) {
w.btnCancel.SetPos(Coord{X: w.x + 1, Y: w.y + w.h - 1})
}
func (w *Prompt) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Prompt) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Prompt) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Prompt) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Prompt) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Prompt) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Prompt) HandleTime(ev *tcell.EventTime) {

View File

@@ -37,7 +37,7 @@ type RelativeLayout struct {
visible bool
focusable bool
keyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*RelativeLayout)(nil)
@@ -85,16 +85,8 @@ func (w *RelativeLayout) HandleResize(ev *tcell.EventResize) {
// TODO: Trickle-down HandleResize
}
func (w *RelativeLayout) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *RelativeLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *RelativeLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *RelativeLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *RelativeLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *RelativeLayout) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) }
func (w *RelativeLayout) HandleTime(ev *tcell.EventTime) {
for i := range w.widgets {

View File

@@ -54,7 +54,7 @@ type Searcher struct {
hideOnSelect bool
logger func(string, ...any)
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Searcher)(nil)
@@ -74,16 +74,15 @@ func (w *Searcher) Init(id string, style tcell.Style) {
w.search.SetOnChange(func(prev, curr string) {
w.updateFilter()
})
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyUp: w.handleKeyUp,
tcell.KeyDown: w.handleKeyDown,
tcell.KeyHome: w.handleKeyHome,
tcell.KeyEnd: w.handleKeyEnd,
tcell.KeyPgUp: w.handleKeyPgUp,
tcell.KeyPgDn: w.handleKeyPgDn,
tcell.KeyEnter: w.handleKeyEnter,
})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyUp), w.handleKeyUp),
NewKey(BuildEK(tcell.KeyDown), w.handleKeyDown),
NewKey(BuildEK(tcell.KeyHome), w.handleKeyHome),
NewKey(BuildEK(tcell.KeyEnd), w.handleKeyEnd),
NewKey(BuildEK(tcell.KeyPgUp), w.handleKeyPgUp),
NewKey(BuildEK(tcell.KeyPgDn), w.handleKeyPgDn),
NewKey(BuildEK(tcell.KeyEnter), w.handleKeyEnter),
)
w.focusable = true
w.filteredToTrue = make(map[int]int)
}
@@ -101,41 +100,22 @@ func (w *Searcher) HandleResize(ev *tcell.EventResize) {
// w.buildBuffer()
}
func (w *Searcher) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Searcher) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Searcher) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Searcher) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Searcher) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Searcher) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
sel := w.cursor
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
var ret bool
if !b1 && !b2 {
ret := w.keyMap.Handle(ev)
if !ret {
ret = w.search.HandleKey(ev)
}
if w.cursor != sel && w.onChange != nil {
w.onChange(w.cursor, w.filteredData[w.cursor])
}
if b1 || b2 || ret {
// w.buildBuffer()
return true
}
return false
return ret
}
func (w *Searcher) handleKeyUp(ev *tcell.EventKey) bool {

View File

@@ -39,9 +39,9 @@ func (w *ShrinkWrap) Init(id string, st tcell.Style) { w.widget.Init(id, st)
func (w *ShrinkWrap) Id() string { return w.widget.Id() }
func (w *ShrinkWrap) HandleResize(ev *tcell.EventResize) { w.widget.HandleResize(ev) }
func (w *ShrinkWrap) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) }
func (w *ShrinkWrap) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) }
func (w *ShrinkWrap) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) }
func (w *ShrinkWrap) GetKeyMap() *KeyMap { return w.widget.GetKeyMap() }
func (w *ShrinkWrap) SetKeyMap(km *KeyMap) { w.widget.SetKeyMap(km) }
func (w *ShrinkWrap) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) }
func (w *ShrinkWrap) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) }
func (w *ShrinkWrap) Draw(screen tcell.Screen) { w.widget.Draw(screen) }

View File

@@ -44,10 +44,10 @@ type SimpleList struct {
list []string
itemsStyle map[int]tcell.Style
onChange func(int, string) bool
onSelect func(int, string) bool
keyMap, customKeyMap KeyMap
vimMode bool
onChange func(int, string) bool
onSelect func(int, string) bool
keyMap *KeyMap
vimMode bool
logger func(string, ...any)
}
@@ -64,49 +64,48 @@ func (w *SimpleList) Init(id string, style tcell.Style) {
w.id = id
w.style = style
w.focusable = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyUp: func(_ *tcell.EventKey) bool { return w.MoveUp() },
tcell.KeyDown: func(_ *tcell.EventKey) bool { return w.MoveDown() },
tcell.KeyEnter: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyUp), func(_ *tcell.EventKey) bool { return w.MoveUp() }),
NewKey(BuildEK(tcell.KeyDown), func(_ *tcell.EventKey) bool { return w.MoveDown() }),
NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onSelect != nil && w.cursor < len(w.list) {
return w.onSelect(w.cursor, w.list[w.cursor])
}
return false
},
tcell.KeyPgDn: func(_ *tcell.EventKey) bool { return w.PageDn() },
tcell.KeyPgUp: func(_ *tcell.EventKey) bool { return w.PageUp() },
})
w.keyMap.AddRune('j', func(ev *tcell.EventKey) bool {
if !w.vimMode {
}),
NewKey(BuildEK(tcell.KeyPgDn), func(_ *tcell.EventKey) bool { return w.PageDn() }),
NewKey(BuildEK(tcell.KeyPgUp), func(_ *tcell.EventKey) bool { return w.PageUp() }),
NewKey(BuildEKr('j'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
return w.MoveDown()
}),
NewKey(BuildEKr('k'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
return w.MoveUp()
}),
NewKey(BuildEKr('b'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageUp()
}
return false
}
return w.MoveDown()
})
w.keyMap.AddRune('k', func(ev *tcell.EventKey) bool {
if !w.vimMode {
}),
NewKey(BuildEKr('f'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageDn()
}
return false
}
return w.MoveUp()
})
w.keyMap.AddRune('b', func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageUp()
}
return false
})
w.keyMap.AddRune('f', func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageDn()
}
return false
})
w.customKeyMap = BlankKeyMap()
}),
)
w.itemsStyle = make(map[int]tcell.Style)
w.focusable = true
}
@@ -114,29 +113,14 @@ func (w *SimpleList) Init(id string, style tcell.Style) {
func (w *SimpleList) Id() string { return w.id }
func (w *SimpleList) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *SimpleList) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *SimpleList) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *SimpleList) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *SimpleList) GetKeyMap() *KeyMap { return w.keyMap }
func (w *SimpleList) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *SimpleList) HandleKey(ev *tcell.EventKey) bool {
if !w.active || !w.focusable {
return false
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *SimpleList) HandleTime(ev *tcell.EventTime) {}
@@ -294,10 +278,10 @@ func (w *SimpleList) PageUp() bool {
func (w *SimpleList) PageDn() bool {
w.cursor += w.h
if len(w.border) > 0 {
w.cursor -= 2
w.cursor -= 1
}
if w.cursor > len(w.list)-2 {
w.cursor = len(w.list) - 2
if w.cursor > len(w.list)-1 {
w.cursor = len(w.list) - 1
}
return true
}

View File

@@ -36,7 +36,7 @@ type Spinner struct {
frames []rune
lastTick time.Time
tickInterval time.Duration
keyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Spinner)(nil)
@@ -60,16 +60,10 @@ func (w *Spinner) Init(id string, st tcell.Style) {
}
func (w *Spinner) Id() string { return w.id }
func (w *Spinner) HandleResize(ev *tcell.EventResize) {}
func (w *Spinner) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *Spinner) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *Spinner) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *Spinner) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Spinner) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Spinner) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *Spinner) HandleTime(ev *tcell.EventTime) {
w.currentFrame = (w.currentFrame + 1) % len(w.frames)

View File

@@ -52,7 +52,7 @@ type Table struct {
columnWidths []int
keyMap, customKeyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Table)(nil)
@@ -85,36 +85,20 @@ func (w *Table) Init(id string, style tcell.Style) {
w.border = wh.BRD_CSIMPLE
w.focusable = true
w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
}
func (w *Table) Id() string { return w.id }
func (w *Table) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size()
}
func (w *Table) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Table) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Table) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Table) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Table) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Table) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
return b1 || b2
return w.keyMap.Handle(ev)
}
func (w *Table) HandleTime(ev *tcell.EventTime) {}
func (w *Table) Draw(screen tcell.Screen) {

View File

@@ -40,7 +40,7 @@ type Text struct {
visible bool
active bool
focusable bool
keyMap KeyMap
keyMap *KeyMap
}
var _ Widget = (*Text)(nil)
@@ -62,16 +62,9 @@ func (w *Text) Init(id string, style tcell.Style) {
func (w *Text) Id() string { return w.id }
func (w *Text) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Text) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *Text) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *Text) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *Text) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Text) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Text) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) }
func (w *Text) HandleTime(ev *tcell.EventTime) {}
func (w *Text) Draw(screen tcell.Screen) {

View File

@@ -57,8 +57,8 @@ type TimeField struct {
widgets []Widget
cursor int
keyMap, customKeyMap KeyMap
cursor int
keyMap *KeyMap
}
// TODO: Allow changing the format.
@@ -87,11 +87,10 @@ func (w *TimeField) Init(id string, style tcell.Style) {
w.fldHour, w.fldMinute, w.fldSecond, w.btnNow,
)
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyHome: w.handleHome,
tcell.KeyEnd: w.handleEnd,
})
w.customKeyMap = BlankKeyMap()
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyHome), w.handleHome),
NewKey(BuildEK(tcell.KeyEnd), w.handleEnd),
)
w.visible = true
w.focusable = true
}
@@ -139,22 +138,8 @@ func (w *TimeField) HandleResize(ev *tcell.EventResize) {
}
}
func (w *TimeField) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *TimeField) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *TimeField) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *TimeField) GetKeyMap() *KeyMap { return w.keyMap }
func (w *TimeField) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *TimeField) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
@@ -162,8 +147,7 @@ func (w *TimeField) HandleKey(ev *tcell.EventKey) bool {
} else if ev.Key() == tcell.KeyTab {
return w.handleTab(ev)
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}
if w.cursor <= len(w.widgets) {

View File

@@ -43,8 +43,8 @@ type TopMenuLayout struct {
visible bool
focusable bool
layoutFlags LayoutFlag
keyMap, customKeyMap KeyMap
layoutFlags LayoutFlag
keyMap *KeyMap
logger func(string, ...any)
}
@@ -68,18 +68,17 @@ func (w *TopMenuLayout) Init(id string, s tcell.Style) {
w.menu.SetType(MenuTypeH)
w.widget = NewBlankWidget("blank")
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
tcell.KeyEscape: func(ev *tcell.EventKey) bool {
w.keyMap = NewKeyMap(
NewKey(BuildEK(tcell.KeyEscape), func(ev *tcell.EventKey) bool {
return w.ToggleMenu()
},
})
w.keyMap.AddRune(' ', func(ev *tcell.EventKey) bool {
if ev.Modifiers()&tcell.ModAlt != 0 {
return w.ToggleMenu()
}
return false
})
w.customKeyMap = BlankKeyMap()
}),
NewKey(BuildEKr(' '), func(ev *tcell.EventKey) bool {
if ev.Modifiers()&tcell.ModAlt != 0 {
return w.ToggleMenu()
}
return false
}),
)
}
func (w *TopMenuLayout) ToggleMenu() bool {
@@ -122,29 +121,14 @@ func (w *TopMenuLayout) HandleResize(ev *tcell.EventResize) {
}
}
func (w *TopMenuLayout) SetKeyMap(km KeyMap, def bool) {
if def {
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *TopMenuLayout) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *TopMenuLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *TopMenuLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *TopMenuLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *TopMenuLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.active {
return false
}
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev)
if b1 || b2 {
if w.keyMap.Handle(ev) {
return true
}
if w.menu != nil && w.menu.Active() {

View File

@@ -33,12 +33,10 @@ type Widget interface {
HandleKey(*tcell.EventKey) bool
HandleTime(*tcell.EventTime)
// KeyMap Handling
// SetKeyMap sets a new keymap
// if 'def' is true, the default keymap is overwritten
// otherwise, it should be treated as a custom keymap
SetKeyMap(km KeyMap, def bool)
AddToKeyMap(km KeyMap)
RemoveFromKeyMap(km KeyMap)
// SetKeyMap overwrites the keymap
GetKeyMap() *KeyMap
SetKeyMap(km *KeyMap)
Draw(tcell.Screen)
Active() bool
SetActive(bool)