1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
wtf/view/keyboard_widget.go
Chris Cummer fd794707cd
☢️ WTF-1031 Support multiple simultaneous configurations (#1032)
* WTF-1031 Rename WtfApp.app to WtfApp.tviewApp

Signed-off-by: Chris Cummer <chriscummer@me.com>

* WTF-1031 Add scaffolding for main to support multiple WtfApp instances

Signed-off-by: Chris Cummer <chriscummer@me.com>

* WTF-1031 WIP

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Remove common functionality from KeyboardWidget and into Base

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Augment with some descriptive comments

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Add full support for multiple app instances via the AppManager.

Still to do:

* Config support for multiple apps/multiple config files
* The ability to switch between apps

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Move SetTerminal out of main and into its own file

Signed-off-by: Chris Cummer <chriscummer@me.com>
2020-12-21 03:25:41 -08:00

169 lines
4.5 KiB
Go

package view
import (
"fmt"
"strings"
"github.com/gdamore/tcell"
"github.com/wtfutil/wtf/cfg"
"github.com/wtfutil/wtf/utils"
)
const helpKeyChar = "/"
const refreshKeyChar = "r"
type helpItem struct {
Key string
Text string
}
// KeyboardWidget manages keyboard control for a widget
type KeyboardWidget struct {
settings *cfg.Common
charMap map[string]func()
keyMap map[tcell.Key]func()
charHelp []helpItem
keyHelp []helpItem
maxKey int
}
// NewKeyboardWidget creates and returns a new instance of KeyboardWidget
// func NewKeyboardWidget(tviewApp *tview.Application, pages *tview.Pages, settings *cfg.Common) *KeyboardWidget {
func NewKeyboardWidget(settings *cfg.Common) *KeyboardWidget {
keyWidget := &KeyboardWidget{
settings: settings,
charMap: make(map[string]func()),
keyMap: make(map[tcell.Key]func()),
charHelp: []helpItem{},
keyHelp: []helpItem{},
}
keyWidget.initializeCommonKeyboardControls()
return keyWidget
}
/* -------------------- Exported Functions --------------------- */
// AssignedChars returns a list of all the text characters assigned to an operation
func (widget *KeyboardWidget) AssignedChars() []string {
chars := []string{}
for char := range widget.charMap {
chars = append(chars, char)
}
return chars
}
// HelpText returns the help text and keyboard command info for this widget
func (widget *KeyboardWidget) HelpText() string {
str := " [green::b]Keyboard commands for " + strings.Title(widget.settings.Module.Type) + "[white]\n\n"
for _, item := range widget.charHelp {
str += fmt.Sprintf(" %s\t%s\n", item.Key, item.Text)
}
str += "\n\n"
for _, item := range widget.keyHelp {
str += fmt.Sprintf(" %-*s\t%s\n", widget.maxKey, item.Key, item.Text)
}
return str
}
// InitializeHelpTextKeyboardControl assigns the function that displays help text to the
// common help text key value
func (widget *KeyboardWidget) InitializeHelpTextKeyboardControl(helpFunc func()) {
if helpFunc != nil {
widget.SetKeyboardChar(helpKeyChar, helpFunc, "Show/hide this help prompt")
}
}
// InitializeRefreshKeyboardControl assigns the module's explicit refresh function to
// the commom refresh key value
func (widget *KeyboardWidget) InitializeRefreshKeyboardControl(refreshFunc func()) {
if refreshFunc != nil {
widget.SetKeyboardChar(refreshKeyChar, refreshFunc, "Refresh widget")
}
}
// InputCapture is the function passed to tview's SetInputCapture() function
// This is done during the main widget's creation process using the following code:
//
// widget.View.SetInputCapture(widget.InputCapture)
//
func (widget *KeyboardWidget) InputCapture(event *tcell.EventKey) *tcell.EventKey {
if event == nil {
return nil
}
fn := widget.charMap[string(event.Rune())]
if fn != nil {
fn()
return nil
}
fn = widget.keyMap[event.Key()]
if fn != nil {
fn()
return nil
}
return event
}
// LaunchDocumentation opens the module docs in a browser
func (widget *KeyboardWidget) LaunchDocumentation() {
path := widget.settings.DocPath
if path == "" {
path = widget.settings.Type
}
url := "https://wtfutil.com/modules/" + path
utils.OpenFile(url)
}
// SetKeyboardChar sets a character/function combination that responds to key presses
// Example:
//
// widget.SetKeyboardChar("d", widget.deleteSelectedItem)
//
func (widget *KeyboardWidget) SetKeyboardChar(char string, fn func(), helpText string) {
if char == "" {
return
}
// Check to ensure that the key trying to be used isn't already being used for something
if _, ok := widget.charMap[char]; ok {
panic(fmt.Sprintf("Key is already mapped to a keyboard command: %s\n", char))
}
widget.charMap[char] = fn
widget.charHelp = append(widget.charHelp, helpItem{char, helpText})
}
// SetKeyboardKey sets a tcell.Key/function combination that responds to key presses
// Example:
//
// widget.SetKeyboardKey(tcell.KeyCtrlD, widget.deleteSelectedItem)
//
func (widget *KeyboardWidget) SetKeyboardKey(key tcell.Key, fn func(), helpText string) {
widget.keyMap[key] = fn
widget.keyHelp = append(widget.keyHelp, helpItem{tcell.KeyNames[key], helpText})
if len(tcell.KeyNames[key]) > widget.maxKey {
widget.maxKey = len(tcell.KeyNames[key])
}
}
/* -------------------- Unexported Functions -------------------- */
// initializeCommonKeyboardControls sets up the keyboard controls that are common to
// all widgets that accept keyboard input
func (widget *KeyboardWidget) initializeCommonKeyboardControls() {
widget.SetKeyboardChar("\\", widget.LaunchDocumentation, "Open the documentation for this module in a browser")
}