Skip to content

Native Carapace Support #3188

@imsys

Description

@imsys

What is Carapace: https://carapace.sh/

From my understanding, it is kind of a Rosetta Stone, we write a single yaml file on how the command should complete, and it does its magic on working on multiple shells. (Bash, Cmd, Elvish, Fish, Nushell, Oil, Powershell, Tcsh, Xonsh, Zsh)

It does already have a bridge to work with Click:
https://github.com/carapace-sh/carapace-bridge/blob/master/pkg/actions/bridge/click.go
https://carapace-sh.github.io/carapace-bin/spec/bridge.html#click
(the amount of bridges to frameworks made me quite surprised of the comprehensive scope of the Carapace project)

So, from my tests, a software written with click does work the autocomplete, but the autocomplete is way too simple, or maybe I'm doing something wrong.

Anyway, I did found the Carapace documentation a bit confusing at first and it took me a while to find myself around it.

To summarize it a bit, Carapace has a Go-lang library offering native support. For non-Golang software, our option is to offer a yaml spec file that should be stored at:
https://carapace-sh.github.io/carapace-bin/setup/userConfigDir.html

Linux/Unix:
{XDG_CONFIG_HOME}/carapace/specs/{app}.yaml
{$HOME}/.config/carapace/specs/{app}.yaml

Apple: $HOME/Library/Application Support/carapace/specs/{app}.yaml
Windows: %AppData%\carapace\specs\{app}.yaml
Plan 9: $home/lib/carapace/specs/{app}.yaml

We can get the current used spec for any command (to learn from examples) by using the command:
carapace {app_name} spec

example: carapace adb spec

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: adb
description: Android Debug Bridge
flags:
    -H: name of adb server host [default=localhost]
    -L=: listen on given socket for adb server [default=tcp:localhost:5037]
    -P: port of adb server [default=5037]
    -a: listen on all network interfaces, not just localhost
    -d: use USB device (error if multiple devices connected)
    -e: use TCP/IP device (error if multiple TCP/IP devices available)
    -s=: use device with given serial (overrides $ANDROID_SERIAL)
    -t=: use device with given transport id
commands:
    - name: bugreport
      description: write bugreport go given path
    - name: connect
      description: connect to a device via TCP/IP
    - name: devices
      description: list connected devices
      flags:
        -l: long output
    - name: disable-verity
      description: disable dm-verity checking on userdebug builds
    - name: disconnect
      description: disconnect from given TCP/IP device or all
    - name: emu
      description: run emulator console command
    - name: enable-verity
      description: re-enable dm-verity checking on userdebug builds
    - name: forward
      description: forward socket connection
      flags:
        --list: list all forward socket connections
        --no-rebind: don't replace existing connection
        --remove: remove specific forward socket connections
        --remove-all: remove all forward socket connections
    - name: get-devpath
      description: print <device-path>
    - name: get-serialno
      description: print <serial-number>
    - name: get-state
      description: print offline | bootloader | device

But most specs I get from that command doesn't use the full potential of carapace.

I will show some of the most useful ones:

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/completion/flag.html
https://carapace-sh.github.io/carapace-spec/carapace-spec/macros/core.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: completion
    commands:
      - name: flag
        flags:
          -e?: executables
          -f, --file=: file
        completion:
          flag:
            e: ["$executables"]
            file: ["$files"]

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/flags.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: flags
    flags:
      -b: bool flag
      -v=: shorthand with value
      --repeatable*: longhand repeatable
      -o, --optarg?: shorthand and longhand with optional argument
      --hidden&: longhand hidden
      --required!: longhand required

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/completion/positional.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: completion
    commands:
      - name: positional
        completion:
          positional:
            - [pos1, positional1]
            - [pos2, positional2]

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/completion/positionalAny.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: completion
    commands:
      - name: positionalany
        completion:
          positionalany: [posany, positionalany]

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/exclusiveFlags.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: exclusiveflags
    flags:
      --add: add package
      --delete: delete package
    exclusiveflags:
      - [add, delete]

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/persistentFlags.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: persistentflags
    persistentflags:
      -p, --persistent: persistent flag
    commands:
      - name: subcommand
        flags:
          -l, --local: local flag

https://carapace-sh.github.io/carapace-spec/carapace-spec/command/hidden.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: command
commands:
  - name: hidden
    hidden: true
    completion:
      positional:
        - [p1, positional1]

https://carapace-sh.github.io/carapace-bin/spec.html

# yaml-language-server: $schema=https://carapace.sh/schemas/command.json
name: mycmd
description: my command
flags:
  --optarg?: optarg flag
  -r, --repeatable*: repeatable flag
  -v=: flag with value
persistentflags:
  --help: bool flag
completion:
  flag:
    optarg: ["one", "two\twith description", "three\twith style\tblue"]
    v: ["$files"]
commands:
- name: sub
  description: subcommand
  completion:
    positional:
      - ["$list(,)", "1", "2", "3"]
      - ["$directories"]

The full available structure is:
https://carapace-sh.github.io/carapace-spec/carapace-spec/command.html

type Command struct {
    Name            string
    Aliases         []string
    Description     string
    Group           string
    Hidden          bool
    Parsing         string
    Flags           map[string]string
    PersistentFlags map[string]string
    ExclusiveFlags  [][]string
    Run             string
    Completion      struct {
        Flag          map[string][]string
        Positional    [][]string
        PositionalAny []string
        Dash          [][]string
        DashAny       []string
    }
    Commands []Command
}

I'm currently almost finishing my work in a project, and I ended up just using argparse and an AI to write the script that outputs to carapace spec. After I finish that project I may save some time to work on implementing Carapace support for Click, though I’m unsure whether I’ll have the bandwidth, so if someone else wants to tackle it, please go ahead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions