mirror of
https://github.com/ddworken/hishtory.git
synced 2024-12-30 18:58:52 +01:00
c933cbc792
* Add support for custom key bindings for #190 * Add tests for configuring custom key bindings * Simplify key bindings test * Add docs on custom key bindings + error message for unhandled actions
327 lines
9.0 KiB
Go
327 lines
9.0 KiB
Go
package keybindings
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/key"
|
|
)
|
|
|
|
type SerializableKeyMap struct {
|
|
Up []string
|
|
Down []string
|
|
PageUp []string
|
|
PageDown []string
|
|
SelectEntry []string
|
|
SelectEntryAndChangeDir []string
|
|
Left []string
|
|
Right []string
|
|
TableLeft []string
|
|
TableRight []string
|
|
DeleteEntry []string
|
|
Help []string
|
|
Quit []string
|
|
JumpStartOfInput []string
|
|
JumpEndOfInput []string
|
|
WordLeft []string
|
|
WordRight []string
|
|
}
|
|
|
|
func prettifyKeyBinding(kb string) string {
|
|
if kb == "up" {
|
|
return "↑ "
|
|
}
|
|
if kb == "down" {
|
|
return "↓ "
|
|
}
|
|
if kb == "left" {
|
|
return "←"
|
|
}
|
|
if kb == "right" {
|
|
return "→"
|
|
}
|
|
subs := [][]string{
|
|
{"+left", "+← "},
|
|
{"+right", "+→ "},
|
|
{"+down", "+↓ "},
|
|
{"+up", "+↑ "},
|
|
{"pgdown", "pgdn"},
|
|
}
|
|
for _, sub := range subs {
|
|
kb = strings.ReplaceAll(kb, sub[0], sub[1])
|
|
}
|
|
return kb
|
|
}
|
|
|
|
func (s SerializableKeyMap) ToKeyMap() KeyMap {
|
|
if len(s.Up) == 0 {
|
|
panic(fmt.Sprintf("%#v", s))
|
|
}
|
|
return KeyMap{
|
|
Up: key.NewBinding(
|
|
key.WithKeys(s.Up...),
|
|
key.WithHelp(prettifyKeyBinding(s.Up[0]), "scroll up "),
|
|
),
|
|
Down: key.NewBinding(
|
|
key.WithKeys(s.Down...),
|
|
key.WithHelp(prettifyKeyBinding(s.Down[0]), "scroll down "),
|
|
),
|
|
PageUp: key.NewBinding(
|
|
key.WithKeys(s.PageUp...),
|
|
key.WithHelp(prettifyKeyBinding(s.PageUp[0]), "page up "),
|
|
),
|
|
PageDown: key.NewBinding(
|
|
key.WithKeys(s.PageDown...),
|
|
key.WithHelp(prettifyKeyBinding(s.PageDown[0]), "page down "),
|
|
),
|
|
SelectEntry: key.NewBinding(
|
|
key.WithKeys(s.SelectEntry...),
|
|
key.WithHelp(prettifyKeyBinding(s.SelectEntry[0]), "select an entry "),
|
|
),
|
|
SelectEntryAndChangeDir: key.NewBinding(
|
|
key.WithKeys(s.SelectEntryAndChangeDir...),
|
|
key.WithHelp(prettifyKeyBinding(s.SelectEntryAndChangeDir[0]), "select an entry and cd into that directory"),
|
|
),
|
|
Left: key.NewBinding(
|
|
key.WithKeys(s.Left...),
|
|
key.WithHelp(prettifyKeyBinding(s.Left[0]), "move left "),
|
|
),
|
|
Right: key.NewBinding(
|
|
key.WithKeys(s.Right...),
|
|
key.WithHelp(prettifyKeyBinding(s.Right[0]), "move right "),
|
|
),
|
|
TableLeft: key.NewBinding(
|
|
key.WithKeys(s.TableLeft...),
|
|
key.WithHelp(prettifyKeyBinding(s.TableLeft[0]), "scroll the table left "),
|
|
),
|
|
TableRight: key.NewBinding(
|
|
key.WithKeys(s.TableRight...),
|
|
key.WithHelp(prettifyKeyBinding(s.TableRight[0]), "scroll the table right "),
|
|
),
|
|
DeleteEntry: key.NewBinding(
|
|
key.WithKeys(s.DeleteEntry...),
|
|
key.WithHelp(prettifyKeyBinding(s.DeleteEntry[0]), "delete the highlighted entry "),
|
|
),
|
|
Help: key.NewBinding(
|
|
key.WithKeys(s.Help...),
|
|
key.WithHelp(prettifyKeyBinding(s.Help[0]), "help "),
|
|
),
|
|
Quit: key.NewBinding(
|
|
key.WithKeys(s.Quit...),
|
|
key.WithHelp(prettifyKeyBinding(s.Quit[0]), "exit hiSHtory "),
|
|
),
|
|
JumpStartOfInput: key.NewBinding(
|
|
key.WithKeys(s.JumpStartOfInput...),
|
|
key.WithHelp(prettifyKeyBinding(s.JumpStartOfInput[0]), "jump to the start of the input "),
|
|
),
|
|
JumpEndOfInput: key.NewBinding(
|
|
key.WithKeys(s.JumpEndOfInput...),
|
|
key.WithHelp(prettifyKeyBinding(s.JumpEndOfInput[0]), "jump to the end of the input "),
|
|
),
|
|
WordLeft: key.NewBinding(
|
|
key.WithKeys(s.WordLeft...),
|
|
key.WithHelp(prettifyKeyBinding(s.WordLeft[0]), "jump left one word "),
|
|
),
|
|
WordRight: key.NewBinding(
|
|
key.WithKeys(s.WordRight...),
|
|
key.WithHelp(prettifyKeyBinding(s.WordRight[0]), "jump right one word "),
|
|
),
|
|
}
|
|
}
|
|
|
|
func (s SerializableKeyMap) WithDefaults() SerializableKeyMap {
|
|
if len(s.Up) == 0 {
|
|
s.Up = DefaultKeyMap.Up.Keys()
|
|
}
|
|
if len(s.Down) == 0 {
|
|
s.Down = DefaultKeyMap.Down.Keys()
|
|
}
|
|
if len(s.PageUp) == 0 {
|
|
s.PageUp = DefaultKeyMap.PageUp.Keys()
|
|
}
|
|
if len(s.PageDown) == 0 {
|
|
s.PageDown = DefaultKeyMap.PageDown.Keys()
|
|
}
|
|
if len(s.SelectEntry) == 0 {
|
|
s.SelectEntry = DefaultKeyMap.SelectEntry.Keys()
|
|
}
|
|
if len(s.SelectEntryAndChangeDir) == 0 {
|
|
s.SelectEntryAndChangeDir = DefaultKeyMap.SelectEntryAndChangeDir.Keys()
|
|
}
|
|
if len(s.Left) == 0 {
|
|
s.Left = DefaultKeyMap.Left.Keys()
|
|
}
|
|
if len(s.Right) == 0 {
|
|
s.Right = DefaultKeyMap.Right.Keys()
|
|
}
|
|
if len(s.TableLeft) == 0 {
|
|
s.TableLeft = DefaultKeyMap.TableLeft.Keys()
|
|
}
|
|
if len(s.TableRight) == 0 {
|
|
s.TableRight = DefaultKeyMap.TableRight.Keys()
|
|
}
|
|
if len(s.DeleteEntry) == 0 {
|
|
s.DeleteEntry = DefaultKeyMap.DeleteEntry.Keys()
|
|
}
|
|
if len(s.Help) == 0 {
|
|
s.Help = DefaultKeyMap.Help.Keys()
|
|
}
|
|
if len(s.Quit) == 0 {
|
|
s.Quit = DefaultKeyMap.Quit.Keys()
|
|
}
|
|
if len(s.JumpStartOfInput) == 0 {
|
|
s.JumpStartOfInput = DefaultKeyMap.JumpStartOfInput.Keys()
|
|
}
|
|
if len(s.JumpEndOfInput) == 0 {
|
|
s.JumpEndOfInput = DefaultKeyMap.JumpEndOfInput.Keys()
|
|
}
|
|
if len(s.WordLeft) == 0 {
|
|
s.WordLeft = DefaultKeyMap.WordLeft.Keys()
|
|
}
|
|
if len(s.WordRight) == 0 {
|
|
s.WordRight = DefaultKeyMap.WordRight.Keys()
|
|
}
|
|
return s
|
|
}
|
|
|
|
type KeyMap struct {
|
|
Up key.Binding
|
|
Down key.Binding
|
|
PageUp key.Binding
|
|
PageDown key.Binding
|
|
SelectEntry key.Binding
|
|
SelectEntryAndChangeDir key.Binding
|
|
Left key.Binding
|
|
Right key.Binding
|
|
TableLeft key.Binding
|
|
TableRight key.Binding
|
|
DeleteEntry key.Binding
|
|
Help key.Binding
|
|
Quit key.Binding
|
|
JumpStartOfInput key.Binding
|
|
JumpEndOfInput key.Binding
|
|
WordLeft key.Binding
|
|
WordRight key.Binding
|
|
}
|
|
|
|
func (k KeyMap) ToSerializable() SerializableKeyMap {
|
|
return SerializableKeyMap{
|
|
Up: k.Up.Keys(),
|
|
Down: k.Down.Keys(),
|
|
PageUp: k.PageUp.Keys(),
|
|
PageDown: k.PageDown.Keys(),
|
|
SelectEntry: k.SelectEntry.Keys(),
|
|
SelectEntryAndChangeDir: k.SelectEntryAndChangeDir.Keys(),
|
|
Left: k.Left.Keys(),
|
|
Right: k.Right.Keys(),
|
|
TableLeft: k.TableLeft.Keys(),
|
|
TableRight: k.TableRight.Keys(),
|
|
DeleteEntry: k.DeleteEntry.Keys(),
|
|
Help: k.Help.Keys(),
|
|
Quit: k.Quit.Keys(),
|
|
JumpStartOfInput: k.JumpStartOfInput.Keys(),
|
|
JumpEndOfInput: k.JumpEndOfInput.Keys(),
|
|
WordLeft: k.WordLeft.Keys(),
|
|
WordRight: k.WordRight.Keys(),
|
|
}
|
|
}
|
|
|
|
var fakeTitleKeyBinding key.Binding = key.NewBinding(
|
|
key.WithKeys(""),
|
|
key.WithHelp("hiSHtory: Search your shell history", ""),
|
|
)
|
|
|
|
var fakeEmptyKeyBinding key.Binding = key.NewBinding(
|
|
key.WithKeys(""),
|
|
key.WithHelp("", ""),
|
|
)
|
|
|
|
func (k KeyMap) ShortHelp() []key.Binding {
|
|
return []key.Binding{fakeTitleKeyBinding, k.Help}
|
|
}
|
|
|
|
func (k KeyMap) FullHelp() [][]key.Binding {
|
|
return [][]key.Binding{
|
|
{fakeTitleKeyBinding, k.Up, k.Left, k.SelectEntry, k.SelectEntryAndChangeDir},
|
|
{fakeEmptyKeyBinding, k.Down, k.Right, k.DeleteEntry},
|
|
{fakeEmptyKeyBinding, k.PageUp, k.TableLeft, k.Quit},
|
|
{fakeEmptyKeyBinding, k.PageDown, k.TableRight, k.Help},
|
|
}
|
|
}
|
|
|
|
type Binding struct {
|
|
Keys []string `json:"keys"`
|
|
Help key.Help `json:"help"`
|
|
}
|
|
|
|
var DefaultKeyMap = KeyMap{
|
|
Up: key.NewBinding(
|
|
key.WithKeys("up", "alt+OA", "ctrl+p"),
|
|
key.WithHelp("↑ ", "scroll up "),
|
|
),
|
|
Down: key.NewBinding(
|
|
key.WithKeys("down", "alt+OB", "ctrl+n"),
|
|
key.WithHelp("↓ ", "scroll down "),
|
|
),
|
|
PageUp: key.NewBinding(
|
|
key.WithKeys("pgup"),
|
|
key.WithHelp("pgup", "page up "),
|
|
),
|
|
PageDown: key.NewBinding(
|
|
key.WithKeys("pgdown"),
|
|
key.WithHelp("pgdn", "page down "),
|
|
),
|
|
SelectEntry: key.NewBinding(
|
|
key.WithKeys("enter"),
|
|
key.WithHelp("enter", "select an entry "),
|
|
),
|
|
SelectEntryAndChangeDir: key.NewBinding(
|
|
key.WithKeys("ctrl+x"),
|
|
key.WithHelp("ctrl+x", "select an entry and cd into that directory"),
|
|
),
|
|
Left: key.NewBinding(
|
|
key.WithKeys("left"),
|
|
key.WithHelp("← ", "move left "),
|
|
),
|
|
Right: key.NewBinding(
|
|
key.WithKeys("right"),
|
|
key.WithHelp("→ ", "move right "),
|
|
),
|
|
TableLeft: key.NewBinding(
|
|
key.WithKeys("shift+left"),
|
|
key.WithHelp("shift+← ", "scroll the table left "),
|
|
),
|
|
TableRight: key.NewBinding(
|
|
key.WithKeys("shift+right"),
|
|
key.WithHelp("shift+→ ", "scroll the table right "),
|
|
),
|
|
DeleteEntry: key.NewBinding(
|
|
key.WithKeys("ctrl+k"),
|
|
key.WithHelp("ctrl+k", "delete the highlighted entry "),
|
|
),
|
|
Help: key.NewBinding(
|
|
key.WithKeys("ctrl+h"),
|
|
key.WithHelp("ctrl+h", "help "),
|
|
),
|
|
Quit: key.NewBinding(
|
|
key.WithKeys("esc", "ctrl+c", "ctrl+d"),
|
|
key.WithHelp("esc", "exit hiSHtory "),
|
|
),
|
|
JumpStartOfInput: key.NewBinding(
|
|
key.WithKeys("ctrl+a"),
|
|
key.WithHelp("ctrl+a", "jump to the start of the input "),
|
|
),
|
|
JumpEndOfInput: key.NewBinding(
|
|
key.WithKeys("ctrl+e"),
|
|
key.WithHelp("ctrl+e", "jump to the end of the input "),
|
|
),
|
|
WordLeft: key.NewBinding(
|
|
key.WithKeys("ctrl+left"),
|
|
key.WithHelp("ctrl+left", "jump left one word "),
|
|
),
|
|
WordRight: key.NewBinding(
|
|
key.WithKeys("ctrl+right"),
|
|
key.WithHelp("ctrl+right", "jump right one word "),
|
|
),
|
|
}
|