repo_description: Open Container Initiative-based implementation of Kubernetes Container Runtime Interface
repo_topics: container-runtime-interface crun hacktoberfest k8s-sig-node kata-containers kubernetes oci oci-runtime runc
code: package criocli
  
  import (
  	"errors"
  	"fmt"
  	"strings"
  
  	"github.com/urfave/cli/v2"
  )
  
  func completion() *cli.Command {
  	return &cli.Command{
  		Name:        "complete",
  		Aliases:     []string{"completion"},
  		Usage:       "Generate bash, fish or zsh completions.",
  		ArgsUsage:   "SHELL",
  		Description: "Output shell completion code for bash, zsh or fish.",
  		Action: func(c *cli.Context) error {
  			// select bash by default for backwards compatibility
  			if c.NArg() == 0 {
  				return bashCompletion(c)
  			}
  
  			if c.NArg() != 1 {
  				return cli.ShowSubcommandHelp(c)
  			}
  
  			switch c.Args().First() {
  			case "bash":
  				return bashCompletion(c)
  			case "fish":
  				return fishCompletion(c)
  			case "zsh":
  				return zshCompletion(c)
  			default:
  				return errors.New("only bash, fish or zsh are supported")
  			}
  		},
  	}
  }
  
  const bashCompletionTemplate = `_cli_bash_autocomplete() {
      local cur opts base
      COMPREPLY=()
      cur="${COMP_WORDS[COMP_CWORD]}"
      opts="%s"
      COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
      return 0
  }
  
  complete -F _cli_bash_autocomplete %s`
  
  func bashCompletion(c *cli.Context) error {
  	subcommands := []string{}
  
  	for _, command := range c.App.Commands {
  		if command.Hidden {
  			continue
  		}
  
  		for j := range command.Names() {
  			subcommands = append(subcommands, command.Names()[j])
  		}
  	}
  
  	for _, flag := range c.App.Flags {
  		// only includes full flag name.
  		subcommands = append(subcommands, "--"+flag.Names()[0])
  	}
  
  	fmt.Fprintln(c.App.Writer,
  		fmt.Sprintf(bashCompletionTemplate,
  			strings.Join(subcommands, "\n"),
  			c.App.Name))
  
  	return nil
  }
  
  const zshCompletionTemplate = `_cli_zsh_autocomplete() {
  
    local -a cmds
    cmds=(
          %s
    )
    _describe 'commands' cmds
  
    local -a opts
    opts=(
          %s
    )
    _describe 'global options' opts
  
    return
  }
  
  compdef _cli_zsh_autocomplete %s`
  
  func zshCompletion(c *cli.Context) error {
  	subcommands := []string{}
  
  	for _, command := range c.App.Commands {
  		if command.Hidden {
  			continue
  		}
  
  		for _, name := range command.Names() {
  			subcommands = append(subcommands, zshQuoteCmd(name, command.Usage))
  		}
  	}
  
  	opts := make([]string, 0, len(c.App.Flags))
  	for _, flag := range c.App.Flags {
  		// only includes full flag name.
  		opts = append(opts, "'--"+flag.Names()[0]+"'")
  	}
  
  	fmt.Fprintln(c.App.Writer,
  		fmt.Sprintf(zshCompletionTemplate,
  			strings.Join(subcommands, "\n        "),
  			strings.Join(opts, "\n        "),
  			c.App.Name))
  
  	return nil
  }
  
  func zshQuoteCmd(name, usage string) string {
  	if !strings.ContainsRune(usage, '\'') {
  		return "'" + name + ":" + usage + "'"
  	}
  
  	return "\"" + name + ":" + strings.ReplaceAll(usage, "$", "\\$") + "\""
  }
  
  func fishCompletion(c *cli.Context) error {
  	completion, err := c.App.ToFishCompletion()
  	if err != nil {
  		return err
  	}
  
  	fmt.Fprintln(c.App.Writer, strings.TrimSpace(completion))
  
  	return nil
  }
  