refactor(config): make config.toml the sole source of keybind keys
defaultKeybinds() now supplies only help descriptions; the actual keys are read from the embedded config.toml at load time, eliminating the duplicate key definitions that could drift out of sync. Add a test that walks every keybind after loading the defaults and fails if any is missing a key (config.toml) or description (defaultKeybinds).
This commit is contained in:
parent
d3b5c21263
commit
b9152f8b21
2 changed files with 92 additions and 64 deletions
|
|
@ -3,6 +3,7 @@ package config
|
|||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
|
@ -66,6 +67,38 @@ func TestLoad(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
// Keys live in config.toml, descriptions in defaultKeybinds(); fail if either is missing.
|
||||
t.Run("default keybinds are fully populated", func(t *testing.T) {
|
||||
cfg, err := Load(filepath.Join(t.TempDir(), "missing.toml"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var walk func(path string, v reflect.Value)
|
||||
walk = func(path string, v reflect.Value) {
|
||||
rt := v.Type()
|
||||
for i := range rt.NumField() {
|
||||
fv, name := v.Field(i), path+rt.Field(i).Name
|
||||
if kb, ok := fv.Interface().(Keybind); ok {
|
||||
if len(kb.Keys()) == 0 {
|
||||
t.Errorf("%s: no keys (missing from config.toml?)", name)
|
||||
}
|
||||
if kb.Help().Desc == "" {
|
||||
t.Errorf("%s: no help description (missing from defaultKeybinds?)", name)
|
||||
}
|
||||
if kb.Help().Key == "" {
|
||||
t.Errorf("%s: help key not populated from config.toml", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if fv.Kind() == reflect.Struct {
|
||||
walk(name+".", fv)
|
||||
}
|
||||
}
|
||||
}
|
||||
walk("Keybinds.", reflect.ValueOf(cfg.Keybinds))
|
||||
})
|
||||
|
||||
t.Run("open with bad path returns error (!= ErrNotExist)", func(t *testing.T) {
|
||||
if _, err := Load("bad\x00path"); err == nil {
|
||||
t.Fatal("expected error")
|
||||
|
|
|
|||
|
|
@ -31,12 +31,10 @@ func (k *Keybind) UnmarshalTOML(value any) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newKeybind(key, desc string) Keybind {
|
||||
// desc builds a Keybind with only a help description; keys come from config.toml.
|
||||
func desc(s string) Keybind {
|
||||
return Keybind{
|
||||
Keybind: keybind.NewKeybind(
|
||||
keybind.WithKeys(key),
|
||||
keybind.WithHelp(key, desc),
|
||||
),
|
||||
Keybind: keybind.NewKeybind(keybind.WithHelp("", s)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,107 +135,104 @@ type Keybinds struct {
|
|||
func defaultPickerKeybinds() PickerKeybinds {
|
||||
return PickerKeybinds{
|
||||
NavigationKeybinds: NavigationKeybinds{
|
||||
Up: newKeybind("ctrl+p", "up"),
|
||||
Down: newKeybind("ctrl+n", "down"),
|
||||
Top: newKeybind("home", "top"),
|
||||
Bottom: newKeybind("end", "bottom"),
|
||||
Up: desc("up"),
|
||||
Down: desc("down"),
|
||||
Top: desc("top"),
|
||||
Bottom: desc("btm"),
|
||||
},
|
||||
Cancel: newKeybind("esc", "cancel"),
|
||||
Select: newKeybind("enter", "sel"),
|
||||
Cancel: desc("cancel"),
|
||||
Select: desc("sel"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultNavigationKeybinds() NavigationKeybinds {
|
||||
return NavigationKeybinds{
|
||||
Up: newKeybind("k", "up"),
|
||||
Down: newKeybind("j", "down"),
|
||||
Top: newKeybind("g", "top"),
|
||||
Bottom: newKeybind("G", "bottom"),
|
||||
Up: desc("up"),
|
||||
Down: desc("down"),
|
||||
Top: desc("top"),
|
||||
Bottom: desc("btm"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultGuildsTreeKeybinds() GuildsTreeKeybinds {
|
||||
return GuildsTreeKeybinds{
|
||||
NavigationKeybinds: defaultNavigationKeybinds(),
|
||||
SelectCurrent: newKeybind("enter", "select"),
|
||||
YankID: newKeybind("i", "copy id"),
|
||||
SelectCurrent: desc("select"),
|
||||
YankID: desc("copy id"),
|
||||
|
||||
CollapseAll: newKeybind("_", "collapse all"),
|
||||
CollapseParentNode: newKeybind("-", "collapse parent"),
|
||||
MoveToParentNode: newKeybind("p", "parent"),
|
||||
CollapseAll: desc("collapse all"),
|
||||
CollapseParentNode: desc("collapse parent"),
|
||||
MoveToParentNode: desc("parent"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultMessagesListKeybinds() MessagesListKeybinds {
|
||||
return MessagesListKeybinds{
|
||||
SelectionKeybinds: SelectionKeybinds{
|
||||
SelectUp: newKeybind("k", "up"),
|
||||
SelectDown: newKeybind("j", "down"),
|
||||
SelectTop: newKeybind("g", "top"),
|
||||
SelectBottom: newKeybind("G", "bottom"),
|
||||
SelectUp: desc("up"),
|
||||
SelectDown: desc("down"),
|
||||
SelectTop: desc("top"),
|
||||
SelectBottom: desc("btm"),
|
||||
},
|
||||
ScrollKeybinds: ScrollKeybinds{
|
||||
ScrollUp: newKeybind("K", "scroll up"),
|
||||
ScrollDown: newKeybind("J", "scroll down"),
|
||||
ScrollTop: newKeybind("home", "scroll top"),
|
||||
ScrollBottom: newKeybind("end", "scroll bottom"),
|
||||
ScrollUp: desc("scr up"),
|
||||
ScrollDown: desc("scr down"),
|
||||
ScrollTop: desc("scr top"),
|
||||
ScrollBottom: desc("scr btm"),
|
||||
},
|
||||
SelectReply: newKeybind("s", "sel reply"),
|
||||
Reply: newKeybind("R", "reply"),
|
||||
ReplyMention: newKeybind("r", "@reply"),
|
||||
Cancel: newKeybind("esc", "cancel"),
|
||||
Edit: newKeybind("e", "edit"),
|
||||
Delete: newKeybind("D", "force delete"),
|
||||
DeleteConfirm: newKeybind(
|
||||
"d",
|
||||
"delete",
|
||||
),
|
||||
Open: newKeybind("o", "open"),
|
||||
YankContent: newKeybind("y", "copy text"),
|
||||
YankURL: newKeybind("u", "copy url"),
|
||||
YankID: newKeybind("i", "copy id"),
|
||||
SelectReply: desc("sel reply"),
|
||||
Reply: desc("reply"),
|
||||
ReplyMention: desc("@reply"),
|
||||
Cancel: desc("cancel"),
|
||||
Edit: desc("edit"),
|
||||
Delete: desc("force delete"),
|
||||
DeleteConfirm: desc("delete"),
|
||||
Open: desc("open"),
|
||||
YankContent: desc("copy text"),
|
||||
YankURL: desc("copy url"),
|
||||
YankID: desc("copy id"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultMessageInputKeybinds() MessageInputKeybinds {
|
||||
return MessageInputKeybinds{
|
||||
Paste: newKeybind("ctrl+v", "paste"),
|
||||
Send: newKeybind("enter", "send"),
|
||||
Cancel: newKeybind("esc", "cancel"),
|
||||
TabComplete: newKeybind("tab", "complete"),
|
||||
Undo: newKeybind("ctrl+u", "undo"),
|
||||
OpenEditor: newKeybind("ctrl+e", "editor"),
|
||||
OpenFilePicker: newKeybind("ctrl+\\", "attach"),
|
||||
Paste: desc("paste"),
|
||||
Send: desc("send"),
|
||||
Cancel: desc("cancel"),
|
||||
TabComplete: desc("complete"),
|
||||
Undo: desc("undo"),
|
||||
OpenEditor: desc("editor"),
|
||||
OpenFilePicker: desc("attach"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultMentionsListKeybinds() MentionsListKeybinds {
|
||||
return MentionsListKeybinds{
|
||||
NavigationKeybinds: NavigationKeybinds{
|
||||
Up: newKeybind("ctrl+p", "up"),
|
||||
Down: newKeybind("ctrl+n", "down"),
|
||||
Top: newKeybind("home", "top"),
|
||||
Bottom: newKeybind("end", "bottom"),
|
||||
Up: desc("up"),
|
||||
Down: desc("down"),
|
||||
Top: desc("top"),
|
||||
Bottom: desc("btm"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func defaultKeybinds() Keybinds {
|
||||
return Keybinds{
|
||||
ToggleGuildsTree: newKeybind("ctrl+b", "toggle guilds"),
|
||||
ToggleChannelsPicker: newKeybind("ctrl+k", "channels picker"),
|
||||
ToggleHelp: newKeybind("ctrl+.", "help"),
|
||||
Suspend: newKeybind("ctrl+z", "suspend"),
|
||||
ToggleGuildsTree: desc("toggle guilds"),
|
||||
ToggleChannelsPicker: desc("channels picker"),
|
||||
ToggleHelp: desc("help"),
|
||||
Suspend: desc("suspend"),
|
||||
|
||||
FocusGuildsTree: newKeybind("ctrl+g", "guilds"),
|
||||
FocusMessagesList: newKeybind("ctrl+t", "messages"),
|
||||
FocusMessageInput: newKeybind("ctrl+i", "input"),
|
||||
FocusGuildsTree: desc("guilds"),
|
||||
FocusMessagesList: desc("messages"),
|
||||
FocusMessageInput: desc("input"),
|
||||
|
||||
FocusPrevious: newKeybind("ctrl+h", "focus prev"),
|
||||
FocusNext: newKeybind("ctrl+l", "focus next"),
|
||||
FocusPrevious: desc("focus prev"),
|
||||
FocusNext: desc("focus next"),
|
||||
|
||||
Logout: newKeybind("ctrl+d", "logout"),
|
||||
Quit: newKeybind("ctrl+c", "quit"),
|
||||
Logout: desc("logout"),
|
||||
Quit: desc("quit"),
|
||||
|
||||
Picker: defaultPickerKeybinds(),
|
||||
GuildsTree: defaultGuildsTreeKeybinds(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue