mirror of
https://github.com/Cheviiot/Vintner.git
synced 2026-08-03 15:57:24 +00:00
Add bash/zsh shell completion
vintner completion bash|zsh prints a completion script meant to be sourced (source <(vintner completion bash)); completes subcommands (including short aliases), download's flags, and directory arguments for install/env --bin. Mentioned in the top-level usage text and documented in the README. The Nivora package doesn't auto-install these system-wide yet - it'd need Stapler's install-completion helper, whose calling convention isn't documented anywhere in this repo or Nivora's other packages, so guessing at it risked a broken package build for a nice-to-have. source <(vintner completion bash) works today regardless of install method (Nivora, prebuilt binary, or from source).
This commit is contained in:
@@ -23,6 +23,7 @@ shims, all work from your `PATH` — including full MSBuild projects and, with
|
|||||||
- [Commands](#commands)
|
- [Commands](#commands)
|
||||||
- [Building drivers (WDK)](#building-drivers-wdk)
|
- [Building drivers (WDK)](#building-drivers-wdk)
|
||||||
- [Language](#language)
|
- [Language](#language)
|
||||||
|
- [Shell completion](#shell-completion)
|
||||||
- [Using clang-cl/lld-link instead of Wine](#using-clang-cllld-link-instead-of-wine)
|
- [Using clang-cl/lld-link instead of Wine](#using-clang-cllld-link-instead-of-wine)
|
||||||
- [Building from source](#building-from-source)
|
- [Building from source](#building-from-source)
|
||||||
- [How the pieces fit together](#how-the-pieces-fit-together)
|
- [How the pieces fit together](#how-the-pieces-fit-together)
|
||||||
@@ -103,6 +104,7 @@ vintner install (i) [dir] wire up wrappe
|
|||||||
vintner env (e) --bin <dir>/bin/<arch> print INCLUDE/LIB for native clang-cl/lld-link use
|
vintner env (e) --bin <dir>/bin/<arch> print INCLUDE/LIB for native clang-cl/lld-link use
|
||||||
vintner version (v) print the version
|
vintner version (v) print the version
|
||||||
vintner help (h) print usage
|
vintner help (h) print usage
|
||||||
|
vintner completion bash|zsh print a shell completion script
|
||||||
```
|
```
|
||||||
|
|
||||||
`--dest`/`[dir]` both default to `~/.vintner` when omitted.
|
`--dest`/`[dir]` both default to `~/.vintner` when omitted.
|
||||||
@@ -150,6 +152,16 @@ VINTNER_LANG=ru vintner help
|
|||||||
|
|
||||||
Deeper error text bubbled up from internal packages stays in English.
|
Deeper error text bubbled up from internal packages stays in English.
|
||||||
|
|
||||||
|
## Shell completion
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source <(vintner completion bash) # or add to ~/.bashrc
|
||||||
|
source <(vintner completion zsh) # or add to ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
Completes subcommands (including the short aliases), `download`'s flags,
|
||||||
|
and directory arguments for `install`/`env --bin`.
|
||||||
|
|
||||||
## Using clang-cl/lld-link instead of Wine
|
## Using clang-cl/lld-link instead of Wine
|
||||||
|
|
||||||
You don't need Wine at all if you drive the (nonredistributable) MSVC/WinSDK
|
You don't need Wine at all if you drive the (nonredistributable) MSVC/WinSDK
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// runCompletion prints a shell completion script for shell ("bash" or
|
||||||
|
// "zsh") to stdout, meant to be sourced directly:
|
||||||
|
//
|
||||||
|
// source <(vintner completion bash) # or add to ~/.bashrc
|
||||||
|
// source <(vintner completion zsh) # or add to ~/.zshrc
|
||||||
|
//
|
||||||
|
// The flag lists below are hand-maintained alongside download.go/env.go's
|
||||||
|
// flag.FlagSet definitions rather than generated from them - there's no
|
||||||
|
// reflection-friendly registry to walk, and the flag set rarely changes.
|
||||||
|
func runCompletion(args []string) int {
|
||||||
|
if len(args) != 1 {
|
||||||
|
fmt.Println("usage: vintner completion bash|zsh")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
switch args[0] {
|
||||||
|
case "bash":
|
||||||
|
fmt.Print(bashCompletionScript)
|
||||||
|
return 0
|
||||||
|
case "zsh":
|
||||||
|
fmt.Print(zshCompletionScript)
|
||||||
|
return 0
|
||||||
|
default:
|
||||||
|
fmt.Printf("vintner completion: unsupported shell %q (want bash or zsh)\n", args[0])
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadFlags = "--dest --cache --major --preview --manifest --accept-license " +
|
||||||
|
"--msvc-version --sdk-version --host-arch --only-host --language " +
|
||||||
|
"--include-optional --skip-recommended --only-download --only-unpack " +
|
||||||
|
"--keep-unpack --skip-patch --list-workloads --list-components " +
|
||||||
|
"--print-deps-tree --with-wdk --architecture --ignore -h --help"
|
||||||
|
|
||||||
|
var bashCompletionScript = `# vintner bash completion - eval "$(vintner completion bash)"
|
||||||
|
_vintner_complete() {
|
||||||
|
local cur cmd
|
||||||
|
COMPREPLY=()
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
cmd="${COMP_WORDS[1]}"
|
||||||
|
|
||||||
|
if [ "$COMP_CWORD" -eq 1 ]; then
|
||||||
|
COMPREPLY=($(compgen -W "download dl install i env e version v help h completion" -- "$cur"))
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$cmd" in
|
||||||
|
download|dl)
|
||||||
|
COMPREPLY=($(compgen -W "` + downloadFlags + `" -- "$cur"))
|
||||||
|
;;
|
||||||
|
install|i)
|
||||||
|
COMPREPLY=($(compgen -d -- "$cur"))
|
||||||
|
;;
|
||||||
|
env|e)
|
||||||
|
COMPREPLY=($(compgen -W "--bin -h --help" -- "$cur"))
|
||||||
|
;;
|
||||||
|
completion)
|
||||||
|
COMPREPLY=($(compgen -W "bash zsh" -- "$cur"))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
complete -F _vintner_complete vintner
|
||||||
|
`
|
||||||
|
|
||||||
|
var zshCompletionScript = `#compdef vintner
|
||||||
|
# vintner zsh completion - source <(vintner completion zsh)
|
||||||
|
|
||||||
|
_vintner() {
|
||||||
|
local -a subcommands
|
||||||
|
subcommands=(
|
||||||
|
'download:fetch and unpack MSVC/WinSDK/WDK'
|
||||||
|
'dl:alias for download'
|
||||||
|
'install:wire up wrappers for a downloaded MSVC'
|
||||||
|
'i:alias for install'
|
||||||
|
'env:print INCLUDE/LIB for native clang-cl/lld-link use'
|
||||||
|
'e:alias for env'
|
||||||
|
'version:print the version'
|
||||||
|
'v:alias for version'
|
||||||
|
'help:print usage'
|
||||||
|
'h:alias for help'
|
||||||
|
'completion:print a shell completion script'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (( CURRENT == 2 )); then
|
||||||
|
_describe 'command' subcommands
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${words[2]}" in
|
||||||
|
download|dl)
|
||||||
|
local -a flags
|
||||||
|
flags=(
|
||||||
|
'--dest[directory to install into]:directory:_files -/'
|
||||||
|
'--cache[persistent download cache directory]:directory:_files -/'
|
||||||
|
'--major[major VS version]:version:'
|
||||||
|
'--preview[use the preview/insiders channel]'
|
||||||
|
'--manifest[use a predownloaded installer manifest file]:file:_files'
|
||||||
|
'--accept-license[do not prompt for accepting the license]'
|
||||||
|
'--msvc-version[install a specific MSVC toolchain version]:version:'
|
||||||
|
'--sdk-version[install a specific Windows SDK version]:version:'
|
||||||
|
'--host-arch[host architecture]:arch:(x86 x64 arm64)'
|
||||||
|
'--only-host[only download packages matching the host architecture]'
|
||||||
|
'--language[preferred package language]:language:'
|
||||||
|
'--include-optional[include all optional dependencies]'
|
||||||
|
'--skip-recommended[skip recommended dependencies]'
|
||||||
|
'--only-download[stop after downloading package files]'
|
||||||
|
'--only-unpack[unpack without pruning to just the CLI tools]'
|
||||||
|
'--keep-unpack[keep the scratch unpack dir]'
|
||||||
|
'--skip-patch[do not apply the Wine compatibility patches]'
|
||||||
|
'--list-workloads[list available workloads and exit]'
|
||||||
|
'--list-components[list available components and exit]'
|
||||||
|
'--print-deps-tree[print the dependency tree and exit]'
|
||||||
|
'--with-wdk[also fetch the Windows Driver Kit]'
|
||||||
|
'--architecture[target architecture]:arch:(x86 x64 arm arm64 host)'
|
||||||
|
'--ignore[package id to skip]:package id:'
|
||||||
|
'-h[show help]'
|
||||||
|
'--help[show help]'
|
||||||
|
)
|
||||||
|
_arguments $flags
|
||||||
|
;;
|
||||||
|
install|i)
|
||||||
|
_files -/
|
||||||
|
;;
|
||||||
|
env|e)
|
||||||
|
_arguments \
|
||||||
|
'--bin[bin/<arch> directory produced by install]:directory:_files -/' \
|
||||||
|
'-h[show help]' '--help[show help]'
|
||||||
|
;;
|
||||||
|
completion)
|
||||||
|
_values 'shell' bash zsh
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_vintner "$@"
|
||||||
|
`
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestCompletionScriptsAreSyntacticallyValid catches the easy way to break
|
||||||
|
// these: a typo in the hand-maintained flag lists that produces invalid
|
||||||
|
// shell syntax. It shells out to bash/zsh -n rather than parsing the script
|
||||||
|
// itself, so it's testing exactly what a user's shell would see.
|
||||||
|
func TestCompletionScriptsAreSyntacticallyValid(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
shell string
|
||||||
|
script string
|
||||||
|
}{
|
||||||
|
{"bash", bashCompletionScript},
|
||||||
|
{"zsh", zshCompletionScript},
|
||||||
|
} {
|
||||||
|
t.Run(tc.shell, func(t *testing.T) {
|
||||||
|
if _, err := exec.LookPath(tc.shell); err != nil {
|
||||||
|
t.Skipf("%s not installed", tc.shell)
|
||||||
|
}
|
||||||
|
cmd := exec.Command(tc.shell, "-n", "/dev/stdin")
|
||||||
|
cmd.Stdin = strings.NewReader(tc.script)
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("%s -n rejected the completion script: %v\n%s", tc.shell, err, out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunCompletionUnknownShell(t *testing.T) {
|
||||||
|
if code := runCompletion([]string{"fish"}); code != 1 {
|
||||||
|
t.Errorf("runCompletion([\"fish\"]) = %d, want 1", code)
|
||||||
|
}
|
||||||
|
if code := runCompletion(nil); code != 1 {
|
||||||
|
t.Errorf("runCompletion(nil) = %d, want 1", code)
|
||||||
|
}
|
||||||
|
if code := runCompletion([]string{"bash", "extra"}); code != 1 {
|
||||||
|
t.Errorf("runCompletion with extra arg = %d, want 1", code)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,8 @@ func runCLI(args []string) int {
|
|||||||
return runInstall(args[1:])
|
return runInstall(args[1:])
|
||||||
case "env", "e":
|
case "env", "e":
|
||||||
return runEnv(args[1:])
|
return runEnv(args[1:])
|
||||||
|
case "completion":
|
||||||
|
return runCompletion(args[1:])
|
||||||
case "version", "v", "--version":
|
case "version", "v", "--version":
|
||||||
fmt.Println("vintner " + version)
|
fmt.Println("vintner " + version)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ Usage:
|
|||||||
vintner env (e) --bin <dir/bin/arch> print INCLUDE/LIB for native clang-cl/lld-link use
|
vintner env (e) --bin <dir/bin/arch> print INCLUDE/LIB for native clang-cl/lld-link use
|
||||||
vintner version (v) print the version
|
vintner version (v) print the version
|
||||||
vintner help (h) show this message
|
vintner help (h) show this message
|
||||||
|
vintner completion bash|zsh print a shell completion script
|
||||||
|
|
||||||
Run "vintner <command> --help" for that command's own options - download
|
Run "vintner <command> --help" for that command's own options - download
|
||||||
has many, including --with-wdk, --list-workloads, --list-components and
|
has many, including --with-wdk, --list-workloads, --list-components and
|
||||||
@@ -81,6 +82,7 @@ has many, including --with-wdk, --list-workloads, --list-components and
|
|||||||
|
|
||||||
--dest/[dir] default to ~/.vintner if omitted.
|
--dest/[dir] default to ~/.vintner if omitted.
|
||||||
Language: set VINTNER_LANG=ru (or LANG=ru_RU...) for Russian output.
|
Language: set VINTNER_LANG=ru (or LANG=ru_RU...) for Russian output.
|
||||||
|
Completion: source <(vintner completion bash) # or zsh
|
||||||
|
|
||||||
Once installed, add <dir>/bin/<arch> to PATH and invoke the tools directly:
|
Once installed, add <dir>/bin/<arch> to PATH and invoke the tools directly:
|
||||||
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
||||||
@@ -94,6 +96,7 @@ Once installed, add <dir>/bin/<arch> to PATH and invoke the tools directly:
|
|||||||
vintner env (e) --bin <dir/bin/arch> вывести INCLUDE/LIB для clang-cl/lld-link напрямую
|
vintner env (e) --bin <dir/bin/arch> вывести INCLUDE/LIB для clang-cl/lld-link напрямую
|
||||||
vintner version (v) показать версию
|
vintner version (v) показать версию
|
||||||
vintner help (h) показать эту справку
|
vintner help (h) показать эту справку
|
||||||
|
vintner completion bash|zsh вывести скрипт автодополнения для оболочки
|
||||||
|
|
||||||
Запустите «vintner <команда> --help» для параметров конкретной команды —
|
Запустите «vintner <команда> --help» для параметров конкретной команды —
|
||||||
у download их много, включая --with-wdk, --list-workloads, --list-components
|
у download их много, включая --with-wdk, --list-workloads, --list-components
|
||||||
@@ -101,6 +104,7 @@ Once installed, add <dir>/bin/<arch> to PATH and invoke the tools directly:
|
|||||||
|
|
||||||
--dest/[каталог] по умолчанию — ~/.vintner.
|
--dest/[каталог] по умолчанию — ~/.vintner.
|
||||||
Язык: установите VINTNER_LANG=en (или LANG=en_US...) для вывода на английском.
|
Язык: установите VINTNER_LANG=en (или LANG=en_US...) для вывода на английском.
|
||||||
|
Автодополнение: source <(vintner completion bash) # или zsh
|
||||||
|
|
||||||
После установки добавьте <dir>/bin/<arch> в PATH и вызывайте инструменты напрямую:
|
После установки добавьте <dir>/bin/<arch> в PATH и вызывайте инструменты напрямую:
|
||||||
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
||||||
|
|||||||
Reference in New Issue
Block a user