github.com/wtfutil/wtf@v0.43.0/view/keyboard_widget.go (about) 1 package view 2 3 import ( 4 "fmt" 5 6 "github.com/gdamore/tcell/v2" 7 "github.com/wtfutil/wtf/cfg" 8 "github.com/wtfutil/wtf/utils" 9 "golang.org/x/text/cases" 10 "golang.org/x/text/language" 11 ) 12 13 const helpKeyChar = "/" 14 const refreshKeyChar = "r" 15 16 type helpItem struct { 17 Key string 18 Text string 19 } 20 21 // KeyboardWidget manages keyboard control for a widget 22 type KeyboardWidget struct { 23 settings *cfg.Common 24 25 charMap map[string]func() 26 keyMap map[tcell.Key]func() 27 charHelp []helpItem 28 keyHelp []helpItem 29 maxKey int 30 } 31 32 // NewKeyboardWidget creates and returns a new instance of KeyboardWidget 33 // func NewKeyboardWidget(tviewApp *tview.Application, pages *tview.Pages, settings *cfg.Common) *KeyboardWidget { 34 func NewKeyboardWidget(settings *cfg.Common) *KeyboardWidget { 35 keyWidget := &KeyboardWidget{ 36 settings: settings, 37 charMap: make(map[string]func()), 38 keyMap: make(map[tcell.Key]func()), 39 charHelp: []helpItem{}, 40 keyHelp: []helpItem{}, 41 } 42 43 keyWidget.initializeCommonKeyboardControls() 44 45 return keyWidget 46 } 47 48 /* -------------------- Exported Functions --------------------- */ 49 50 // AssignedChars returns a list of all the text characters assigned to an operation 51 func (widget *KeyboardWidget) AssignedChars() []string { 52 chars := []string{} 53 54 for char := range widget.charMap { 55 chars = append(chars, char) 56 } 57 58 return chars 59 } 60 61 // HelpText returns the help text and keyboard command info for this widget 62 func (widget *KeyboardWidget) HelpText() string { 63 c := cases.Title(language.English) 64 str := " [green::b]Keyboard commands for " + c.String(widget.settings.Module.Type) + "[white]\n\n" 65 66 for _, item := range widget.charHelp { 67 str += fmt.Sprintf(" %s\t%s\n", item.Key, item.Text) 68 } 69 70 str += "\n\n" 71 72 for _, item := range widget.keyHelp { 73 str += fmt.Sprintf(" %-*s\t%s\n", widget.maxKey, item.Key, item.Text) 74 } 75 76 return str 77 } 78 79 // InitializeHelpTextKeyboardControl assigns the function that displays help text to the 80 // common help text key value 81 func (widget *KeyboardWidget) InitializeHelpTextKeyboardControl(helpFunc func()) { 82 if helpFunc != nil { 83 widget.SetKeyboardChar(helpKeyChar, helpFunc, "Show/hide this help prompt") 84 } 85 } 86 87 // InitializeRefreshKeyboardControl assigns the module's explicit refresh function to 88 // the commom refresh key value 89 func (widget *KeyboardWidget) InitializeRefreshKeyboardControl(refreshFunc func()) { 90 if refreshFunc != nil { 91 widget.SetKeyboardChar(refreshKeyChar, refreshFunc, "Refresh widget") 92 } 93 } 94 95 // InputCapture is the function passed to tview's SetInputCapture() function 96 // This is done during the main widget's creation process using the following code: 97 // 98 // widget.View.SetInputCapture(widget.InputCapture) 99 func (widget *KeyboardWidget) InputCapture(event *tcell.EventKey) *tcell.EventKey { 100 if event == nil { 101 return nil 102 } 103 104 fn := widget.charMap[string(event.Rune())] 105 if fn != nil { 106 fn() 107 return nil 108 } 109 110 fn = widget.keyMap[event.Key()] 111 if fn != nil { 112 fn() 113 return nil 114 } 115 116 return event 117 } 118 119 // LaunchDocumentation opens the module docs in a browser 120 func (widget *KeyboardWidget) LaunchDocumentation() { 121 path := widget.settings.DocPath 122 if path == "" { 123 path = widget.settings.Type 124 } 125 126 url := "https://wtfutil.com/modules/" + path 127 utils.OpenFile(url) 128 } 129 130 // SetKeyboardChar sets a character/function combination that responds to key presses 131 // Example: 132 // 133 // widget.SetKeyboardChar("d", widget.deleteSelectedItem) 134 func (widget *KeyboardWidget) SetKeyboardChar(char string, fn func(), helpText string) { 135 if char == "" { 136 return 137 } 138 139 // Check to ensure that the key trying to be used isn't already being used for something 140 if _, ok := widget.charMap[char]; ok { 141 panic(fmt.Sprintf("Key is already mapped to a keyboard command: %s\n", char)) 142 } 143 144 widget.charMap[char] = fn 145 widget.charHelp = append(widget.charHelp, helpItem{char, helpText}) 146 } 147 148 // SetKeyboardKey sets a tcell.Key/function combination that responds to key presses 149 // Example: 150 // 151 // widget.SetKeyboardKey(tcell.KeyCtrlD, widget.deleteSelectedItem) 152 func (widget *KeyboardWidget) SetKeyboardKey(key tcell.Key, fn func(), helpText string) { 153 widget.keyMap[key] = fn 154 widget.keyHelp = append(widget.keyHelp, helpItem{tcell.KeyNames[key], helpText}) 155 156 if len(tcell.KeyNames[key]) > widget.maxKey { 157 widget.maxKey = len(tcell.KeyNames[key]) 158 } 159 } 160 161 /* -------------------- Unexported Functions -------------------- */ 162 163 // initializeCommonKeyboardControls sets up the keyboard controls that are common to 164 // all widgets that accept keyboard input 165 func (widget *KeyboardWidget) initializeCommonKeyboardControls() { 166 widget.SetKeyboardChar("\\", widget.LaunchDocumentation, "Open the documentation for this module in a browser") 167 }