Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sxcli completion — shell completion for sxcli.dev/fw binaries

sxcli.dev/completion adds bash and zsh completion to any binary built on sxcli.dev/fw v0.3.0+. Each shell package catalogs one service; the composition names what it takes — the same identity model as every other sxcli service, no blank-import magic:

import (
    "sxcli.dev/completion/bash"
    "sxcli.dev/completion/zsh"
)

fw.Builder().
    Accept(bash.ID, zsh.ID /* , your services… */).
    Main()

(fw.Solo and fw.Main() compositions accept everything cataloged, so single-applet binaries just import and go.)

That is the entire integration. There is nothing to declare beyond what the framework already knows: completions are computed from the same config structs, usage: tags and registration metadata that drive the binary's arguments, environment variables and config files. Declare once, get everything.

Installing the completions

Each import registers a system applet (completionbash, completionzsh) — machinery of the binary, never listed in usage, invoked by the generated scripts rather than by humans. The script for a command name is generated by the binary itself:

eval "$(mybin completionbash --script)"     # bash
eval "$(mybin completionzsh --script)"      # zsh, after compinit

In a busybox-style installation, generate through each symlink you actually created — each name gets its own registration with the target applet baked in:

eval "$(cat completionbash --script)"       # ./cat -> mybin
eval "$(ls completionbash --script)"

What completes

  • Applet names — the first word of a multi-applet binary, public applets only.
  • Argument names — long forms of the dispatched applet's whole closure, core arguments included; already-used scalars drop out, repeatable slice arguments stay.
  • Declared value domains — a field with Allowed metadata completes exactly its legal values; the same declaration the framework already enforces at startup.
  • Files and directories — fields declaring HintFile / HintDirectory hand over to the shell's native file completion (the core's own --config does this).
  • Service ids — fields declaring HintServiceID complete from the binary's actual registry (--disable, --enable).
  • --name=value — bools complete true/false after the =.

Zsh additionally renders each candidate's description from the usage: text and Doc metadata.

Everything is computed per keystroke against the real configuration: an --enable already typed on the line changes the closure — and the completions with it.

How it works

The framework core exposes a read-only introspection service; this module consumes it from the outside, with no privileged access — the completion engine sees exactly what any other module could see. The generated scripts are deliberately dumb transports: they forward the shell's raw completion state and every decision happens in Go, where it is tested (unit tests against a fake introspector, integration tests that re-exec a real framework binary, and the generated scripts executed under the real shells).

Other shells

Bash and zsh are what this module ships — and the machinery they are built on is public API. A third-party adapter (fish, PowerShell, elvish, …) is two small pieces over two packages:

  • sxcli.dev/completion/engineComplete(src, query) answers what completes: applet names, argument names, declared domains, file/directory directives. The adapter only decodes its shell's transport into a Query and encodes the Candidates back.
  • sxcli.dev/completion/script — the --script generation policy (which target to bake for the name the binary was invoked as), so dispatch semantics are never reimplemented per shell.

The bash and zsh packages are the reference implementations — each is one template plus the Go that decodes its shell's transport (bash's word-reassembly makes that the bigger half).

License

Apache-2.0

Releases

Packages

Contributors

Languages