feat(config): add config get subcommand with suggestions
This commit is contained in:
parent
cc19ee5c0f
commit
6bba227654
3 changed files with 66 additions and 1 deletions
|
|
@ -2,6 +2,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
@ -27,6 +28,27 @@ var configListCmd = &cobra.Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var configGetCmd = &cobra.Command{
|
||||||
|
Use: "get <key>",
|
||||||
|
Short: "Print a configuration value",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
SilenceUsage: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
defaults := defaultConfig()
|
||||||
|
fields := configFields(&config, &defaults)
|
||||||
|
f := findConfigField(fields, args[0])
|
||||||
|
if f == nil {
|
||||||
|
err := fmt.Errorf("unknown config key '%s'", args[0])
|
||||||
|
if suggestions := suggestConfigKey(fields, args[0]); len(suggestions) > 0 {
|
||||||
|
return withHint(err, fmt.Sprintf("did you mean '%s'?", strings.Join(suggestions, "', '")))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("%v\n", f.Value)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var configPathCmd = &cobra.Command{
|
var configPathCmd = &cobra.Command{
|
||||||
Use: "path",
|
Use: "path",
|
||||||
Short: "Print config file path",
|
Short: "Print config file path",
|
||||||
|
|
@ -43,6 +65,7 @@ var configPathCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
configCmd.AddCommand(configGetCmd)
|
||||||
configCmd.AddCommand(configListCmd)
|
configCmd.AddCommand(configListCmd)
|
||||||
configCmd.AddCommand(configPathCmd)
|
configCmd.AddCommand(configPathCmd)
|
||||||
rootCmd.AddCommand(configCmd)
|
rootCmd.AddCommand(configCmd)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import "reflect"
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/agnivade/levenshtein"
|
||||||
|
)
|
||||||
|
|
||||||
// ConfigField represents a single leaf field in the Config struct,
|
// ConfigField represents a single leaf field in the Config struct,
|
||||||
// mapped to its dotted TOML key path.
|
// mapped to its dotted TOML key path.
|
||||||
|
|
@ -53,3 +57,28 @@ func walk(cv, dv reflect.Value, prefix string, out *[]ConfigField) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findConfigField returns the ConfigField matching the given dotted key,
|
||||||
|
// or nil if not found.
|
||||||
|
func findConfigField(fields []ConfigField, key string) *ConfigField {
|
||||||
|
for i := range fields {
|
||||||
|
if fields[i].Key == key {
|
||||||
|
return &fields[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// suggestConfigKey returns Levenshtein-based suggestions for a mistyped config key.
|
||||||
|
func suggestConfigKey(fields []ConfigField, target string) []string {
|
||||||
|
minThreshold := 1
|
||||||
|
maxThreshold := 4
|
||||||
|
threshold := min(max(len(target)/3, minThreshold), maxThreshold)
|
||||||
|
var suggestions []string
|
||||||
|
for _, f := range fields {
|
||||||
|
if levenshtein.ComputeDistance(target, f.Key) <= threshold {
|
||||||
|
suggestions = append(suggestions, f.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return suggestions
|
||||||
|
}
|
||||||
|
|
|
||||||
13
testdata/config-get.ct
vendored
Normal file
13
testdata/config-get.ct
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
$ pda config get display_ascii_art
|
||||||
|
true
|
||||||
|
|
||||||
|
$ pda config get store.default_store_name
|
||||||
|
default
|
||||||
|
|
||||||
|
$ pda config get git.auto_commit
|
||||||
|
false
|
||||||
|
|
||||||
|
# Unknown key with suggestion
|
||||||
|
$ pda config get git.auto_comit --> FAIL
|
||||||
|
FAIL unknown config key 'git.auto_comit'
|
||||||
|
hint did you mean 'git.auto_commit'?
|
||||||
Loading…
Add table
Add a link
Reference in a new issue