|
|
|
@ -4,171 +4,110 @@ import (
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/cointop-sh/cointop/pkg/gocui"
|
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func keyMap(k string) string {
|
|
|
|
|
// compatability mapping
|
|
|
|
|
key := k
|
|
|
|
|
switch k {
|
|
|
|
|
case "lsqrbracket", "leftsqrbracket", "leftsquarebracket":
|
|
|
|
|
key = "["
|
|
|
|
|
case "rsqrbracket", "rightsqrbracket", "rightsquarebracket":
|
|
|
|
|
key = "]"
|
|
|
|
|
case "space":
|
|
|
|
|
key = " "
|
|
|
|
|
case "backslash":
|
|
|
|
|
key = "\\"
|
|
|
|
|
case "underscore":
|
|
|
|
|
key = "_"
|
|
|
|
|
// case "\\\\":
|
|
|
|
|
// key = '\\'
|
|
|
|
|
}
|
|
|
|
|
return key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseKeys returns string keyboard key as gocui key type
|
|
|
|
|
func (ct *Cointop) ParseKeys(s string) (interface{}, gocui.Modifier) {
|
|
|
|
|
func (ct *Cointop) ParseKeys(s string) (interface{}, tcell.ModMask) {
|
|
|
|
|
// TODO: change file convention to match tcell
|
|
|
|
|
|
|
|
|
|
// TODO: change to return EventKey
|
|
|
|
|
var key interface{}
|
|
|
|
|
mod := gocui.ModNone
|
|
|
|
|
mod := tcell.ModNone
|
|
|
|
|
|
|
|
|
|
// First try looking up keyname directly
|
|
|
|
|
keyName := strings.ToLower(strings.TrimSpace(strings.Replace(s, "+", "-", -1)))
|
|
|
|
|
for key, name := range tcell.KeyNames {
|
|
|
|
|
if strings.ToLower(name) == keyName {
|
|
|
|
|
// Found direct match
|
|
|
|
|
if strings.HasPrefix(name, "Ctrl-") {
|
|
|
|
|
mod = tcell.ModCtrl
|
|
|
|
|
}
|
|
|
|
|
// log.Debugf("XXX direct map %s: %d %s", s, key, mod) // TODO: remove
|
|
|
|
|
return key, mod
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
split := strings.Split(s, "+")
|
|
|
|
|
if len(split) > 1 {
|
|
|
|
|
m := strings.ToLower(strings.TrimSpace(split[0]))
|
|
|
|
|
k := strings.ToLower(strings.TrimSpace(split[1]))
|
|
|
|
|
k = keyMap(k)
|
|
|
|
|
if m == "alt" {
|
|
|
|
|
mod = gocui.ModAlt
|
|
|
|
|
mod = tcell.ModAlt
|
|
|
|
|
s = k
|
|
|
|
|
} else if m == "ctrl" {
|
|
|
|
|
switch k {
|
|
|
|
|
case "0":
|
|
|
|
|
key = '0'
|
|
|
|
|
case "1":
|
|
|
|
|
key = '1'
|
|
|
|
|
case "2":
|
|
|
|
|
key = gocui.KeyCtrl2
|
|
|
|
|
case "3":
|
|
|
|
|
key = gocui.KeyCtrl3
|
|
|
|
|
case "4":
|
|
|
|
|
key = gocui.KeyCtrl4
|
|
|
|
|
case "5":
|
|
|
|
|
key = gocui.KeyCtrl5
|
|
|
|
|
case "6":
|
|
|
|
|
key = gocui.KeyCtrl6
|
|
|
|
|
case "7":
|
|
|
|
|
key = gocui.KeyCtrl7
|
|
|
|
|
case "8":
|
|
|
|
|
key = gocui.KeyCtrl8
|
|
|
|
|
case "9":
|
|
|
|
|
key = '9'
|
|
|
|
|
case "a":
|
|
|
|
|
key = gocui.KeyCtrlA
|
|
|
|
|
case "b":
|
|
|
|
|
key = gocui.KeyCtrlB
|
|
|
|
|
case "c":
|
|
|
|
|
key = gocui.KeyCtrlC
|
|
|
|
|
case "d":
|
|
|
|
|
key = gocui.KeyCtrlD
|
|
|
|
|
case "e":
|
|
|
|
|
key = gocui.KeyCtrlE
|
|
|
|
|
case "f":
|
|
|
|
|
key = gocui.KeyCtrlF
|
|
|
|
|
case "g":
|
|
|
|
|
key = gocui.KeyCtrlG
|
|
|
|
|
case "h":
|
|
|
|
|
key = gocui.KeyCtrlH
|
|
|
|
|
case "i":
|
|
|
|
|
key = gocui.KeyCtrlI
|
|
|
|
|
case "j":
|
|
|
|
|
key = gocui.KeyCtrlJ
|
|
|
|
|
case "k":
|
|
|
|
|
key = gocui.KeyCtrlK
|
|
|
|
|
case "l":
|
|
|
|
|
key = gocui.KeyCtrlL
|
|
|
|
|
case "m":
|
|
|
|
|
key = gocui.KeyCtrlL
|
|
|
|
|
case "n":
|
|
|
|
|
key = gocui.KeyCtrlN
|
|
|
|
|
case "o":
|
|
|
|
|
key = gocui.KeyCtrlO
|
|
|
|
|
case "p":
|
|
|
|
|
key = gocui.KeyCtrlP
|
|
|
|
|
case "q":
|
|
|
|
|
key = gocui.KeyCtrlQ
|
|
|
|
|
case "r":
|
|
|
|
|
key = gocui.KeyCtrlR
|
|
|
|
|
case "s":
|
|
|
|
|
key = gocui.KeyCtrlS
|
|
|
|
|
case "t":
|
|
|
|
|
key = gocui.KeyCtrlT
|
|
|
|
|
case "u":
|
|
|
|
|
key = gocui.KeyCtrlU
|
|
|
|
|
case "v":
|
|
|
|
|
key = gocui.KeyCtrlV
|
|
|
|
|
case "w":
|
|
|
|
|
key = gocui.KeyCtrlW
|
|
|
|
|
case "x":
|
|
|
|
|
key = gocui.KeyCtrlX
|
|
|
|
|
case "y":
|
|
|
|
|
key = gocui.KeyCtrlY
|
|
|
|
|
case "z":
|
|
|
|
|
key = gocui.KeyCtrlZ
|
|
|
|
|
case "~":
|
|
|
|
|
key = gocui.KeyCtrlTilde
|
|
|
|
|
case "[", "lsqrbracket", "leftsqrbracket", "leftsquarebracket":
|
|
|
|
|
key = gocui.KeyCtrlLsqBracket
|
|
|
|
|
case "]", "rsqrbracket", "rightsqrbracket", "rightsquarebracket":
|
|
|
|
|
key = gocui.KeyCtrlRsqBracket
|
|
|
|
|
case "space":
|
|
|
|
|
key = gocui.KeyCtrlSpace
|
|
|
|
|
case "backslash":
|
|
|
|
|
key = gocui.KeyCtrlBackslash
|
|
|
|
|
case "underscore":
|
|
|
|
|
key = gocui.KeyCtrlUnderscore
|
|
|
|
|
case "\\\\":
|
|
|
|
|
key = '\\'
|
|
|
|
|
}
|
|
|
|
|
return key, mod
|
|
|
|
|
// k = keyMap(k)
|
|
|
|
|
}
|
|
|
|
|
// return key, mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = keyMap(s)
|
|
|
|
|
if len(s) == 1 {
|
|
|
|
|
r := []rune(s)
|
|
|
|
|
key = r[0]
|
|
|
|
|
// log.Debugf("XXX one-rune map %s: %d %s", s, key, mod) // TODO: remove
|
|
|
|
|
return key, mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = strings.ToLower(s)
|
|
|
|
|
switch s {
|
|
|
|
|
case "arrowup", "uparrow", "up":
|
|
|
|
|
key = gocui.KeyArrowUp
|
|
|
|
|
case "arrowdown", "downarrow", "down":
|
|
|
|
|
key = gocui.KeyArrowDown
|
|
|
|
|
case "arrowleft", "leftarrow", "left":
|
|
|
|
|
key = gocui.KeyArrowLeft
|
|
|
|
|
case "arrowright", "rightarrow", "right":
|
|
|
|
|
key = gocui.KeyArrowRight
|
|
|
|
|
case "enter", "return":
|
|
|
|
|
key = gocui.KeyEnter
|
|
|
|
|
case "space", "spacebar":
|
|
|
|
|
key = gocui.KeySpace
|
|
|
|
|
case "esc", "escape":
|
|
|
|
|
key = gocui.KeyEsc
|
|
|
|
|
case "f1":
|
|
|
|
|
key = gocui.KeyF1
|
|
|
|
|
case "f2":
|
|
|
|
|
key = gocui.KeyF2
|
|
|
|
|
case "f3":
|
|
|
|
|
key = gocui.KeyF3
|
|
|
|
|
case "f4":
|
|
|
|
|
key = gocui.KeyF4
|
|
|
|
|
case "f5":
|
|
|
|
|
key = gocui.KeyF5
|
|
|
|
|
case "f6":
|
|
|
|
|
key = gocui.KeyF6
|
|
|
|
|
case "f7":
|
|
|
|
|
key = gocui.KeyF7
|
|
|
|
|
case "f8":
|
|
|
|
|
key = gocui.KeyF8
|
|
|
|
|
case "f9":
|
|
|
|
|
key = gocui.KeyF9
|
|
|
|
|
case "tab":
|
|
|
|
|
key = gocui.KeyTab
|
|
|
|
|
// case "arrowup", "uparrow", "up":
|
|
|
|
|
// key = tcell.KeyUp
|
|
|
|
|
// case "arrowdown", "downarrow", "down":
|
|
|
|
|
// key = tcell.KeyDown
|
|
|
|
|
// case "arrowleft", "leftarrow", "left":
|
|
|
|
|
// key = tcell.KeyLeft
|
|
|
|
|
// case "arrowright", "rightarrow", "right":
|
|
|
|
|
// key = tcell.KeyRight
|
|
|
|
|
// case "enter", "return":
|
|
|
|
|
// key = tcell.KeyEnter
|
|
|
|
|
// case "space", "spacebar":
|
|
|
|
|
// key = " "
|
|
|
|
|
// case "esc", "escape":
|
|
|
|
|
// key = tcell.KeyEsc
|
|
|
|
|
// case "tab":
|
|
|
|
|
// key = tcell.KeyTab
|
|
|
|
|
case "pageup", "pgup":
|
|
|
|
|
key = gocui.KeyPgup
|
|
|
|
|
key = tcell.KeyPgUp
|
|
|
|
|
case "pagedown", "pgdown", "pgdn":
|
|
|
|
|
key = gocui.KeyPgdn
|
|
|
|
|
case "home":
|
|
|
|
|
key = gocui.KeyHome
|
|
|
|
|
case "end":
|
|
|
|
|
key = gocui.KeyEnd
|
|
|
|
|
key = tcell.KeyPgDn
|
|
|
|
|
// case "home":
|
|
|
|
|
// key = tcell.KeyHome
|
|
|
|
|
// case "end":
|
|
|
|
|
// key = tcell.KeyEnd
|
|
|
|
|
case "\\\\":
|
|
|
|
|
key = '\\'
|
|
|
|
|
case "scrollup":
|
|
|
|
|
key = gocui.MouseWheelUp
|
|
|
|
|
key = gocui.MouseWheelUp // TODO: change to mouse event
|
|
|
|
|
case "scrolldown":
|
|
|
|
|
key = gocui.MouseWheelDown
|
|
|
|
|
key = gocui.MouseWheelDown // TODO: change to mouse event
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if key == nil {
|
|
|
|
|
log.Debugf("XXX NO map %s: %d %s", s, key, mod) // TODO: remove
|
|
|
|
|
}
|
|
|
|
|
return key, mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -347,47 +286,48 @@ func (ct *Cointop) SetKeybindings() error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// keys to force quit
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyCtrlC, gocui.ModNone, ct.Keyfn(ct.Quit), "")
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyCtrlZ, gocui.ModNone, ct.Keyfn(ct.Quit), "")
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyCtrlC, tcell.ModNone, ct.Keyfn(ct.Quit), "")
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyCtrlZ, tcell.ModNone, ct.Keyfn(ct.Quit), "")
|
|
|
|
|
|
|
|
|
|
// searchfield keys
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEnter, gocui.ModNone, ct.Keyfn(ct.DoSearch), ct.Views.SearchField.Name())
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEsc, gocui.ModNone, ct.Keyfn(ct.CancelSearch), ct.Views.SearchField.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEnter, tcell.ModNone, ct.Keyfn(ct.DoSearch), ct.Views.SearchField.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEsc, tcell.ModNone, ct.Keyfn(ct.CancelSearch), ct.Views.SearchField.Name())
|
|
|
|
|
|
|
|
|
|
// keys to quit help when open
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEsc, gocui.ModNone, ct.Keyfn(ct.HideHelp), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', gocui.ModNone, ct.Keyfn(ct.HideHelp), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEsc, tcell.ModNone, ct.Keyfn(ct.HideHelp), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', tcell.ModNone, ct.Keyfn(ct.HideHelp), ct.Views.Menu.Name())
|
|
|
|
|
|
|
|
|
|
// keys to quit portfolio update menu when open
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEsc, gocui.ModNone, ct.Keyfn(ct.HidePortfolioUpdateMenu), ct.Views.Input.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', gocui.ModNone, ct.Keyfn(ct.HidePortfolioUpdateMenu), ct.Views.Input.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEsc, tcell.ModNone, ct.Keyfn(ct.HidePortfolioUpdateMenu), ct.Views.Input.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', tcell.ModNone, ct.Keyfn(ct.HidePortfolioUpdateMenu), ct.Views.Input.Name())
|
|
|
|
|
|
|
|
|
|
// keys to quit convert menu when open
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEsc, gocui.ModNone, ct.Keyfn(ct.HideConvertMenu), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', gocui.ModNone, ct.Keyfn(ct.HideConvertMenu), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEsc, tcell.ModNone, ct.Keyfn(ct.HideConvertMenu), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod('q', tcell.ModNone, ct.Keyfn(ct.HideConvertMenu), ct.Views.Menu.Name())
|
|
|
|
|
|
|
|
|
|
// keys to update portfolio holdings
|
|
|
|
|
ct.SetKeybindingMod(gocui.KeyEnter, gocui.ModNone, ct.Keyfn(ct.EnterKeyPressHandler), ct.Views.Input.Name())
|
|
|
|
|
ct.SetKeybindingMod(tcell.KeyEnter, tcell.ModNone, ct.Keyfn(ct.EnterKeyPressHandler), ct.Views.Input.Name())
|
|
|
|
|
|
|
|
|
|
key, mod := ct.ParseKeys("/")
|
|
|
|
|
ct.DeleteKeybindingMod(key, mod, "")
|
|
|
|
|
// TODO: FIXME
|
|
|
|
|
// key, mod := ct.ParseKeys("/")
|
|
|
|
|
// ct.DeleteKeybindingMod(key, mod, "")
|
|
|
|
|
|
|
|
|
|
// mouse events
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.MouseLeftClick), ct.Views.Table.Name()) // click to focus
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, tcell.ModNone, ct.Keyfn(ct.MouseLeftClick), ct.Views.Table.Name()) // click to focus
|
|
|
|
|
|
|
|
|
|
// clicking table headers sorts table
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.TableHeaderMouseLeftClick), ct.Views.TableHeader.Name())
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.StatusbarMouseLeftClick), ct.Views.Statusbar.Name())
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, tcell.ModNone, ct.Keyfn(ct.TableHeaderMouseLeftClick), ct.Views.TableHeader.Name())
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, tcell.ModNone, ct.Keyfn(ct.StatusbarMouseLeftClick), ct.Views.Statusbar.Name())
|
|
|
|
|
// debug mouse clicks
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.MouseDebug), "")
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, tcell.ModNone, ct.Keyfn(ct.MouseDebug), "")
|
|
|
|
|
|
|
|
|
|
// character key press to select option
|
|
|
|
|
// TODO: use scrolling table
|
|
|
|
|
keys := ct.SortedSupportedCurrencyConversions()
|
|
|
|
|
for i, k := range keys {
|
|
|
|
|
ct.SetKeybindingMod(alphanumericcharacters[i], gocui.ModNone, ct.Keyfn(ct.SetCurrencyConverstionFn(k)), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod(alphanumericcharacters[i], tcell.ModNone, ct.Keyfn(ct.SetCurrencyConverstionFn(k)), ct.Views.Menu.Name())
|
|
|
|
|
}
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.ConversionMouseLeftClick), ct.Views.Menu.Name())
|
|
|
|
|
ct.SetKeybindingMod(gocui.MouseLeft, tcell.ModNone, ct.Keyfn(ct.ConversionMouseLeftClick), ct.Views.Menu.Name())
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -403,13 +343,14 @@ func (ct *Cointop) MouseDebug() error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetKeybindingMod sets the keybinding modifier key
|
|
|
|
|
func (ct *Cointop) SetKeybindingMod(key interface{}, mod gocui.Modifier, callback func(g *gocui.Gui, v *gocui.View) error, view string) error {
|
|
|
|
|
func (ct *Cointop) SetKeybindingMod(key interface{}, mod tcell.ModMask, callback func(g *gocui.Gui, v *gocui.View) error, view string) error {
|
|
|
|
|
// TODO: take EventKey
|
|
|
|
|
var err error
|
|
|
|
|
switch t := key.(type) {
|
|
|
|
|
case gocui.Key:
|
|
|
|
|
err = ct.g.SetKeybinding(view, t, mod, callback)
|
|
|
|
|
case tcell.Key:
|
|
|
|
|
err = ct.g.SetKeybinding(view, t, 0, mod, callback)
|
|
|
|
|
case rune:
|
|
|
|
|
err = ct.g.SetKeybinding(view, t, mod, callback)
|
|
|
|
|
err = ct.g.SetKeybinding(view, tcell.KeyRune, t, mod, callback)
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@ -421,13 +362,14 @@ func (ct *Cointop) DeleteKeybinding(shortcutKey string) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DeleteKeybindingMod ...
|
|
|
|
|
func (ct *Cointop) DeleteKeybindingMod(key interface{}, mod gocui.Modifier, view string) error {
|
|
|
|
|
func (ct *Cointop) DeleteKeybindingMod(key interface{}, mod tcell.ModMask, view string) error {
|
|
|
|
|
// TODO: take EventKey
|
|
|
|
|
var err error
|
|
|
|
|
switch t := key.(type) {
|
|
|
|
|
case gocui.Key:
|
|
|
|
|
err = ct.g.DeleteKeybinding(view, t, mod)
|
|
|
|
|
case tcell.Key:
|
|
|
|
|
err = ct.g.DeleteKeybinding(view, t, 0, mod)
|
|
|
|
|
case rune:
|
|
|
|
|
err = ct.g.DeleteKeybinding(view, t, mod)
|
|
|
|
|
err = ct.g.DeleteKeybinding(view, tcell.KeyRune, t, mod)
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|