mirror of https://github.com/containers/podman.git
Merge pull request #14216 from Luap99/format-completion
shell completion --format: work with pointer functions
This commit is contained in:
commit
45e9f1ff09
|
@ -992,13 +992,6 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t
|
||||||
fields := strings.Split(field[len(field)-1], ".")
|
fields := strings.Split(field[len(field)-1], ".")
|
||||||
f := reflect.ValueOf(o)
|
f := reflect.ValueOf(o)
|
||||||
for i := 1; i < len(fields); i++ {
|
for i := 1; i < len(fields); i++ {
|
||||||
val := getActualStructType(f)
|
|
||||||
if val == nil {
|
|
||||||
// no struct return nothing to complete
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
f = *val
|
|
||||||
|
|
||||||
// last field get all names to suggest
|
// last field get all names to suggest
|
||||||
if i == len(fields)-1 {
|
if i == len(fields)-1 {
|
||||||
suggestions := getStructFields(f, fields[i])
|
suggestions := getStructFields(f, fields[i])
|
||||||
|
@ -1008,6 +1001,14 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t
|
||||||
toComplete = strings.Join(toCompArr, ".")
|
toComplete = strings.Join(toCompArr, ".")
|
||||||
return prefixSlice(toComplete, suggestions), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
|
return prefixSlice(toComplete, suggestions), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val := getActualStructType(f)
|
||||||
|
if val == nil {
|
||||||
|
// no struct return nothing to complete
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
f = *val
|
||||||
|
|
||||||
// set the next struct field
|
// set the next struct field
|
||||||
f = f.FieldByName(fields[i])
|
f = f.FieldByName(fields[i])
|
||||||
}
|
}
|
||||||
|
@ -1038,12 +1039,15 @@ func getActualStructType(f reflect.Value) *reflect.Value {
|
||||||
|
|
||||||
// getStructFields reads all struct field names and method names and returns them.
|
// getStructFields reads all struct field names and method names and returns them.
|
||||||
func getStructFields(f reflect.Value, prefix string) []string {
|
func getStructFields(f reflect.Value, prefix string) []string {
|
||||||
suggestions := []string{}
|
var suggestions []string
|
||||||
|
if f.IsValid() {
|
||||||
|
suggestions = append(suggestions, getMethodNames(f, prefix)...)
|
||||||
|
}
|
||||||
|
|
||||||
val := getActualStructType(f)
|
val := getActualStructType(f)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
// no struct return nothing to complete
|
// no struct return nothing to complete
|
||||||
return nil
|
return suggestions
|
||||||
}
|
}
|
||||||
f = *val
|
f = *val
|
||||||
|
|
||||||
|
@ -1069,7 +1073,11 @@ func getStructFields(f reflect.Value, prefix string) []string {
|
||||||
suggestions = append(suggestions, fname+suffix)
|
suggestions = append(suggestions, fname+suffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return suggestions
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMethodNames(f reflect.Value, prefix string) []string {
|
||||||
|
suggestions := make([]string, 0, f.NumMethod())
|
||||||
for j := 0; j < f.NumMethod(); j++ {
|
for j := 0; j < f.NumMethod(); j++ {
|
||||||
fname := f.Type().Method(j).Name
|
fname := f.Type().Method(j).Name
|
||||||
if strings.HasPrefix(fname, prefix) {
|
if strings.HasPrefix(fname, prefix) {
|
||||||
|
@ -1077,7 +1085,6 @@ func getStructFields(f reflect.Value, prefix string) []string {
|
||||||
suggestions = append(suggestions, fname+"}}")
|
suggestions = append(suggestions, fname+"}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return suggestions
|
return suggestions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ func (c Car) Type() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Car) Color() string {
|
// Note: It is important that this function is *Car and the Type one is just Car.
|
||||||
|
// The reflect logic behaves differently for these cases so we have to test both.
|
||||||
|
func (c *Car) Color() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +96,7 @@ func TestAutocompleteFormat(t *testing.T) {
|
||||||
{
|
{
|
||||||
"second level struct field name",
|
"second level struct field name",
|
||||||
"{{ .Car.",
|
"{{ .Car.",
|
||||||
[]string{"{{ .Car.Brand}}", "{{ .Car.Stats.", "{{ .Car.Extras}}", "{{ .Car.Color}}", "{{ .Car.Type}}"},
|
[]string{"{{ .Car.Color}}", "{{ .Car.Type}}", "{{ .Car.Brand}}", "{{ .Car.Stats.", "{{ .Car.Extras}}"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"second level struct field name",
|
"second level struct field name",
|
||||||
|
@ -104,7 +106,7 @@ func TestAutocompleteFormat(t *testing.T) {
|
||||||
{
|
{
|
||||||
"second level nil struct field name",
|
"second level nil struct field name",
|
||||||
"{{ .Car2.",
|
"{{ .Car2.",
|
||||||
[]string{"{{ .Car2.Brand}}", "{{ .Car2.Stats.", "{{ .Car2.Extras}}", "{{ .Car2.Color}}", "{{ .Car2.Type}}"},
|
[]string{"{{ .Car2.Color}}", "{{ .Car2.Type}}", "{{ .Car2.Brand}}", "{{ .Car2.Stats.", "{{ .Car2.Extras}}"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"three level struct field name",
|
"three level struct field name",
|
||||||
|
@ -134,8 +136,8 @@ func TestAutocompleteFormat(t *testing.T) {
|
||||||
{
|
{
|
||||||
"two variables struct field name",
|
"two variables struct field name",
|
||||||
"{{ .Car.Brand }} {{ .Car.",
|
"{{ .Car.Brand }} {{ .Car.",
|
||||||
[]string{"{{ .Car.Brand }} {{ .Car.Brand}}", "{{ .Car.Brand }} {{ .Car.Stats.", "{{ .Car.Brand }} {{ .Car.Extras}}",
|
[]string{"{{ .Car.Brand }} {{ .Car.Color}}", "{{ .Car.Brand }} {{ .Car.Type}}", "{{ .Car.Brand }} {{ .Car.Brand}}",
|
||||||
"{{ .Car.Brand }} {{ .Car.Color}}", "{{ .Car.Brand }} {{ .Car.Type}}"},
|
"{{ .Car.Brand }} {{ .Car.Stats.", "{{ .Car.Brand }} {{ .Car.Extras}}"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"only dot without variable",
|
"only dot without variable",
|
||||||
|
|
Loading…
Reference in New Issue