summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2022-05-12 15:32:58 +0200
committerGitHub <noreply@github.com>2022-05-12 15:32:58 +0200
commit45e9f1ff097adca65a5bb2a7367883508900667d (patch)
tree2a1c5ec19c87ac1c1a00b63ab4628bebe2ef4753 /cmd
parente9a114f5a59e4216ee08edadd5e6d8f30cbdbb78 (diff)
parent9df3906553fb78c32cd231e5de5de0074a181241 (diff)
downloadpodman-45e9f1ff097adca65a5bb2a7367883508900667d.tar.gz
podman-45e9f1ff097adca65a5bb2a7367883508900667d.tar.bz2
podman-45e9f1ff097adca65a5bb2a7367883508900667d.zip
Merge pull request #14216 from Luap99/format-completion
shell completion --format: work with pointer functions
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/common/completion.go27
-rw-r--r--cmd/podman/common/completion_test.go12
2 files changed, 24 insertions, 15 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 6149a4465..e07e28dab 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -992,13 +992,6 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t
fields := strings.Split(field[len(field)-1], ".")
f := reflect.ValueOf(o)
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
if i == len(fields)-1 {
suggestions := getStructFields(f, fields[i])
@@ -1008,6 +1001,14 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t
toComplete = strings.Join(toCompArr, ".")
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
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.
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)
if val == nil {
// no struct return nothing to complete
- return nil
+ return suggestions
}
f = *val
@@ -1069,7 +1073,11 @@ func getStructFields(f reflect.Value, prefix string) []string {
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++ {
fname := f.Type().Method(j).Name
if strings.HasPrefix(fname, prefix) {
@@ -1077,7 +1085,6 @@ func getStructFields(f reflect.Value, prefix string) []string {
suggestions = append(suggestions, fname+"}}")
}
}
-
return suggestions
}
diff --git a/cmd/podman/common/completion_test.go b/cmd/podman/common/completion_test.go
index ae117a173..13f45a662 100644
--- a/cmd/podman/common/completion_test.go
+++ b/cmd/podman/common/completion_test.go
@@ -25,7 +25,9 @@ func (c Car) Type() string {
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 ""
}
@@ -94,7 +96,7 @@ func TestAutocompleteFormat(t *testing.T) {
{
"second level struct field name",
"{{ .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",
@@ -104,7 +106,7 @@ func TestAutocompleteFormat(t *testing.T) {
{
"second level nil struct field name",
"{{ .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",
@@ -134,8 +136,8 @@ func TestAutocompleteFormat(t *testing.T) {
{
"two variables struct field name",
"{{ .Car.Brand }} {{ .Car.",
- []string{"{{ .Car.Brand }} {{ .Car.Brand}}", "{{ .Car.Brand }} {{ .Car.Stats.", "{{ .Car.Brand }} {{ .Car.Extras}}",
- "{{ .Car.Brand }} {{ .Car.Color}}", "{{ .Car.Brand }} {{ .Car.Type}}"},
+ []string{"{{ .Car.Brand }} {{ .Car.Color}}", "{{ .Car.Brand }} {{ .Car.Type}}", "{{ .Car.Brand }} {{ .Car.Brand}}",
+ "{{ .Car.Brand }} {{ .Car.Stats.", "{{ .Car.Brand }} {{ .Car.Extras}}"},
},
{
"only dot without variable",