mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-12 12:55:47 +02:00
Validate keybindings
This commit is contained in:
parent
130801dbf6
commit
f3791e6ab6
3 changed files with 75 additions and 0 deletions
|
@ -1,6 +1,9 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
@ -74,3 +77,17 @@ var LabelByKey = map[gocui.Key]string{
|
||||||
}
|
}
|
||||||
|
|
||||||
var KeyByLabel = lo.Invert(LabelByKey)
|
var KeyByLabel = lo.Invert(LabelByKey)
|
||||||
|
|
||||||
|
func isValidKeybindingKey(key string) bool {
|
||||||
|
runeCount := utf8.RuneCountInString(key)
|
||||||
|
if key == "<disabled>" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if runeCount > 1 {
|
||||||
|
_, ok := KeyByLabel[strings.ToLower(key)]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,12 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (config *UserConfig) Validate() error {
|
func (config *UserConfig) Validate() error {
|
||||||
|
@ -15,6 +19,9 @@ func (config *UserConfig) Validate() error {
|
||||||
[]string{"none", "onlyArrow", "arrowAndNumber"}); err != nil {
|
[]string{"none", "onlyArrow", "arrowAndNumber"}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := validateKeybindings(config.Keybinding); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,3 +32,41 @@ func validateEnum(name string, value string, allowedValues []string) error {
|
||||||
allowedValuesStr := strings.Join(allowedValues, ", ")
|
allowedValuesStr := strings.Join(allowedValues, ", ")
|
||||||
return fmt.Errorf("Unexpected value '%s' for '%s'. Allowed values: %s", value, name, allowedValuesStr)
|
return fmt.Errorf("Unexpected value '%s' for '%s'. Allowed values: %s", value, name, allowedValuesStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateKeybindingsRecurse(path string, node any) error {
|
||||||
|
value := reflect.ValueOf(node)
|
||||||
|
if value.Kind() == reflect.Struct {
|
||||||
|
for _, field := range reflect.VisibleFields(reflect.TypeOf(node)) {
|
||||||
|
var newPath string
|
||||||
|
if len(path) == 0 {
|
||||||
|
newPath = field.Name
|
||||||
|
} else {
|
||||||
|
newPath = fmt.Sprintf("%s.%s", path, field.Name)
|
||||||
|
}
|
||||||
|
if err := validateKeybindingsRecurse(newPath,
|
||||||
|
value.FieldByName(field.Name).Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if value.Kind() == reflect.Slice {
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
if err := validateKeybindingsRecurse(
|
||||||
|
fmt.Sprintf("%s[%d]", path, i), value.Index(i).Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if value.Kind() == reflect.String {
|
||||||
|
key := node.(string)
|
||||||
|
if !isValidKeybindingKey(key) {
|
||||||
|
return fmt.Errorf("Unrecognized key '%s' for keybinding '%s'. For permitted values see %s",
|
||||||
|
key, path, constants.Links.Docs.CustomKeybindings)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Unexpected type for property '%s': %s", path, value.Kind())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateKeybindings(keybindingConfig KeybindingConfig) error {
|
||||||
|
return validateKeybindingsRecurse("", keybindingConfig)
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,19 @@ func TestUserConfigValidate_enums(t *testing.T) {
|
||||||
{value: "invalid_value", valid: false},
|
{value: "invalid_value", valid: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Keybindings",
|
||||||
|
setup: func(config *UserConfig, value string) {
|
||||||
|
config.Keybinding.Universal.Quit = value
|
||||||
|
},
|
||||||
|
testCases: []testCase{
|
||||||
|
{value: "", valid: true},
|
||||||
|
{value: "<disabled>", valid: true},
|
||||||
|
{value: "q", valid: true},
|
||||||
|
{value: "<c-c>", valid: true},
|
||||||
|
{value: "invalid_value", valid: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue