diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2019-01-05 13:25:18 +0100 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2019-01-05 13:25:18 +0100 |
commit | 7e6a3d73413ad665a87cecf39d1dd05a91c1a31e (patch) | |
tree | 6e826685afbd476b340d311d2c08af12b3e81a8e /Completion/Unix/Command | |
parent | feaf8570c138e4372ae9517f1f5658ae74640c41 (diff) | |
parent | 325fceab3b4ffa871777bacc420e0e8efcb0afb9 (diff) | |
download | zsh-7e6a3d73413ad665a87cecf39d1dd05a91c1a31e.tar.gz zsh-7e6a3d73413ad665a87cecf39d1dd05a91c1a31e.zip |
New upstream release candidate 5.6.2-test-3
Merge branch 'upstream' at 'zsh-5.6.2-test-3' into branch debian
Diffstat (limited to 'Completion/Unix/Command')
-rw-r--r-- | Completion/Unix/Command/_composer | 850 | ||||
-rw-r--r-- | Completion/Unix/Command/_git | 12 | ||||
-rw-r--r-- | Completion/Unix/Command/_ipsec | 179 | ||||
-rw-r--r-- | Completion/Unix/Command/_swanctl | 225 |
4 files changed, 1256 insertions, 10 deletions
diff --git a/Completion/Unix/Command/_composer b/Completion/Unix/Command/_composer new file mode 100644 index 000000000..2b9f2cd32 --- /dev/null +++ b/Completion/Unix/Command/_composer @@ -0,0 +1,850 @@ +#compdef composer composer.phar + +# Notes: +# - With some re-arranging, this function could be used as a base for completing +# any Symfony Console application. It's worth mentioning that most Console +# applications provide their help output in structured XML and JSON formats, +# and a helper function could be written to parse these and produce basic +# completion similar to what `_arguments --` does. But it wouldn't be fully +# featured like this +# - Completing arbitrary package names from Packagist, even with caching enabled +# (which it is by default here), can be very slow; it may even hang the shell. +# To disable the fetching of remote packages and use only local cache/JSON +# information for completion, set the fetch-packages style as follows: +# zstyle ':completion:*:composer:*' fetch-packages no +# - @todo We don't complete custom commands (including script aliases). This is +# easy to do in the general case, but it probably requires some clever caching +# to avoid introducing a noticeable lag to every completion operation, due to +# the way command resolution works and the fact that discovering custom +# commands requires making slow calls to Composer +# - @todo We don't complete version constraints + +# Check cache validity +__composer_cache_policy() { + # Invalidate if the cache is over a week old + [[ -n $1(#qmw+1N) ]] && return 0 + + __composer_update_work_dir + + # Invalidate if the current project JSON file is newer than the cache + [[ -e $_composer_work_dir/composer.json ]] && + [[ $_composer_work_dir/composer.json -nt $1 ]] +} + +# _call_program wrapper (same eval/quoting rules apply) +# $1 => tag +# $2 ... => composer arguments +(( $+functions[__composer_call] )) || +__composer_call() { + local -a cmd + + __composer_update_work_dir + + cmd=( ${_composer_cmd:-composer} -d${_composer_work_dir:-${(q)PWD}} ) + (( _composer_is_global )) && cmd+=( global ) + + _call_program $1 $cmd "${@[2,-1]}" +} + +# Resolve potentially abbreviated/aliased command name to canonical name +# $1 => name of scalar parameter to set +# $2 => provided command name +(( $+functions[__composer_resolve_cmd] )) || +__composer_resolve_cmd() { + local __i __ret=1 + local -a __cmds __tmp=( ${(@)_composer_cmds%%:*} ) + + __cmds=( $__tmp[(r)$2] ) + (( $#__cmds )) || __cmds=( ${(M)__tmp:#$2*} ) + + if (( $#__cmds == 1 )); then + 2=$__cmds[1] + (( $+_composer_cmd_aliases[$2] )) && 2=$_composer_cmd_aliases[$2] + __ret=0 + else + 3=$__cmds[1] + + # An ambiguous prefix match isn't ambiguous if all the matches are aliases + # of each other + for (( __i = 2; __i <= $#__cmds; __i++ )); do + if [[ $_composer_cmd_aliases[$__cmds[__i]] == $3 ]]; then + __cmds[__i]=() + elif [[ $_composer_cmd_aliases[$3] == $__cmds[__i] ]]; then + 3=$__cmds[__i] + __cmds[__i]=() + fi + done + + if (( $#__cmds == 1 )); then + 2=$3 + __ret=0 + elif (( $#__cmds )); then + _message -e ambiguous-commands "ambiguous command: $2 ($__cmds)" + else + # @todo Too annoying without handling custom commands + : _message -e unrecognized-commands "unrecognized command: $2" + fi + fi + : ${(P)1::=$2} + return __ret +} + +# Remove already-used global options (this is a bit silly admittedly) +# $1 ... => options given (e.g. ${(k)opt_args}) +(( $+functions[__composer_prune_global_opts] )) || +__composer_prune_global_opts() { + local opt + local -a excls specs remove + + for opt in $@; do + specs=( ${(M)_composer_global_opts:#(*[\*\)]|)${opt}[=+-]#\[*} ) + excls=( ${=${(@)${(@M)specs#\([^\)]##\)}//[ \(\)]/ }} ) + remove+=( + # Don't remove used options like *-v + ${specs:#(*\)|)\*${opt}[=+-]#\[*} + # But do remove them if a used option excludes them + ${(M)_composer_global_opts:#(*[\*\)]|)(${(j<|>)~${(@b)excls}})[=+-]#\[*} + ) + done + + _composer_global_opts=( ${_composer_global_opts:#(${(j<|>)~${(@b)remove}})} ) +} + +# Update the working directory from opt_args/PWD. This is a little irritating to +# deal with; for now we're just calling it anywhere it might be important +(( $+functions[__composer_update_work_dir] )) || +__composer_update_work_dir() { + if [[ -n ${(v)opt_args[(i)(-d|--working-dir)]} ]]; then + eval _composer_work_dir=${(v)opt_args[(i)(-d|--working-dir)]} + elif [[ -z $_composer_work_dir ]]; then + _composer_work_dir=$PWD + fi +} + +# Complete local/vendored binaries +(( $+functions[__composer_binaries] )) || +__composer_binaries() { + local -a expl tmp + + tmp=( ${(f)"$( __composer_call exec-list exec -l )"} ) + tmp=( ${(@)tmp%%[[:space:]]##} ) + [[ $tmp[1] == *: ]] && tmp[1]=() + tmp=( ${(@)tmp##[\*-][[:space:]]#} ) + tmp=( ${(@)tmp%%[[:space:]]##\(local\)} ) + + _wanted -x commands expl binary compadd -a "$@" - tmp +} + +# Complete commands +(( $+functions[__composer_commands] )) || +__composer_commands() { + _describe -t commands command _composer_cmds +} + +# Complete package licences +(( $+functions[__composer_licenses] )) || +__composer_licenses() { + # These are just the ones the Composer documentation recommends; the full list + # of supported identifiers can be found at https://spdx.org/licenses/. If + # other functions need to complete licences in the future, it might be wise to + # break this out into a _licenses type + local -a tmp=( + 'Apache-2.0:Apache License 2.0' + 'BSD-2-Clause:BSD 2-Clause "Simplified" License' + 'BSD-3-Clause:BSD 3-Clause "New" or "Revised" License' + 'BSD-4-Clause:BSD 4-Clause "Original" or "Old" License' + 'GPL-2.0-only:GNU General Public License v2.0 only' + 'GPL-2.0-or-later:GNU General Public License v2.0 or later' + 'GPL-3.0-only:GNU General Public License v3.0 only' + 'GPL-3.0-or-later:GNU General Public License v3.0 or later' + 'LGPL-2.1-only:GNU Lesser General Public License v2.1 only' + 'LGPL-2.1-or-later:GNU Lesser General Public License v2.1 or later' + 'LGPL-3.0-only:GNU Lesser General Public License v3.0 only' + 'LGPL-3.0-or-later:GNU Lesser General Public License v3.0 or later' + 'MIT:MIT License' + 'proprietary:proprietary/closed-source license' + ) + _describe -t licenses 'package license' tmp +} + +# Complete packages +# --pairs => complete as package:constraint pairs +# --vendor => complete only vendored (installed) packages +(( $+functions[__composer_packages] )) || +__composer_packages() { + local cwd + local -a pairs vendor home_dirs pkgs + + __composer_update_work_dir + + zparseopts -D -E - -vendor=vendor -pairs=pairs + + (( $#pairs )) && compset -P '*[:= ]' && { + _message -e versions 'version constraint' + return + } + + home_dirs=( + $COMPOSER_HOME(#q/N) + $HOME/.composer(#q/N) + $HOME/.config/composer(#q/N) + ${XDG_CONFIG_HOME:-/@err@}/composer(#q/N) + ) + + pkgs=( $_composer_work_dir/vendor/*/*(#q/N) ) + + # Trying to work out the path to the vendor directory when we're global is + # tedious, so we'll just take everything we can find + (( ! $#vendor || _composer_is_global )) && + pkgs+=( $^home_dirs/vendor/*/*(#q/N) ) + + (( $#vendor )) || pkgs+=( + ${COMPOSER_CACHE_DIR:-/@err@}/files/*/*(#q/N) + $^home_dirs/cache/files/*/*(#q/N) + ) + + pkgs=( ${(@M)pkgs%%[^/]##/[^/]##} ) + + (( $#vendor )) || { + pkgs+=( + ${(f)"$( + _call_program packages-json \ + command grep -soE ${(qq):-'"[^/]+\\?/[^/]+"\s*:'} -- \ + ${(qq)_composer_work_dir}/composer.json + )"//[$':" \t\\']/} + ${(@)${(f)"$( + _call_program packages-lock \ + command grep -soE ${(qq):-'"name"\s*:\s*"[^/]+\\?/[^/]+"'} -- \ + ${(qq)_composer_work_dir}/composer.lock + )"//\"name\"/}//[$':" \t\\']/} + ) + + zstyle -T ":completion:*:*:$service:*" fetch-packages && { + { (( ! $#_composer_cache_pkgs )) || _cache_invalid composer-pkgs } && + ! _retrieve_cache composer-pkgs && { + _composer_cache_pkgs=( ${(f)"$( + __composer_call packages-fetch show -aN | + LC_ALL=C tr -d '\t ' # Seems faster than ${...//.../} here + )"} ) + _store_cache composer-pkgs _composer_cache_pkgs + } + pkgs+=( $_composer_cache_pkgs ) + } + } + + (( $#pkgs )) || { + _message -e packages package + return + } + + if [[ $PREFIX == */* ]]; then + _description packages expl "${PREFIX%%/*}/* package" + else + _description packages expl 'package vendor' + fi + _multi_parts "${(@)expl}" "$@" / pkgs +} + +# Complete package repositories +(( $+functions[__composer_repositories] )) || +__composer_repositories() { + _alternative \ + 'urls:repository URL:_urls' \ + 'files:repository JSON configuration file:_files -g "*.json(#q-.)"' \ + 'json:repository JSON configuration object:' +} + +# Complete composer.json scripts +(( $+functions[__composer_scripts] )) || +__composer_scripts() { + local -a expl tmp + + tmp=( ${(f)"$( __composer_call run-script-list run-script -l )"} ) + tmp=( ${(@)tmp##[[:space:]]##} ) + tmp=( ${(@)tmp%%[[:space:]]##} ) + [[ $tmp[1] == *: ]] && tmp[1]=() + tmp=( ${(@)tmp##[\*-][[:space:]]#} ) + tmp=( ${(@)tmp%%[[:space:]]*} ) + + _wanted -x commands expl script compadd -a "$@" - tmp +} + +# Complete package stabilities +(( $+functions[__composer_stabilities] )) || +__composer_stabilities() { + local -a expl + _wanted stabilities expl 'package stability' compadd "$@" - \ + stable RC beta alpha dev +} + +# Complete package types +(( $+functions[__composer_types] )) || +__composer_types() { + local -a expl + # Only the first four here are official types listed in the documentation; the + # others are popular custom types + _wanted types expl 'package type' compadd "$@" - \ + composer-plugin library metapackage project \ + cakephp-plugin cantao-module drupal-module magento2-module package \ + phpcodesniffer-standard silverstripe-module symfony-bundle \ + typo3-cms-extension wordpress-plugin yii2-extension +} + +(( $+functions[_composer_archive] )) || +_composer_archive() { + _arguments -s -S : \ + $_composer_global_opts \ + '--dir=[specify output directory]:output directory:_files -/' \ + '--file=[specify output file name]:output file name (without extension):_files' \ + '(-f --format)'{-f+,--format=}'[specify archive format]:archive format:(tar zip)' \ + '1:: :__composer_packages' \ + '2:: :_guard "^-*" "version constraint"' +} + +(( $+functions[_composer_check-platform-reqs] )) || +_composer_check-platform-reqs() { + _arguments -s -S : \ + $_composer_global_opts \ + '--no-dev[do not check require-dev package requirements]' +} + +(( $+functions[_composer_config] )) || +_composer_config() { + local ret=1 + local -a context expl line state state_descr cmd tmp + local -A opt_args + + # -a and -f can be used together, in which case auth.json will be looked up in + # the base directory of the -f file. -f and -g can't be used together, but -f + # can still be used to specify config.json with `composer global config` + _arguments -s -S : \ + $_composer_global_opts \ + + '(a)' '(A l u : *)'{-a,--auth}'[edit auth.json (with -e)]' \ + + '(A)' '(a e u)--absolute[display absolute *-dir setting paths]' \ + + '(e)' '(A l u : *)'{-e,--editor}'[open configuration in $EDITOR]' \ + + '(f)' '(g)'{-f+,--file=}'[specify {composer,config}.json path]:configuration file:_files' \ + + '(g)' {-g,--global}'[use global config.json]' \ + + '(l)' '(a e u : *)'{-l,--list}'[list configuration settings]' \ + + '(u)' '(a A e l *)--unset[unset specified setting key]' \ + + k '(a e l)1: :->key' \ + + v '(a e l u)*:: :->val' \ + && ret=0 + __composer_update_work_dir + + case $state in + key) + # `composer config` doesn't seem to actually respect -d... + tmp=( ${(v)opt_args[(i)([^-]##-|)(-f|--file)]} ) + cmd=( config -f$^tmp $opt_args[(i)([^-]##-|)(-g|--global)] -l ) + + tmp=( ${(@M)${(f)"$( __composer_call config-list $cmd )"}#\[*\]} ) + tmp=( ${(@)tmp//[ \]\[]/} ) + + _wanted setting-keys expl 'setting key' compadd -a "$@" - tmp && ret=0 + ;; + val) + case $words[1] in + *[.-]dirs#|home) + _wanted setting-values expl 'setting value' _files -/ "$@" && ret=0 + ;; + *[.-]domains#) + _wanted setting-values expl 'setting value' _hosts "$@" && ret=0 + ;; + *[.-]urls#) + _wanted setting-values expl 'setting value' _urls "$@" && ret=0 + ;; + *) + # If we wanted we could get specific about booleans, etc., here + _wanted setting-values expl 'setting value' _default "$@" && ret=0 + ;; + esac + ;; + esac + + return ret +} + +(( $+functions[_composer_create-project] )) || +_composer_create-project() { + _arguments -s -S : \ + $_composer_global_opts \ + '(--no-dev)--dev[install require-dev packages]' \ + '--ignore-platform-reqs[ignore PHP platform requirements]' \ + '(--remove-vcs)--keep-vcs[do not remove VCS directory]' \ + '!(--no-plugins)--no-custom-installers' \ + '(--dev)--no-dev[do not install require-dev packages]' \ + '--no-install[skip installation of package dependencies]' \ + '--no-progress[do not display download progress]' \ + '--no-secure-http[do not use HTTPS]' \ + '--no-scripts[prevent execution of scripts defined in root package]' \ + '(--prefer-source)--prefer-dist[prefer installation from dist]' \ + '(--prefer-dist)--prefer-source[prefer installation from source]' \ + '(--keep-vcs)--remove-vcs[force removal of VCS directory]' \ + '--repository=[specify package repository]: :__composer_repositories' \ + '!(--repository)--repository_url:repository URL:_urls' \ + '(-s --stability)'{-s+,--stability=}'[specify minimum stability]: :__composer_stabilities' \ + '1: :__composer_packages' \ + '2::project directory:_files -/' \ + '3:: :_guard "^-*" "version constraint"' +} + +(( $+functions[_composer_depends] )) || +_composer_depends() { + _arguments -s -S : \ + $_composer_global_opts \ + '(-r --recursive)'{-r,--recursive}'[resolve recursively up to root package]' \ + '(-t --tree)'{-t,--tree}'[display in tree format]' \ + '1: :__composer_packages --vendor' \ + '2:: :_guard "^-*" "version constraint"' +} + +(( $+functions[_composer_dump-autoload] )) || +_composer_dump-autoload() { + _arguments -s -S : \ + $_composer_global_opts \ + '--apcu[use APCu to cache found/not-found classes]' \ + '--no-dev[ignore autoload-dev rules]' \ + '--no-scripts[prevent execution of scripts defined in composer.json]' \ + + '(a)' '(o)'{-a,--classmap-authoritative}'[autoload from class maps only (implies -o)]' \ + + '(o)' {-o,--optimize}'[use class maps for PSR-0/4 packages]' +} + +(( $+functions[_composer_exec] )) || +_composer_exec() { + local ret=1 + local -a context line state state_descr + local -A opt_args + + _arguments -s -S : \ + $_composer_global_opts \ + '(: * -l --list)'{-l,--list}'[display available binaries]' \ + '1: :__composer_binaries' \ + '*: :->next' \ + && ret=0 + + # Can't use *:: here, it won't complete subsequent options + [[ $state == next ]] && { + shift words + (( CURRENT-- )) + unset _composer_cmd + _normal && ret=0 + } + + return ret +} + +(( $+functions[_composer_global] )) || +_composer_global() { + _composer_is_global=1 + _composer "$@" +} + +(( $+functions[_composer_help] )) || +_composer_help() { + _arguments -s -S : \ + $_composer_global_opts \ + '--format=[specify output format]:output format [txt]:(json md txt xml)' \ + '--raw[output raw help (with text format)]' \ + '1: :__composer_commands' +} + +(( $+functions[_composer_home] )) || +_composer_home() { + _arguments -s -S : \ + $_composer_global_opts \ + '(-H --homepage)'{-H,--homepage}'[use home page instead of repository]' \ + '(-s --show)'{-s,--show}'[display URL only (do not open)]' \ + '*: :__composer_packages' \ +} + +(( $+functions[_composer_init] )) || +_composer_init() { + _arguments -s -S : \ + $_composer_global_opts \ + '--author=[specify package author]:package author' \ + '--description=[specify package description]:package description' \ + '--homepage=[specify package home page]:package home page:_urls' \ + '(-l --license)'{-l+,--license=}'[specify package license]: :__composer_licenses' \ + '--name=[specify package name]: :__composer_packages' \ + '*--repository=[specify custom package repository]: :__composer_repositories' \ + '*--require=[specify package to require]: :__composer_packages --pairs' \ + '*--require-dev=[specify package to require for development]: :__composer_packages --pairs' \ + '(-s --stability)'{-s+,--stability=}'[specify minimum stability]: :__composer_stabilities' \ + '--type=-[specify package type]:: :__composer_types' +} + +(( $+functions[_composer_install] )) || +_composer_install() { + _arguments -s -S : \ + $_composer_global_opts \ + '(--no-dev)--dev[install require-dev packages]' \ + '--dry-run[do not actually install (implies -v)]' \ + '--ignore-platform-reqs[ignore PHP platform requirements]' \ + '!(--no-plugins)--no-custom-installers' \ + '(--dev)--no-dev[do not install require-dev packages]' \ + '--no-progress[do not display download progress]' \ + '--no-scripts[prevent execution of scripts defined in composer.json]' \ + '--no-suggest[do not display package suggestions]' \ + '(--prefer-source)--prefer-dist[prefer installation from dist]' \ + '(--prefer-dist)--prefer-source[prefer installation from source]' \ + + '(a)' '(n o)'{-a,--classmap-authoritative}'[autoload from class maps only (implies -o)]' \ + + '(A)' '(n)--apcu-autoloader[use APCu to cache found/not-found classes]' \ + + '(n)' '(a A o)--no-autoload[skip autoloader generation]' \ + + '(o)' '(n)'{-o,--optimize}'[use class maps for PSR-0/4 packages]' +} + +(( $+functions[_composer_licenses] )) || +_composer_licenses() { + _arguments -s -S : \ + $_composer_global_opts \ + '--no-dev[ignore require-dev packages]' \ + '--format=[specify output format]:output format [text]:(json text)' +} + +(( $+functions[_composer_list] )) || +_composer_list() { + _arguments -s -S : \ + $_composer_global_opts \ + '--format=[specify output format]:output format [txt]:(json md txt xml)' \ + '--raw[output raw help (with text format)]' \ + '1: :_guard "^-*" namespace' +} + +(( $+functions[_composer_outdated] )) || +_composer_outdated() { + _arguments -s -S : \ + $_composer_global_opts \ + '--format=[specify output format]:output format [text]:(json text)' \ + '--strict[return non-zero exit code if there are outdated packages]' \ + '1: :__composer_packages --vendor' \ + + '(a)' '(D I)'{-a,--all}'[display all installed packages]' \ + + '(D)' '(a)'{-D,--direct}'[display only packages directly required by root package]' \ + + '(I)' '(a)*--ignore=[ignore specified package (with -o)]: :__composer_packages' \ + + '(m)' '(a)'{-m,--minor-only}'[display only packages with minor semver updates (with -o)]' \ + + '(o)' '!(a)'{-o,--outdated} +} + +(( $+functions[_composer_prohibits] )) || +_composer_prohibits() { + _arguments -s -S : \ + $_composer_global_opts \ + '(-r --recursive)'{-r,--recursive}'[resolve recursively up to root package]' \ + '(-t --tree)'{-t,--tree}'[display in tree format]' \ + '1: :__composer_packages --vendor' \ + '2:: :_guard "^-*" "version constraint"' +} + +(( $+functions[_composer_remove] )) || +_composer_remove() { + _arguments -s -S : \ + $_composer_global_opts \ + '--dev[remove package from require-dev]' \ + '--ignore-platform-reqs[ignore PHP platform requirements]' \ + '(--dev)--no-dev[do not install require-dev packages]' \ + '--no-progress[do not display download progress]' \ + '--no-scripts[prevent execution of scripts defined in composer.json]' \ + '(--update-no-dev)--no-update[do not update dependencies]' \ + '(--update-with-dependencies)--no-update-with-dependencies[do not update inherited dependencies]' \ + '(--no-update)--update-no-dev[update dependencies with --no-dev option]' \ + '(--no-update-with-dependencies)--update-with-dependencies[update inherited dependencies]' \ + '*: :__composer_packages --vendor' \ + + '(a)' '(n o)'{-a,--classmap-authoritative}'[autoload from class maps only (implies -o)]' \ + + '(A)' '(n)--apcu-autoloader[use APCu to cache found/not-found classes]' \ + + '(n)' '(a A o)--no-autoload[skip autoloader generation]' \ + + '(o)' '(n)'{-o,--optimize}'[use class maps for PSR-0/4 packages]' +} + +(( $+functions[_composer_require] )) || +_composer_require() { + _arguments -s -S : \ + $_composer_global_opts \ + '--dev[add package to require-dev]' \ + '--ignore-platform-reqs[ignore PHP platform requirements]' \ + '--no-progress[do not display download progress]' \ + '--no-scripts[prevent execution of scripts defined in composer.json]' \ + '--no-suggest[do not display package suggestions]' \ + '(--prefer-source)--prefer-dist[prefer installation from dist]' \ + '--prefer-lowest[prefer lowest versions of dependencies]' \ + '(--prefer-dist)--prefer-source[prefer installation from source]' \ + '--prefer-stable[prefer stable versions of dependencies]' \ + '--sort-packages[sort packages when adding/updating dependencies]' \ + '(--no-update)--update-no-dev[update dependencies with --no-dev option]' \ + '*: :__composer_packages --pairs' \ + + '(a)' '(n o)'{-a,--classmap-authoritative}'[autoload from class maps only (implies -o)]' \ + + '(A)' '(n)--apcu-autoloader[use APCu to cache found/not-found classes]' \ + + '(n)' '(a A o)--no-autoload[skip autoloader generation]' \ + + '(o)' '(n)'{-o,--optimize}'[use class maps for PSR-0/4 packages]' \ + + '(u)' \ + '(--update-no-dev)--no-update[do not update dependencies]' \ + '--update-with-dependencies[update inherited dependencies, except root requirements]' \ + '--update-with-all-dependencies[update all inherited dependencies]' +} + +(( $+functions[_composer_run-script] )) || +_composer_run-script() { + local ret=1 + local -a context line state state_descr + local -A opt_args + + _arguments -s -S : \ + $_composer_global_opts \ + '(--no-dev)--dev[enable dev mode]' \ + '(: * -l --list)'{-l,--list}'[display available scripts]' \ + '(--dev)--no-dev[disable dev mode]' \ + '--timeout=[specify script timeout]:timeout (seconds)' \ + '1: :__composer_scripts' \ + '*: :->next' \ + && ret=0 + + # Can't use *:: here, it won't complete subsequent options + [[ $state == next ]] && { + shift words + (( CURRENT-- )) + unset _composer_cmd + _normal && ret=0 + } + + return ret +} + +(( $+functions[_composer_search] )) || +_composer_search() { + _arguments -s -S : \ + $_composer_global_opts \ + '(-N --only-name)'{-N,--only-name}'[search package names only]' \ + '(-t --type)'{-t+,--type=}'[search for specified package type]: :__composer_types' \ + '*: :__composer_packages' +} + +(( $+functions[_composer_self-update] )) || +_composer_self-update() { + _arguments -s -S : \ + $_composer_global_opts \ + + '(c)' \ + '--preview[force update to preview channel]' \ + '--snapshot[force update to snapshot channel]' \ + '--stable[force update to stable channel]' \ + + '(C)' '(u)--set-channel-only[set channel as default and exit]' \ + + u \ + '(C -r --rollback)--clean-backups[delete old back-ups during update]' \ + '(C)--no-progress[do not display download progress]' \ + '(c C -r --rollback)'{-r,--rollback}'[roll back to earlier installation]' \ + '(C)--update-keys[prompt for key update]' \ + '(C)1: :_guard "^-*" "Composer version"' +} + +(( $+functions[_composer_show] )) || +_composer_show() { + local ret=1 + local -a context line state state_descr + local -A opt_args + + _arguments -s -S : \ + $_composer_global_opts \ + '--format=[specify output format]:output format [text]:(json text)' \ + '--strict[return non-zero exit code if there are outdated packages]' \ + '1: :->pkgs' \ + '2:: :_guard "^-*" "version constraint"' \ + + '(a)' '(D I s t)'{-a,--available}'[display only available packages]' \ + + '(A)' '(D I s t)--all[display all packages]' \ + + '(D)' '(a A p s)'{-D,--direct}'[display only packages directly required by root package]' \ + + '(i)' '(s)'{-i,--installed}'[display only installed packages]' \ + + '(I)' '(a A s t)*--ignore=[ignore specified package (with -o)]: :__composer_packages' \ + + '(l)' '(s t)'{-l,--latest}'[display only latest version of installed packages]' \ + + '(m)' '(a A s t)'{-m,--minor-only}'[display only packages with minor semver updates (with -o)]' \ + + '(N)' '(P)'{-N,--name-only}'[display package names only]' \ + + '(o)' '(l t s)'{-o,--outdated}'[like -l, but display only outdated packages]' \ + + '(p)' '(D)'{-p,--platform}'[display only PHP platform packages]' \ + + '(P)' '(a A N)'{-P,--path}'[display package file paths]' \ + + '(s)' '(a A I l o t)'{-s,--self}'[display root package information]' \ + + '(t)' '(a A I l o s)'{-t,--tree}'[display in tree format]' \ + && ret=0 + + [[ $state == pkgs ]] && + if [[ -n $opt_args[(i)[aA]-*] ]]; then + __composer_packages && ret=0 + else + __composer_packages --vendor && ret=0 + fi + + return ret +} + +(( $+functions[_composer_suggests] )) || +_composer_suggests() { + _arguments -s -S : \ + $_composer_global_opts \ + '(--by-suggestion)--by-package[group results by suggesting package]' \ + '(--by-package)--by-suggestion[group results by suggested package]' \ + '--no-dev[exclude suggestions from require-dev packages]' \ + '*: :__composer_packages --vendor' +} + +(( $+functions[_composer_update] )) || +_composer_update() { + _arguments -s -S : \ + $_composer_global_opts \ + '(--no-dev)--dev[install require-dev packages]' \ + '--dry-run[do not actually update (implies -v)]' \ + '(-i -n --interactive --no-interaction)'{-i,--interactive}'[update with interactive interface]' \ + '--ignore-platform-reqs[ignore PHP platform requirements]' \ + '--lock[update composer.lock hash only]' \ + '!(--no-plugins)--no-custom-installers' \ + '(--dev)--no-dev[do not install require-dev packages]' \ + '--no-progress[do not display download progress]' \ + '--no-scripts[prevent execution of scripts defined in composer.json]' \ + '--no-suggest[do not display package suggestions]' \ + '(--prefer-source)--prefer-dist[prefer installation from dist]' \ + '--prefer-lowest[prefer lowest versions of dependencies]' \ + '(--prefer-dist)--prefer-source[prefer installation from source]' \ + '--prefer-stable[prefer stable versions of dependencies]' \ + '--root-reqs[update only root-package dependencies]' \ + '*:: :__composer_packages --vendor' \ + + '(a)' '(n o)'{-a,--classmap-authoritative}'[autoload from class maps only (implies -o)]' \ + + '(A)' '(n)--apcu-autoloader[use APCu to cache found/not-found classes]' \ + + '(n)' '(a A o)--no-autoload[skip autoloader generation]' \ + + '(o)' '(n)'{-o,--optimize}'[use class maps for PSR-0/4 packages]' \ + + '(u)' \ + '--with-dependencies[update dependencies of whitelisted packages, except root requirements]' \ + '--with-all-dependencies[update all dependencies of whitelisted packages]' +} + +(( $+functions[_composer_validate] )) || +_composer_validate() { + _arguments -s -S : \ + $_composer_global_opts \ + '(-A --with-dependencies)'{-A,--with-dependencies}'[validate composer.json of installed dependencies]' \ + '--no-check-all[do not validate completely]' \ + '--no-check-lock[ignore out-of-date composer.lock]' \ + '--no-check-publish[ignore publish errors]' \ + '--strict[return non-zero exit code for warnings as well as errors]' \ + '1::composer.json file:_files -g "*.json(#q-.)"' +} + +_composer() { + local ret=1 tmp helps cmd + local -a context line state state_descr + local -A opt_args + + # These are meant for use by helper functions; we check for set-ness first in + # case of `composer global` + (( $+_composer_cmd )) || { + local _composer_cmd=$words[1] _composer_is_global=0 _composer_work_dir= + local -a _composer_cmds _composer_global_opts _composer_cache_pkgs + local -A _composer_cmd_aliases + + # alias -> canonical (mappings derived from source) + _composer_cmd_aliases=( + browse home + clearcache clear-cache + dumpautoload dump-autoload + i install + info show + selfupdate self-update + u update + upgrade update + why depends + why-not prohibits + ) + # Official commands (see note at top about custom ones) + _composer_cmds=( + about:'display short information about Composer' + archive:'create archive of project/package' + check-platform-reqs:'check that platform requirements are satisfied' + clear{-,}cache:'clear internal package cache' + config:'set configuration options' + create-project:'create new project from package' + {depends,why}:'display packages depending on package' + diagnose:'diagnose system problems' + dump{-,}autoload:'dump class autoloader' + exec:'execute vendored binary/script' + global:'run command in global Composer directory' + help:'display help information' + {home,browse}:'open package home page or repository in browser' + init:'create basic composer.json' + {install,i}:'install packages in composer.{lock,json}' + licenses:'display dependency license information' + list:'display supported commands' + outdated:'display outdated packages' + {prohibits,why-not}:'display packages preventing package from being installed' + remove:'remove and uninstall required package' + require:'add and install required package' + run-script:'run scripts in composer.json' + search:'search packages' + self{-,}update:'upgrade Composer' + {show,info}:'display package information' + status:'display locally modified packages' + suggests:'display package suggestions' + {update,u,upgrade}:'upgrade packages in composer.json and update composer.lock' + validate:'validate composer.{json,lock}' + ) + # Global options (can be used both before and after a command) + _composer_global_opts=( + '(-h --help)'{-h,--help}'[display help information]' + '(: * -)'{-V,--version}'[display version information]' + + # Symfony handles -vv and -vvv specially + '(-q -v --quiet --verbose)'{-q,--quiet}'[reduce output verbosity]' + '(-q --quiet --verbose)*-v[increase output verbosity]' + '(-q --quiet --verbose)--verbose[increase output verbosity]' + + '(--no-ansi)--ansi[force ANSI (color) output]' + '(--ansi)--no-ansi[disable ANSI (color) output]' + + '(-n --no-interaction)'{-n,--no-interaction}'[run non-interactively]' + + '--no-plugins[disable plug-ins]' + '--profile[display timing and memory usage information]' + '(-d --working-dir)'{-d+,--working-dir=}'[specify working directory]:working directory:_files -/' + ) + + # Use caching by default; Composer is very slow + zstyle -s ":completion:*:*:$service:*" cache-policy tmp + [[ -n $tmp ]] || + zstyle ":completion:*:*:$service:*" cache-policy __composer_cache_policy + + zstyle -s ":completion:*:*:$service:*" use-cache tmp + [[ -n $tmp ]] || + zstyle ":completion:*:*:$service:*" use-cache yes + } + + # Symfony's Application class naively intercepts --version and --help no + # matter where they appear on the command line. --version is handled + # sufficiently by the global option spec above; for --help, we need to + # simulate the help command + [[ -n $words[(r)(-h|--help)] ]] && { + helps=${#${(M)words[2,CURRENT]:#(-h|--help)}} + words=( "$words[1]" help "${(@)words[2,CURRENT]:#(-h|--help)}" ) + (( CURRENT -= helps - 1 )) + __composer_prune_global_opts -h --help + } + + _arguments -s -S -A '-*' : \ + $_composer_global_opts \ + '1: :__composer_commands' \ + '*:: :->next' \ + && ret=0 + __composer_update_work_dir + + [[ $state == next ]] && { + # Resolve abbreviated/aliased command names and ensure that $words[1] works + # as expected in our helper functions + __composer_resolve_cmd cmd $words[1] + words[1]=$_composer_cmd + + # Don't offer global options again after they've been given + __composer_prune_global_opts ${(k)opt_args} + # This is intentionally done twice + [[ $cmd == help ]] && __composer_prune_global_opts -h --help + + if (( $+functions[_composer_$cmd] )); then + _composer_$cmd "$@" && ret=0 + else + _arguments -s -S : $_composer_global_opts && ret=0 + fi + } + + return ret +} + +_composer "$@" diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 093464625..0ebbbe861 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -2017,15 +2017,6 @@ _git-subtree () { (( $+functions[_git-tag] )) || _git-tag () { - local -a message_opts - - if (( words[(I)-[asu]] )); then - message_opts=( - '(-m --message -F --file)'{-m+,--message=}'[specify tag message]:message' - '(-m --message -F --file)'{-F+,--file=}'[read tag message from given file]:message file:_files' - ) - fi - _arguments \ - creation \ '(-a --annotate -s --sign -u --local-user)'{-a,--annotate}'[create an unsigned, annotated tag]' \ @@ -2035,7 +2026,8 @@ _git-tag () { '(-f --force)'{-f,--force}'[replace existing tag]' \ '--create-reflog[create a reflog]' \ '--cleanup=[cleanup message]:mode:((verbatim\:"no cleanup" whitespace\:"remove leading and trailing whitespace" strip\:"remove leading and trailing whitespace and comments"))' \ - $message_opts \ + '(-m --message -F --file)'{-F+,--file=}'[read tag message from given file]:message file:_files' \ + '(-m --message -F --file)'{-m+,--message=}'[specify tag message]:message' \ ': :__git_tags' \ ':: :__git_commits' \ - deletion \ diff --git a/Completion/Unix/Command/_ipsec b/Completion/Unix/Command/_ipsec new file mode 100644 index 000000000..631d2bc9a --- /dev/null +++ b/Completion/Unix/Command/_ipsec @@ -0,0 +1,179 @@ +#compdef ipsec strongswan + +# Completion for the ipsec script (aka strongswan on some systems) provided by +# FreeS/WAN, Openswan, Libreswan, and strongSwan. See also strongSwan's swanctl. +# +# As with swanctl, elevated privileges are usually required to complete SA names +# and the like; consider setting the gain-privileges style as follows: +# zstyle ':completion:*:(ipsec|strongswan)/*' gain-privileges yes +# +# @todo We don't complete pool names or virtual IPs + +# Complete connection (IKE SA) names and optionally SA/instance names +# --instances => also complete SA/instance names +(( $+functions[_ipsec_connections] )) || +_ipsec_connections() { + local -a instances tmp ipsec_conns ipsec_insts + + zparseopts -D -E -a instances - -instances + + tmp=( ${(f)${"$( + _call_program -p ipsec-status ${_ipsec_cmd:-$words[1]} statusall + )"#*$'\n'[[:space:]]#[Cc]onnections:[[:space:]]#$'\n'}} ) + tmp=( ${(@M)tmp:#[[:space:]]#[^[:space:]]##:[[:space:]]##?*} ) + tmp=( ${(@)${(@)tmp##[[:space:]]##}%%:*} ) + + ipsec_conns=( ${(@)tmp%%['[{']<->['}]']} ) + ipsec_insts=( ${(@M)tmp:#*['[{']<->['}]']} ) + + (( $#ipsec_conns )) || { + _message -e connections 'connection name' + return + } + + tmp=( 'connections:connection name:compadd -a - ipsec_conns' ) + (( $#instances && $#ipsec_insts )) && + tmp+=( 'instances:connection SA/instance name:compadd -a - ipsec_insts' ) + + _alternative $tmp +} + +# Complete arguments to /usr/lib/ipsec/starter. This is rarely invoked directly, +# and there is almost no documentation on it, but the start/restart commands +# pass options to it +(( $+functions[_ipsec_starter] )) || +_ipsec_starter() { + _arguments : \ + '(--nofork)--attach-gdb[start daemon under gdb (implies --nofork)]' \ + '--auto-update[specify select time-out]:select time-out (seconds)' \ + '--conf[specify path to ipsec.conf]:ipsec.conf file:_files' \ + '--daemon[specify daemon name]:daemon name' \ + '--nofork[do not fork daemon]' \ + + '(d)' \ + '--debug[set log level 2]' \ + '--debug-more[set log level 3]' \ + '--debug-all[set log level 4]' \ + '--nolog[set log level 0]' +} + +_ipsec() { + local ret=1 variant _ipsec_cmd=$words[1] + local -a context line state state_descr tmp + local -A opt_args + + _pick_variant -r variant \ + freeswan='(#i)frees/#wan' \ + libreswan='(#i)libreswan' \ + openswan='(#i)openswan' \ + strongswan='(#i)strongswan' \ + unix \ + --version + + # Provide only basic completion for non-strongSwan implementations + if [[ $variant == unix ]]; then + _default + return + elif [[ $variant == (free|libre|open)* ]]; then + tmp=( ${(f)"$( _call_program ipsec-help $words[1] --help )"} ) + tmp=( ${(@M)tmp:#($' '|$'\t')*} ) + tmp=( ${(@)tmp:#*[':/<>()[]']*} ) + tmp=( ${(f)${(F)tmp//[[:space:]]##/$'\n'}} ) + + _arguments -S -A '-*' : \ + '(: * -)--help[display help information]' \ + '(: * -)--version[display version information]' \ + "(-)1:command:(${(j< >)${(@q-)tmp}})" \ + '(-)2: :_default' + return + fi + + _arguments -A '-*' \ + '(: * -)--confdir[display path to configuration directory (IPSEC_CONFDIR)]' \ + '(: * -)--copyright[display copyright information]' \ + '(: * -)--directory[display path to libexec/utility directory (IPSEC_DIR)]' \ + '(: * -)--help[display help information]' \ + '(: * -)--piddir[display path to PID directory (IPSEC_PIDDIR)]' \ + '(: * -)--version[display version information]' \ + '(: * -)--versioncode[display brief version information]' \ + '1:command:(( + down\:"terminate IPsec connection/SA" + down-srcip\:"terminate IKE SAs by client virtual IP" + leases\:"display IP address/pool status" + listaacerts\:"display X.509 authorization authority certificates" + listacerts\:"display X.509 attribute certificates" + listalgs\:"display loaded algorithms" + listall\:"execute all list commands" + listcacerts\:"display X.509 certificate authority certificates" + listcainfos\:"display certificate authority information" + listcerts\:"display X.509/OpenPGP certificates" + listcounters\:"display IKE counter information" + listcrls\:"display certificate revocation lists" + listgroups\:"display groups for user authorization profiles" + listocsp\:"display OCSP revocation information" + listocspcerts\:"display X.509 OCSP signer certificates" + listplugins\:"display loaded plug-in features" + listpubkeys\:"display RSA public keys" + purgecerts\:"purge cached certificates" + purgecrl\:"purge cached certificate revocation lists" + purgeike\:"purge IKE SAs without a quick mode or CHILD_SA" + purgeocsp\:"purge cached OCSP information" + reload\:"reload entire configuration (send SIGUSR1)" + rereadacerts\:"re-read attribute certificates" + rereadaacerts\:"flush and re-read authorization authority certificates" + rereadall\:"execute all re-read commands" + rereadcacerts\:"flush and re-read certificate authority certificates" + rereadcrls\:"re-read certificate revocation lists" + rereadocspcerts\:"re-read OCSP certificates" + rereadsecrets\:"flush and re-read secrets" + resetcounters\:"reset IKE counter information" + restart\:"equivalent to stop + start" + route\:"insert kernel IPsec policy for connection" + start\:"start IKE daemon" + status\:"display concise connection status" + statusall\:"display detailed connection status" + stop\:"terminate all IPsec connections and stop IKE daemon" + stroke\:"issue stroke command" + unroute\:"remove kernel IPsec policy for connection" + up\:"bring up IPsec connection" + update\:"reload changes in configuration (send SIGHUP)" + ))' \ + '*:: :->next' \ + && ret=0 + + [[ $state == next ]] && + case $words[1] in + down) + _arguments : '1: :_ipsec_connections --instances' && ret=0 + ;; + listcounters|resetcounters|route|status|statusall|unroute|up) + _arguments : '1: :_ipsec_connections' && ret=0 + ;; + down-srcip) + _arguments : \ + '1:virtual IP address (start)' \ + '2::virtual IP address (end)' \ + && ret=0 + ;; + leases) + _arguments : '1:pool name' '2::virtual IP address' && ret=0 + ;; + list*~list(counters|plugins)) + _arguments : '--utc[use UTC for time fields]' && ret=0 + ;; + start|restart) + _ipsec_starter && ret=0 + ;; + stroke) + _arguments -s -S -A '-*' \ + '(: * -)'{-h,--help}'[display help information]' \ + '(-d --daemon)'{-d+,--daemon=}'[specify daemon name]:daemon name' \ + '1: :_guard "^-*" "stroke command"' \ + '*:stroke command argument:_default' \ + && ret=0 + ;; + esac + + return ret +} + +_ipsec "$@" diff --git a/Completion/Unix/Command/_swanctl b/Completion/Unix/Command/_swanctl new file mode 100644 index 000000000..ba2f5402d --- /dev/null +++ b/Completion/Unix/Command/_swanctl @@ -0,0 +1,225 @@ +#compdef swanctl + +# Completion for strongSwan's swanctl. See also ipsec, which is deprecated but +# still supported by strongSwan, and also used by Openswan/Libreswan. +# +# Note that in most cases elevated privileges are required to connect to the +# VICI socket, so the gain-privileges style may be necessary to complete SA +# names and the like: zstyle ':completion:*:swanctl/*' gain-privileges yes +# +# Other notes: +# - One of swanctl's selling points is that it can provide 'raw' structured +# responses for scripting, etc. In practice, though, the output formatted for +# humans seems easier to 'parse' from the shell than the plist-like raw output +# - @todo We don't complete authority names, pool names, peer IPs, etc. + +# Complete connection names, SA names, or SA unique IDs. The distinctions +# between concepts like 'connections' and 'SAs' are very blurry here, partially +# for convenience and partially due to author confusion +# --child => complete only child/CHILD_SA names/IDs +# --ids => complete unique SA IDs rather than connection/SA names +# --ike => complete only connection/IKE_SA names/IDs +(( $+functions[_swanctl_connections] )) || +_swanctl_connections() { + local i which + local -a expl tmp matches + local -A opts + + zparseopts -D -E -A opts - -child -ids -ike + + tmp=( ${(@M)${(f)"$( + _call_program -p swanctl-sas $words[1] -l + )"}:#[^:]##: \#<->*} ) + (( $+opts[--ids] )) || tmp+=( ${(@M)${(f)"$( + _call_program -p swanctl-conns $words[1] -L + )"}:#[^:]##: ([A-Z][A-Za-z0-9]#|),*} ) + + for i in $tmp; do + if (( $+opts[--child] )) && [[ $i != [[:space:]]* ]]; then + continue + elif (( $+opts[--ike] )) && [[ $i == [[:space:]]* ]]; then + continue + fi + + # <name>: #<unique id>, ... + i=${i//[#:,]/ } + + if (( $+opts[--ids] )); then + matches+=( "${i[(w)2]}:${i[(w)1]} #${i[(w)2]}" ) + else + matches+=( ${i[(w)1]} ) + fi + done + + if (( $+opts[--ids] )); then + matches=( ${(onu)matches} ) + if (( $+opts[--child] )); then + which=CHILD_ + elif (( $+opts[--ike] )); then + which=IKE_ + fi + _describe -x2Vt sa-ids "${which}SA unique ID" matches + else + if (( $+opts[--child] )); then + which='child ' + elif (( $+opts[--ike] )); then + which='IKE ' + fi + _wanted -x connections expl "${which}connection/SA name" compadd - $matches + fi +} + +_swanctl() { + # Although swanctl will correctly parse multiple short options in the first + # word, as in `swanctl -lh`, it won't actually *do* anything with the + # subsequent options -- so we'll require that they be separated. Also, --help + # doesn't take any further options, so just stop if we've got that + if (( CURRENT == 2 )) || [[ $words[2] == (-h*|--help) ]]; then + _arguments : \ + '(-)'{-a,--load-pools}'[(re)load pool configuration]' \ + '(-)'{-A,--list-pools}'[display loaded pool configurations]' \ + '(-)'{-b,--load-authorities}'[(re)load authority configuration]' \ + '(-)'{-B,--list-authorities}'[display loaded authority configurations]' \ + '(-)'{-c,--load-conns}'[(re)load connection configuration]' \ + '(-)'{-C,--counters}'[display or reset IKE event counters]' \ + '(-)'{-d,--redirect}'[redirect IKE_SA]' \ + '(-)'{-f,--flush-certs}'[flush cached certificates]' \ + '(-)'{-g,--list-algs}'[display loaded algorithms]' \ + '(-)'{-h,--help}'[display help information]' \ + '(-)'{-i,--initiate}'[initiate a connection]' \ + '(-)'{-l,--list-sas}'[display currently active IKE_SAs]' \ + '(-)'{-L,--list-conns}'[display loaded configurations]' \ + '(-)'{-m,--monitor-sa}'[monitor for IKE_SA and CHILD_SA changes]' \ + '(-)'{-p,--install}'[install trap or shunt policy]' \ + '(-)'{-P,--list-pols}'[display currently installed policies]' \ + '(-)'{-q,--load-all}'[load credentials, authorities, pools, and connections]' \ + '(-)'{-r,--reload-settings}'[reload daemon strongswan.conf]' \ + '(-)'{-R,--rekey}'[rekey SA]' \ + '(-)'{-s,--load-creds}'[(re)load credentials]' \ + '(-)'{-S,--stats}'[display daemon statistics]' \ + '(-)'{-t,--terminate}'[terminate connection]' \ + '(-)'{-T,--log}'[trace logging output]' \ + '(-)'{-u,--uninstall}'[uninstall trap or shunt policy]' \ + '(-)'{-v,--version}'[display version information]' \ + '(-)'{-x,--list-certs}'[display stored certificates]' + return + fi + + local ret=1 cmd + local -a args cert_flags cert_types + + cert_flags=( aa any ca none ocsp ) + cert_types=( ocsp_response pubkey x509 x509_ac x509_crl ) + + if [[ $words[2] == -[^-]* ]]; then + cmd=${(M)words[2]#??} + else + cmd=$words[2] + fi + words=( $words[1] "${(@)words[3,-1]}" ) + (( CURRENT-- )) + + # Technically, only -v, -u, and -+ are truly global command options. However, + # in practice, all commands also support -h, -P, and -r + args=( + '(: * -)'{-h,--help}'[display help information]' + '(-P -r --pretty --raw)'{-P,--pretty}'[dump raw response message in pretty print]' + '(-P -r --pretty --raw)'{-r,--raw}'[dump raw response message]' + # https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration + # https://github.com/strongswan/strongswan/blob/master/src/libstrongswan/utils/debug.h + '(-v --debug)'{-v+,--debug=}'[specify debug level]:debug level [1]:(( + -1\:"absolutely silent (SILENT)" + 0\:"basic auditing (AUDIT)" + 1\:"generic control flow with errors (CTRL)" + 2\:"detailed control flow (DIAG)" + 3\:"raw binary blobs (RAW)" + 4\:"sensitive data (PRIVATE)" + ))' + '(-u --uri)'{-u+,--uri=}'[specify service URI to connect to]:VICI service URI:_urls' + '(-+ --options)'{'-\++',--options=}'[read command-line options from specified file]:options file:_files' + ) + + case $cmd in + -A|--list-pools) args+=( + '(-n --name)'{-n+,--name=}'[filter by specified pool name]:pool name' + '(-l --leases)'{-l,--leases}'[display leases of each pool]' + ) ;; + -B|--list-authorities) args+=( + '(-n --name)'{-n+,--name=}'[filter by specified authority name]:authority name' + ) ;; + -C|--counters) args+=( + '(-a -n --all --name)'{-a,--all}'[display/reset counters for all tracked connections]' + '(-a -n --all --name)'{-n+,--name=}'[specify connection name]: :_swanctl_connections --ike' + '(-r --reset)'{-r,--reset}'[reset counters]' + ) ;; + -d|--redirect) args+=( + '(-d --peer-id)'{-d+,--peer-id=}'[redirect by IKE_SA matching specified peer identity]:peer identity' + '(-g --gateway)'{-g+,--gateway=}'[redirect to specified gateway]:target gateway' + '(-i --ike)'{-i+,--ike=}'[redirect by specified IKE_SA name]: :_swanctl_connections --ike' + '(-I --ike-id)'{-I+,--ike-id=}'[redirect by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike' + '(-p --peer-ip)'{-p+,--peer-ip=}'[redirect by IKE_SA matching specified peer IP]:peer IP address' + ) ;; + -f|--flush-certs) args+=( + '(-t --type)'{-t+,--type=}"[filter by specified certificate type]:certificate type:( + ${(j< >)${(@q-)cert_types}} + )" + ) ;; + -i|--initiate) args+=( + '(-c --child)'{-c+,--child=}'[specify CHILD_SA name]: :_swanctl_connections --child' + '(-i --ike)'{-i+,--ike=}"[specify CHILD_SA's connection name]: :_swanctl_connections --ike" + '(-t --timeout)'{-t+,--timeout=}'[specify timeout before detaching]:timeout (seconds)' + ) ;; + -l|--list-sas) args+=( + '(-i --ike)'{-i+,--ike=}'[filter by specified IKE_SA name]: :_swanctl_connections --ike' + '(-I --ike-id)'{-I+,--ike-id=}'[filter by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike' + '(-n --noblock)'{-n,--noblock}'[do not wait for IKE_SAs in use]' + ) ;; + -p|-u|--install|--uninstall) args+=( + '(-c --child)'{-c+,--child=}'[specify CHILD_SA name]: :_swanctl_connections --child' + '(-i --ike)'{-i+,--ike=}"[specify CHILD_SA's connection name]: :_swanctl_connections --ike" + ) ;; + -P|--list-pols) args+=( + '(-c --child)'{-c+,--child=}'[filter by specified CHILD_SA name]: :_swanctl_connections --child' + '(-d --drop)'{-d,--drop}'[list drop policies]' + '(-p --pass)'{-p,--pass}'[list bypass policies]' + '(-t --trap)'{-t,--trap}'[list trap policies]' + ) ;; + -q|-s|--load-all|--load-creds) args+=( + '(-c --clear)'{-c,--clear}'[clear previously loaded credentials]' + '(-n --noprompt)'{-n,--noprompt}'[do not prompt for passwords]' + ) ;; + -R|--rekey) args+=( + '(-c --child)'{-c+,--child=}'[rekey by specified CHILD_SA name]: :_swanctl_connections --child' + '(-C --child-id)'{-C+,--child-id=}'[rekey by specified CHILD_SA unique ID]: :_swanctl_connections --ids --child' + '(-i --ike)'{-i+,--ike=}'[rekey by specified IKE_SA name]: :_swanctl_connections --ike' + '(-I --ike-id)'{-I+,--ike-id=}'[rekey by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike' + ) ;; + -t|--terminate) args+=( + '(-t --timeout)'{-t+,--timeout=}'[specify timeout before detaching]:timeout (seconds)' + '(-c --child)'{-c+,--child=}'[terminate by specified CHILD_SA name]: :_swanctl_connections --child' + '(-C --child-id)'{-C+,--child-id=}'[terminate by specified CHILD_SA unique ID]: :_swanctl_connections --ids --child' + '(-i --ike)'{-i+,--ike=}'[terminate by specified IKE_SA name]: :_swanctl_connections --ike' + '(-I --ike-id)'{-I+,--ike-id=}'[terminate by specified IKE_SA unique ID]: :_swanctl_connections --ids --ike' + ) ;; + -v|--version) args+=( + '(-d --daemon)'{-d,--daemon}'[query daemon version]' + ) ;; + -x|--list-certs) args+=( + '(-f --flag)'{-f+,--flag=}"[filter by specified X.509 certificate flag]:certificate flag:( + ${(j< >)${(@q-)cert_flags}} + )" + '(-p --pem)'{-p,--pem}'[display PEM encoding of certificate]' + '(-s --subject)'{-s+,--subject=}'[filter by specified certificate subject]:certificate subject' + '(-S --short)'{-S,--short}'[omit some certificate details]' + '(-t --type)'{-t+,--type=}"[filter by specified certificate type]:certificate type:( + ${(j< >)${(@q-)cert_types}} + )" + '(-u --utc)'{-u,--utc}'[use UTC for time fields]' + ) ;; + esac + + _arguments -s -S : $args && ret=0 + return ret +} + +_swanctl "$@" |