From b41bcfb9590264fe1e9252b589466e38b5087b78 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Wed, 16 Dec 2020 13:38:27 +0100 Subject: [PATCH] Add new completions based on new upstream completion system Adapted the completion we had previously to the new completion system from cobra 1.0. I started to use the client-go directly but since there is no caching, the is unusably slow. So using the kuebctl binrary directly instead (I can't use tkn since caching is not there as well) to get the completions. This is how we were doing it previously (using kubectl or tkn) and completions should be much faster. We are winning support for other shells (powershell, fish) along the way an d not having an outdated fork in tree. Signed-off-by: Chmouel Boudjnah --- README.md | 2 +- docs/cmd/tkn_completion.md | 34 +++++- docs/man/man1/tkn-completion.1 | 47 +++++++- go.mod | 1 - pkg/cmd/clustertask/delete.go | 3 +- pkg/cmd/clustertask/describe.go | 6 +- pkg/cmd/clustertask/start.go | 10 +- pkg/cmd/clustertriggerbinding/delete.go | 15 +-- pkg/cmd/clustertriggerbinding/describe.go | 10 +- pkg/cmd/completion/completion.go | 129 ++++++---------------- pkg/cmd/condition/delete.go | 15 +-- pkg/cmd/condition/describe.go | 14 +-- pkg/cmd/eventlistener/delete.go | 15 +-- pkg/cmd/eventlistener/describe.go | 6 +- pkg/cmd/eventlistener/logs.go | 5 +- pkg/cmd/pipeline/delete.go | 15 +-- pkg/cmd/pipeline/describe.go | 4 +- pkg/cmd/pipeline/logs.go | 4 +- pkg/cmd/pipeline/start.go | 27 ++++- pkg/cmd/pipelineresource/delete.go | 15 +-- pkg/cmd/pipelineresource/describe.go | 2 +- pkg/cmd/pipelinerun/cancel.go | 12 +- pkg/cmd/pipelinerun/delete.go | 16 +-- pkg/cmd/pipelinerun/describe.go | 3 +- pkg/cmd/pipelinerun/logs.go | 5 +- pkg/cmd/task/delete.go | 14 ++- pkg/cmd/task/describe.go | 10 +- pkg/cmd/task/logs.go | 4 +- pkg/cmd/task/start.go | 19 +++- pkg/cmd/taskrun/cancel.go | 13 ++- pkg/cmd/taskrun/delete.go | 15 +-- pkg/cmd/taskrun/describe.go | 3 +- pkg/cmd/taskrun/logs.go | 3 +- pkg/cmd/triggerbinding/delete.go | 15 +-- pkg/cmd/triggerbinding/describe.go | 6 +- pkg/cmd/triggertemplate/delete.go | 15 +-- pkg/cmd/triggertemplate/describe.go | 6 +- pkg/flags/flags.go | 23 +--- pkg/flags/flags_test.go | 18 --- pkg/formatted/completion.go | 31 ++++++ 40 files changed, 332 insertions(+), 278 deletions(-) create mode 100644 pkg/formatted/completion.go diff --git a/README.md b/README.md index 8f062702a..4d4fc82f4 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ The following commands help you understand and effectively use the Tekton CLI: * `tkn help:` Displays a list of the commands with helpful information. * [`tkn clustertask:`](docs/cmd/tkn_clustertask.md) Parent command of the ClusterTask command group. * [`tkn clustertriggerbinding:`](docs/cmd/tkn_clustertriggerbinding.md) Parent command of the ClusterTriggerBinding command group. - * [`tkn completion:`](docs/cmd/tkn_completion.md) Outputs a BASH or ZSH completion script for `tkn` to allow command completion with Tab. + * [`tkn completion:`](docs/cmd/tkn_completion.md) Outputs a BASH, ZSH, Fish or PowerShell completion script for `tkn` to allow command completion with Tab. * [`tkn condition:`](docs/cmd/tkn_condition.md) Parent command of the Condition command group. * [`tkn eventlistener:`](docs/cmd/tkn_eventlistener.md) Parent command of the Eventlistener command group. * [`tkn hub:`](docs/cmd/tkn_hub.md) Search and install Tekton Resources from [Hub](https://hub-preview.tekton.dev) diff --git a/docs/cmd/tkn_completion.md b/docs/cmd/tkn_completion.md index 13809a499..4a9aed709 100644 --- a/docs/cmd/tkn_completion.md +++ b/docs/cmd/tkn_completion.md @@ -10,7 +10,6 @@ tkn completion [SHELL] ### Synopsis - This command prints shell completion code which must be evaluated to provide interactive completion @@ -21,12 +20,37 @@ Supported Shells: ### Examples +To load completions: + +Bash: + +$ source <(tkn completion bash) + +# To load completions for each session, execute once: +Linux: + $ tkn completion bash > /etc/bash_completion.d/tkn + +MacOS: + $ tkn completion bash > /usr/local/etc/bash_completion.d/tkn + +Zsh: + +# If shell completion is not already enabled in your environment you will need +# to enable it. You can execute the following once: + +$ echo "autoload -U compinit; compinit" >> ~/.zshrc + +# To load completions for each session, execute once: +$ tkn completion zsh > "${fpath[1]}/_tkn" + +# You will need to start a new shell for this setup to take effect. + +Fish: - # generate completion code for bash - source <(tkn completion bash) +$ tkn completion fish | source - # generate completion code for zsh - source <(tkn completion zsh) +# To load completions for each session, execute once: +$ tkn completion fish > ~/.config/fish/completions/tkn.fish ### Options diff --git a/docs/man/man1/tkn-completion.1 b/docs/man/man1/tkn-completion.1 index 86e1d2ad3..d431901fd 100644 --- a/docs/man/man1/tkn-completion.1 +++ b/docs/man/man1/tkn-completion.1 @@ -32,12 +32,51 @@ Supported Shells: .SH EXAMPLE .PP -# generate completion code for bash - source <(tkn completion bash) +To load completions: .PP -# generate completion code for zsh - source <(tkn completion zsh) +Bash: + +.PP +$ source <(tkn completion bash) + + +.SH To load completions for each session, execute once: +.PP +Linux: + $ tkn completion bash > /etc/bash\_completion.d/tkn + +.PP +MacOS: + $ tkn completion bash > /usr/local/etc/bash\_completion.d/tkn + +.PP +Zsh: + + +.SH If shell completion is not already enabled in your environment you will need + +.SH to enable it. You can execute the following once: +.PP +$ echo "autoload \-U compinit; compinit" >> \~/.zshrc + + +.SH To load completions for each session, execute once: +.PP +$ tkn completion zsh > "${fpath[1]}/\_tkn" + + +.SH You will need to start a new shell for this setup to take effect. +.PP +Fish: + +.PP +$ tkn completion fish | source + + +.SH To load completions for each session, execute once: +.PP +$ tkn completion fish > \~/.config/fish/completions/tkn.fish .SH SEE ALSO diff --git a/go.mod b/go.mod index 5096af121..94f10aef1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/Netflix/go-expect v0.0.0-20200312175327-da48e75238e2 github.com/blang/semver v3.5.1+incompatible github.com/cpuguy83/go-md2man v1.0.10 - github.com/davecgh/go-spew v1.1.1 github.com/fatih/color v1.9.0 github.com/ghodss/yaml v1.0.0 github.com/google/go-cmp v0.5.2 diff --git a/pkg/cmd/clustertask/delete.go b/pkg/cmd/clustertask/delete.go index 18f71f9fe..3e5ae5d3a 100644 --- a/pkg/cmd/clustertask/delete.go +++ b/pkg/cmd/clustertask/delete.go @@ -22,6 +22,7 @@ import ( "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/clustertask" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/task" trlist "github.com/tektoncd/cli/pkg/taskrun/list" @@ -52,6 +53,7 @@ or Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ In: cmd.InOrStdin(), @@ -70,7 +72,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAll, "all", "", false, "Delete all ClusterTasks (default: false)") c.Flags().BoolVarP(&opts.DeleteRelated, "trs", "", false, "Whether to delete ClusterTask(s) and related resources (TaskRuns) (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_clustertasks") return c } func deleteClusterTasks(opts *options.DeleteOptions, s *cli.Stream, p cli.Params, ctNames []string) error { diff --git a/pkg/cmd/clustertask/describe.go b/pkg/cmd/clustertask/describe.go index d45f618cc..3672675a5 100644 --- a/pkg/cmd/clustertask/describe.go +++ b/pkg/cmd/clustertask/describe.go @@ -116,7 +116,7 @@ const describeTemplate = `{{decorate "bold" "Name"}}: {{ .ClusterTask.Name }} No steps {{- else }} {{- range $step := .ClusterTask.Spec.Steps }} - {{ autoStepName $step.Name | decorate "bullet" }} + {{ autoStepName $step.Name | decorate "bullet" }} {{- end }} {{- end }} @@ -152,7 +152,8 @@ or Annotations: map[string]string{ "commandType": "main", }, - SilenceUsage: true, + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -190,7 +191,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_clustertasks") f.AddFlags(c) return c } diff --git a/pkg/cmd/clustertask/start.go b/pkg/cmd/clustertask/start.go index dc5695f11..cac53155c 100644 --- a/pkg/cmd/clustertask/start.go +++ b/pkg/cmd/clustertask/start.go @@ -34,6 +34,7 @@ import ( "github.com/tektoncd/cli/pkg/cmd/taskrun" "github.com/tektoncd/cli/pkg/file" "github.com/tektoncd/cli/pkg/flags" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/labels" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/params" @@ -131,8 +132,9 @@ like cat,foo,bar Annotations: map[string]string{ "commandType": "main", }, - Example: eg, - SilenceUsage: true, + Example: eg, + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Args: func(cmd *cobra.Command, args []string) error { if opt.UseParamDefaults && (opt.Last || opt.UseTaskRun != "") { return errors.New("cannot use --last or --use-taskrun options with --use-param-defaults option") @@ -165,10 +167,8 @@ like cat,foo,bar c.Flags().StringSliceVarP(&opt.OutputResources, "outputresource", "o", []string{}, "pass the output resource name and ref as name=ref") c.Flags().StringArrayVarP(&opt.Params, "param", "p", []string{}, "pass the param as key=value for string type, or key=value1,value2,... for array type") c.Flags().StringVarP(&opt.ServiceAccountName, "serviceaccount", "s", "", "pass the serviceaccount name") - flags.AddShellCompletion(c.Flags().Lookup("serviceaccount"), "__kubectl_get_serviceaccount") c.Flags().BoolVarP(&opt.Last, "last", "L", false, "re-run the ClusterTask using last TaskRun values") c.Flags().StringVarP(&opt.UseTaskRun, "use-taskrun", "", "", "specify a TaskRun name to use its values to re-run the TaskRun") - flags.AddShellCompletion(c.Flags().Lookup("use-taskrun"), "__tkn_get_taskrun") c.Flags().StringSliceVarP(&opt.Labels, "labels", "l", []string{}, "pass labels as label=value.") c.Flags().StringArrayVarP(&opt.Workspaces, "workspace", "w", []string{}, "pass one or more workspaces to map to the corresponding physical volumes as name=name,claimName=pvcName or name=name,emptyDir=") c.Flags().BoolVarP(&opt.ShowLog, "showlog", "", false, "show logs right after starting the ClusterTask") @@ -179,8 +179,6 @@ like cat,foo,bar c.Flags().StringVar(&opt.PodTemplate, "pod-template", "", "local or remote file containing a PodTemplate definition") c.Flags().BoolVar(&opt.UseParamDefaults, "use-param-defaults", false, "use default parameter values without prompting for input") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_clustertasks") - return c } diff --git a/pkg/cmd/clustertriggerbinding/delete.go b/pkg/cmd/clustertriggerbinding/delete.go index 5d7f8dfed..54796cf7a 100644 --- a/pkg/cmd/clustertriggerbinding/delete.go +++ b/pkg/cmd/clustertriggerbinding/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete ClusterTriggerBindings", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete ClusterTriggerBindings", + Example: eg, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Annotations: map[string]string{ "commandType": "main", }, @@ -66,7 +68,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAll, "all", "", false, "Delete all ClusterTriggerBindings (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_clustertriggerbinding") return c } diff --git a/pkg/cmd/clustertriggerbinding/describe.go b/pkg/cmd/clustertriggerbinding/describe.go index 4c7a68d71..796bddea9 100644 --- a/pkg/cmd/clustertriggerbinding/describe.go +++ b/pkg/cmd/clustertriggerbinding/describe.go @@ -57,10 +57,11 @@ or ` c := &cobra.Command{ - Use: "describe", - Aliases: []string{"desc"}, - Short: "Describes a ClusterTriggerBinding", - Example: eg, + Use: "describe", + Aliases: []string{"desc"}, + Short: "Describes a ClusterTriggerBinding", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, Annotations: map[string]string{ "commandType": "main", }, @@ -85,7 +86,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_clustertriggerbindings") f.AddFlags(c) return c } diff --git a/pkg/cmd/completion/completion.go b/pkg/cmd/completion/completion.go index 98d79bf4c..0ae6888b8 100644 --- a/pkg/cmd/completion/completion.go +++ b/pkg/cmd/completion/completion.go @@ -15,82 +15,50 @@ package completion import ( - "io" "os" "github.com/spf13/cobra" ) -var ( - // ShellCompletionMap define a map between a flag to a custom shell - // completion which should be in commonCompletion variable - ShellCompletionMap = map[string]string{ - "namespace": "__kubectl_get_namespace", - "kubeconfig": "_filedir", - } -) - const ( - desc = ` -This command prints shell completion code which must be evaluated to provide + desc = `This command prints shell completion code which must be evaluated to provide interactive completion Supported Shells: - bash - zsh ` - eg = ` - # generate completion code for bash - source <(tkn completion bash) + eg = `To load completions: - # generate completion code for zsh - source <(tkn completion zsh) -` +Bash: - commonCompletion = ` -# Custom function for Completions -function __tkn_get_object() { - local type=$1 - local util=$2 - local template begin tkn_out - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - - if [[ ${util} == "kubectl" ]];then - tkn_out=($(kubectl get ${type} -o template --template="${template}" 2>/dev/null)) - elif [[ ${util} == "tkn" ]];then - tkn_out=($(tkn ${type} ls -o template --template="${template}" 2>/dev/null)) - fi - - if [[ -n ${tkn_out} ]]; then - [[ -n ${BASH_VERSION} ]] && COMPREPLY=( $( compgen -W "${tkn_out}" -- "$cur" ) ) - [[ -n ${ZSH_VERSION} ]] && compadd ${tkn_out} - fi -} +$ source <(tkn completion bash) -function __kubectl_get_namespace() { __tkn_get_object namespace kubectl ;} -function __kubectl_get_serviceaccount() { __tkn_get_object serviceaccount kubectl ;} -function __tkn_get_pipeline() { __tkn_get_object pipeline tkn ;} -function __tkn_get_pipelinerun() { __tkn_get_object pipelinerun tkn ;} -function __tkn_get_task() { __tkn_get_object task tkn ;} -function __tkn_get_taskrun() { __tkn_get_object taskrun tkn ;} -function __tkn_get_pipelineresource() { __tkn_get_object resource tkn ;} -function __tkn_get_clustertasks() { __tkn_get_object clustertasks tkn ;} -` - bashCompletion = ` -function __custom_func() { - case ${last_command} in - *_delete|*_start|*_describe|*_logs) - obj=${last_command/tkn_/}; - # really need to find something better for this - obj=${obj/_describe/}; obj=${obj/_logs/};obj=${obj/_start/}; - obj=${obj/_delete/}; - __tkn_get_object ${obj} tkn - return - ;; - *) - ;; - esac -} +# To load completions for each session, execute once: +Linux: + $ tkn completion bash > /etc/bash_completion.d/tkn + +MacOS: + $ tkn completion bash > /usr/local/etc/bash_completion.d/tkn + +Zsh: + +# If shell completion is not already enabled in your environment you will need +# to enable it. You can execute the following once: + +$ echo "autoload -U compinit; compinit" >> ~/.zshrc + +# To load completions for each session, execute once: +$ tkn completion zsh > "${fpath[1]}/_tkn" + +# You will need to start a new shell for this setup to take effect. + +Fish: + +$ tkn completion fish | source + +# To load completions for each session, execute once: +$ tkn completion fish > ~/.config/fish/completions/tkn.fish ` ) @@ -99,7 +67,7 @@ func Command() *cobra.Command { Use: "completion [SHELL]", Short: "Prints shell completion scripts", Long: desc, - ValidArgs: []string{"bash", "zsh"}, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, Example: eg, Annotations: map[string]string{ "commandType": "utility", @@ -109,9 +77,13 @@ func Command() *cobra.Command { if len(args) == 1 { switch args[0] { case "bash": - return runCompletionBash(os.Stdout, cmd.Parent()) + _ = cmd.Root().GenBashCompletion(os.Stdout) case "zsh": - return runCompletionZsh(os.Stdout, cmd.Parent()) + _ = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + _ = cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + _ = cmd.Root().GenPowerShellCompletion(os.Stdout) } } return nil @@ -119,32 +91,3 @@ func Command() *cobra.Command { } return cmd } - -// runCompletionBash generate completion with custom functions for bash -func runCompletionBash(out io.Writer, tkn *cobra.Command) error { - if err := tkn.Root().GenBashCompletion(out); err != nil { - return err - } - - if _, err := out.Write([]byte(commonCompletion)); err != nil { - return err - } - - if _, err := out.Write([]byte(bashCompletion)); err != nil { - return err - } - - return nil -} - -// runCompletionZsh generate completion with custom functions for bash -func runCompletionZsh(out io.Writer, tkn *cobra.Command) error { - if err := tkn.Root().GenZshCompletion(out); err != nil { - return err - } - - if _, err := out.Write([]byte(commonCompletion)); err != nil { - return err - } - return nil -} diff --git a/pkg/cmd/condition/delete.go b/pkg/cmd/condition/delete.go index 54d2454fc..79ea5018d 100644 --- a/pkg/cmd/condition/delete.go +++ b/pkg/cmd/condition/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete Conditions in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete Conditions in a namespace", + Example: eg, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Annotations: map[string]string{ "commandType": "main", }, @@ -65,7 +67,6 @@ or f.AddFlags(c) c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all Conditions in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_condition") return c } diff --git a/pkg/cmd/condition/describe.go b/pkg/cmd/condition/describe.go index f3d75ceea..b46f80ed5 100644 --- a/pkg/cmd/condition/describe.go +++ b/pkg/cmd/condition/describe.go @@ -90,12 +90,13 @@ or ` c := &cobra.Command{ - Use: "describe", - Aliases: []string{"desc"}, - Short: "Describe Conditions in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(1), - SilenceUsage: true, + Use: "describe", + Aliases: []string{"desc"}, + Short: "Describe Conditions in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(1), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -126,7 +127,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_condition") f.AddFlags(c) return c } diff --git a/pkg/cmd/eventlistener/delete.go b/pkg/cmd/eventlistener/delete.go index 36bd76ff0..fd7acfdcf 100644 --- a/pkg/cmd/eventlistener/delete.go +++ b/pkg/cmd/eventlistener/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete EventListeners in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete EventListeners in a namespace", + Example: eg, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Annotations: map[string]string{ "commandType": "main", }, @@ -66,7 +68,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all EventListeners in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_eventlistener") return c } diff --git a/pkg/cmd/eventlistener/describe.go b/pkg/cmd/eventlistener/describe.go index 185bafd0f..a1c36df74 100644 --- a/pkg/cmd/eventlistener/describe.go +++ b/pkg/cmd/eventlistener/describe.go @@ -146,8 +146,9 @@ or Annotations: map[string]string{ "commandType": "main", }, - Args: cobra.MinimumNArgs(1), - SilenceUsage: true, + Args: cobra.MinimumNArgs(1), + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -170,7 +171,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_eventlistener") f.AddFlags(c) return c } diff --git a/pkg/cmd/eventlistener/logs.go b/pkg/cmd/eventlistener/logs.go index 084f8967b..9cd8c80f0 100644 --- a/pkg/cmd/eventlistener/logs.go +++ b/pkg/cmd/eventlistener/logs.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -48,7 +49,8 @@ Show 2 lines of most recent logs from all EventListener pods: Annotations: map[string]string{ "commandType": "main", }, - Args: cobra.ExactValidArgs(1), + Args: cobra.ExactValidArgs(1), + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { if opts.Tail <= 0 && opts.Tail != -1 { return fmt.Errorf("tail cannot be 0 or less than 0 unless -1 for all pods") @@ -68,7 +70,6 @@ Show 2 lines of most recent logs from all EventListener pods: }, } c.Flags().Int64VarP(&opts.Tail, "tail", "t", 10, "Number of most recent log lines to show. Specify -1 for all logs from each pod.") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_eventlistener") return c } diff --git a/pkg/cmd/pipeline/delete.go b/pkg/cmd/pipeline/delete.go index 0d2fe501c..332382407 100644 --- a/pkg/cmd/pipeline/delete.go +++ b/pkg/cmd/pipeline/delete.go @@ -21,6 +21,7 @@ import ( "github.com/tektoncd/cli/pkg/actions" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/pipeline" "github.com/tektoncd/cli/pkg/pipelinerun" @@ -42,12 +43,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete Pipelines in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete Pipelines in a namespace", + Example: eg, + Args: cobra.MinimumNArgs(0), + ValidArgsFunction: formatted.ParentCompletion, + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -70,7 +72,6 @@ or c.Flags().BoolVarP(&opts.DeleteRelated, "prs", "", false, "Whether to delete Pipeline(s) and related resources (PipelineRuns) (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all Pipelines in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipeline") return c } diff --git a/pkg/cmd/pipeline/describe.go b/pkg/cmd/pipeline/describe.go index 3de63c06d..b774d66b2 100644 --- a/pkg/cmd/pipeline/describe.go +++ b/pkg/cmd/pipeline/describe.go @@ -122,7 +122,8 @@ func describeCommand(p cli.Params) *cobra.Command { Annotations: map[string]string{ "commandType": "main", }, - SilenceUsage: true, + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { output, err := cmd.LocalFlags().GetString("output") if err != nil { @@ -155,7 +156,6 @@ func describeCommand(p cli.Params) *cobra.Command { }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipeline") f.AddFlags(c) return c } diff --git a/pkg/cmd/pipeline/logs.go b/pkg/cmd/pipeline/logs.go index 75bb1c943..14ae84d5a 100644 --- a/pkg/cmd/pipeline/logs.go +++ b/pkg/cmd/pipeline/logs.go @@ -22,6 +22,7 @@ import ( "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/cmd/pipelinerun" "github.com/tektoncd/cli/pkg/flags" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/pipeline" phelper "github.com/tektoncd/cli/pkg/pipeline" @@ -69,9 +70,11 @@ Show logs for given Pipeline and PipelineRun: Short: "Show Pipeline logs", Example: eg, SilenceUsage: true, + Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, Args: func(cmd *cobra.Command, args []string) error { if err := flags.InitParams(p, cmd); err != nil { return err @@ -92,7 +95,6 @@ Show logs for given Pipeline and PipelineRun: c.Flags().BoolVarP(&opts.Follow, "follow", "f", false, "stream live logs") c.Flags().IntVarP(&opts.Limit, "limit", "", 5, "lists number of PipelineRuns") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipeline") return c } diff --git a/pkg/cmd/pipeline/start.go b/pkg/cmd/pipeline/start.go index f02ccdc46..e6cca01c9 100644 --- a/pkg/cmd/pipeline/start.go +++ b/pkg/cmd/pipeline/start.go @@ -33,6 +33,7 @@ import ( prcmd "github.com/tektoncd/cli/pkg/cmd/pipelinerun" "github.com/tektoncd/cli/pkg/file" "github.com/tektoncd/cli/pkg/flags" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/labels" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/params" @@ -118,6 +119,8 @@ For params value, if you want to provide multiple values, provide them comma sep like cat,foo,bar `, SilenceUsage: true, + + ValidArgsFunction: formatted.ParentCompletion, Args: func(cmd *cobra.Command, args []string) error { if err := flags.InitParams(p, cmd); err != nil { return err @@ -155,13 +158,14 @@ like cat,foo,bar c.Flags().BoolVarP(&opt.ShowLog, "showlog", "", false, "show logs right after starting the Pipeline") c.Flags().StringSliceVarP(&opt.Resources, "resource", "r", []string{}, "pass the resource name and ref as name=ref") c.Flags().StringArrayVarP(&opt.Params, "param", "p", []string{}, "pass the param as key=value for string type, or key=value1,value2,... for array type") - c.Flags().StringVarP(&opt.ServiceAccountName, "serviceaccount", "s", "", "pass the serviceaccount name") - flags.AddShellCompletion(c.Flags().Lookup("serviceaccount"), "__kubectl_get_serviceaccount") - c.Flags().StringSliceVar(&opt.ServiceAccounts, "task-serviceaccount", []string{}, "pass the service account corresponding to the task") - flags.AddShellCompletion(c.Flags().Lookup("task-serviceaccount"), "__kubectl_get_serviceaccount") c.Flags().BoolVarP(&opt.Last, "last", "L", false, "re-run the Pipeline using last PipelineRun values") c.Flags().StringVarP(&opt.UsePipelineRun, "use-pipelinerun", "", "", "use this pipelinerun values to re-run the pipeline. ") - flags.AddShellCompletion(c.Flags().Lookup("use-pipelinerun"), "__tkn_get_pipelinerun") + _ = c.RegisterFlagCompletionFunc("use-pipelinerun", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("pipelinerun", args) + }, + ) + c.Flags().StringSliceVarP(&opt.Labels, "labels", "l", []string{}, "pass labels as label=value.") c.Flags().StringArrayVarP(&opt.Workspaces, "workspace", "w", []string{}, "pass the workspace.") c.Flags().BoolVarP(&opt.DryRun, "dry-run", "", false, "preview PipelineRun without running it") @@ -172,8 +176,19 @@ like cat,foo,bar c.Flags().BoolVarP(&opt.UseParamDefaults, "use-param-defaults", "", false, "use default parameter values without prompting for input") c.Flags().StringVar(&opt.PodTemplate, "pod-template", "", "local or remote file containing a PodTemplate definition") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipeline") + c.Flags().StringVarP(&opt.ServiceAccountName, "serviceaccount", "s", "", "pass the serviceaccount name") + _ = c.RegisterFlagCompletionFunc("serviceaccount", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("serviceaccount", args) + }, + ) + c.Flags().StringSliceVar(&opt.ServiceAccounts, "task-serviceaccount", []string{}, "pass the service account corresponding to the task") + _ = c.RegisterFlagCompletionFunc("task-serviceaccount", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("serviceaccount", args) + }, + ) return c } diff --git a/pkg/cmd/pipelineresource/delete.go b/pkg/cmd/pipelineresource/delete.go index bab51f160..e0b505a30 100644 --- a/pkg/cmd/pipelineresource/delete.go +++ b/pkg/cmd/pipelineresource/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete pipeline resources in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete pipeline resources in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -66,7 +68,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all PipelineResources in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelineresource") return c } diff --git a/pkg/cmd/pipelineresource/describe.go b/pkg/cmd/pipelineresource/describe.go index acffde90b..390d90fe8 100644 --- a/pkg/cmd/pipelineresource/describe.go +++ b/pkg/cmd/pipelineresource/describe.go @@ -83,6 +83,7 @@ or Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -112,7 +113,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelineresource") f.AddFlags(c) return c } diff --git a/pkg/cmd/pipelinerun/cancel.go b/pkg/cmd/pipelinerun/cancel.go index 5925f256f..2477bdea6 100644 --- a/pkg/cmd/pipelinerun/cancel.go +++ b/pkg/cmd/pipelinerun/cancel.go @@ -19,6 +19,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/pipelinerun" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,14 +32,16 @@ func cancelCommand(p cli.Params) *cobra.Command { ` c := &cobra.Command{ - Use: "cancel", - Short: "Cancel a PipelineRun in a namespace", - Example: eg, + Use: "cancel", + Short: "Cancel a PipelineRun in a namespace", + Example: eg, + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, - Args: cobra.ExactArgs(1), + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { pr := args[0] @@ -51,7 +54,6 @@ func cancelCommand(p cli.Params) *cobra.Command { }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelinerun") return c } diff --git a/pkg/cmd/pipelinerun/delete.go b/pkg/cmd/pipelinerun/delete.go index 1587cbc28..ea9095378 100644 --- a/pkg/cmd/pipelinerun/delete.go +++ b/pkg/cmd/pipelinerun/delete.go @@ -22,6 +22,7 @@ import ( "github.com/tektoncd/cli/pkg/actions" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" pr "github.com/tektoncd/cli/pkg/pipelinerun" prsort "github.com/tektoncd/cli/pkg/pipelinerun/sort" @@ -44,12 +45,14 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete PipelineRuns in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete PipelineRuns in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, + Annotations: map[string]string{ "commandType": "main", }, @@ -80,7 +83,6 @@ or c.Flags().StringVarP(&opts.ParentResourceName, "pipeline", "p", "", "The name of a Pipeline whose PipelineRuns should be deleted (does not delete the Pipeline)") c.Flags().IntVarP(&opts.Keep, "keep", "", 0, "Keep n most recent number of PipelineRuns") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all PipelineRuns in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelinerun") return c } diff --git a/pkg/cmd/pipelinerun/describe.go b/pkg/cmd/pipelinerun/describe.go index 4d364231b..a81838bec 100644 --- a/pkg/cmd/pipelinerun/describe.go +++ b/pkg/cmd/pipelinerun/describe.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/actions" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" prhelper "github.com/tektoncd/cli/pkg/pipelinerun" prdesc "github.com/tektoncd/cli/pkg/pipelinerun/description" @@ -55,6 +56,7 @@ or Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -115,7 +117,6 @@ or c.Flags().IntVarP(&opts.Limit, "limit", "", defaultDescribeLimit, "lists number of PipelineRuns when selecting a PipelineRun to describe") c.Flags().BoolVarP(&opts.Fzf, "fzf", "F", false, "use fzf to select a PipelineRun to describe") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelinerun") f.AddFlags(c) return c diff --git a/pkg/cmd/pipelinerun/logs.go b/pkg/cmd/pipelinerun/logs.go index 1ca86925b..f59e42efb 100644 --- a/pkg/cmd/pipelinerun/logs.go +++ b/pkg/cmd/pipelinerun/logs.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/log" "github.com/tektoncd/cli/pkg/options" prhelper "github.com/tektoncd/cli/pkg/pipelinerun" @@ -53,7 +54,8 @@ Show the logs of PipelineRun named 'microservice-1' for all Tasks and steps (inc Annotations: map[string]string{ "commandType": "main", }, - Example: eg, + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 0 { opts.PipelineRunName = args[0] @@ -81,7 +83,6 @@ Show the logs of PipelineRun named 'microservice-1' for all Tasks and steps (inc c.Flags().StringSliceVarP(&opts.Tasks, "task", "t", []string{}, "show logs for mentioned Tasks only") c.Flags().IntVarP(&opts.Limit, "limit", "", defaultLimit, "lists number of PipelineRuns") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelinerun") return c } diff --git a/pkg/cmd/task/delete.go b/pkg/cmd/task/delete.go index 662cb2ac2..cb4232811 100644 --- a/pkg/cmd/task/delete.go +++ b/pkg/cmd/task/delete.go @@ -21,6 +21,7 @@ import ( "github.com/tektoncd/cli/pkg/actions" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/task" trlist "github.com/tektoncd/cli/pkg/taskrun/list" @@ -42,15 +43,17 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete Tasks in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete Tasks in a namespace", + Example: eg, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ In: cmd.InOrStdin(), @@ -70,7 +73,6 @@ or c.Flags().BoolVarP(&opts.DeleteRelated, "trs", "", false, "Whether to delete Task(s) and related resources (TaskRuns) (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all Tasks in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_task") return c } diff --git a/pkg/cmd/task/describe.go b/pkg/cmd/task/describe.go index e0f9a573d..16108dc87 100644 --- a/pkg/cmd/task/describe.go +++ b/pkg/cmd/task/describe.go @@ -148,10 +148,11 @@ or ` c := &cobra.Command{ - Use: "describe", - Aliases: []string{"desc"}, - Short: "Describe a Task in a namespace", - Example: eg, + Use: "describe", + Aliases: []string{"desc"}, + ValidArgsFunction: formatted.ParentCompletion, + Short: "Describe a Task in a namespace", + Example: eg, Annotations: map[string]string{ "commandType": "main", }, @@ -193,7 +194,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_task") f.AddFlags(c) return c } diff --git a/pkg/cmd/task/logs.go b/pkg/cmd/task/logs.go index 25b6b30a2..f8b4c2904 100644 --- a/pkg/cmd/task/logs.go +++ b/pkg/cmd/task/logs.go @@ -22,6 +22,7 @@ import ( "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/cmd/taskrun" "github.com/tektoncd/cli/pkg/flags" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" thelper "github.com/tektoncd/cli/pkg/task" trlist "github.com/tektoncd/cli/pkg/taskrun/list" @@ -67,9 +68,11 @@ Show logs for given Task and associated TaskRun: Short: "Show Task logs", Example: eg, SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Annotations: map[string]string{ "commandType": "main", }, + Args: func(cmd *cobra.Command, args []string) error { if err := flags.InitParams(p, cmd); err != nil { return err @@ -90,7 +93,6 @@ Show logs for given Task and associated TaskRun: c.Flags().BoolVarP(&opts.Follow, "follow", "f", false, "stream live logs") c.Flags().IntVarP(&opts.Limit, "limit", "", 5, "lists number of TaskRuns") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_task") return c } diff --git a/pkg/cmd/task/start.go b/pkg/cmd/task/start.go index 14257c31c..bd632672a 100644 --- a/pkg/cmd/task/start.go +++ b/pkg/cmd/task/start.go @@ -33,6 +33,7 @@ import ( "github.com/tektoncd/cli/pkg/cmd/taskrun" "github.com/tektoncd/cli/pkg/file" "github.com/tektoncd/cli/pkg/flags" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/labels" "github.com/tektoncd/cli/pkg/options" "github.com/tektoncd/cli/pkg/params" @@ -118,6 +119,7 @@ func startCommand(p cli.Params) *cobra.Command { c := &cobra.Command{ Use: "start [RESOURCES...] [PARAMS...] [SERVICEACCOUNT]", Short: "Start Tasks", + Annotations: map[string]string{ "commandType": "main", }, @@ -131,7 +133,8 @@ or in a file using the --filename argument. For params values, if you want to provide multiple values, provide them comma separated like cat,foo,bar `, - SilenceUsage: true, + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, Args: func(cmd *cobra.Command, args []string) error { if err := flags.InitParams(p, cmd); err != nil { return err @@ -176,10 +179,18 @@ like cat,foo,bar c.Flags().StringSliceVarP(&opt.OutputResources, "outputresource", "o", []string{}, "pass the output resource name and ref as name=ref") c.Flags().StringArrayVarP(&opt.Params, "param", "p", []string{}, "pass the param as key=value for string type, or key=value1,value2,... for array type") c.Flags().StringVarP(&opt.ServiceAccountName, "serviceaccount", "s", "", "pass the serviceaccount name") - flags.AddShellCompletion(c.Flags().Lookup("serviceaccount"), "__kubectl_get_serviceaccount") + _ = c.RegisterFlagCompletionFunc("serviceaccount", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("serviceaccount", args) + }, + ) c.Flags().BoolVarP(&opt.Last, "last", "L", false, "re-run the Task using last TaskRun values") c.Flags().StringVarP(&opt.UseTaskRun, "use-taskrun", "", "", "specify a TaskRun name to use its values to re-run the TaskRun") - flags.AddShellCompletion(c.Flags().Lookup("use-taskrun"), "__tkn_get_taskrun") + _ = c.RegisterFlagCompletionFunc("use-taskrun", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("taskrun", args) + }, + ) c.Flags().StringSliceVarP(&opt.Labels, "labels", "l", []string{}, "pass labels as label=value.") c.Flags().StringArrayVarP(&opt.Workspaces, "workspace", "w", []string{}, "pass the workspace.") c.Flags().BoolVarP(&opt.ShowLog, "showlog", "", false, "show logs right after starting the Task") @@ -191,8 +202,6 @@ like cat,foo,bar c.Flags().BoolVarP(&opt.UseParamDefaults, "use-param-defaults", "", false, "use default parameter values without prompting for input") c.Flags().StringVar(&opt.PodTemplate, "pod-template", "", "local or remote file containing a PodTemplate definition") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_task") - return c } diff --git a/pkg/cmd/taskrun/cancel.go b/pkg/cmd/taskrun/cancel.go index 711a0b41a..289adae35 100644 --- a/pkg/cmd/taskrun/cancel.go +++ b/pkg/cmd/taskrun/cancel.go @@ -19,6 +19,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/taskrun" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,11 +32,12 @@ func cancelCommand(p cli.Params) *cobra.Command { ` c := &cobra.Command{ - Use: "cancel", - Short: "Cancel a TaskRun in a namespace", - Example: eg, - Args: cobra.ExactArgs(1), - SilenceUsage: true, + Use: "cancel", + Short: "Cancel a TaskRun in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.ExactArgs(1), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -49,7 +51,6 @@ func cancelCommand(p cli.Params) *cobra.Command { }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun") return c } diff --git a/pkg/cmd/taskrun/delete.go b/pkg/cmd/taskrun/delete.go index f0d213fc0..03c1df399 100644 --- a/pkg/cmd/taskrun/delete.go +++ b/pkg/cmd/taskrun/delete.go @@ -18,6 +18,7 @@ import ( "errors" "fmt" + "github.com/tektoncd/cli/pkg/formatted" taskpkg "github.com/tektoncd/cli/pkg/task" trsort "github.com/tektoncd/cli/pkg/taskrun/sort" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" @@ -46,12 +47,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete TaskRuns in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete TaskRuns in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -82,7 +84,6 @@ or c.Flags().StringVarP(&opts.ParentResourceName, "task", "t", "", "The name of a Task whose TaskRuns should be deleted (does not delete the task)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all TaskRuns in a namespace (default: false)") c.Flags().IntVarP(&opts.Keep, "keep", "", 0, "Keep n most recent number of TaskRuns") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun") return c } diff --git a/pkg/cmd/taskrun/describe.go b/pkg/cmd/taskrun/describe.go index cb3c1a0f2..919c3b31d 100644 --- a/pkg/cmd/taskrun/describe.go +++ b/pkg/cmd/taskrun/describe.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/actions" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" trdesc "github.com/tektoncd/cli/pkg/taskrun/description" trlist "github.com/tektoncd/cli/pkg/taskrun/list" @@ -55,6 +56,7 @@ or Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -115,7 +117,6 @@ or c.Flags().IntVarP(&opts.Limit, "limit", "", defaultTaskRunLimit, "lists number of TaskRuns when selecting a TaskRun to describe") c.Flags().BoolVarP(&opts.Fzf, "fzf", "F", false, "use fzf to select a taskrun to describe") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun") f.AddFlags(c) return c diff --git a/pkg/cmd/taskrun/logs.go b/pkg/cmd/taskrun/logs.go index a8d44fd59..c30ecdfce 100644 --- a/pkg/cmd/taskrun/logs.go +++ b/pkg/cmd/taskrun/logs.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/log" "github.com/tektoncd/cli/pkg/options" trlist "github.com/tektoncd/cli/pkg/taskrun/list" @@ -54,6 +55,7 @@ Show the logs of TaskRun named 'microservice-1' for step 'build' only from names Annotations: map[string]string{ "commandType": "main", }, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 0 { opts.TaskrunName = args[0] @@ -85,7 +87,6 @@ Show the logs of TaskRun named 'microservice-1' for step 'build' only from names c.Flags().BoolVarP(&opts.Fzf, "fzf", "F", false, "use fzf to select a TaskRun") c.Flags().StringSliceVarP(&opts.Steps, "step", "s", []string{}, "show logs for mentioned steps only") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun") return c } diff --git a/pkg/cmd/triggerbinding/delete.go b/pkg/cmd/triggerbinding/delete.go index 38ddea391..136ff3b2d 100644 --- a/pkg/cmd/triggerbinding/delete.go +++ b/pkg/cmd/triggerbinding/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete TriggerBindings in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete TriggerBindings in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -66,7 +68,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all TriggerBindings in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_triggerbinding") return c } diff --git a/pkg/cmd/triggerbinding/describe.go b/pkg/cmd/triggerbinding/describe.go index 143d84c12..e98d6b015 100644 --- a/pkg/cmd/triggerbinding/describe.go +++ b/pkg/cmd/triggerbinding/describe.go @@ -65,8 +65,9 @@ or Annotations: map[string]string{ "commandType": "main", }, - Args: cobra.MinimumNArgs(1), - SilenceUsage: true, + Args: cobra.MinimumNArgs(1), + SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -86,7 +87,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_triggerbindings") f.AddFlags(c) return c } diff --git a/pkg/cmd/triggertemplate/delete.go b/pkg/cmd/triggertemplate/delete.go index 8065f9bab..e65650fdb 100644 --- a/pkg/cmd/triggertemplate/delete.go +++ b/pkg/cmd/triggertemplate/delete.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/deleter" + "github.com/tektoncd/cli/pkg/formatted" "github.com/tektoncd/cli/pkg/options" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -39,12 +40,13 @@ or ` c := &cobra.Command{ - Use: "delete", - Aliases: []string{"rm"}, - Short: "Delete TriggerTemplates in a namespace", - Example: eg, - Args: cobra.MinimumNArgs(0), - SilenceUsage: true, + Use: "delete", + Aliases: []string{"rm"}, + Short: "Delete TriggerTemplates in a namespace", + Example: eg, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(0), + SilenceUsage: true, Annotations: map[string]string{ "commandType": "main", }, @@ -66,7 +68,6 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all TriggerTemplates in a namespace (default: false)") - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_triggertemplate") return c } diff --git a/pkg/cmd/triggertemplate/describe.go b/pkg/cmd/triggertemplate/describe.go index 5bd6e29f6..b1bf736df 100644 --- a/pkg/cmd/triggertemplate/describe.go +++ b/pkg/cmd/triggertemplate/describe.go @@ -85,8 +85,9 @@ or Annotations: map[string]string{ "commandType": "main", }, - Args: cobra.MinimumNArgs(1), - SilenceUsage: true, + ValidArgsFunction: formatted.ParentCompletion, + Args: cobra.MinimumNArgs(1), + SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { s := &cli.Stream{ Out: cmd.OutOrStdout(), @@ -106,7 +107,6 @@ or }, } - _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_triggertemplate") f.AddFlags(c) return c } diff --git a/pkg/flags/flags.go b/pkg/flags/flags.go index df68225a9..35b99ecd0 100644 --- a/pkg/flags/flags.go +++ b/pkg/flags/flags.go @@ -19,9 +19,8 @@ import ( "runtime" "github.com/spf13/cobra" - "github.com/spf13/pflag" "github.com/tektoncd/cli/pkg/cli" - "github.com/tektoncd/cli/pkg/cmd/completion" + "github.com/tektoncd/cli/pkg/formatted" "golang.org/x/crypto/ssh/terminal" ) @@ -52,6 +51,11 @@ func AddTektonOptions(cmd *cobra.Command) { cmd.PersistentFlags().StringP( namespace, "n", "", "namespace to use (default: from $KUBECONFIG)") + _ = cmd.RegisterFlagCompletionFunc(namespace, + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return formatted.BaseCompletion("namespace", args) + }, + ) cmd.PersistentFlags().BoolP( nocolour, "", false, @@ -65,13 +69,6 @@ func AddTektonOptions(cmd *cobra.Command) { cmd.PersistentFlags().BoolP( "no-color", "C", false, "disable coloring (default: false)") - - // Add custom completion for that command as specified in - // bashCompletionFlags map - for name, completion := range completion.ShellCompletionMap { - pflag := cmd.PersistentFlags().Lookup(name) - AddShellCompletion(pflag, completion) - } } // GetTektonOptions get the global tekton Options that are not passed to a subcommands @@ -147,11 +144,3 @@ func InitParams(p cli.Params, cmd *cobra.Command) error { return nil } - -// AddShellCompletion add a hint to the cobra flag annotation for how to do a completion -func AddShellCompletion(pflag *pflag.Flag, shellfunction string) { - if pflag.Annotations == nil { - pflag.Annotations = map[string][]string{} - } - pflag.Annotations[cobra.BashCompCustom] = append(pflag.Annotations[cobra.BashCompCustom], shellfunction) -} diff --git a/pkg/flags/flags_test.go b/pkg/flags/flags_test.go index 0a9ecdc7f..cdbf06af1 100644 --- a/pkg/flags/flags_test.go +++ b/pkg/flags/flags_test.go @@ -23,24 +23,6 @@ import ( "gotest.tools/v3/assert" ) -func TestFlags_add_shell_completion(t *testing.T) { - newflag := "newflag" - shellfunc := "__test_function" - cmd := cobra.Command{} - cmd.PersistentFlags().String(newflag, "", "Completion pinpon pinpon 🎤") - - pflag := cmd.PersistentFlags().Lookup(newflag) - AddShellCompletion(pflag, shellfunc) - - if pflag.Annotations[cobra.BashCompCustom] == nil { - t.Errorf("annotation should be have been added to the flag") - } - - if pflag.Annotations[cobra.BashCompCustom][0] != shellfunc { - t.Errorf("annotation should have been added to the flag") - } -} - func TestFlags_colouring(t *testing.T) { // When running it on CI, our test don't have a tty so this gets disabled // automatically, not really sure how can we workaround that :( diff --git a/pkg/formatted/completion.go b/pkg/formatted/completion.go new file mode 100644 index 000000000..e093d5707 --- /dev/null +++ b/pkg/formatted/completion.go @@ -0,0 +1,31 @@ +package formatted + +import ( + "os/exec" + "strings" + + "github.com/spf13/cobra" +) + +// GetObjectsWithKubectl return completions with kubectl, we are doing this with +// kubectl since we have caching and without it completion is way too slow +func GetObjectsWithKubectl(obj string) []string { + out, err := exec.Command("kubectl", "get", obj, "-o=jsonpath={range .items[*]}{.metadata.name} {end}").Output() + if err != nil { + return nil + } + return strings.Fields(string(out)) +} + +// BaseCompletion return a completion for a kubernetes object using Kubectl +func BaseCompletion(target string, args []string) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return GetObjectsWithKubectl(target), cobra.ShellCompDirectiveNoFileComp +} + +// ParentCompletion do completion of command to the Parent +func ParentCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return BaseCompletion(cmd.Parent().Name(), args) +}