Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH/RFC] Completion: Add _composer
- X-seq: zsh-workers 43909
- From: Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx>
- To: dana <dana@xxxxxxx>, Zsh workers <zsh-workers@xxxxxxx>
- Subject: Re: [PATCH/RFC] Completion: Add _composer
- Date: Tue, 18 Dec 2018 00:19:31 +0000
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= daniel.shahaf.name; h=message-id:from:to:mime-version :content-transfer-encoding:content-type:in-reply-to:date :references:subject; s=fm2; bh=bJte9Ga8/TeNYOG2DNKWG43Iz63w57qn5 RQK7VT46OM=; b=bHgJP3Ud3Fk7ogyO6AtAN62FzznRcj0KOCyM5rCMQCZgSQJ1u o8Gi7Ip5Y8+Jylm70aNT1mQ0Ihj77HNR3oshuG3ztzmVekd0gjGvxSpqyArrSs9b T0tSm0Lp1+U8nJRUmndGXPwPQPvWeJYiBgXYsWwUQKCJLL5uNka9anKx6FnUGVGM mMKm8mzX4E6+70/qtOQ5uMyUHgJ8cZEy0PSVoxHq/oepbF6aigVvi6Q/z7obZS/P lBgZGmgxFMaM6vl6D2+0HpbFb7pCid7SGlD+52GRzQvTq3LtCHhu3cIN4OQlDYeF hsYrCFJFjbYjXyPAF8d6URpDkv7uA9kuSCTKg==
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=bJte9Ga8/TeNYOG2DNKWG43Iz63w57qn5RQK7VT46 OM=; b=pX+s7r2ewteXxza9SYNsa5NbjJIIJLOoHo7PY2OeDfO5RA3XCnCbUHngS AZnNwZWHQymf5OR+R833aVmHhFwhqjDoanwc7CUqiElGq7rN5OnjwOqMsbr89W43 MJvFQYU08A11rpjkW1HUSW/SFpRErRNdyKu4IAXsvgJDOxecgLqcgly79/bAxEur 7QNk1gAQ1nvshyWYFZx5bH1sJlSX/buAo7nxmXgMkLzzatUpu2lEmNCvQrj54koH MUsSZ/rj9ezJAuQCRp0ABBptOcfxmkUOBBcaSIEo7Ozbc1cpoEUfmV/6x8dtPUou 2egXpZlgXw3HHDJAZeTAbGPQxNi7A==
- In-reply-to: <6D1B6E3C-52B9-4AB6-BC48-3C279FCF33FC@dana.is>
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- List-unsubscribe: <mailto:zsh-workers-unsubscribe@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
- References: <6D1B6E3C-52B9-4AB6-BC48-3C279FCF33FC@dana.is>
dana wrote on Mon, 17 Dec 2018 17:09 -0600:
> * Perhaps most questionable is __composer_packages. I couldn't figure out how
> to reliably complete arbitrary package names, because Composer is incredibly
> slow to return them, and there are so many that it didn't perform much better
> when i tried the usual array-caching mechanism. Even asking Composer about
> packages listed in the project JSON files is pretty slow, and not always
> accurate. To work around those problems i 'seeded' the function with a bunch
> of the most popular packages, and then i used `grep -o` to 'parse' the names
> out of the JSON files. Hard-coding package names in feels especially weird,
> but...?
Are you familiar with _store_cache and cache-policy? It's not clear from the comments
whether you've tried that.
> Sorry in advance to anyone who actually combs through this
>
> dana
>
>
> diff --git a/Completion/Unix/Command/_composer b/Completion/Unix/
> Command/_composer
> new file mode 100644
> index 000000000..2f7dc5421
> --- /dev/null
> +++ b/Completion/Unix/Command/_composer
> @@ -0,0 +1,828 @@
> +#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
> +# - @todo As mentioned below, we don't offer full completion for
> arbitrary
> +# package names; see __composer_packages for details
> +# - @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
> +
> +# _call_program wrapper (same eval/quoting rules applies)
> +# $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 tmp
> +
> + tmp=( ${(f)"$( __composer_call exec-list exec -l )"} )
> + tmp=( ${(@)tmp%%[[:space:]]##} )
> + [[ $tmp[1] == *: ]] && tmp[1]=()
> + tmp=( ${(@)tmp##[\*-][[:space:]]#} )
> + tmp=( ${(@)tmp%%[[:space:]]##\(local\)} )
> +
> + (( $#tmp )) || {
> + _message -e commands 'binary'
> + }
> + _wanted 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) )
> +
> + # We could use `composer search` or `composer show` here to fetch all
> of the
> + # packages from the repositories, but Composer is SO slow to list
> them, and
> + # there are SO many of them, that even with array caching it's a
> deeply
> + # unpleasant experience trying to complete them. For now we'll just
> do the
> + # best we can with the local vendor/cache, JSON files, and some hard-
> coded
> + # stuff pulled from https://packagist.org/explore/popular and
> + # https://github.com/topics/php
> + (( $#vendor )) || pkgs+=(
> + ${COMPOSER_CACHE_DIR:-/@err@}/files/*/*(#q/N)
> + $^home_dirs/cache/files/*/*(#q/N)
> + )
> +
> + pkgs=( ${(@M)pkgs%%[^/]##/[^/]##} )
> +
> + (( $#vendor )) || pkgs+=(
> + cakephp/cakephp codeigniter/framework composer/composer doctrine/
> {dbal,orm}
> + erusev/parsedown fzaninotto/faker getgrav/grav guzzlehttp/guzzle
> + laravel/{framework,installer,laravel}
> + league/{climate,commonmark,csv,flysystem} michelf/php-markdown
> + mockery/mockery monolog/monolog nesbot/carbon phpmailer/phpmailer
> + phpunit/phpunit pimple/pimple reactphp/{promise,react}
> + slim/{slim,slim-skeleton} squizlabs/php_codesniffer smarty/smarty
> + swiftmailer/swiftmailer
> + symfony/{console,finder,process,skeleton,symfony,website-skeleton}
> + twbs/bootstrap twig/twig vlucas/phpdotenv yiisoft/{yii2,yii2-app-
> basic}
> + ${(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\\']/}
> + )
> +
> + 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 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:]]*} )
> +
> + (( $#tmp )) || {
> + _message -e commands 'script'
> + }
> + _wanted commands expl 'script' compadd -a "$@" - tmp
> +}
> +
> +# Complete package stabilities
> +(( $+functions[__composer_stabilities] )) ||
> +__composer_stabilities() {
> + _wanted stabilities expl 'package stability' compadd "$@" - \
> + stable RC beta alpha dev
> +}
> +
> +# Complete package types
> +(( $+functions[__composer_types] )) ||
> +__composer_types() {
> + # 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}'[auto-load 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}'[auto-load 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 auto-loader 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}'[auto-load 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 auto-loader 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}'[auto-load 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 auto-loader 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 time-out]:time-out (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}'[auto-load 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 auto-loader 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 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
> + 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 auto-loader'
> + 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 -/'
> + )
> + }
> +
> + # 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 "$@"
>
Messages sorted by:
Reverse Date,
Date,
Thread,
Author