Merge pull request #1773 from ulyssessouza/completion

This commit is contained in:
Nicolas De loof 2021-07-26 08:23:13 +02:00 committed by GitHub
commit 3d83989f5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 91 additions and 18 deletions

View File

@ -68,6 +68,9 @@ var (
"serve": {},
"version": {},
"backend-metadata": {},
// Special hidden commands used by cobra for completion
"__complete": {},
"__completeNoDesc": {},
}
unknownCommandRegexp = regexp.MustCompile(`unknown docker command: "([^"]*)"`)
)
@ -167,7 +170,7 @@ func main() {
})
// populate the opts with the global flags
flags.Parse(os.Args[1:]) //nolint: errcheck
flags.Parse(os.Args[1:]) // nolint: errcheck
level, err := logrus.ParseLevel(opts.LogLevel)
if err != nil {
@ -223,18 +226,16 @@ func main() {
volume.Command(ctype),
)
if ctype != store.DefaultContextType {
// On default context, "compose" is implemented by CLI Plugin
proxy := api.NewServiceProxy().WithService(service.ComposeService())
command := compose2.RootCommand(ctype, proxy)
// On default context, "compose" is implemented by CLI Plugin
proxy := api.NewServiceProxy().WithService(service.ComposeService())
command := compose2.RootCommand(ctype, proxy)
if ctype == store.AciContextType {
customizeCliForACI(command, proxy)
}
root.AddCommand(command)
if ctype == store.AciContextType {
customizeCliForACI(command, proxy)
}
root.AddCommand(command)
if err = root.ExecuteContext(ctx); err != nil {
handleError(ctx, err, ctype, currentContext, cc, root)
}

View File

@ -61,6 +61,7 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runBuild(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT")
cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.")

48
cmd/compose/completion.go Normal file
View File

@ -0,0 +1,48 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"strings"
"github.com/spf13/cobra"
)
// validArgsFn defines a completion func to be returned to fetch completion options
type validArgsFn func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
func noCompletion() validArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
}
func serviceCompletion(p *projectOptions) validArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
project, err := p.toProject(nil)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
var serviceNames []string
for _, s := range project.ServiceNames() {
if toComplete == "" || strings.HasPrefix(s, toComplete) {
serviceNames = append(serviceNames, s)
}
}
return serviceNames, cobra.ShellCompDirectiveNoFileComp
}
}

View File

@ -41,10 +41,10 @@ import (
"github.com/docker/compose-cli/pkg/compose"
)
//Command defines a compose CLI command as a func with args
// Command defines a compose CLI command as a func with args
type Command func(context.Context, []string) error
//Adapt a Command func to cobra library
// Adapt a Command func to cobra library
func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

View File

@ -86,6 +86,7 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
return runConvert(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags.StringVar(&opts.Format, "format", "yaml", "Format the output. Values: [yaml | json]")

View File

@ -60,6 +60,7 @@ func copyCommand(p *projectOptions, backend api.Service) *cobra.Command {
opts.destination = args[1]
return runCopy(ctx, backend, opts)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := copyCmd.Flags()

View File

@ -64,6 +64,7 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
QuietPull: false,
})
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")

View File

@ -57,6 +57,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runDown(ctx, backend, opts)
}),
ValidArgsFunction: noCompletion(),
}
flags := downCmd.Flags()
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")

View File

@ -43,6 +43,7 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runEvents(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
cmd.Flags().BoolVar(&opts.json, "json", false, "Output events as a stream of json objects")

View File

@ -61,6 +61,7 @@ func execCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runExec(ctx, backend, opts)
}),
ValidArgsFunction: serviceCompletion(p),
}
runCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: Run command in the background.")

View File

@ -48,6 +48,7 @@ func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runImages(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
imgCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
return imgCmd

View File

@ -33,6 +33,7 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: p.WithProject(func(ctx context.Context, project *types.Project) error {
return backend.Kill(ctx, project, opts)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()

View File

@ -46,6 +46,7 @@ func listCommand(contextType string, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runList(ctx, backend, opts)
}),
ValidArgsFunction: noCompletion(),
}
lsCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs.")

View File

@ -44,11 +44,12 @@ func logsCommand(p *projectOptions, contextType string, backend api.Service) *co
projectOptions: p,
}
logsCmd := &cobra.Command{
Use: "logs [service...]",
Use: "logs [SERVICE...]",
Short: "View output from containers",
RunE: Adapt(func(ctx context.Context, args []string) error {
return runLogs(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := logsCmd.Flags()
flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output.")

View File

@ -38,6 +38,7 @@ func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPause(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
return cmd
}
@ -67,6 +68,7 @@ func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runUnPause(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
return cmd
}

View File

@ -52,6 +52,7 @@ func portCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPort(ctx, backend, opts, args[0])
}),
ValidArgsFunction: serviceCompletion(p),
}
cmd.Flags().StringVar(&opts.protocol, "protocol", "tcp", "tcp or udp")
cmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if service has multiple replicas")

View File

@ -67,8 +67,8 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
opts := psOptions{
projectOptions: p,
}
cmd := &cobra.Command{
Use: "ps [options] [SERVICE...]",
psCmd := &cobra.Command{
Use: "ps [SERVICE...]",
Short: "List containers",
PreRunE: func(cmd *cobra.Command, args []string) error {
return opts.parseFilter()
@ -76,8 +76,9 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPs(ctx, backend, args, opts)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags := psCmd.Flags()
flags.StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json]")
flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property")
flags.StringVar(&opts.Status, "status", "", "Filter services by status")
@ -85,7 +86,7 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
flags.BoolVar(&opts.Services, "services", false, "Display services")
flags.BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
flags.Lookup("filter").Hidden = true
return cmd
return psCmd
}
func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {

View File

@ -54,6 +54,7 @@ func pullCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPull(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Pull without printing progress information")

View File

@ -41,6 +41,7 @@ func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPush(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
pushCmd.Flags().BoolVar(&opts.Ignorefailures, "ignore-push-failures", false, "Push what it can and ignores images with push failures")

View File

@ -46,6 +46,7 @@ Any data which is not in a volume will be lost.`,
RunE: Adapt(func(ctx context.Context, args []string) error {
return runRemove(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
f := cmd.Flags()
f.BoolVarP(&opts.force, "force", "f", false, "Don't ask to confirm removal")

View File

@ -40,6 +40,7 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runRestart(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := restartCmd.Flags()
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")

View File

@ -126,6 +126,7 @@ func runCommand(p *projectOptions, backend api.Service) *cobra.Command {
}
return runRun(ctx, backend, project, opts)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags.BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")

View File

@ -37,6 +37,7 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runStart(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
return startCmd
}

View File

@ -44,6 +44,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: Adapt(func(ctx context.Context, args []string) error {
return runStop(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := cmd.Flags()
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")

View File

@ -39,11 +39,12 @@ func topCommand(p *projectOptions, backend api.Service) *cobra.Command {
projectOptions: p,
}
topCmd := &cobra.Command{
Use: "top",
Use: "top [SERVICES...]",
Short: "Display the running processes",
RunE: Adapt(func(ctx context.Context, args []string) error {
return runTop(ctx, backend, opts, args)
}),
ValidArgsFunction: serviceCompletion(p),
}
return topCmd
}

View File

@ -120,6 +120,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
RunE: p.WithServices(func(ctx context.Context, project *types.Project, services []string) error {
return runUp(ctx, backend, create, up, project, services)
}),
ValidArgsFunction: serviceCompletion(p),
}
flags := upCmd.Flags()
flags.StringArrayVarP(&up.Environment, "environment", "e", []string{}, "Environment variables")