diff --git a/camelcase.go b/camelcase.go index 20dfda1..d817110 100644 --- a/camelcase.go +++ b/camelcase.go @@ -42,37 +42,37 @@ const ( // // Examples // -// "" => [""] -// "lowercase" => ["lowercase"] -// "Class" => ["Class"] -// "MyClass" => ["My", "Class"] -// "MyC" => ["My", "C"] -// "HTML" => ["HTML"] -// "PDFLoader" => ["PDF", "Loader"] -// "AString" => ["A", "String"] -// "SimpleXMLParser" => ["Simple", "XML", "Parser"] -// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] -// "GL11Version" => ["GL11", "Version"] -// "99Bottles" => ["99", "Bottles"] -// "May5" => ["May5"] -// "BFG9000" => ["BFG9000"] -// "BöseÜberraschung" => ["Böse", "Überraschung"] -// "Two spaces" => ["Two", " ", "spaces"] -// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] +// "" => [""] +// "lowercase" => ["lowercase"] +// "Class" => ["Class"] +// "MyClass" => ["My", "Class"] +// "MyC" => ["My", "C"] +// "HTML" => ["HTML"] +// "PDFLoader" => ["PDF", "Loader"] +// "AString" => ["A", "String"] +// "SimpleXMLParser" => ["Simple", "XML", "Parser"] +// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] +// "GL11Version" => ["GL11", "Version"] +// "99Bottles" => ["99", "Bottles"] +// "May5" => ["May5"] +// "BFG9000" => ["BFG9000"] +// "BöseÜberraschung" => ["Böse", "Überraschung"] +// "Two spaces" => ["Two", " ", "spaces"] +// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] // // Splitting rules // -// 1) If string is not valid UTF-8, return it without splitting as +// 1. If string is not valid UTF-8, return it without splitting as // single item array. -// 2) Assign all unicode characters into one of 4 sets: lower case +// 2. Assign all unicode characters into one of 4 sets: lower case // letters, upper case letters, numbers, and all other characters. -// 3) Iterate through characters of string, introducing splits +// 3. Iterate through characters of string, introducing splits // between adjacent characters that belong to different sets. -// 4) Iterate through array of split strings, and if a given string +// 4. Iterate through array of split strings, and if a given string // is upper case: -// if subsequent string is lower case: -// move last character of upper case string to beginning of -// lower case string +// if subsequent string is lower case: +// move last character of upper case string to beginning of +// lower case string func split(src string) (entries []string) { // don't split invalid utf8 if !utf8.ValidString(src) { diff --git a/camelcase_test.go b/camelcase_test.go index 4a2c0b1..97b096b 100644 --- a/camelcase_test.go +++ b/camelcase_test.go @@ -2,7 +2,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2015 Fatih Arslan +// # Copyright (c) 2015 Fatih Arslan // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in diff --git a/example/example b/example/example index 99fa902..c1312d3 100755 Binary files a/example/example and b/example/example differ diff --git a/example/opts/options.go b/example/opts/options.go index de31c8d..5bea687 100644 --- a/example/opts/options.go +++ b/example/opts/options.go @@ -31,8 +31,8 @@ type Machines string // Complete provides user@host completions. func (m *Machines) Complete(ctx carapace.Context) carapace.Action { - if strings.Contains(ctx.CallbackValue, "@") { - prefix := strings.SplitN(ctx.CallbackValue, "@", 2)[0] + if strings.Contains(ctx.Value, "@") { + prefix := strings.SplitN(ctx.Value, "@", 2)[0] return net.ActionHosts().Invoke(ctx).Prefix(prefix + "@").ToA() } else { return net.ActionHosts() diff --git a/flags.go b/flags.go index 73b4324..0f2a4e8 100644 --- a/flags.go +++ b/flags.go @@ -12,26 +12,27 @@ // package main // // import ( -// "github.com/reeflective/flags/example/commands" // -// "github.com/reeflective/flags" -// genflags "github.com/reeflective/flags/gen/flags" +// "github.com/reeflective/flags/example/commands" // -// "github.com/reeflective/flags/validator" -// "github.com/reeflective/flags/gen/completions" -// ) +// "github.com/reeflective/flags" +// genflags "github.com/reeflective/flags/gen/flags" +// +// "github.com/reeflective/flags/validator" +// "github.com/reeflective/flags/gen/completions" // -// func main() { -// var opts []flags.OptFunc +// ) // -// opts = append(opts, flags.Validator(validator.New())) +// func main() { +// var opts []flags.OptFunc // -// rootData := &commands.Root{} -// rootCmd := genflags.Generate(rootData, opts...) +// opts = append(opts, flags.Validator(validator.New())) // -// comps, _ := completions.Generate(rootCmd, rootData, nil) -// } +// rootData := &commands.Root{} +// rootCmd := genflags.Generate(rootData, opts...) // +// comps, _ := completions.Generate(rootCmd, rootData, nil) +// } // // 2) Global parsing options (base) ------------------------------------------------------ // @@ -64,7 +65,6 @@ // tag attached to them. This is because by default the library does not considers untagged field anymore. // func ParseAll() // -// // 3) Special parsing options/functions--------------------------------------------------- // // ValidateFunc describes a validation func, that takes string val for flag from command line, @@ -73,13 +73,10 @@ // // type ValidateFunc func(val string, field reflect.StructField, data interface{}) error // -// // Validator sets validator function for flags. // Check existing validators in flags/validator and flags/validator/govalidator packages. // // func Validator(val ValidateFunc) -// -// // FlagFunc is a generic function that can be applied to each // value that will end up being a flags *Flag, so that users // can perform more arbitrary operations on each, such as checking @@ -87,10 +84,8 @@ // // type FlagFunc func(flag string, tag tag.MultiTag, val reflect.Value) error // -// // FlagHandler sets the handler function for flags, in order to perform arbitrary // operations on the value of the flag identified by the name parameter of FlagFunc. // // func FlagHandler(val FlagFunc) -// package flags diff --git a/go.mod b/go.mod index aff4831..e45c9e1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-playground/validator/v10 v10.11.1 github.com/rsteube/carapace v0.30.0 github.com/rsteube/carapace-bin v0.19.0 - github.com/spf13/cobra v1.6.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.0 ) @@ -25,4 +25,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/rsteube/carapace v0.30.0 => github.com/reeflective/carapace v0.25.2-0.20230106225838-382407e213d4 +replace github.com/rsteube/carapace v0.30.0 => github.com/reeflective/carapace v0.25.2-0.20230416191807-fc9b8c3aa6f6 diff --git a/go.sum b/go.sum index ff7204c..d236223 100644 --- a/go.sum +++ b/go.sum @@ -13,7 +13,6 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -29,16 +28,16 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/reeflective/carapace v0.25.2-0.20230106225838-382407e213d4 h1:FTPSPEnA0dklTQm61gv7gtYh85/WFqeJSSENa7BCdxk= -github.com/reeflective/carapace v0.25.2-0.20230106225838-382407e213d4/go.mod h1:/ALYHicIpak6TjQnKl7HupclqJydy2LQb6CkawYBxDo= +github.com/reeflective/carapace v0.25.2-0.20230416191807-fc9b8c3aa6f6 h1:3HHTRiXvaEz8iACxwlOBc9jHDYxYNvW60U63Q97/31w= +github.com/reeflective/carapace v0.25.2-0.20230416191807-fc9b8c3aa6f6/go.mod h1:jkLt41Ne2TD2xPuMdX/2O05Smhy8vMgG7O2TYvC0yOc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rsteube/carapace-bin v0.19.0 h1:pmWOrtO0Fz4G+55OKHjjA4ihIKZKzDZh3Z8X1pY8IBk= github.com/rsteube/carapace-bin v0.19.0/go.mod h1:yAF4advL85gx7ZFxYYsJu8Rgp2akz4TqvD6M0Bg0VGc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/vendor/github.com/rsteube/carapace/.dockerignore b/vendor/github.com/rsteube/carapace/.dockerignore index 72e8ffc..fb89b31 100644 --- a/vendor/github.com/rsteube/carapace/.dockerignore +++ b/vendor/github.com/rsteube/carapace/.dockerignore @@ -1 +1,2 @@ * +!.dockerfile diff --git a/vendor/github.com/rsteube/carapace/.goreleaser.yml b/vendor/github.com/rsteube/carapace/.goreleaser.yml new file mode 100644 index 0000000..1a57ff3 --- /dev/null +++ b/vendor/github.com/rsteube/carapace/.goreleaser.yml @@ -0,0 +1,40 @@ +before: + hooks: + - go mod download +builds: + - id: example + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + main: ./example + binary: example + - id: example-nonposix + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + main: ./example-nonposix + binary: example-nonposix +archives: + - replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 + name_template: "example_{{ .Version }}_{{ .Os }}_{{ .Arch }}" +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/vendor/github.com/rsteube/carapace/Dockerfile b/vendor/github.com/rsteube/carapace/Dockerfile index 5b492f0..91698fa 100644 --- a/vendor/github.com/rsteube/carapace/Dockerfile +++ b/vendor/github.com/rsteube/carapace/Dockerfile @@ -1,16 +1,16 @@ -FROM cimg/go:1.18.1 as base +FROM golang:1.20-bullseye as base LABEL org.opencontainers.image.source https://github.com/rsteube/carapace USER root FROM base as bat -ARG version=0.20.0 +ARG version=0.22.1 RUN curl -L https://github.com/sharkdp/bat/releases/download/v${version}/bat-v${version}-x86_64-unknown-linux-gnu.tar.gz \ | tar -C /usr/local/bin/ --strip-components=1 -xvz bat-v${version}-x86_64-unknown-linux-gnu/bat \ && chmod +x /usr/local/bin/bat FROM base as ble RUN git clone --recursive https://github.com/akinomyoga/ble.sh.git \ - && apt-get update && apt-get install gawk \ + && apt-get update && apt-get install -y gawk \ && make -C ble.sh FROM base as elvish @@ -19,7 +19,7 @@ RUN curl https://dl.elv.sh/linux-amd64/elvish-v${version}.tar.gz | tar -xvz \ && mv elvish-* /usr/local/bin/elvish FROM base as goreleaser -ARG version=1.8.3 +ARG version=1.15.1 RUN curl -L https://github.com/goreleaser/goreleaser/releases/download/v${version}/goreleaser_Linux_x86_64.tar.gz | tar -xvz goreleaser \ && mv goreleaser /usr/local/bin/goreleaser @@ -33,12 +33,12 @@ FROM rsteube/ion-poc as ion-poc # && sudo make update-shells prefix=/usr FROM base as nushell -ARG version=0.61.0 -RUN curl -L https://github.com/nushell/nushell/releases/download/${version}/nu_${version//./_}_linux.tar.gz | tar -xvz \ - && mv nu_${version//./_}_linux/nushell-${version}/nu* /usr/local/bin +ARG version=0.75.0 +RUN curl -L https://github.com/nushell/nushell/releases/download/${version}/nu-${version}-x86_64-unknown-linux-gnu.tar.gz | tar -xvz \ + && mv nu-${version}-x86_64-unknown-linux-gnu/nu* /usr/local/bin FROM base as oil -ARG version=0.9.9 +ARG version=0.14.0 RUN apt-get update && apt-get install -y libreadline-dev RUN curl https://www.oilshell.org/download/oil-${version}.tar.gz | tar -xvz \ && cd oil-*/ \ @@ -46,14 +46,8 @@ RUN curl https://www.oilshell.org/download/oil-${version}.tar.gz | tar -xvz \ && make \ && ./install -FROM base as shellcheck -ARG version=stable -RUN wget -qO- "https://github.com/koalaman/shellcheck/releases/download/${version?}/shellcheck-${version?}.linux.x86_64.tar.xz" | tar -xJv shellcheck-stable/shellcheck \ - && mv shellcheck-stable/shellcheck /usr/local/bin/ \ - && chmod +x /usr/local/bin/shellcheck - FROM base as starship -ARG version=1.6.3 +ARG version=1.12.0 RUN wget -qO- "https://github.com/starship/starship/releases/download/v${version}/starship-x86_64-unknown-linux-gnu.tar.gz" | tar -xvz starship \ && mv starship /usr/local/bin/ @@ -63,22 +57,22 @@ RUN wget -qO- "https://github.com/sharkdp/vivid/releases/download/v${version}/vi && mv vivid-v${version}-x86_64-unknown-linux-gnu/vivid /usr/local/bin/ FROM base as mdbook -ARG version=0.4.18 +ARG version=0.4.25 RUN curl -L "https://github.com/rust-lang/mdBook/releases/download/v${version}/mdbook-v${version}-x86_64-unknown-linux-gnu.tar.gz" | tar -xvz mdbook \ && curl -L "https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases/download/v0.7.0/mdbook-linkcheck-v0.7.0-x86_64-unknown-linux-gnu.tar.gz" | tar -xvz mdbook-linkcheck \ && mv mdbook* /usr/local/bin/ FROM base -RUN wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb \ - && dpkg -i packages-microsoft-prod.deb \ - && rm packages-microsoft-prod.deb \ - && add-apt-repository universe +RUN apt-get update && apt-get install -y libicu67 +RUN wget -q https://github.com/PowerShell/PowerShell/releases/download/v7.3.0/powershell_7.3.0-1.deb_amd64.deb\ + && dpkg -i powershell_7.3.0-1.deb_amd64.deb \ + && rm powershell_7.3.0-1.deb_amd64.deb RUN apt-get update \ && apt-get install -y fish \ elvish \ - powershell \ python3-pip \ + shellcheck \ tcsh \ zsh \ expect @@ -88,8 +82,10 @@ RUN pip3 install --no-cache-dir --disable-pip-version-check xonsh prompt_toolkit RUN pwsh -Command "Install-Module PSScriptAnalyzer -Scope AllUsers -Force" +RUN git config --system safe.directory '*' + COPY --from=bat /usr/local/bin/* /usr/local/bin/ -COPY --from=ble /home/circleci/project/ble.sh /opt/ble.sh +COPY --from=ble /go/ble.sh /opt/ble.sh COPY --from=elvish /usr/local/bin/* /usr/local/bin/ COPY --from=goreleaser /usr/local/bin/* /usr/local/bin/ #COPY --from=ion /ion/target/release/ion /usr/local/bin/ @@ -97,126 +93,11 @@ COPY --from=ion-poc /usr/local/bin/ion /usr/local/bin/ COPY --from=nushell /usr/local/bin/* /usr/local/bin/ COPY --from=mdbook /usr/local/bin/* /usr/local/bin/ COPY --from=oil /usr/local/bin/* /usr/local/bin/ -COPY --from=shellcheck /usr/local/bin/* /usr/local/bin/ COPY --from=starship /usr/local/bin/* /usr/local/bin/ COPY --from=vivid /usr/local/bin/* /usr/local/bin/ -RUN ln -s /carapace/example/example /usr/local/bin/example - -RUN echo -e "\n\ -[shell]\n\ -disabled = false\n\ -unknown_indicator = \"oil\"" \ - > ~/.config/starship.toml - -# bash -RUN echo -e "\n\ -export SHELL=bash\n\ -export STARSHIP_SHELL=bash\n\ -export LS_COLORS=\"\$(vivid generate dracula)\"\n\ -[[ ! -z \$BLE ]] && source /opt/ble.sh/out/ble.sh \n\ -eval \"\$(starship init bash)\"\n\ -source <(\${TARGET} _carapace)" \ - > ~/.bashrc - -# fish -RUN mkdir -p ~/.config/fish \ - && echo -e "\n\ - set SHELL 'fish'\n\ - set STARSHIP_SHELL 'fish'\n\ - set LS_COLORS (vivid generate dracula)\n\ - starship init fish | source \n\ - mkdir -p ~/.config/fish/completions\n\ - \$TARGET _carapace fish | source" \ - > ~/.config/fish/config.fish - -# elvish -RUN mkdir -p ~/.elvish/lib \ - && echo -e "\ - set-env SHELL elvish\n\ - set-env STARSHIP_SHELL elvish\n\ - set-env LS_COLORS (vivid generate dracula)\n\ - set edit:prompt = { starship prompt }\n\ - eval (\$E:TARGET _carapace|slurp)" \ - > ~/.elvish/rc.elv - -# ion -RUN mkdir -p ~/.config/ion \ - && echo -e "\ - fn PROMPT\n\ - printf 'carapace-ion '\n\ - end" \ - > ~/.config/ion/initrc - -# nushell -RUN touch /carapace.nu \ - && mkdir -p ~/.config/nushell \ - && starship init nushell > ~/.config/nushell/starship.nu \ - && echo -e "\ -ln -s \$env.TARGET /tmp/target \n\ -/tmp/target _carapace | save /carapace.nu \n\ -source /carapace.nu \n\ -" > ~/.config/nushell/config.nu \ - && echo -e "\ -source ~/.config/nushell/starship.nu \n\ -" > ~/.config/nushell/env.nu - -# oil -RUN mkdir -p ~/.config/oil \ - && echo -e "\n\ - export SHELL='oil'\n\ - export STARSHIP_SHELL='oil'\n\ - export LS_COLORS=\"\$(vivid generate dracula)\"\n\ - PS1=\"\$(starship prompt)\"\n\ - source <(\${TARGET} _carapace)" \ - > ~/.config/oil/oshrc - -# powershell -RUN mkdir -p ~/.config/powershell \ - && echo -e "\n\ - \$env:SHELL = 'powershell'\n\ - \$env:STARSHIP_SHELL = 'powershell'\n\ - \$env:LS_COLORS = (&vivid generate dracula)\n\ - Invoke-Expression (&starship init powershell)\n\ - Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete\n\ - & \$Env:TARGET _carapace | out-string | Invoke-Expression" \ - > ~/.config/powershell/Microsoft.PowerShell_profile.ps1 - -# tcsh -RUN echo -e "\n\ - eval `starship init tcsh`\n\ - set autolist\n\ - eval "'`'"\${TARGET} _carapace"'`'"" \ - > ~/.tcshrc - -# xonsh -RUN mkdir -p ~/.config/xonsh \ - && echo -e "\n\ -\$SHELL=\"xonsh\"\n\ -\$STARSHIP_SHELL=\"xonsh\"\n\ -\$LS_COLROS=\$(vivid generate dracula)\n\ -\$PROMPT=lambda: \$(starship prompt)\n\ -\$COMPLETIONS_CONFIRM=True\n\ -exec(\$(\$TARGET _carapace xonsh))"\ - > ~/.config/xonsh/rc.xsh - -# zsh -RUN echo -e "\n\ - export SHELL=zsh\n\ - export STARSHIP_SHELL=zsh\n\ - export LS_COLORS=\"\$(vivid generate dracula)\"\n\ - eval \"\$(starship init zsh)\"\n\ - \n\ - zstyle ':completion:*' menu select \n\ - zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*' \n\ - \n\ - autoload -U compinit && compinit \n\ - source <(\$TARGET _carapace zsh)" > ~/.zshrc +ADD .dockerfile/root /root +ADD .dockerfile/usr/local/bin/* /usr/local/bin/ ENV TERM xterm -RUN echo -e "#"'!'"/bin/bash\n\ - export PATH=\${PATH}:\$(dirname \"\${TARGET}\")\n\ - exec \"\$@\"" \ - > /entrypoint.sh \ - && chmod a+x /entrypoint.sh -ENTRYPOINT [ "/entrypoint.sh" ] +ENTRYPOINT [ "entrypoint.sh" ] diff --git a/vendor/github.com/rsteube/carapace/README.md b/vendor/github.com/rsteube/carapace/README.md index 1074139..8344123 100644 --- a/vendor/github.com/rsteube/carapace/README.md +++ b/vendor/github.com/rsteube/carapace/README.md @@ -1,6 +1,5 @@ # carapace -[![CircleCI](https://circleci.com/gh/rsteube/carapace.svg?style=svg)](https://circleci.com/gh/rsteube/carapace) [![PkgGoDev](https://pkg.go.dev/badge/github.com/rsteube/carapace)](https://pkg.go.dev/github.com/rsteube/carapace) [![documentation](https://img.shields.io/badge/‌-documentation-blue?logo=gitbook)](https://rsteube.github.io/carapace/) [![GoReportCard](https://goreportcard.com/badge/github.com/rsteube/carapace)](https://goreportcard.com/report/github.com/rsteube/carapace) @@ -46,8 +45,11 @@ See [carapace-bin](https://github.com/rsteube/carapace-bin) for examples. ## Related Projects - [carapace-bin](https://github.com/rsteube/carapace-bin) multi-shell multi-command argument completer +- [carapace-bridge](https://github.com/rsteube/carapace-bridge) completion bridge - [carapace-pflag](https://github.com/rsteube/carapace-pflag) Drop-in replacement for spf13/pflag with support for non-posix variants - [carapace-spec](https://github.com/rsteube/carapace-spec) define simple completions using a spec file - [carapace-spec-clap](https://github.com/rsteube/carapace-spec-clap) spec generation for clap-rs/clap +- [carapace-spec-kong](https://github.com/rsteube/carapace-spec-kong) spec generation for alecthomas/kong +- [carapace-spec-urfavecli](https://github.com/rsteube/carapace-spec-urfavecli) spec generation for urfave/cli [cobra]:https://github.com/spf13/cobra diff --git a/vendor/github.com/rsteube/carapace/action.go b/vendor/github.com/rsteube/carapace/action.go index 36d4498..4ad418d 100644 --- a/vendor/github.com/rsteube/carapace/action.go +++ b/vendor/github.com/rsteube/carapace/action.go @@ -31,17 +31,22 @@ func (a Action) Cache(timeout time.Duration, keys ...pkgcache.Key) Action { cachedCallback := a.callback _, file, line, _ := runtime.Caller(1) // generate uid from wherever Cache() was called a.callback = func(c Context) Action { - if cacheFile, err := cache.File(file, line, keys...); err == nil { - if rawValues, err := cache.Load(cacheFile, timeout); err == nil { - return Action{rawValues: rawValues} - } - invokedAction := (Action{callback: cachedCallback}).Invoke(c) - if invokedAction.meta.Messages.IsEmpty() { - _ = cache.Write(cacheFile, invokedAction.rawValues) + cacheFile, err := cache.File(file, line, keys...) + if err != nil { + return cachedCallback(c) + } + + if cached, err := cache.Load(cacheFile, timeout); err == nil { + return Action{meta: cached.Meta, rawValues: cached.Values} + } + + invokedAction := (Action{callback: cachedCallback}).Invoke(c) + if invokedAction.meta.Messages.IsEmpty() { + if cacheFile, err := cache.File(file, line, keys...); err == nil { // regenerate as cache keys might have changed due to invocation + _ = cache.Write(cacheFile, invokedAction.export()) } - return invokedAction.ToA() } - return cachedCallback(c) + return invokedAction.ToA() } } return a @@ -58,19 +63,13 @@ func (a Action) Invoke(c Context) InvokedAction { if c.Parts == nil { c.Parts = []string{} } - return InvokedAction{a.nestedAction(c, 10)} -} -func (a Action) nestedAction(c Context, maxDepth int) Action { - if maxDepth < 0 { - return ActionMessage("maximum recursion depth exceeded") - } if a.rawValues == nil && a.callback != nil { - result := a.callback(c).nestedAction(c, maxDepth-1) + result := a.callback(c).Invoke(c) result.meta.Merge(a.meta) return result } - return a + return InvokedAction{a} } // NoSpace disables space suffix for given characters (or all if none are given). @@ -101,7 +100,7 @@ func (a Action) UsageF(f func() string) Action { }) } -// Style sets the style +// Style sets the style. // // ActionValues("yes").Style(style.Green) // ActionValues("no").Style(style.Red) @@ -111,7 +110,7 @@ func (a Action) Style(s string) Action { }) } -// Style sets the style using a reference +// Style sets the style using a reference. // // ActionValues("value").StyleR(&style.Carapace.Value) // ActionValues("description").StyleR(&style.Carapace.Value) @@ -124,7 +123,7 @@ func (a Action) StyleR(s *string) Action { }) } -// Style sets the style using a function +// Style sets the style using a function. // // ActionValues("dir/", "test.txt").StyleF(style.ForPathExt) // ActionValues("true", "false").StyleF(style.ForKeyword) @@ -162,7 +161,7 @@ func (a Action) TagF(f func(value string) string) Action { }) } -// Chdir changes the current working directory to the named directory during invocation. +// Chdir changes the current working directory to the named directory for the duration of invocation. func (a Action) Chdir(dir string) Action { return ActionCallback(func(c Context) Action { abs, err := c.Abs(dir) @@ -216,7 +215,7 @@ func (a Action) UniqueList(divider string) Action { }) } -// Prefix adds a prefix to values (only the ones inserted, not the display values) +// Prefix adds a prefix to values (only the ones inserted, not the display values). // // carapace.ActionValues("melon", "drop", "fall").Prefix("water") func (a Action) Prefix(prefix string) Action { @@ -225,7 +224,7 @@ func (a Action) Prefix(prefix string) Action { }) } -// Suffix adds a suffx to values (only the ones inserted, not the display values) +// Suffix adds a suffx to values (only the ones inserted, not the display values). // // carapace.ActionValues("apple", "melon", "orange").Suffix("juice") func (a Action) Suffix(suffix string) Action { @@ -233,3 +232,28 @@ func (a Action) Suffix(suffix string) Action { return a.Invoke(c).Suffix(suffix).ToA() }) } + +// Timeout sets the maximum duration an Action may take to invoke. +// +// carapace.ActionCallback(func(c carapace.Context) carapace.Action { +// time.Sleep(2*time.Second) +// return carapace.ActionValues("done") +// }).Timeout(1*time.Second, carapace.ActionMessage("timeout exceeded")) +func (a Action) Timeout(d time.Duration, alternative Action) Action { + return ActionCallback(func(c Context) Action { + currentChannel := make(chan string, 1) + + var result InvokedAction + go func() { + result = a.Invoke(c) + currentChannel <- "" + }() + + select { + case <-currentChannel: + case <-time.After(d): + return alternative + } + return result.ToA() + }) +} diff --git a/vendor/github.com/rsteube/carapace/carapace.go b/vendor/github.com/rsteube/carapace/carapace.go index 175a8ba..6573567 100644 --- a/vendor/github.com/rsteube/carapace/carapace.go +++ b/vendor/github.com/rsteube/carapace/carapace.go @@ -17,36 +17,33 @@ type Carapace struct { // Gen initialized Carapace for given command. func Gen(cmd *cobra.Command) *Carapace { addCompletionCommand(cmd) - - cobra.OnInitialize(func() { - if opts.BridgeCompletion { - registerValidArgsFunction(cmd) - registerFlagCompletion(cmd) - } - }) + storage.bridge(cmd) return &Carapace{ cmd: cmd, } } -// PreRun sets a function to be run before completion (use on rootCmd). +// PreRun sets a function to be run before completion. func (c Carapace) PreRun(f func(cmd *cobra.Command, args []string)) { - if completionCmd, _, err := c.cmd.Find([]string{"_carapace"}); err == nil { - completionCmd.PreRun = func(cmd *cobra.Command, args []string) { - if len(args) > 2 { // skip script generation - f(c.cmd, args[2:]) - } + if entry := storage.get(c.cmd); entry.prerun != nil { + _f := entry.prerun + entry.prerun = func(cmd *cobra.Command, args []string) { + // TODO yuck - probably best to append to a slice in storage + _f(cmd, args) + f(cmd, args) } + } else { + entry.prerun = f } } -// PreInvoke sets a function to alter actions before they are invoked (use on rootCmd). +// PreInvoke sets a function to alter actions before they are invoked. func (c Carapace) PreInvoke(f func(cmd *cobra.Command, flag *pflag.Flag, action Action) Action) { if entry := storage.get(c.cmd); entry.preinvoke != nil { _f := entry.preinvoke entry.preinvoke = func(cmd *cobra.Command, flag *pflag.Flag, action Action) Action { - return f(cmd, flag, _f(cmd, flag, action)) // TODO verify if this is correct + return f(cmd, flag, _f(cmd, flag, action)) } } else { entry.preinvoke = f diff --git a/vendor/github.com/rsteube/carapace/command.go b/vendor/github.com/rsteube/carapace/command.go index ed88d19..6de00c4 100644 --- a/vendor/github.com/rsteube/carapace/command.go +++ b/vendor/github.com/rsteube/carapace/command.go @@ -21,17 +21,21 @@ func addCompletionCommand(cmd *cobra.Command) { carapaceCmd := &cobra.Command{ Use: "_carapace", Hidden: true, - PreRun: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, args []string) { + LOG.Printf("%#v", os.Args) + if len(args) > 2 && strings.HasPrefix(args[2], "_") { cmd.Hidden = false } - }, - Run: func(cmd *cobra.Command, args []string) { - logger.PrintArgs(os.Args) - if s, err := complete(cmd, args); err != nil { - fmt.Fprintln(io.MultiWriter(cmd.OutOrStderr(), logger.Writer()), err.Error()) + + if !cmd.HasParent() { + panic("missing parent command") // this should never happen + } + + if s, err := complete(cmd.Parent(), args); err != nil { + fmt.Fprintln(io.MultiWriter(cmd.OutOrStderr(), LOG.Writer()), err.Error()) } else { - fmt.Fprintln(io.MultiWriter(cmd.OutOrStdout(), logger.Writer()), s) + fmt.Fprintln(io.MultiWriter(cmd.OutOrStdout(), LOG.Writer()), s) } }, FParseErrWhitelist: cobra.FParseErrWhitelist{ @@ -64,7 +68,7 @@ func addCompletionCommand(cmd *cobra.Command) { ActionCallback(func(c Context) Action { args := []string{"_carapace", "export", ""} args = append(args, c.Args[2:]...) - args = append(args, c.CallbackValue) + args = append(args, c.Value) return ActionExecCommand(uid.Executable(), args...)(func(output []byte) Action { if string(output) == "" { return ActionValues() diff --git a/vendor/github.com/rsteube/carapace/compat.go b/vendor/github.com/rsteube/carapace/compat.go index aec14f7..69a02fa 100644 --- a/vendor/github.com/rsteube/carapace/compat.go +++ b/vendor/github.com/rsteube/carapace/compat.go @@ -10,7 +10,7 @@ import ( func registerValidArgsFunction(cmd *cobra.Command) { if cmd.ValidArgsFunction == nil { cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - action := storage.getPositional(cmd, len(args)).Invoke(Context{Args: args, CallbackValue: toComplete}) + action := storage.getPositional(cmd, len(args)).Invoke(Context{Args: args, Value: toComplete}) return cobraValuesFor(action), cobraDirectiveFor(action) } } @@ -18,11 +18,14 @@ func registerValidArgsFunction(cmd *cobra.Command) { func registerFlagCompletion(cmd *cobra.Command) { cmd.Flags().VisitAll(func(f *pflag.Flag) { - cmd.RegisterFlagCompletionFunc(f.Name, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + err := cmd.RegisterFlagCompletionFunc(f.Name, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { a := storage.getFlag(cmd, f.Name) - action := a.Invoke(Context{Args: args, CallbackValue: toComplete}) + action := a.Invoke(Context{Args: args, Value: toComplete}) return cobraValuesFor(action), cobraDirectiveFor(action) }) + if err != nil { + LOG.Printf("failed to register flag completion func: %v", err.Error()) + } }) } diff --git a/vendor/github.com/rsteube/carapace/complete.go b/vendor/github.com/rsteube/carapace/complete.go index b535e30..62367b6 100644 --- a/vendor/github.com/rsteube/carapace/complete.go +++ b/vendor/github.com/rsteube/carapace/complete.go @@ -1,15 +1,11 @@ package carapace import ( - "strings" - "github.com/rsteube/carapace/internal/common" "github.com/rsteube/carapace/internal/config" - "github.com/rsteube/carapace/internal/pflagfork" "github.com/rsteube/carapace/pkg/ps" "github.com/rsteube/carapace/pkg/style" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) // Complete can be used by Go programs wishing to produce completions for @@ -21,10 +17,13 @@ import ( // Also, and before calling `onFinalize` if not nil, the completion storage is cleared. func Complete(cmd *cobra.Command, args []string, onFinalize func()) (common.RawValues, common.Meta) { // Generate the completion as normally done for an external system shell - action, current := generate(cmd, args) + // action, current := generate(cmd, args) + action, context := traverse(cmd, args[2:]) + + invoked := action.Invoke(context) // And adapt/fetch the results from invoked action - return internalValues(action, current, onFinalize) + return internalValues(invoked, context.Value, onFinalize) } func complete(cmd *cobra.Command, args []string) (string, error) { @@ -33,112 +32,25 @@ func complete(cmd *cobra.Command, args []string) (string, error) { return Gen(cmd).Snippet(ps.DetermineShell()) case 1: return Gen(cmd).Snippet(args[0]) - } - - shell := args[0] - - // Generate the completions and get the resulting invoked action. - action, current := generate(cmd, args) - - // And generate the completions string for the target shell caller. - return action.value(shell, current), nil -} - -func generate(cmd *cobra.Command, args []string) (InvokedAction, string) { - current := args[len(args)-1] - previous := "" - if len(args) > 1 { - previous = args[len(args)-2] - } - - if err := config.Load(); err != nil { - return ActionMessage("failed to load config: " + err.Error()).Invoke(Context{CallbackValue: current}), current - } - - targetCmd, targetArgs, err := findTarget(cmd, args) - if err != nil { - return ActionMessage(err.Error()).Invoke(Context{CallbackValue: current}), current - } - - context := NewContext(append(targetArgs, current)) - - // TODO needs more cleanup and tests - var targetAction Action - if flag := lookupFlag(targetCmd, previous); !targetCmd.DisableFlagParsing && flag != nil && flag.NoOptDefVal == "" && !common.IsDash(targetCmd) { // previous arg is a flag and needs a value - targetAction = storage.getFlag(targetCmd, flag.Name) - } else if !targetCmd.DisableFlagParsing && strings.HasPrefix(current, "-") && !common.IsDash(targetCmd) { // assume flag - if strings.Contains(current, "=") { // complete value for optarg flag - if flag := lookupFlag(targetCmd, current); flag != nil && flag.NoOptDefVal != "" { - a := storage.getFlag(targetCmd, flag.Name) - splitted := strings.SplitN(current, "=", 2) - context.CallbackValue = splitted[1] - current = strings.Replace(current, "=", opts.OptArgDelimiter, 1) // revert (potentially) overridden optarg divider for `.value()` invocation below - targetAction = a.Invoke(context).Prefix(splitted[0] + opts.OptArgDelimiter).ToA() // prefix with (potentially) overridden optarg delimiter - } - } else { // complete flagnames - targetAction = actionFlags(targetCmd) + default: + action, context := traverse(cmd, args[2:]) + if err := config.Load(); err != nil { + action = ActionMessage("failed to load config: " + err.Error()) } - } else { - if len(context.Args) > 0 { - context.Args = context.Args[:len(context.Args)-1] // current word being completed is a positional so remove it from context.Args - } - - if common.IsDash(targetCmd) { - dashArgs := targetArgs[targetCmd.ArgsLenAtDash() : len(targetArgs)-1] - context.Args = dashArgs - targetAction = findAction(targetCmd, dashArgs) - } else { - targetAction = findAction(targetCmd, targetArgs) - if targetCmd.HasAvailableSubCommands() && len(targetArgs) <= 1 { - subcommandA := actionSubcommands(targetCmd).Invoke(context) - targetAction = targetAction.Invoke(context).Merge(subcommandA).ToA() - } - } - } - - return targetAction.Invoke(context), current -} - -func findAction(targetCmd *cobra.Command, targetArgs []string) Action { - // TODO handle Action not found - if len(targetArgs) == 0 { - return storage.getPositional(targetCmd, 0) - } - return storage.getPositional(targetCmd, len(targetArgs)-1) -} - -func findTarget(cmd *cobra.Command, args []string) (*cobra.Command, []string, error) { - origArg := []string{} - if len(args) > 2 { - origArg = args[2:] - } - return common.TraverseLenient(cmd, origArg) -} - -func lookupFlag(cmd *cobra.Command, arg string) (flag *pflag.Flag) { - nameOrShorthand := strings.TrimLeft(strings.SplitN(arg, "=", 2)[0], "-") - if strings.HasPrefix(arg, "--") { - flag = cmd.Flags().Lookup(nameOrShorthand) - } else if strings.HasPrefix(arg, "-") && len(nameOrShorthand) > 0 { - if (pflagfork.FlagSet{FlagSet: cmd.Flags()}).IsPosix() { - flag = cmd.Flags().ShorthandLookup(string(nameOrShorthand[len(nameOrShorthand)-1])) - } else { - flag = cmd.Flags().ShorthandLookup(nameOrShorthand) - } + return action.Invoke(context).value(args[0], args[len(args)-1]), nil } - return } -func internalValues(a InvokedAction, current string, onFinalize func()) (common.RawValues, common.Meta) { - unsorted := common.RawValues(a.rawValues) +func internalValues(action InvokedAction, current string, onFinalize func()) (common.RawValues, common.Meta) { + unsorted := action.rawValues sorted := make(common.RawValues, 0) // Ensure values are sorted. - unsorted.EachTag(func(tag string, values common.RawValues) { + unsorted.EachTag(func(_ string, values common.RawValues) { vals := make(common.RawValues, len(values)) for index, val := range values { - if !a.meta.Nospace.Matches(val.Value) { + if !action.meta.Nospace.Matches(val.Value) { val.Value += " " } if val.Style != "" { @@ -152,14 +64,15 @@ func internalValues(a InvokedAction, current string, onFinalize func()) (common. // Merge/filter completions and meta stuff. filtered := sorted.FilterPrefix(current) - filtered = a.meta.Messages.Integrate(filtered, current) + filtered = action.meta.Messages.Integrate(filtered, current) // Reset the storage (empty all commands) and run the finalize function, which is // generally in charge of binding new command instances, with blank flags. if onFinalize != nil { storage = make(_storage) + onFinalize() } - return filtered, a.meta + return filtered, action.meta } diff --git a/vendor/github.com/rsteube/carapace/context.go b/vendor/github.com/rsteube/carapace/context.go index 599c8c6..2cf61c1 100644 --- a/vendor/github.com/rsteube/carapace/context.go +++ b/vendor/github.com/rsteube/carapace/context.go @@ -15,25 +15,30 @@ import ( // Context provides information during completion. type Context struct { - // CallbackValue contains the (partial) value (or part of it during an ActionMultiParts) currently being completed - CallbackValue string - // Args contains the positional arguments of current (sub)command (exclusive the one currently being completed) + // Value contains the value currently being completed (or part of it during an ActionMultiParts). + Value string + // Args contains the positional arguments of current (sub)command (exclusive the one currently being completed). Args []string - // Parts contains the splitted CallbackValue during an ActionMultiParts (exclusive the part currently being completed) + // Parts contains the splitted Value during an ActionMultiParts (exclusive the part currently being completed). Parts []string - // Env contains environment variables for current context + // Env contains environment variables for current context. Env []string - // Dir contains the working directory for current context + // Dir contains the working directory for current context. Dir string mockedReplies map[string]string } -func NewContext(args []string) Context { +// NewContext creates a new context for given arguments. +func NewContext(args ...string) Context { + if len(args) == 0 { + args = append(args, "") + } + context := Context{ - CallbackValue: args[len(args)-1], - Args: args[:len(args)-1], - Env: os.Environ(), + Value: args[len(args)-1], + Args: args[:len(args)-1], + Env: os.Environ(), } if wd, err := os.Getwd(); err == nil { @@ -43,9 +48,7 @@ func NewContext(args []string) Context { isGoRun := func() bool { return strings.HasPrefix(os.Args[0], os.TempDir()+"/go-build") } if value, exists := os.LookupEnv("CARAPACE_SANDBOX"); exists && isGoRun() { var m common.Mock - if err := json.Unmarshal([]byte(value), &m); err != nil { - panic(err.Error()) // TODO - } + _ = json.Unmarshal([]byte(value), &m) context.Dir = m.Dir context.mockedReplies = m.Replies } @@ -77,6 +80,7 @@ func (c *Context) Setenv(key, value string) { c.Env = append(c.Env, fmt.Sprintf("%v=%v", key, value)) } +// Envsubst replaces ${var} in the string based on environment variables in current context. func (c Context) Envsubst(s string) (string, error) { return envsubst.Eval(s, c.Getenv) } @@ -105,7 +109,7 @@ func expandHome(s string) (string, error) { return zsh.NamedDirectories.Replace(s), nil } - home, err := os.UserHomeDir() // TODO duplicated code + home, err := os.UserHomeDir() if err != nil { return "", err } @@ -114,27 +118,21 @@ func expandHome(s string) (string, error) { return s, nil } -func (c Context) Abs(s string) (string, error) { - var path string - if strings.HasPrefix(s, "/") || strings.HasPrefix(s, "~") { - path = s // path is absolute - } else { - expanded, err := expandHome(c.Dir) - if err != nil { - return "", err - } - abs, err := filepath.Abs(expanded) - if err != nil { - return "", err +// Abs returns an absolute representation of path. +func (c Context) Abs(path string) (string, error) { + if !strings.HasPrefix(path, "/") && !strings.HasPrefix(path, "~") { // path is relative + switch c.Dir { + case "": + path = "./" + path + default: + path = c.Dir + "/" + path } - path = abs + "/" + s } - expanded, err := expandHome(path) + path, err := expandHome(path) if err != nil { return "", err } - path = expanded result, err := filepath.Abs(path) if err != nil { diff --git a/vendor/github.com/rsteube/carapace/defaultActions.go b/vendor/github.com/rsteube/carapace/defaultActions.go index 4d45725..adfc516 100644 --- a/vendor/github.com/rsteube/carapace/defaultActions.go +++ b/vendor/github.com/rsteube/carapace/defaultActions.go @@ -3,12 +3,16 @@ package carapace import ( "bytes" "encoding/json" + "errors" "fmt" + "os" + "os/exec" "strings" "github.com/rsteube/carapace/internal/common" "github.com/rsteube/carapace/internal/config" - "github.com/rsteube/carapace/internal/shell/export" + "github.com/rsteube/carapace/internal/export" + "github.com/rsteube/carapace/internal/man" "github.com/rsteube/carapace/pkg/style" "github.com/rsteube/carapace/third_party/github.com/acarl005/stripansi" "github.com/spf13/cobra" @@ -28,18 +32,45 @@ func ActionCallback(callback CompletionCallback) Action { // }) func ActionExecCommand(name string, arg ...string) func(f func(output []byte) Action) Action { return func(f func(output []byte) Action) Action { + return ActionExecCommandE(name, arg...)(func(output []byte, err error) Action { + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + if firstLine := strings.SplitN(string(exitErr.Stderr), "\n", 2)[0]; strings.TrimSpace(firstLine) != "" { + err = errors.New(firstLine) + } + } + return ActionMessage(err.Error()) + } + return f(output) + }) + } +} + +// ActionExecCommandE is like ActionExecCommand but with custom error handling. +// +// carapace.ActionExecCommandE("supervisorctl", "--configuration", path, "status")(func(output []byte, err error) carapace.Action { +// if err != nil { +// const NOT_RUNNING = 3 +// if exitErr, ok := err.(*exec.ExitError); !ok || exitErr.ExitCode() != NOT_RUNNING { +// return carapace.ActionMessage(err.Error()) +// } +// } +// return carapace.ActionValues("success") +// }) +func ActionExecCommandE(name string, arg ...string) func(f func(output []byte, err error) Action) Action { + return func(f func(output []byte, err error) Action) Action { return ActionCallback(func(c Context) Action { var stdout, stderr bytes.Buffer cmd := c.Command(name, arg...) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - if firstLine := strings.SplitN(stderr.String(), "\n", 2)[0]; strings.TrimSpace(firstLine) != "" { - return ActionMessage(stripansi.Strip(firstLine)) + if exitErr, ok := err.(*exec.ExitError); ok { + exitErr.Stderr = stderr.Bytes() // seems this needs to be set manually due to stdout being collected? } - return ActionMessage(err.Error()) + return f(stdout.Bytes(), err) } - return f(stdout.Bytes()) + return f(stdout.Bytes(), nil) }) } } @@ -50,7 +81,7 @@ func ActionExecCommand(name string, arg ...string) func(f func(output []byte) Ac // carapace.ActionCallback(func(c carapace.Context) carapace.Action { // args := []string{"_carapace", "export", ""} // args = append(args, c.Args...) -// args = append(args, c.CallbackValue) +// args = append(args, c.Value) // return carapace.ActionExecCommand("command", args...)(func(output []byte) carapace.Action { // return carapace.ActionImport(output) // }) @@ -63,7 +94,7 @@ func ActionImport(output []byte) Action { return ActionMessage(err.Error()) } return Action{ - rawValues: e.RawValues, + rawValues: e.Values, meta: e.Meta, } }) @@ -75,7 +106,7 @@ func ActionExecute(cmd *cobra.Command) Action { return ActionCallback(func(c Context) Action { args := []string{"_carapace", "export", cmd.Name()} args = append(args, c.Args...) - args = append(args, c.CallbackValue) + args = append(args, c.Value) cmd.SetArgs(args) Gen(cmd).PreInvoke(func(cmd *cobra.Command, flag *pflag.Flag, action Action) Action { @@ -174,22 +205,22 @@ func ActionMessage(msg string, args ...interface{}) Action { msg = fmt.Sprintf(msg, args...) } a := ActionValues().NoSpace() - a.meta.Messages.Add(msg) + a.meta.Messages.Add(stripansi.Strip(msg)) return a }) } -// ActionMultiParts completes multiple parts of words separately where each part is separated by some char (CallbackValue is set to the currently completed part during invocation). +// ActionMultiParts completes multiple parts of words separately where each part is separated by some char (Context.Value is set to the currently completed part during invocation). func ActionMultiParts(divider string, callback func(c Context) Action) Action { return ActionCallback(func(c Context) Action { - index := strings.LastIndex(c.CallbackValue, string(divider)) + index := strings.LastIndex(c.Value, string(divider)) prefix := "" if len(divider) == 0 { - prefix = c.CallbackValue - c.CallbackValue = "" + prefix = c.Value + c.Value = "" } else if index != -1 { - prefix = c.CallbackValue[0 : index+len(divider)] - c.CallbackValue = c.CallbackValue[index+len(divider):] // update CallbackValue to only contain the currently completed part + prefix = c.Value[0 : index+len(divider)] + c.Value = c.Value[index+len(divider):] // update Context.Value to only contain the currently completed part } parts := strings.Split(prefix, string(divider)) if len(parts) > 0 && len(divider) > 0 { @@ -307,7 +338,7 @@ func ActionStyles(styles ...string) Action { style.BrightWhite, _s(style.BrightWhite), )) - if strings.HasPrefix(c.CallbackValue, "color") { + if strings.HasPrefix(c.Value, "color") { for i := 0; i <= 255; i++ { batch = append(batch, ActionStyledValues( fmt.Sprintf("color%v", i), _s(style.XTerm256Color(uint8(i))), @@ -339,7 +370,7 @@ func ActionStyles(styles ...string) Action { style.BgBrightWhite, _s(style.BgBrightWhite), )) - if strings.HasPrefix(c.CallbackValue, "bg-color") { + if strings.HasPrefix(c.Value, "bg-color") { for i := 0; i <= 255; i++ { batch = append(batch, ActionStyledValues( fmt.Sprintf("bg-color%v", i), _s("bg-"+style.XTerm256Color(uint8(i))), @@ -362,3 +393,64 @@ func ActionStyles(styles ...string) Action { return batch.ToA() }).Tag("styles") } + +// ActionExecutables completes PATH executables +// +// nvim +// chmod +func ActionExecutables() Action { + return ActionCallback(func(c Context) Action { + // TODO allow additional descriptions to be registered somewhere for carapace-bin (key, value,...) + batch := Batch() + manDescriptions := man.Descriptions(c.Value) + dirs := strings.Split(os.Getenv("PATH"), string(os.PathListSeparator)) + for i := len(dirs) - 1; i >= 0; i-- { + batch = append(batch, actionDirectoryExecutables(dirs[i], c.Value, manDescriptions)) + } + return batch.ToA() + }).Tag("executables") +} + +func actionDirectoryExecutables(dir string, prefix string, manDescriptions map[string]string) Action { + return ActionCallback(func(c Context) Action { + if files, err := os.ReadDir(dir); err == nil { + vals := make([]string, 0) + for _, f := range files { + if strings.HasPrefix(f.Name(), prefix) { + if info, err := f.Info(); err == nil && !f.IsDir() && isExecAny(info.Mode()) { + vals = append(vals, f.Name(), manDescriptions[f.Name()], style.ForPath(dir+"/"+f.Name(), c)) + } + } + } + return ActionStyledValuesDescribed(vals...) + } + return ActionValues() + }) +} + +func isExecAny(mode os.FileMode) bool { + return mode&0o111 != 0 +} + +// ActionPositional completes positional arguments for given command ignoring `--` (dash). +// TODO: experimental - likely gives issues with preinvoke (does not have the full args) +// +// carapace.Gen(cmd).DashAnyCompletion( +// carapace.ActionPositional(cmd), +// ) +func ActionPositional(cmd *cobra.Command) Action { + return ActionCallback(func(c Context) Action { + if cmd.ArgsLenAtDash() < 0 { + return ActionMessage("only allowed for dash arguments [ActionPositional]") + } + + c.Args = cmd.Flags().Args() + entry := storage.get(cmd) + + a := entry.positionalAny + if index := len(c.Args); index < len(entry.positional) { + a = entry.positional[len(c.Args)] + } + return a.Invoke(c).ToA() + }) +} diff --git a/vendor/github.com/rsteube/carapace/docker-compose.yml b/vendor/github.com/rsteube/carapace/docker-compose.yml index 2702982..04ea586 100644 --- a/vendor/github.com/rsteube/carapace/docker-compose.yml +++ b/vendor/github.com/rsteube/carapace/docker-compose.yml @@ -4,12 +4,11 @@ services: build: &base build: . image: ghcr.io/rsteube/carapace - command: sh -c 'cd /carapace/example && go build .' + command: sh -c 'cd /carapace/example && go build -buildvcs=false .' environment: TARGET: /carapace/example/example volumes: - '.:/carapace/' - - 'go:/home/circleci/go/' bash: <<: *base diff --git a/vendor/github.com/rsteube/carapace/go.work b/vendor/github.com/rsteube/carapace/go.work new file mode 100644 index 0000000..8af5174 --- /dev/null +++ b/vendor/github.com/rsteube/carapace/go.work @@ -0,0 +1,6 @@ +go 1.19 + +use ( + . + ./example-nonposix +) diff --git a/vendor/github.com/rsteube/carapace/go.work.sum b/vendor/github.com/rsteube/carapace/go.work.sum new file mode 100644 index 0000000..46640fb --- /dev/null +++ b/vendor/github.com/rsteube/carapace/go.work.sum @@ -0,0 +1,7 @@ +github.com/rsteube/carapace-pflag v0.0.4 h1:Onb0cLNLxg1xJr2EsMlBldAI5KkybrvZ89b5cRElZXI= +github.com/rsteube/carapace-pflag v0.0.4/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/rsteube/carapace-pflag v0.0.5 h1:QQC0KnthHMayHsX7B7DxqOkr0B6JSIM0glB+KrSTruU= +github.com/rsteube/carapace-pflag v0.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/rsteube/carapace-pflag v0.1.0 h1:CPJRlj3jbyOnxuMf5pdrM76hEwdQ0STDDmkAHQcGbhg= +github.com/rsteube/carapace-pflag v0.1.0/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/vendor/github.com/rsteube/carapace/internal/cache/cache.go b/vendor/github.com/rsteube/carapace/internal/cache/cache.go index a86f489..e90ab03 100644 --- a/vendor/github.com/rsteube/carapace/internal/cache/cache.go +++ b/vendor/github.com/rsteube/carapace/internal/cache/cache.go @@ -11,29 +11,30 @@ import ( "strings" "time" - "github.com/rsteube/carapace/internal/common" + "github.com/rsteube/carapace/internal/export" "github.com/rsteube/carapace/internal/uid" "github.com/rsteube/carapace/pkg/cache" + "github.com/rsteube/carapace/pkg/xdg" ) // Write persistests given values to file as json. -func Write(file string, rawValues []common.RawValue) (err error) { +func Write(file string, e export.Export) (err error) { var m []byte - if m, err = json.Marshal(rawValues); err == nil { + if m, err = json.Marshal(e); err == nil { err = os.WriteFile(file, m, 0o600) } return } // Load loads values from file unless modification date exceeds timeout. -func Load(file string, timeout time.Duration) (rawValues []common.RawValue, err error) { - var content []byte +func Load(file string, timeout time.Duration) (e export.Export, err error) { var stat os.FileInfo if stat, err = os.Stat(file); os.IsNotExist(err) || (timeout > 0 && stat.ModTime().Add(timeout).Before(time.Now())) { err = errors.New("not exists or timeout exceeded") } else { + var content []byte if content, err = os.ReadFile(file); err == nil { - err = json.Unmarshal(content, &rawValues) + err = json.Unmarshal(content, &e) } } return @@ -42,7 +43,7 @@ func Load(file string, timeout time.Duration) (rawValues []common.RawValue, err // CacheDir creates a cache folder for current user and returns the path. func CacheDir(name string) (dir string, err error) { var userCacheDir string - if userCacheDir, err = os.UserCacheDir(); err == nil { + if userCacheDir, err = xdg.UserCacheDir(); err == nil { dir = fmt.Sprintf("%v/carapace/%v/%v", userCacheDir, uid.Executable(), name) err = os.MkdirAll(dir, 0o700) } diff --git a/vendor/github.com/rsteube/carapace/internal/common/dash.go b/vendor/github.com/rsteube/carapace/internal/common/dash.go index e149299..0787e09 100644 --- a/vendor/github.com/rsteube/carapace/internal/common/dash.go +++ b/vendor/github.com/rsteube/carapace/internal/common/dash.go @@ -6,6 +6,5 @@ import "github.com/spf13/cobra" // // example action positional1 -- dash1 dash2 func IsDash(cmd *cobra.Command) bool { - // TODO add test - return cmd.ArgsLenAtDash() != -1 && (cmd.ArgsLenAtDash() != len(cmd.Flags().Args())) + return cmd.ArgsLenAtDash() != -1 } diff --git a/vendor/github.com/rsteube/carapace/internal/common/message.go b/vendor/github.com/rsteube/carapace/internal/common/message.go index 943c085..e183c61 100644 --- a/vendor/github.com/rsteube/carapace/internal/common/message.go +++ b/vendor/github.com/rsteube/carapace/internal/common/message.go @@ -96,7 +96,7 @@ func (m Messages) Integrate(values RawValues, prefix string) RawValues { for { if i > 0 { value = fmt.Sprintf("%vERR%v", prefix, i) - value = fmt.Sprintf("ERR%v", i) + display = fmt.Sprintf("ERR%v", i) } i += 1 diff --git a/vendor/github.com/rsteube/carapace/internal/common/meta.go b/vendor/github.com/rsteube/carapace/internal/common/meta.go index 86003cb..953b43c 100644 --- a/vendor/github.com/rsteube/carapace/internal/common/meta.go +++ b/vendor/github.com/rsteube/carapace/internal/common/meta.go @@ -1,9 +1,9 @@ package common type Meta struct { - Messages Messages - Nospace SuffixMatcher - Usage string + Messages Messages `json:"messages"` + Nospace SuffixMatcher `json:"nospace"` + Usage string `json:"usage"` } func (m *Meta) Merge(other Meta) { diff --git a/vendor/github.com/rsteube/carapace/internal/common/suffix.go b/vendor/github.com/rsteube/carapace/internal/common/suffix.go index 90ea88c..d4ae4b9 100644 --- a/vendor/github.com/rsteube/carapace/internal/common/suffix.go +++ b/vendor/github.com/rsteube/carapace/internal/common/suffix.go @@ -27,13 +27,13 @@ func (sm *SuffixMatcher) Add(suffixes ...rune) { } func (sm *SuffixMatcher) Merge(other SuffixMatcher) { - for _, r := range []rune(other.string) { + for _, r := range other.string { sm.Add(r) } } func (sm SuffixMatcher) Matches(s string) bool { - for _, r := range []rune(sm.string) { + for _, r := range sm.string { if r == '*' || strings.HasSuffix(s, string(r)) { return true } diff --git a/vendor/github.com/rsteube/carapace/internal/common/traverse.go b/vendor/github.com/rsteube/carapace/internal/common/traverse.go deleted file mode 100644 index 9a77825..0000000 --- a/vendor/github.com/rsteube/carapace/internal/common/traverse.go +++ /dev/null @@ -1,115 +0,0 @@ -package common - -import ( - "fmt" - "regexp" - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// TraverseLenient traverses the command tree but filters errors regarding arguments currently being completed. -func TraverseLenient(cmd *cobra.Command, args []string) (*cobra.Command, []string, error) { - a := args - - // needed so that completion for positional argument that has no value yet to work - if len(args) > 0 && args[len(args)-1] == "" { - a = args[0 : len(args)-1] - } - - targetCmd, targetArgs, err := cmd.Root().Traverse(a) - if len(args) > 0 && args[len(args)-1] == "" { - targetArgs = append(targetArgs, "") - } - if err != nil { - return targetCmd, targetArgs, filterError(args, err) - } - - if targetCmd.DisableFlagParsing { - return targetCmd, targetArgs, nil // TODO might need to consider logic below regarding parent command as well - } - - err = targetCmd.ParseFlags(targetArgs) - for _, name := range append(targetCmd.Aliases, targetCmd.Name()) { - if len(args) > 0 && - name == args[len(args)-1] && - len(targetCmd.Flags().Args()) == 0 && - !anyFlagChanged(targetCmd) { - if targetCmd.HasParent() { - targetCmd = targetCmd.Parent() // when argument currently being completed is fully matching a subcommand it will be returned, so fix this to parent - } - } - } - return targetCmd, targetCmd.Flags().Args(), filterError(args, err) -} - -func anyFlagChanged(cmd *cobra.Command) (changed bool) { - cmd.LocalFlags().VisitAll(func(f *pflag.Flag) { - changed = changed || f.Changed - }) - return -} - -func filterError(args []string, err error) error { - if err == nil || len(args) == 0 { - return err - } - - msg := err.Error() - - current := args[len(args)-1] - if strings.HasPrefix(current, "--") && msg == fmt.Sprintf("flag needs an argument: %v", current) { - // ignore long flag argument currently being completed - return nil - } - - if strings.HasPrefix(current, "-") && msg == fmt.Sprintf("flag needs an argument: '%v' in -%v", current[len(current)-1:], current[len(current)-1:]) { // spf13/pflag - // ignore shorthand flag currently being completed - return nil - } - - if strings.HasPrefix(current, "-") && msg == fmt.Sprintf(`flag needs an argument: "%v" in -%v`, current[len(current)-1:], current[len(current)-1:]) { // rsteube/carapace-pflag: shorthand chain - // ignore shorthand flag currently being completed - return nil - } - - if strings.HasPrefix(current, "-") && msg == fmt.Sprintf(`flag needs an argument: "%v" in %v`, current[1:], current) { // rsteube/carapace-pflag: long shorthand - // ignore shorthand flag currently being completed - return nil - } - - if strings.HasPrefix(current, "--") && msg == fmt.Sprintf("unknown flag: %v", current) { - // ignore long flag curently being completed - return nil - } - - if strings.HasPrefix(current, "-") && msg == fmt.Sprintf("unknown shorthand flag: %v", current) { // rsteube/carapace-pflag: long shorthand - // ignore non-posix shorthand flag currently being completed - return nil - } - - if re := regexp.MustCompile(`invalid argument ".*" for "(?P.*)" flag:.*`); re.MatchString(msg) && strings.SplitN(current, "=", 2)[0] == re.FindStringSubmatch(msg)[1] { - // ignore invalid argument for flag currently being completed (e.g. empty IntSlice) - return nil - } - - if len(args) > 1 { - previous := args[len(args)-2] - if strings.HasPrefix(previous, "--") && msg == fmt.Sprintf("flag needs an argument: %v", previous) { - // ignore long flag argument currently being completed - return nil - } - - if strings.HasPrefix(previous, "-") && msg == fmt.Sprintf("flag needs an argument: '%v' in -%v", previous[len(previous)-1:], previous[len(previous)-1:]) { - // ignore shorthand flag argument currently being completed - return nil - } - - if re := regexp.MustCompile(`invalid argument ".*" for "(?P-., )?(?P.*)" flag:.*`); re.MatchString(msg) && previous == re.FindStringSubmatch(msg)[2] { - // ignore invalid argument for flag currently being completed (e.g. empty IntSlice) - return nil - } - } - return err -} diff --git a/vendor/github.com/rsteube/carapace/internal/common/value.go b/vendor/github.com/rsteube/carapace/internal/common/value.go index deb9b55..2a25640 100644 --- a/vendor/github.com/rsteube/carapace/internal/common/value.go +++ b/vendor/github.com/rsteube/carapace/internal/common/value.go @@ -14,11 +14,11 @@ var FromInvokedAction func(action interface{}) (Meta, RawValues) // RawValue represents a completion candidate. type RawValue struct { - Value string - Display string - Description string `json:",omitempty"` - Style string `json:",omitempty"` - Tag string `json:",omitempty"` + Value string `json:"value"` + Display string `json:"display"` + Description string `json:"description,omitempty"` + Style string `json:"style,omitempty"` + Tag string `json:"tag,omitempty"` } // TrimmedDescription returns the trimmed description. diff --git a/vendor/github.com/rsteube/carapace/internal/config/config.go b/vendor/github.com/rsteube/carapace/internal/config/config.go index e672f02..90fc3ca 100644 --- a/vendor/github.com/rsteube/carapace/internal/config/config.go +++ b/vendor/github.com/rsteube/carapace/internal/config/config.go @@ -8,6 +8,8 @@ import ( "path/filepath" "reflect" "strings" + + "github.com/rsteube/carapace/pkg/xdg" ) type configMap map[string]interface{} @@ -62,7 +64,7 @@ func Load() error { } func load(name string, c configMap) error { - if dir, err := os.UserConfigDir(); err == nil { + if dir, err := xdg.UserConfigDir(); err == nil { content, err := os.ReadFile(fmt.Sprintf("%v/carapace/%v.json", dir, name)) if err != nil { if os.IsNotExist(err) { @@ -97,7 +99,7 @@ func SetStyle(key, value string) error { } func set(name, key, value string) error { - dir, err := os.UserConfigDir() + dir, err := xdg.UserConfigDir() if err != nil { return err } @@ -108,7 +110,9 @@ func set(name, key, value string) error { if !os.IsNotExist(err) { return err } - os.MkdirAll(filepath.Dir(file), os.ModePerm) + if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil { + return err + } content = []byte("{}") } @@ -134,7 +138,5 @@ func set(name, key, value string) error { if err != nil { return err } - os.WriteFile(file, marshalled, os.ModePerm) - - return nil + return os.WriteFile(file, marshalled, os.ModePerm) } diff --git a/vendor/github.com/rsteube/carapace/internal/config/env.go b/vendor/github.com/rsteube/carapace/internal/config/env.go new file mode 100644 index 0000000..02a0e9a --- /dev/null +++ b/vendor/github.com/rsteube/carapace/internal/config/env.go @@ -0,0 +1,8 @@ +package config + +import "os" + +func IsLenient() (lenient bool) { + _, lenient = os.LookupEnv("CARAPACE_LENIENT") + return +} diff --git a/vendor/github.com/rsteube/carapace/internal/export/export.go b/vendor/github.com/rsteube/carapace/internal/export/export.go new file mode 100644 index 0000000..61df619 --- /dev/null +++ b/vendor/github.com/rsteube/carapace/internal/export/export.go @@ -0,0 +1,39 @@ +package export + +import ( + "encoding/json" + "runtime/debug" + "sort" + + "github.com/rsteube/carapace/internal/common" +) + +type Export struct { + Version string `json:"version"` + common.Meta + Values common.RawValues `json:"values"` +} + +func (e Export) MarshalJSON() ([]byte, error) { + sort.Sort(common.ByValue(e.Values)) + return json.Marshal(&struct { + Version string `json:"version"` + common.Meta + Values common.RawValues `json:"values"` + }{ + Version: version(), + Meta: e.Meta, + Values: e.Values, + }) +} + +func version() string { + if info, ok := debug.ReadBuildInfo(); ok { + for _, dep := range info.Deps { + if dep.Path == "github.com/rsteube/carapace" { + return dep.Version + } + } + } + return "unknown" +} diff --git a/vendor/github.com/rsteube/carapace/internal/man/man.go b/vendor/github.com/rsteube/carapace/internal/man/man.go new file mode 100644 index 0000000..a4dabab --- /dev/null +++ b/vendor/github.com/rsteube/carapace/internal/man/man.go @@ -0,0 +1,30 @@ +package man + +import ( + "regexp" + "strings" + + "github.com/rsteube/carapace/third_party/golang.org/x/sys/execabs" +) + +// Descriptions returns manpage descriptions for commands matching given prefix. +func Descriptions(s string) (descriptions map[string]string) { + descriptions = make(map[string]string) + if strings.HasPrefix(s, ".") || strings.HasPrefix(s, "~") || strings.HasPrefix(s, "/") { + return + } + + output, err := execabs.Command("man", "--names-only", "-k", "^"+s).Output() + if err != nil { + return + } + + r := regexp.MustCompile(`^(?P[^ ]+) [^-]+- (?P.*)$`) + lines := strings.Split(string(output), "\n") + for _, line := range lines { + if matches := r.FindStringSubmatch(line); len(matches) > 2 { + descriptions[matches[1]] = matches[2] + } + } + return +} diff --git a/vendor/github.com/rsteube/carapace/internal/pflagfork/flag.go b/vendor/github.com/rsteube/carapace/internal/pflagfork/flag.go index a02b903..1fb3ff5 100644 --- a/vendor/github.com/rsteube/carapace/internal/pflagfork/flag.go +++ b/vendor/github.com/rsteube/carapace/internal/pflagfork/flag.go @@ -1,32 +1,48 @@ package pflagfork import ( + "fmt" "reflect" "strings" + "github.com/rsteube/carapace/pkg/style" "github.com/spf13/pflag" ) -// style defines how flags are represented. -type style int +// mode defines how flags are represented. +type mode int const ( - Default style = iota // default behaviour - ShorthandOnly // only the shorthand should be used - NameAsShorthand // non-posix style where the name is also added as shorthand (single `-` prefix) + Default mode = iota // default behaviour + ShorthandOnly // only the shorthand should be used + NameAsShorthand // non-posix mode where the name is also added as shorthand (single `-` prefix) ) type Flag struct { *pflag.Flag } -func (f Flag) Style() style { - if field := reflect.ValueOf(f.Flag).Elem().FieldByName("Style"); field.IsValid() && field.Kind() == reflect.Int { - return style(field.Int()) +func (f Flag) Nargs() int { + if field := reflect.ValueOf(f.Flag).Elem().FieldByName("Nargs"); field.IsValid() && field.Kind() == reflect.Int { + return int(field.Int()) + } + return 0 +} + +func (f Flag) Mode() mode { + if field := reflect.ValueOf(f.Flag).Elem().FieldByName("Mode"); field.IsValid() && field.Kind() == reflect.Int { + return mode(field.Int()) } return Default } +func (f Flag) OptargDelimiter() rune { + if field := reflect.ValueOf(f.Flag).Elem().FieldByName("OptargDelimiter"); field.IsValid() && field.Kind() == reflect.Int32 { + return (rune(field.Int())) + } + return '=' +} + func (f Flag) IsRepeatable() bool { if strings.Contains(f.Value.Type(), "Slice") || strings.Contains(f.Value.Type(), "Array") || @@ -35,3 +51,110 @@ func (f Flag) IsRepeatable() bool { } return false } + +func (f Flag) Split(arg string) (prefix, optarg string) { + delimiter := string(f.OptargDelimiter()) + splitted := strings.SplitN(arg, delimiter, 2) + return splitted[0] + delimiter, splitted[1] +} + +func (f Flag) Matches(arg string, posix bool) bool { + if !strings.HasPrefix(arg, "-") { // not a flag + return false + } + + switch { + + case strings.HasPrefix(arg, "--"): + name := strings.TrimPrefix(arg, "--") + name = strings.SplitN(name, string(f.OptargDelimiter()), 2)[0] + + switch f.Mode() { + case ShorthandOnly, NameAsShorthand: + return false + default: + return name == f.Name + } + + case !posix: + name := strings.TrimPrefix(arg, "-") + name = strings.SplitN(name, string(f.OptargDelimiter()), 2)[0] + + if name == "" { + return false + } + + switch f.Mode() { + case ShorthandOnly: + return name == f.Shorthand + default: + return name == f.Name || name == f.Shorthand + } + + default: + if f.Shorthand != "" { + return strings.HasSuffix(arg, f.Shorthand) + } + return false + } +} + +func (f Flag) TakesValue() bool { + switch f.Value.Type() { + case "bool", "boolSlice", "count": + return false + default: + return true + } +} + +func (f Flag) IsOptarg() bool { + return f.NoOptDefVal != "" +} + +func (f Flag) Style() string { + switch { + case !f.TakesValue(): + return style.Carapace.FlagNoArg + case f.IsOptarg(): + return style.Carapace.FlagOptArg + case f.Nargs() != 0: + return style.Carapace.FlagMultiArg + default: + return style.Carapace.FlagArg + } +} + +func (f Flag) Definition() string { + var definition string + switch f.Mode() { + case ShorthandOnly: + definition = fmt.Sprintf("-%v", f.Shorthand) + case NameAsShorthand: + definition = fmt.Sprintf("-%v, -%v", f.Shorthand, f.Name) + default: + switch f.Shorthand { + case "": + definition = fmt.Sprintf("--%v", f.Name) + default: + definition = fmt.Sprintf("-%v, --%v", f.Shorthand, f.Name) + } + } + + if f.IsRepeatable() { + definition += "*" + } + + switch { + case f.IsOptarg(): + switch f.Value.Type() { + case "bool", "boolSlice", "count": + default: + definition += "?" + } + case f.TakesValue(): + definition += "=" + } + + return definition +} diff --git a/vendor/github.com/rsteube/carapace/internal/pflagfork/flagset.go b/vendor/github.com/rsteube/carapace/internal/pflagfork/flagset.go index ee901ce..53b3aae 100644 --- a/vendor/github.com/rsteube/carapace/internal/pflagfork/flagset.go +++ b/vendor/github.com/rsteube/carapace/internal/pflagfork/flagset.go @@ -2,6 +2,7 @@ package pflagfork import ( "reflect" + "regexp" "strings" "github.com/spf13/pflag" @@ -20,6 +21,11 @@ func (f FlagSet) IsPosix() bool { return true } +func (f FlagSet) IsShorthandSeries(arg string) bool { + re := regexp.MustCompile("^-(?P[^-=]+)") + return re.MatchString(arg) && f.IsPosix() +} + func (f FlagSet) IsMutuallyExclusive(flag *pflag.Flag) bool { if groups, ok := flag.Annotations["cobra_annotation_mutually_exclusive"]; ok { for _, group := range groups { @@ -38,3 +44,17 @@ func (f *FlagSet) VisitAll(fn func(*Flag)) { fn(&Flag{flag}) }) } + +func (fs FlagSet) LookupArg(arg string) (result *Flag) { + isPosix := fs.IsPosix() + fs.VisitAll(func(f *Flag) { + if result != nil { + return + } + + if f.Matches(arg, isPosix) { + result = f + } + }) + return +} diff --git a/vendor/github.com/rsteube/carapace/internal/shell/export/action.go b/vendor/github.com/rsteube/carapace/internal/shell/export/action.go index e2b27cb..3504347 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/export/action.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/export/action.go @@ -2,35 +2,15 @@ package export import ( "encoding/json" - "runtime/debug" - "sort" "github.com/rsteube/carapace/internal/common" + "github.com/rsteube/carapace/internal/export" ) -type Export struct { - Version string - common.Meta - RawValues common.RawValues -} - func ActionRawValues(currentWord string, meta common.Meta, values common.RawValues) string { - sort.Sort(common.ByValue(values)) - m, _ := json.Marshal(Export{ - Version: version(), - Meta: meta, - RawValues: values, + m, _ := json.Marshal(export.Export{ + Meta: meta, + Values: values, }) return string(m) } - -func version() string { - if info, ok := debug.ReadBuildInfo(); ok { - for _, dep := range info.Deps { - if dep.Path == "github.com/rsteube/carapace" { - return dep.Version - } - } - } - return "unknown" -} diff --git a/vendor/github.com/rsteube/carapace/internal/shell/export/snippet.go b/vendor/github.com/rsteube/carapace/internal/shell/export/snippet.go index 58a20dd..8314c2f 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/export/snippet.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/export/snippet.go @@ -29,7 +29,7 @@ type flag struct { func convertFlag(f *pflag.Flag) flag { longhand := "" - if (pflagfork.Flag{Flag: f}).Style() != pflagfork.ShorthandOnly { + if (pflagfork.Flag{Flag: f}).Mode() != pflagfork.ShorthandOnly { longhand = f.Name } diff --git a/vendor/github.com/rsteube/carapace/internal/shell/nushell/snippet.go b/vendor/github.com/rsteube/carapace/internal/shell/nushell/snippet.go index 5e42415..72357e4 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/nushell/snippet.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/nushell/snippet.go @@ -18,6 +18,11 @@ func Snippet(cmd *cobra.Command) string { } let-env config = { - external_completer: $external_completer + completions: { + external: { + enable: true + completer: $external_completer + } + } }`, cmd.Name(), uid.Executable()) } diff --git a/vendor/github.com/rsteube/carapace/internal/shell/shell.go b/vendor/github.com/rsteube/carapace/internal/shell/shell.go index ab51c2b..fc5e239 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/shell.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/shell.go @@ -55,7 +55,7 @@ func Snippet(cmd *cobra.Command, shell string) (string, error) { return "", fmt.Errorf("expected one of '%v' [was: %v]", strings.Join(expected, "', '"), shell) } -func Value(shell string, callbackValue string, meta common.Meta, values common.RawValues) string { // TODO use context instead? +func Value(shell string, value string, meta common.Meta, values common.RawValues) string { // TODO use context instead? shellFuncs := map[string]func(currentWord string, meta common.Meta, values common.RawValues) string{ "bash": bash.ActionRawValues, "bash-ble": bash_ble.ActionRawValues, @@ -71,14 +71,14 @@ func Value(shell string, callbackValue string, meta common.Meta, values common.R "zsh": zsh.ActionRawValues, } if f, ok := shellFuncs[shell]; ok { - filtered := values.FilterPrefix(callbackValue) + filtered := values.FilterPrefix(value) switch shell { case "elvish", "export", "zsh": // shells with support for showing messages default: - filtered = meta.Messages.Integrate(filtered, callbackValue) + filtered = meta.Messages.Integrate(filtered, value) } sort.Sort(common.ByDisplay(filtered)) - return f(callbackValue, meta, filtered) + return f(value, meta, filtered) } return "" } diff --git a/vendor/github.com/rsteube/carapace/internal/shell/spec/command.go b/vendor/github.com/rsteube/carapace/internal/shell/spec/command.go new file mode 100644 index 0000000..49eb17d --- /dev/null +++ b/vendor/github.com/rsteube/carapace/internal/shell/spec/command.go @@ -0,0 +1,18 @@ +package spec + +type Command struct { + Name string `yaml:"name"` + Aliases []string `yaml:"aliases,omitempty"` + Description string `yaml:"description,omitempty"` + Group string `yaml:"group,omitempty"` + Flags map[string]string `yaml:"flags,omitempty"` + PersistentFlags map[string]string `yaml:"persistentflags,omitempty"` + Completion struct { + Flag map[string][]string `yaml:"flag,omitempty"` + Positional [][]string `yaml:"positional,omitempty"` + PositionalAny []string `yaml:"positionalany,omitempty"` + Dash [][]string `yaml:"dash,omitempty"` + DashAny []string `yaml:"dashany,omitempty"` + } `yaml:"completion,omitempty"` + Commands []Command `yaml:"commands,omitempty"` +} diff --git a/vendor/github.com/rsteube/carapace/internal/shell/spec/snippet.go b/vendor/github.com/rsteube/carapace/internal/shell/spec/snippet.go index 4e53cae..d34e2d6 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/spec/snippet.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/spec/snippet.go @@ -2,24 +2,52 @@ package spec import ( - "fmt" - "strings" - - "github.com/rsteube/carapace/internal/uid" + "github.com/rsteube/carapace/internal/pflagfork" "github.com/spf13/cobra" + "github.com/spf13/pflag" + "gopkg.in/yaml.v3" ) // Snippet generates the spec file. func Snippet(cmd *cobra.Command) string { - replacer := strings.NewReplacer( // TODO might need more replacements - `"`, `\"`, - `'`, `\'`, - `[`, `\[`, - `]`, `\]`, - ) - return fmt.Sprintf(`name: %v -description: %v -completion: - positionalany: ["$_bridge.Carapace(%v)"] -`, uid.Executable(), replacer.Replace(cmd.Short), uid.Executable()) + m, _ := yaml.Marshal(command(cmd)) + return string(m) +} + +func command(cmd *cobra.Command) Command { + c := Command{ + Name: cmd.Use, + Description: cmd.Short, + Aliases: cmd.Aliases, + Group: cmd.GroupID, + Flags: make(map[string]string), + PersistentFlags: make(map[string]string), + Commands: make([]Command, 0), + } + + cmd.LocalFlags().VisitAll(func(flag *pflag.Flag) { + if flag.Hidden { + return + } + f := pflagfork.Flag{Flag: flag} + c.Flags[f.Definition()] = f.Usage + + }) + + cmd.PersistentFlags().VisitAll(func(flag *pflag.Flag) { + if flag.Hidden { + return + } + f := pflagfork.Flag{Flag: flag} + c.PersistentFlags[f.Definition()] = f.Usage + + }) + + for _, subcmd := range cmd.Commands() { + if !subcmd.Hidden { + c.Commands = append(c.Commands, command(subcmd)) + } + } + + return c } diff --git a/vendor/github.com/rsteube/carapace/internal/shell/zsh/message.go b/vendor/github.com/rsteube/carapace/internal/shell/zsh/message.go index 1a4406a..0dd8fea 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/zsh/message.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/zsh/message.go @@ -18,7 +18,7 @@ func (m message) Format() string { formatted = append(formatted, m.formatMessage(message, style.Carapace.Error)) } if m.Usage != "" { - formatted = append(formatted, m.formatMessage(m.Usage, style.Carapace.Description)) + formatted = append(formatted, m.formatMessage(m.Usage, style.Carapace.Usage)) } if len(formatted) > 0 { diff --git a/vendor/github.com/rsteube/carapace/internal/shell/zsh/zstyle.go b/vendor/github.com/rsteube/carapace/internal/shell/zsh/zstyle.go index 0be92a0..0933b49 100644 --- a/vendor/github.com/rsteube/carapace/internal/shell/zsh/zstyle.go +++ b/vendor/github.com/rsteube/carapace/internal/shell/zsh/zstyle.go @@ -31,17 +31,6 @@ func (z zstyles) valueSGR(val common.RawValue) string { return style.SGR(style.Default) } -func (z zstyles) hasAliases() bool { - descriptions := make(map[string]bool) - for _, val := range z.rawValues { - if _, exists := descriptions[val.Description]; exists && val.Description != "" { - return true - } - descriptions[val.Description] = true - } - return false -} - func (z zstyles) Format() string { replacer := strings.NewReplacer( "#", `\#`, @@ -58,9 +47,9 @@ func (z zstyles) Format() string { if len(z.rawValues) < 1000 { // disable styling for large amount of values (bad performance) for _, val := range z.rawValues { // match value with description - formatted = append(formatted, fmt.Sprintf("=(#b)(%v)( * -- *)=0=%v=%v", replacer.Replace(val.Display), z.valueSGR(val), z.descriptionSGR())) + formatted = append(formatted, fmt.Sprintf("=(#b)(%v)([ ]## -- *)=0=%v=%v", replacer.Replace(val.Display), z.valueSGR(val), z.descriptionSGR())) // only match value (also matches aliased completions that are placed on the same line if the space allows it) - formatted = append(formatted, fmt.Sprintf("=(#b)(%v)()=0=%v=%v", replacer.Replace(val.Display), z.valueSGR(val), z.descriptionSGR())) + formatted = append(formatted, fmt.Sprintf("=(#b)(%v)=0=%v", replacer.Replace(val.Display), z.valueSGR(val))) } } formatted = append(formatted, fmt.Sprintf("=(#b)(%v)=0=%v", "-- *", z.descriptionSGR())) // match description for aliased completions diff --git a/vendor/github.com/rsteube/carapace/internalActions.go b/vendor/github.com/rsteube/carapace/internalActions.go index e777b1f..b0cd9d4 100644 --- a/vendor/github.com/rsteube/carapace/internalActions.go +++ b/vendor/github.com/rsteube/carapace/internalActions.go @@ -4,7 +4,6 @@ import ( "io/ioutil" "os" "path/filepath" - "regexp" "strings" "github.com/rsteube/carapace/internal/common" @@ -15,12 +14,12 @@ import ( func actionPath(fileSuffixes []string, dirOnly bool) Action { return ActionCallback(func(c Context) Action { - abs, err := c.Abs(c.CallbackValue) + abs, err := c.Abs(c.Value) if err != nil { return ActionMessage(err.Error()) } - displayFolder := filepath.Dir(c.CallbackValue) + displayFolder := filepath.Dir(c.Value) if displayFolder == "." { displayFolder = "" } else if !strings.HasSuffix(displayFolder, "/") { @@ -62,7 +61,7 @@ func actionPath(fileSuffixes []string, dirOnly bool) Action { } } } - if strings.HasPrefix(c.CallbackValue, "./") { + if strings.HasPrefix(c.Value, "./") { return ActionStyledValues(vals...).Invoke(Context{}).Prefix("./").ToA() } return ActionStyledValues(vals...) @@ -72,55 +71,46 @@ func actionPath(fileSuffixes []string, dirOnly bool) Action { func actionFlags(cmd *cobra.Command) Action { return ActionCallback(func(c Context) Action { flagSet := pflagfork.FlagSet{FlagSet: cmd.Flags()} - re := regexp.MustCompile("^-(?P[^-=]+)") - isShorthandSeries := re.MatchString(c.CallbackValue) && flagSet.IsPosix() + isShorthandSeries := flagSet.IsShorthandSeries(c.Value) vals := make([]string, 0) flagSet.VisitAll(func(f *pflagfork.Flag) { - if f.Deprecated != "" { + switch { + case f.Deprecated != "": return // skip deprecated flags - } - - if f.Changed && !f.IsRepeatable() { + case f.Changed && !f.IsRepeatable(): return // don't repeat flag - } - - if flagSet.IsMutuallyExclusive(f.Flag) { + case flagSet.IsMutuallyExclusive(f.Flag): return // skip flag of group already set } if isShorthandSeries { if f.Shorthand != "" && f.ShorthandDeprecated == "" { - for _, shorthand := range c.CallbackValue[1:] { + for _, shorthand := range c.Value[1:] { if shorthandFlag := cmd.Flags().ShorthandLookup(string(shorthand)); shorthandFlag != nil && shorthandFlag.Value.Type() != "bool" && shorthandFlag.Value.Type() != "count" && shorthandFlag.NoOptDefVal == "" { return // abort shorthand flag series if a previous one is not bool or count and requires an argument (no default value) } } - vals = append(vals, f.Shorthand, f.Usage) + vals = append(vals, f.Shorthand, f.Usage, f.Style()) } } else { - if flagstyle := f.Style(); flagstyle != pflagfork.ShorthandOnly { - if flagstyle == pflagfork.NameAsShorthand { - vals = append(vals, "-"+f.Name, f.Usage) - } else { - vals = append(vals, "--"+f.Name, f.Usage) - } + switch f.Mode() { + case pflagfork.NameAsShorthand: + vals = append(vals, "-"+f.Name, f.Usage, f.Style()) + case pflagfork.Default: + vals = append(vals, "--"+f.Name, f.Usage, f.Style()) } + if f.Shorthand != "" && f.ShorthandDeprecated == "" { - vals = append(vals, "-"+f.Shorthand, f.Usage) + vals = append(vals, "-"+f.Shorthand, f.Usage, f.Style()) } } }) if isShorthandSeries { - return ActionValuesDescribed(vals...).Invoke(c).Prefix(c.CallbackValue).ToA().NoSpace('*') - } - for i := 0; i < len(vals); i = i + 2 { // TODO experimental - hardcoded multiparts completion if flags are "grouped" with `.` - if strings.Contains(vals[i], ".") { - return ActionValuesDescribed(vals...).Invoke(c).ToMultiPartsA(".") - } + return ActionStyledValuesDescribed(vals...).Prefix(c.Value).NoSpace('*') } - return ActionValuesDescribed(vals...) + return ActionStyledValuesDescribed(vals...).MultiParts(".") // multiparts completion for flags grouped with `.` }).Tag("flags") } diff --git a/vendor/github.com/rsteube/carapace/invokedAction.go b/vendor/github.com/rsteube/carapace/invokedAction.go index f7d1dc3..0b1d603 100644 --- a/vendor/github.com/rsteube/carapace/invokedAction.go +++ b/vendor/github.com/rsteube/carapace/invokedAction.go @@ -1,11 +1,10 @@ package carapace import ( - "fmt" - "regexp" "strings" "github.com/rsteube/carapace/internal/common" + "github.com/rsteube/carapace/internal/export" _shell "github.com/rsteube/carapace/internal/shell" ) @@ -14,6 +13,10 @@ type InvokedAction struct { Action } +func (a InvokedAction) export() export.Export { + return export.Export{Meta: a.meta, Values: a.rawValues} +} + // Filter filters given values (this should be done before any call to Prefix/Suffix as those alter the values being filtered) // // a := carapace.ActionValues("A", "B", "C").Invoke(c) @@ -62,39 +65,34 @@ func (a InvokedAction) ToA() Action { return a.Action } +func tokenize(s string, dividers ...string) []string { + if len(dividers) == 0 { + return []string{s} + } + + result := make([]string, 0) + for _, word := range strings.SplitAfter(s, dividers[0]) { + tokens := tokenize(strings.TrimSuffix(word, dividers[0]), dividers[1:]...) + if len(tokens) > 0 && strings.HasSuffix(word, dividers[0]) { + tokens[len(tokens)-1] = tokens[len(tokens)-1] + dividers[0] + } + result = append(result, tokens...) + } + return result +} + // ToMultiPartsA create an ActionMultiParts from values with given dividers // // a := carapace.ActionValues("A/B/C", "A/C", "B/C", "C").Invoke(c) // b := a.ToMultiPartsA("/") // completes segments separately (first one is ["A/", "B/", "C"]) func (a InvokedAction) ToMultiPartsA(dividers ...string) Action { return ActionCallback(func(c Context) Action { - _split := func() func(s string) []string { - quotedDividiers := make([]string, 0) - for _, d := range dividers { - quotedDividiers = append(quotedDividiers, regexp.QuoteMeta(d)) - } - f := fmt.Sprintf("([^%v]*(%v)?)", strings.Join(quotedDividiers, "|"), strings.Join(quotedDividiers, "|")) // TODO quickfix - this is wrong (fails for dividers longer than one character) an might need a reverse lookahead for character sequence - r := regexp.MustCompile(f) - return func(s string) []string { - if matches := r.FindAllString(s, -1); matches != nil { - return matches - } - return []string{} - } - }() - - splittedCV := _split(c.CallbackValue) - for _, d := range dividers { - if strings.HasSuffix(c.CallbackValue, d) { - splittedCV = append(splittedCV, "") - break - } - } + splittedCV := tokenize(c.Value, dividers...) uniqueVals := make(map[string]common.RawValue) for _, val := range a.rawValues { - if strings.HasPrefix(val.Value, c.CallbackValue) { - if splitted := _split(val.Value); len(splitted) >= len(splittedCV) { + if strings.HasPrefix(val.Value, c.Value) { + if splitted := tokenize(val.Value, dividers...); len(splitted) >= len(splittedCV) { v := strings.Join(splitted[:len(splittedCV)], "") d := splitted[len(splittedCV)-1] @@ -135,8 +133,8 @@ func (a InvokedAction) ToMultiPartsA(dividers ...string) Action { }) } -func (a InvokedAction) value(shell string, callbackValue string) string { - return _shell.Value(shell, callbackValue, a.meta, a.rawValues) +func (a InvokedAction) value(shell string, value string) string { + return _shell.Value(shell, value, a.meta, a.rawValues) } func init() { diff --git a/vendor/github.com/rsteube/carapace/log.go b/vendor/github.com/rsteube/carapace/log.go index ff1e140..5f5646c 100644 --- a/vendor/github.com/rsteube/carapace/log.go +++ b/vendor/github.com/rsteube/carapace/log.go @@ -1,7 +1,6 @@ package carapace import ( - "encoding/json" "fmt" "io/ioutil" "log" @@ -11,17 +10,7 @@ import ( "github.com/rsteube/carapace/pkg/ps" ) -type _logger struct { - *log.Logger -} - -func (l _logger) PrintArgs(args []string) { - if m, err := json.Marshal(args); err == nil { - l.Println(string(m)) - } -} - -var logger = _logger{log.New(ioutil.Discard, "", log.Flags())} +var LOG = log.New(ioutil.Discard, "", log.Flags()) func init() { if _, enabled := os.LookupEnv("CARAPACE_LOG"); !enabled { @@ -37,6 +26,6 @@ func init() { if logfileWriter, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o666); err != nil { log.Fatal(err.Error()) } else { - logger = _logger{log.New(logfileWriter, ps.DetermineShell()+" ", log.Flags()|log.Lmsgprefix)} + LOG = log.New(logfileWriter, ps.DetermineShell()+" ", log.Flags()|log.Lmsgprefix|log.Lmicroseconds) } } diff --git a/vendor/github.com/rsteube/carapace/override.go b/vendor/github.com/rsteube/carapace/override.go deleted file mode 100644 index 8796d70..0000000 --- a/vendor/github.com/rsteube/carapace/override.go +++ /dev/null @@ -1,48 +0,0 @@ -package carapace - -import ( - "os" - "strings" -) - -var opts Opts - -// Opts contains overrides for completion behaviour. -type Opts struct { - // OptArgDelimiter changes the delimiter for optional flag arguments - // "=" // tail --verbose=descriptor (default) - // ":" // java -verbose:class - OptArgDelimiter string - // BridgeCompletion registers carapace completions to cobra's default completion - BridgeCompletion bool -} - -func init() { - opts.OptArgDelimiter = "=" -} - -// Override changes completion behaviour for non-posix style flags in standalone mode. -// Mostly done by patching `os.Args` before command execution and thus must be called before it. -// These are considered hacks and might undergo changes in future (or replaced by a custom pflag fork). -// -// func Execute() error { -// carapace.Override(carapace.Opts{ -// LongShorthand: true, -// OptArgDelimiter: ":", -// }) -// return rootCmd.Execute() -// } -func Override(o Opts) { - if o.OptArgDelimiter != "=" && - o.OptArgDelimiter != "" { - opts.OptArgDelimiter = o.OptArgDelimiter - for index, arg := range os.Args { - if strings.HasPrefix(arg, "-") { - // TODO needs solution compatible with ActionInvoke (not changing os.Args) - os.Args[index] = strings.Replace(arg, o.OptArgDelimiter, `=`, 1) - } - } - } - - opts.BridgeCompletion = o.BridgeCompletion -} diff --git a/vendor/github.com/rsteube/carapace/pkg/style/config.go b/vendor/github.com/rsteube/carapace/pkg/style/config.go index b10a0b4..a1a70e5 100644 --- a/vendor/github.com/rsteube/carapace/pkg/style/config.go +++ b/vendor/github.com/rsteube/carapace/pkg/style/config.go @@ -28,6 +28,7 @@ type carapace struct { Value string `desc:"default style for values" tag:"core styles"` Description string `desc:"default style for descriptions" tag:"core styles"` Error string `desc:"default style for errors" tag:"core styles"` + Usage string `desc:"default style for usage" tag:"core styles"` KeywordAmbiguous string `desc:"keyword describing a ambiguous state" tag:"keyword styles"` KeywordNegative string `desc:"keyword describing a negative state" tag:"keyword styles"` @@ -56,12 +57,18 @@ type carapace struct { Highlight11 string `desc:"Highlight 11" tag:"highlight styles"` Highlight12 string `desc:"Highlight 12" tag:"highlight styles"` + + FlagArg string `desc:"flag with argument" tag:"flag styles"` + FlagMultiArg string `desc:"flag with multiple arguments" tag:"flag styles"` + FlagNoArg string `desc:"flag without argument" tag:"flag styles"` + FlagOptArg string `desc:"flag with optional argument" tag:"flag styles"` } var Carapace = carapace{ Value: Default, Description: Gray, Error: Of(Bold, Red), + Usage: Gray, KeywordAmbiguous: Yellow, KeywordNegative: Red, @@ -90,6 +97,11 @@ var Carapace = carapace{ Highlight11: Bold, Highlight12: Of(Bold, Dim), + + FlagArg: Blue, + FlagMultiArg: Magenta, + FlagNoArg: Default, + FlagOptArg: Yellow, } // Highlight returns the style for given level (0..n). diff --git a/vendor/github.com/rsteube/carapace/pkg/style/keyword.go b/vendor/github.com/rsteube/carapace/pkg/style/keyword.go index 837815c..d9e9220 100644 --- a/vendor/github.com/rsteube/carapace/pkg/style/keyword.go +++ b/vendor/github.com/rsteube/carapace/pkg/style/keyword.go @@ -3,6 +3,9 @@ package style import "strings" var keywords = map[string]*string{ + "y": &Carapace.KeywordPositive, + "n": &Carapace.KeywordNegative, + "yes": &Carapace.KeywordPositive, "no": &Carapace.KeywordNegative, @@ -13,25 +16,45 @@ var keywords = map[string]*string{ "off": &Carapace.KeywordNegative, "all": &Carapace.KeywordPositive, + "some": &Carapace.KeywordAmbiguous, "none": &Carapace.KeywordNegative, + "full": &Carapace.KeywordPositive, + "empty": &Carapace.KeywordNegative, + + "strict": &Carapace.KeywordPositive, + "loose": &Carapace.KeywordNegative, + + "open": &Carapace.KeywordPositive, + "opened": &Carapace.KeywordPositive, + "close": &Carapace.KeywordNegative, + "closed": &Carapace.KeywordNegative, + "always": &Carapace.KeywordPositive, "auto": &Carapace.KeywordAmbiguous, "never": &Carapace.KeywordNegative, "start": &Carapace.KeywordPositive, "started": &Carapace.KeywordPositive, + "starting": &Carapace.KeywordPositive, + "run": &Carapace.KeywordPositive, "running": &Carapace.KeywordPositive, "inprogress": &Carapace.KeywordAmbiguous, "pause": &Carapace.KeywordAmbiguous, "paused": &Carapace.KeywordAmbiguous, + "pausing": &Carapace.KeywordAmbiguous, "restart": &Carapace.KeywordAmbiguous, + "restarted": &Carapace.KeywordAmbiguous, "restarting": &Carapace.KeywordAmbiguous, + "remove": &Carapace.KeywordNegative, "removed": &Carapace.KeywordNegative, "removing": &Carapace.KeywordNegative, "stop": &Carapace.KeywordNegative, "stopped": &Carapace.KeywordNegative, + "stopping": &Carapace.KeywordNegative, + "exit": &Carapace.KeywordNegative, "exited": &Carapace.KeywordNegative, + "exiting": &Carapace.KeywordNegative, "dead": &Carapace.KeywordNegative, "create": &Carapace.KeywordPositive, @@ -45,9 +68,11 @@ var keywords = map[string]*string{ "success": &Carapace.KeywordPositive, "unknown": &Carapace.KeywordUnknown, + "backoff": &Carapace.KeywordUnknown, "warn": &Carapace.KeywordAmbiguous, "error": &Carapace.KeywordNegative, "failed": &Carapace.KeywordNegative, + "fatal": &Carapace.KeywordNegative, "nonblock": &Carapace.KeywordAmbiguous, "block": &Carapace.KeywordNegative, diff --git a/vendor/github.com/rsteube/carapace/pkg/xdg/xdg.go b/vendor/github.com/rsteube/carapace/pkg/xdg/xdg.go new file mode 100644 index 0000000..7347a29 --- /dev/null +++ b/vendor/github.com/rsteube/carapace/pkg/xdg/xdg.go @@ -0,0 +1,19 @@ +package xdg + +import "os" + +// UserCacheDir returns the cache base directory. +func UserCacheDir() (dir string, err error) { + if dir = os.Getenv("XDG_CACHE_HOME"); dir == "" { + dir, err = os.UserCacheDir() + } + return +} + +// UserConfigDir returns the config base directory. +func UserConfigDir() (dir string, err error) { + if dir = os.Getenv("XDG_CONFIG_HOME"); dir == "" { + dir, err = os.UserConfigDir() + } + return +} diff --git a/vendor/github.com/rsteube/carapace/storage.go b/vendor/github.com/rsteube/carapace/storage.go index 66334be..9673ffc 100644 --- a/vendor/github.com/rsteube/carapace/storage.go +++ b/vendor/github.com/rsteube/carapace/storage.go @@ -19,6 +19,8 @@ type entry struct { dash []Action dashAny Action preinvoke func(cmd *cobra.Command, flag *pflag.Flag, action Action) Action + prerun func(cmd *cobra.Command, args []string) + bridged bool } type _storage map[*cobra.Command]*entry @@ -32,6 +34,16 @@ func (s _storage) get(cmd *cobra.Command) (e *entry) { return } +func (s _storage) bridge(cmd *cobra.Command) { + if entry := storage.get(cmd); !entry.bridged { + cobra.OnInitialize(func() { + registerValidArgsFunction(cmd) + registerFlagCompletion(cmd) + }) + entry.bridged = true + } +} + func (s _storage) getFlag(cmd *cobra.Command, name string) Action { if flag := cmd.LocalFlags().Lookup(name); flag == nil && cmd.HasParent() { return s.getFlag(cmd.Parent(), name) @@ -48,42 +60,44 @@ func (s _storage) getFlag(cmd *cobra.Command, name string) Action { } } +func (s _storage) preRun(cmd *cobra.Command, args []string) { + if entry := s.get(cmd); entry.prerun != nil { + LOG.Printf("executing PreRun for %#v with args %#v", cmd.Name(), args) + entry.prerun(cmd, args) + } +} + func (s _storage) preinvoke(cmd *cobra.Command, flag *pflag.Flag, action Action) Action { - // TODO yuck - clean this up - entry := s.get(cmd) a := action - if entry.preinvoke != nil { + if entry := s.get(cmd); entry.preinvoke != nil { a = ActionCallback(func(c Context) Action { return entry.preinvoke(cmd, flag, action) }) } + if cmd.HasParent() { - // TODO from cmd passed to preinvoke function return s.preinvoke(cmd.Parent(), flag, a) } return a } -func (s _storage) getPositional(cmd *cobra.Command, pos int) Action { +func (s _storage) getPositional(cmd *cobra.Command, index int) Action { entry := s.get(cmd) + isDash := common.IsDash(cmd) var a Action - // TODO nil check? - if !common.IsDash(cmd) { - if len(entry.positional) > pos { - a = s.preinvoke(cmd, nil, entry.positional[pos]) - } else { - a = s.preinvoke(cmd, nil, entry.positionalAny) - } - } else { - if len(entry.dash) > pos { - a = s.preinvoke(cmd, nil, entry.dash[pos]) - } else { - a = s.preinvoke(cmd, nil, entry.dashAny) - } + switch { + case !isDash && len(entry.positional) > index: + a = s.preinvoke(cmd, nil, entry.positional[index]) + case !isDash: + a = s.preinvoke(cmd, nil, entry.positionalAny) + case len(entry.dash) > index: + a = s.preinvoke(cmd, nil, entry.dash[index]) + default: + a = s.preinvoke(cmd, nil, entry.dashAny) } - return ActionCallback(func(c Context) Action { // TODO verify order of execution is correct + return ActionCallback(func(c Context) Action { invoked := a.Invoke(c) if invoked.meta.Usage == "" && len(strings.Fields(cmd.Use)) > 1 { invoked.meta.Usage = cmd.Use diff --git a/vendor/github.com/rsteube/carapace/traverse.go b/vendor/github.com/rsteube/carapace/traverse.go new file mode 100644 index 0000000..2aa4a9f --- /dev/null +++ b/vendor/github.com/rsteube/carapace/traverse.go @@ -0,0 +1,192 @@ +package carapace + +import ( + "strings" + + "github.com/rsteube/carapace/internal/common" + "github.com/rsteube/carapace/internal/config" + "github.com/rsteube/carapace/internal/pflagfork" + "github.com/rsteube/carapace/pkg/style" + "github.com/spf13/cobra" +) + +type _inFlag struct { // TODO rename or integrate into pflagfork.Flag? + *pflagfork.Flag + // currently consumed args since encountered flag + Args []string +} + +func (f _inFlag) Consumes(arg string) bool { + switch { + case f.Flag == nil: + return false + case !f.TakesValue(): + return false + case f.IsOptarg(): + return false + case len(f.Args) == 0: + return true + case f.Nargs() > 1 && len(f.Args) < f.Nargs(): + return true + case f.Nargs() < 0 && !strings.HasPrefix(arg, "-"): + return true + default: + return false + } +} + +func traverse(c *cobra.Command, args []string) (Action, Context) { + LOG.Printf("traverse called for %#v with args %#v\n", c.Name(), args) + storage.preRun(c, args) + + if config.IsLenient() { + LOG.Printf("allowing unknown flags") + c.FParseErrWhitelist.UnknownFlags = true + } + + inArgs := []string{} // args consumed by current command + var inFlag *_inFlag // last encountered flag that still expects arguments + c.LocalFlags() // TODO force c.mergePersistentFlags() which is missing from c.Flags() + fs := pflagfork.FlagSet{FlagSet: c.Flags()} + + context := NewContext(args...) +loop: + for i, arg := range context.Args { + switch { + // flag argument + case inFlag != nil && inFlag.Consumes(arg): + LOG.Printf("arg %#v is a flag argument\n", arg) + inArgs = append(inArgs, arg) + inFlag.Args = append(inFlag.Args, arg) + + if !inFlag.Consumes("") { + inFlag = nil // no more args expected + } + continue + + // dash + case arg == "--": + LOG.Printf("arg %#v is dash\n", arg) + inArgs = append(inArgs, context.Args[i:]...) + break loop + + // flag + case !c.DisableFlagParsing && strings.HasPrefix(arg, "-"): + LOG.Printf("arg %#v is a flag\n", arg) + inArgs = append(inArgs, arg) + inFlag = &_inFlag{ + Flag: fs.LookupArg(arg), + Args: []string{}, + } + + if inFlag.Flag == nil { + LOG.Printf("flag %#v is unknown", arg) + } + continue + + // subcommand + case subcommand(c, arg) != nil: + LOG.Printf("arg %#v is a subcommand\n", arg) + + switch { + case c.DisableFlagParsing: + LOG.Printf("flag parsing disabled for %#v\n", c.Name()) + + default: + LOG.Printf("parsing flags for %#v with args %#v\n", c.Name(), inArgs) + if err := c.ParseFlags(inArgs); err != nil { + return ActionMessage(err.Error()), context + } + context.Args = c.Flags().Args() + } + + return traverse(subcommand(c, arg), args[i+1:]) + + // positional + default: + LOG.Printf("arg %#v is a positional\n", arg) + inArgs = append(inArgs, arg) + } + } + + toParse := inArgs + if inFlag != nil && len(inFlag.Args) == 0 && inFlag.Consumes("") { + LOG.Printf("removing arg %#v since it is a flag missing its argument\n", toParse[len(toParse)-1]) + toParse = toParse[:len(toParse)-1] + } else if fs.IsShorthandSeries(context.Value) { + LOG.Printf("arg %#v is a shorthand flag series", context.Value) + localInFlag := &_inFlag{ + Flag: fs.LookupArg(context.Value), + Args: []string{}, + } + if localInFlag.Consumes("") && len(context.Value) > 2 { + LOG.Printf("removing shorthand %#v from flag series since it is missing its argument\n", localInFlag.Shorthand) + toParse = append(toParse, strings.TrimSuffix(context.Value, localInFlag.Shorthand)) + } else { + toParse = append(toParse, context.Value) + } + + } + + // TODO duplicated code + switch { + case c.DisableFlagParsing: + LOG.Printf("flag parsing is disabled for %#v\n", c.Name()) + + default: + LOG.Printf("parsing flags for %#v with args %#v\n", c.Name(), toParse) + if err := c.ParseFlags(toParse); err != nil { + return ActionMessage(err.Error()), context + } + context.Args = c.Flags().Args() + } + + switch { + // dash argument + case common.IsDash(c): + LOG.Printf("completing dash for arg %#v\n", context.Value) + context.Args = c.Flags().Args()[c.ArgsLenAtDash():] + LOG.Printf("context: %#v\n", context.Args) + + return storage.getPositional(c, len(context.Args)), context + + // flag argument + case inFlag != nil && inFlag.Consumes(context.Value): + LOG.Printf("completing flag argument of %#v for arg %#v\n", inFlag.Name, context.Value) + context.Parts = inFlag.Args + return storage.getFlag(c, inFlag.Name), context + + // flag + case !c.DisableFlagParsing && strings.HasPrefix(context.Value, "-"): + if f := fs.LookupArg(context.Value); f != nil && f.IsOptarg() && strings.Contains(context.Value, string(f.OptargDelimiter())) { + LOG.Printf("completing optional flag argument for arg %#v\n", context.Value) + prefix, optarg := f.Split(context.Value) + context.Value = optarg + + switch f.Value.Type() { + case "bool": + return ActionValues("true", "false").StyleF(style.ForKeyword).Prefix(prefix), context + default: + return storage.getFlag(c, f.Name).Prefix(prefix), context + } + } + LOG.Printf("completing flags for arg %#v\n", context.Value) + return actionFlags(c), context + + // positional or subcommand + default: + LOG.Printf("completing positionals and subcommands for arg %#v\n", context.Value) + batch := Batch(storage.getPositional(c, len(context.Args))) + if c.HasAvailableSubCommands() && len(context.Args) == 0 { + batch = append(batch, actionSubcommands(c)) + } + return batch.ToA(), context + } +} + +func subcommand(cmd *cobra.Command, arg string) *cobra.Command { + if subcommand, _, _ := cmd.Find([]string{arg}); subcommand != cmd { + return subcommand + } + return nil +} diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml index 439d3e1..2578d94 100644 --- a/vendor/github.com/spf13/cobra/.golangci.yml +++ b/vendor/github.com/spf13/cobra/.golangci.yml @@ -1,4 +1,4 @@ -# Copyright 2013-2022 The Cobra Authors +# Copyright 2013-2023 The Cobra Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/Makefile b/vendor/github.com/spf13/cobra/Makefile index c433a01..0da8d7a 100644 --- a/vendor/github.com/spf13/cobra/Makefile +++ b/vendor/github.com/spf13/cobra/Makefile @@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint)) $(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh") endif -ifeq (, $(shell which richgo)) -$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest") -endif - .PHONY: fmt lint test install_deps clean default: all @@ -25,6 +21,10 @@ lint: test: install_deps $(info ******************** running tests ********************) + go test -v ./... + +richtest: install_deps + $(info ******************** running tests with kyoh86/richgo ********************) richgo test -v ./... install_deps: diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 7cc726b..592c0b8 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -1,4 +1,4 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) +![cobra logo](assets/CobraMain.png) Cobra is a library for creating powerful modern CLI applications. @@ -6,7 +6,7 @@ Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), [Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra. -[![](https://img.shields.io/github/workflow/status/spf13/cobra/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) +[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) [![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra) [![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199) diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go index 95e03ae..2d02394 100644 --- a/vendor/github.com/spf13/cobra/active_help.go +++ b/vendor/github.com/spf13/cobra/active_help.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go index 2c1f99e..e79ec33 100644 --- a/vendor/github.com/spf13/cobra/args.go +++ b/vendor/github.com/spf13/cobra/args.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import ( type PositionalArgs func(cmd *Command, args []string) error -// Legacy arg validation has the following behaviour: +// legacyArgs validation has the following behaviour: // - root commands with no subcommands can take arbitrary arguments // - root commands with subcommands will do subcommand validity checking // - subcommands will always accept arbitrary arguments diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 3acdb27..10c7884 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -532,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { } } -// Setup annotations for go completions for registered flags +// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags func prepareCustomAnnotationsForFlags(cmd *Command) { flagCompletionMutex.RLock() defer flagCompletionMutex.RUnlock() diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go index bb4b718..19b0956 100644 --- a/vendor/github.com/spf13/cobra/bash_completionsV2.go +++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) { __%[1]s_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } @@ -65,7 +65,7 @@ __%[1]s_get_completion_results() { lastChar=${lastParam:$((${#lastParam}-1)):1} __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}" - if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then + if [[ -z ${cur} && ${lastChar} != = ]]; then # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" @@ -75,7 +75,7 @@ __%[1]s_get_completion_results() { # When completing a flag with an = (e.g., %[1]s -n=) # bash focuses on the part after the =, so we need to remove # the flag part from $cur - if [[ "${cur}" == -*=* ]]; then + if [[ ${cur} == -*=* ]]; then cur="${cur#*=}" fi @@ -87,7 +87,7 @@ __%[1]s_get_completion_results() { directive=${out##*:} # Remove the directive out=${out%%:*} - if [ "${directive}" = "${out}" ]; then + if [[ ${directive} == "${out}" ]]; then # There is not directive specified directive=0 fi @@ -101,22 +101,36 @@ __%[1]s_process_completion_results() { local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + if (((directive & shellCompDirectiveError) != 0)); then # Error code. No completion. __%[1]s_debug "Received error from custom completion go code" return else - if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveNoSpace) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no space" compopt -o nospace else __%[1]s_debug "No space directive not supported in this version of bash" fi fi - if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveKeepOrder) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + # no sort isn't supported for bash less than < 4.4 + if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then + __%[1]s_debug "No sort directive not supported in this version of bash" + else + __%[1]s_debug "Activating keep order" + compopt -o nosort + fi + else + __%[1]s_debug "No sort directive not supported in this version of bash" + fi + fi + if (((directive & shellCompDirectiveNoFileComp) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no file completion" compopt +o default else @@ -130,7 +144,7 @@ __%[1]s_process_completion_results() { local activeHelp=() __%[1]s_extract_activeHelp - if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + if (((directive & shellCompDirectiveFilterFileExt) != 0)); then # File extension filtering local fullFilter filter filteringCmd @@ -143,13 +157,12 @@ __%[1]s_process_completion_results() { filteringCmd="_filedir $fullFilter" __%[1]s_debug "File filtering command: $filteringCmd" $filteringCmd - elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + elif (((directive & shellCompDirectiveFilterDirs) != 0)); then # File completion for directories only - # Use printf to strip any trailing newline local subdir - subdir=$(printf "%%s" "${completions[0]}") - if [ -n "$subdir" ]; then + subdir=${completions[0]} + if [[ -n $subdir ]]; then __%[1]s_debug "Listing directories in $subdir" pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return else @@ -164,7 +177,7 @@ __%[1]s_process_completion_results() { __%[1]s_handle_special_char "$cur" = # Print the activeHelp statements before we finish - if [ ${#activeHelp[*]} -ne 0 ]; then + if ((${#activeHelp[*]} != 0)); then printf "\n"; printf "%%s\n" "${activeHelp[@]}" printf "\n" @@ -184,21 +197,21 @@ __%[1]s_process_completion_results() { # Separate activeHelp lines from real completions. # Fills the $activeHelp and $completions arrays. __%[1]s_extract_activeHelp() { - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} while IFS='' read -r comp; do - if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then + if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then comp=${comp:endIndex} __%[1]s_debug "ActiveHelp found: $comp" - if [ -n "$comp" ]; then + if [[ -n $comp ]]; then activeHelp+=("$comp") fi else # Not an activeHelp line but a normal completion completions+=("$comp") fi - done < <(printf "%%s\n" "${out}") + done <<<"${out}" } __%[1]s_handle_completion_types() { @@ -254,7 +267,7 @@ __%[1]s_handle_standard_completion_case() { done < <(printf "%%s\n" "${completions[@]}") # If there is a single completion left, remove the description text - if [ ${#COMPREPLY[*]} -eq 1 ]; then + if ((${#COMPREPLY[*]} == 1)); then __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" comp="${COMPREPLY[0]%%%%$tab*}" __%[1]s_debug "Removed description from single completion, which is now: ${comp}" @@ -271,8 +284,8 @@ __%[1]s_handle_special_char() if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then local word=${comp%%"${comp##*${char}}"} local idx=${#COMPREPLY[*]} - while [[ $((--idx)) -ge 0 ]]; do - COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"} + while ((--idx >= 0)); do + COMPREPLY[idx]=${COMPREPLY[idx]#"$word"} done fi } @@ -298,7 +311,7 @@ __%[1]s_format_comp_descriptions() # Make sure we can fit a description of at least 8 characters # if we are to align the descriptions. - if [[ $maxdesclength -gt 8 ]]; then + if ((maxdesclength > 8)); then # Add the proper number of spaces to align the descriptions for ((i = ${#comp} ; i < longest ; i++)); do comp+=" " @@ -310,8 +323,8 @@ __%[1]s_format_comp_descriptions() # If there is enough space for any description text, # truncate the descriptions that are too long for the shell width - if [ $maxdesclength -gt 0 ]; then - if [ ${#desc} -gt $maxdesclength ]; then + if ((maxdesclength > 0)); then + if ((${#desc} > maxdesclength)); then desc=${desc:0:$(( maxdesclength - 1 ))} desc+="…" fi @@ -332,9 +345,9 @@ __start_%[1]s() # Call _init_completion from the bash-completion package # to prepare the arguments properly if declare -F _init_completion >/dev/null 2>&1; then - _init_completion -n "=:" || return + _init_completion -n =: || return else - __%[1]s_init_completion -n "=:" || return + __%[1]s_init_completion -n =: || return fi __%[1]s_debug @@ -361,7 +374,7 @@ fi # ex: ts=4 sw=4 et filetype=sh `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index fe44bc8..b07b44a 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -167,8 +167,8 @@ func appendIfNotPresent(s, stringToAppend string) string { // rpad adds padding to the right of a string. func rpad(s string, padding int) string { - template := fmt.Sprintf("%%-%ds", padding) - return fmt.Sprintf(template, s) + formattedString := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(formattedString, s) } // tmpl executes the given template text on data, writing the result to w. diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 6ff47dd..01f7c6f 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" // FParseErrWhitelist configures Flag parse errors to be ignored type FParseErrWhitelist flag.ParseErrorsWhitelist -// Structure to manage groups for commands +// Group Structure to manage groups for commands type Group struct { ID string Title string @@ -47,7 +47,7 @@ type Group struct { // definition to ensure usability. type Command struct { // Use is the one-line usage message. - // Recommended syntax is as follow: + // Recommended syntax is as follows: // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. // ... indicates that you can specify multiple values for the previous argument. // | indicates mutually exclusive information. You can use the argument to the left of the separator or the @@ -321,7 +321,7 @@ func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// SetHelpCommandGroup sets the group id of the help command. +// SetHelpCommandGroupID sets the group id of the help command. func (c *Command) SetHelpCommandGroupID(groupID string) { if c.helpCommand != nil { c.helpCommand.GroupID = groupID @@ -330,7 +330,7 @@ func (c *Command) SetHelpCommandGroupID(groupID string) { c.helpCommandGroupID = groupID } -// SetCompletionCommandGroup sets the group id of the completion command. +// SetCompletionCommandGroupID sets the group id of the completion command. func (c *Command) SetCompletionCommandGroupID(groupID string) { // completionCommandGroupID is used if no completion command is defined by the user c.Root().completionCommandGroupID = groupID @@ -655,20 +655,44 @@ Loop: // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). -func argsMinusFirstX(args []string, x string) []string { - for i, y := range args { - if x == y { - ret := []string{} - ret = append(ret, args[:i]...) - ret = append(ret, args[i+1:]...) - return ret +// Special care needs to be taken not to remove a flag value. +func (c *Command) argsMinusFirstX(args []string, x string) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + flags := c.Flags() + +Loop: + for pos := 0; pos < len(args); pos++ { + s := args[pos] + switch { + case s == "--": + // -- means we have reached the end of the parseable args. Break out of the loop now. + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + fallthrough + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip + // over the next arg, because that is the value of this flag. + pos++ + continue + case !strings.HasPrefix(s, "-"): + // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, + // return the args, excluding the one at this position. + if s == x { + ret := []string{} + ret = append(ret, args[:pos]...) + ret = append(ret, args[pos+1:]...) + return ret + } } } return args } func isFlagArg(arg string) bool { - return ((len(arg) >= 3 && arg[1] == '-') || + return ((len(arg) >= 3 && arg[0:2] == "--") || (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) } @@ -686,7 +710,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) { cmd := c.findNext(nextSubCmd) if cmd != nil { - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) + return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) } return c, innerArgs } @@ -1272,7 +1296,7 @@ func (c *Command) AllChildCommandsHaveGroup() bool { return true } -// ContainGroups return if groupID exists in the list of command groups. +// ContainsGroup return if groupID exists in the list of command groups. func (c *Command) ContainsGroup(groupID string) bool { for _, x := range c.commandgroups { if x.ID == groupID { diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go index 2b77f8f..307f0c1 100644 --- a/vendor/github.com/spf13/cobra/command_notwin.go +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index 520f23a..adbef39 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go index e8a0206..ee38c4d 100644 --- a/vendor/github.com/spf13/cobra/completions.go +++ b/vendor/github.com/spf13/cobra/completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -77,6 +77,10 @@ const ( // obtain the same behavior but only for flags. ShellCompDirectiveFilterDirs + // ShellCompDirectiveKeepOrder indicates that the shell should preserve the order + // in which the completions are provided + ShellCompDirectiveKeepOrder + // =========================================================================== // All directives using iota should be above this one. @@ -159,6 +163,9 @@ func (d ShellCompDirective) string() string { if d&ShellCompDirectiveFilterDirs != 0 { directives = append(directives, "ShellCompDirectiveFilterDirs") } + if d&ShellCompDirectiveKeepOrder != 0 { + directives = append(directives, "ShellCompDirectiveKeepOrder") + } if len(directives) == 0 { directives = append(directives, "ShellCompDirectiveDefault") } @@ -169,7 +176,7 @@ func (d ShellCompDirective) string() string { return strings.Join(directives, ", ") } -// Adds a special hidden command that can be used to request custom completions. +// initCompleteCmd adds a special hidden command that can be used to request custom completions. func (c *Command) initCompleteCmd(args []string) { completeCmd := &Command{ Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd), @@ -727,7 +734,7 @@ to enable it. You can execute the following once: To load completions in your current shell session: - source <(%[1]s completion zsh); compdef _%[1]s %[1]s + source <(%[1]s completion zsh) To load completions for every new session, execute once: diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go index 97112a1..12ca0d2 100644 --- a/vendor/github.com/spf13/cobra/fish_completions.go +++ b/vendor/github.com/spf13/cobra/fish_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ function __%[1]s_perform_completion __%[1]s_debug "last arg: $lastArg" # Disable ActiveHelp which is not supported for fish shell - set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg" + set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg" __%[1]s_debug "Calling $requestComp" set -l results (eval $requestComp 2> /dev/null) @@ -89,6 +89,60 @@ function __%[1]s_perform_completion printf "%%s\n" "$directiveLine" end +# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result +function __%[1]s_perform_completion_once + __%[1]s_debug "Starting __%[1]s_perform_completion_once" + + if test -n "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion" + return 0 + end + + set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion) + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "No completions, probably due to a failure" + return 1 + end + + __%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result" + return 0 +end + +# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run +function __%[1]s_clear_perform_completion_once_result + __%[1]s_debug "" + __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" + set --erase __%[1]s_perform_completion_once_result + __%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result" +end + +function __%[1]s_requires_order_preservation + __%[1]s_debug "" + __%[1]s_debug "========= checking if order preservation is required ==========" + + __%[1]s_perform_completion_once + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Error determining if order preservation is required" + return 1 + end + + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + __%[1]s_debug "Directive is: $directive" + + set -l shellCompDirectiveKeepOrder %[9]d + set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2) + __%[1]s_debug "Keeporder is: $keeporder" + + if test $keeporder -ne 0 + __%[1]s_debug "This does require order preservation" + return 0 + end + + __%[1]s_debug "This doesn't require order preservation" + return 1 +end + + # This function does two things: # - Obtain the completions and store them in the global __%[1]s_comp_results # - Return false if file completion should be performed @@ -99,17 +153,17 @@ function __%[1]s_prepare_completions # Start fresh set --erase __%[1]s_comp_results - set -l results (__%[1]s_perform_completion) - __%[1]s_debug "Completion results: $results" + __%[1]s_perform_completion_once + __%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result" - if test -z "$results" + if test -z "$__%[1]s_perform_completion_once_result" __%[1]s_debug "No completion, probably due to a failure" # Might as well do file completion, in case it helps return 1 end - set -l directive (string sub --start 2 $results[-1]) - set --global __%[1]s_comp_results $results[1..-2] + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2] __%[1]s_debug "Completions are: $__%[1]s_comp_results" __%[1]s_debug "Directive is: $directive" @@ -205,13 +259,17 @@ end # Remove any pre-existing completions for the program since we will be handling all of them. complete -c %[2]s -e +# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global +complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result' # The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results # which provides the program's completion choices. -complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' - +# If this doesn't require order preservation, we don't use the -k flag +complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +# otherwise we use the -k flag +complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' `, nameForVar, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } // GenFishCompletion generates fish completion file and writes to the passed writer. diff --git a/vendor/github.com/spf13/cobra/flag_groups.go b/vendor/github.com/spf13/cobra/flag_groups.go index 9c377aa..b35fde1 100644 --- a/vendor/github.com/spf13/cobra/flag_groups.go +++ b/vendor/github.com/spf13/cobra/flag_groups.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go index 004de42..177d275 100644 --- a/vendor/github.com/spf13/cobra/powershell_completions.go +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -77,6 +77,7 @@ filter __%[1]s_escapeStringWithSpecialChars { $ShellCompDirectiveNoFileComp=%[6]d $ShellCompDirectiveFilterFileExt=%[7]d $ShellCompDirectiveFilterDirs=%[8]d + $ShellCompDirectiveKeepOrder=%[9]d # Prepare the command to request completions for the program. # Split the command at the first space to separate the program and arguments. @@ -106,13 +107,22 @@ filter __%[1]s_escapeStringWithSpecialChars { # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" -`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+` -`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + # PowerShell 7.2+ changed the way how the arguments are passed to executables, + # so for pre-7.2 or when Legacy argument passing is enabled we need to use +`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+` + if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or + ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or + (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and + $PSNativeCommandArgumentPassing -eq 'Legacy')) { +`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + } else { + $RequestComp="$RequestComp" + ' ""' + } } __%[1]s_debug "Calling $RequestComp" # First disable ActiveHelp which is not supported for Powershell - $env:%[9]s=0 + $env:%[10]s=0 #call the command store the output in $out and redirect stderr and stdout to null # $Out is an array contains each line per element @@ -137,7 +147,7 @@ filter __%[1]s_escapeStringWithSpecialChars { } $Longest = 0 - $Values = $Out | ForEach-Object { + [Array]$Values = $Out | ForEach-Object { #Split the output in name and description `+" $Name, $Description = $_.Split(\"`t\",2)"+` __%[1]s_debug "Name: $Name Description: $Description" @@ -182,6 +192,11 @@ filter __%[1]s_escapeStringWithSpecialChars { } } + # we sort the values in ascending order by name if keep order isn't passed + if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) { + $Values = $Values | Sort-Object -Property Name + } + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { __%[1]s_debug "ShellCompDirectiveNoFileComp is called" @@ -267,7 +282,7 @@ filter __%[1]s_escapeStringWithSpecialChars { Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock `, name, nameForVar, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error { diff --git a/vendor/github.com/spf13/cobra/projects_using_cobra.md b/vendor/github.com/spf13/cobra/projects_using_cobra.md index 6865f88..8a291eb 100644 --- a/vendor/github.com/spf13/cobra/projects_using_cobra.md +++ b/vendor/github.com/spf13/cobra/projects_using_cobra.md @@ -1,11 +1,13 @@ ## Projects using Cobra - [Allero](https://github.com/allero-io/allero) +- [Arewefastyet](https://benchmark.vitess.io) - [Arduino CLI](https://github.com/arduino/arduino-cli) - [Bleve](https://blevesearch.com/) - [Cilium](https://cilium.io/) - [CloudQuery](https://github.com/cloudquery/cloudquery) - [CockroachDB](https://www.cockroachlabs.com/) +- [Constellation](https://github.com/edgelesssys/constellation) - [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) - [Datree](https://github.com/datreeio/datree) - [Delve](https://github.com/derekparker/delve) @@ -25,7 +27,7 @@ - [Istio](https://istio.io) - [Kool](https://github.com/kool-dev/kool) - [Kubernetes](https://kubernetes.io/) -- [Kubescape](https://github.com/armosec/kubescape) +- [Kubescape](https://github.com/kubescape/kubescape) - [KubeVirt](https://github.com/kubevirt/kubevirt) - [Linkerd](https://linkerd.io/) - [Mattermost-server](https://github.com/mattermost/mattermost-server) @@ -51,10 +53,12 @@ - [Random](https://github.com/erdaltsksn/random) - [Rclone](https://rclone.org/) - [Scaleway CLI](https://github.com/scaleway/scaleway-cli) +- [Sia](https://github.com/SiaFoundation/siad) - [Skaffold](https://skaffold.dev/) - [Tendermint](https://github.com/tendermint/tendermint) - [Twitch CLI](https://github.com/twitchdev/twitch-cli) - [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli) +- [Vitess](https://vitess.io) - VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework) - [Werf](https://werf.io/) - [ZITADEL](https://github.com/zitadel/zitadel) diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go index 126e83c..b035742 100644 --- a/vendor/github.com/spf13/cobra/shell_completions.go +++ b/vendor/github.com/spf13/cobra/shell_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/github.com/spf13/cobra/shell_completions.md b/vendor/github.com/spf13/cobra/shell_completions.md index 553ee5d..065c062 100644 --- a/vendor/github.com/spf13/cobra/shell_completions.md +++ b/vendor/github.com/spf13/cobra/shell_completions.md @@ -71,7 +71,7 @@ PowerShell: `,cmd.Root().Name()), DisableFlagsInUseLine: true, ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, - Args: cobra.ExactValidArgs(1), + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { switch args[0] { case "bash": @@ -162,16 +162,7 @@ cmd := &cobra.Command{ } ``` -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion algorithm if entered manually, e.g. in: - -```bash -$ kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of -replication controllers following `rc`. +The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`. ### Dynamic completion of nouns @@ -237,6 +228,10 @@ ShellCompDirectiveFilterFileExt // return []string{"themes"}, ShellCompDirectiveFilterDirs // ShellCompDirectiveFilterDirs + +// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order +// in which the completions are provided +ShellCompDirectiveKeepOrder ``` ***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function. @@ -385,6 +380,19 @@ or ```go ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"} ``` + +If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like: + +```bash +$ source <(helm completion bash) +$ helm completion [tab][tab] +bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell) +fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh) + +$ source <(helm completion bash --no-descriptions) +$ helm completion [tab][tab] +bash fish powershell zsh +``` ## Bash completions ### Dependencies diff --git a/vendor/github.com/spf13/cobra/user_guide.md b/vendor/github.com/spf13/cobra/user_guide.md index e55367e..85201d8 100644 --- a/vendor/github.com/spf13/cobra/user_guide.md +++ b/vendor/github.com/spf13/cobra/user_guide.md @@ -188,6 +188,37 @@ var versionCmd = &cobra.Command{ } ``` +### Organizing subcommands + +A command may have subcommands which in turn may have other subcommands. This is achieved by using +`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in +its own go package. + +The suggested approach is for the parent command to use `AddCommand` to add its most immediate +subcommands. For example, consider the following directory structure: + +```text +├── cmd +│   ├── root.go +│   └── sub1 +│   ├── sub1.go +│   └── sub2 +│   ├── leafA.go +│   ├── leafB.go +│   └── sub2.go +└── main.go +``` + +In this case: + +* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command. +* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command. +* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the + sub2 command. + +This approach ensures the subcommands are always included at compile time while avoiding cyclic +references. + ### Returning and handling errors If you wish to return an error to the caller of a command, `RunE` can be used. @@ -313,8 +344,8 @@ rootCmd.MarkFlagsRequiredTogether("username", "password") You can also prevent different flags from being provided together if they represent mutually exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: ```go -rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON") -rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML") +rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") +rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") ``` @@ -349,7 +380,7 @@ shown below: ```go var cmd = &cobra.Command{ Short: "hello", - Args: MatchAll(ExactArgs(2), OnlyValidArgs), + Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") }, diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go index 84cec76..1856e4c 100644 --- a/vendor/github.com/spf13/cobra/zsh_completions.go +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -90,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) { compCmd = ShellCompNoDescRequestCmd } WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s +compdef _%[1]s %[1]s # zsh completion for %-36[1]s -*- shell-script -*- @@ -108,8 +109,9 @@ _%[1]s() local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace + local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder local -a completions __%[1]s_debug "\n========= starting completion logic ==========" @@ -177,7 +179,7 @@ _%[1]s() return fi - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} local startIndex=$((${#activeHelpMarker}+1)) local hasActiveHelp=0 @@ -227,6 +229,11 @@ _%[1]s() noSpace="-S ''" fi + if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then + __%[1]s_debug "Activating keep order." + keepOrder="-V" + fi + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then # File extension filtering local filteringCmd @@ -262,7 +269,7 @@ _%[1]s() return $result else __%[1]s_debug "Calling _describe" - if eval _describe "completions" completions $flagPrefix $noSpace; then + if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then __%[1]s_debug "_describe found some completions" # Return the success of having called _describe @@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then fi `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index c43dfec..0303278 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -23,12 +23,14 @@ github.com/leodido/go-urn # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/rsteube/carapace v0.30.0 => github.com/reeflective/carapace v0.25.2-0.20230106225838-382407e213d4 +# github.com/rsteube/carapace v0.30.0 => github.com/reeflective/carapace v0.25.2-0.20230416191807-fc9b8c3aa6f6 ## explicit; go 1.15 github.com/rsteube/carapace github.com/rsteube/carapace/internal/cache github.com/rsteube/carapace/internal/common github.com/rsteube/carapace/internal/config +github.com/rsteube/carapace/internal/export +github.com/rsteube/carapace/internal/man github.com/rsteube/carapace/internal/pflagfork github.com/rsteube/carapace/internal/shell github.com/rsteube/carapace/internal/shell/bash @@ -48,6 +50,7 @@ github.com/rsteube/carapace/internal/uid github.com/rsteube/carapace/pkg/cache github.com/rsteube/carapace/pkg/ps github.com/rsteube/carapace/pkg/style +github.com/rsteube/carapace/pkg/xdg github.com/rsteube/carapace/third_party/github.com/acarl005/stripansi github.com/rsteube/carapace/third_party/github.com/drone/envsubst github.com/rsteube/carapace/third_party/github.com/drone/envsubst/parse @@ -60,7 +63,7 @@ github.com/rsteube/carapace/third_party/golang.org/x/sys/execabs ## explicit; go 1.19 github.com/rsteube/carapace-bin/pkg/actions/net github.com/rsteube/carapace-bin/pkg/actions/number -# github.com/spf13/cobra v1.6.1 +# github.com/spf13/cobra v1.7.0 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.5