Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

experimental

Multi Completer

A multi completer is a single binary that provides completion for multiple independent commands (e.g. magick identify, magick convert). This is useful for tools that bundle several subcommands as separate executables via symlinks or wrappers.

Setup

Use WithSubcommands when calling Gen on the root command, and call Execute instead of cmd.Execute():

// root.go
package cmd

import (
    "github.com/carapace-sh/carapace"
    "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{Use: "mytool"}

func init() {
    rootCmd.AddCommand(identifyCmd)
    rootCmd.AddCommand(convertCmd)

    carapace.Gen(rootCmd, carapace.WithSubcommands(identifyCmd, convertCmd))
}

func Execute() error {
    return carapace.Gen(rootCmd).Execute()
}

Each subcommand is defined in its own file:

// identify.go
package cmd

import (
    "github.com/carapace-sh/carapace"
    "github.com/spf13/cobra"
)

var identifyCmd = &cobra.Command{
    Use:   "identify",
    Short: "identify image format",
    Run:   func(cmd *cobra.Command, args []string) {},
}

func init() {
    identifyCmd.Flags().StringP("format", "f", "", "image format")

    carapace.Gen(identifyCmd).FlagCompletion(carapace.ActionMap{
        "format": carapace.ActionValues("png", "jpeg", "gif"),
    })
    carapace.Gen(identifyCmd).PositionalCompletion(
        carapace.ActionFiles(".png", ".jpg"),
    )
}
// convert.go
package cmd

import (
    "github.com/carapace-sh/carapace"
    "github.com/spf13/cobra"
)

var convertCmd = &cobra.Command{
    Use:   "convert",
    Short: "convert image format",
    Run:   func(cmd *cobra.Command, args []string) {},
}

func init() {
    convertCmd.Flags().StringP("output", "o", "", "output format")
    convertCmd.Flags().IntP("quality", "q", 0, "output quality")

    carapace.Gen(convertCmd).FlagCompletion(carapace.ActionMap{
        "output":  carapace.ActionValues("png", "jpeg"),
        "quality": carapace.ActionValues("1", "50", "75", "90", "100"),
    })
    carapace.Gen(convertCmd).PositionalCompletion(
        carapace.ActionFiles(".png", ".jpg"),
    )
}

How It Works

Snippet Generation

When WithSubcommands is set, Snippet() produces a multi-completer snippet that registers all subcommand completers at once. This replaces the normal single-command snippet. The binary name is automatically included as a pseudo-subcommand for self-completion.

# Generate snippet for all completers at once
mytool _carapace bash

Individual subcommand snippets are also available:

mytool identify _carapace bash

Arg Rewriting

Execute() intercepts os.Args to route completion callbacks to the correct subcommand. For example, a bridge call like:

mytool _carapace export "" identify -verbose image.png

is rewritten to:

mytool identify _carapace export "" -verbose image.png

For single completers (no WithSubcommands), Execute() simply calls cmd.Execute().

Default Subcommand

When the routing logic encounters an unknown subcommand name, it falls back to the default. By default this is the first subcommand listed in WithSubcommands. Override with WithDefault:

carapace.Gen(rootCmd,
    carapace.WithSubcommands(identifyCmd, convertCmd),
    carapace.WithDefault("convert"),
)

Supported Shells

Multi-completer snippets are supported for:

  • bash
  • bash-ble
  • elvish
  • fish
  • nushell
  • oil
  • powershell
  • tcsh
  • xonsh
  • zsh

cmd-clink and ion are not supported for multi-completer snippets.

WithSnippetFuncs

WithSnippetFuncs injects custom shell code into the generated snippet. This works for both single and multi completers. Multiple calls accumulate per shell in order.

carapace.Gen(rootCmd, carapace.WithSnippetFuncs(map[string]string{
    "bash": "# custom bash initialization\n",
    "zsh":  "# custom zsh initialization\n",
}))