#compdef dub # Useful help: # https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org # http://zsh.sourceforge.net/Doc/Release/Completion-System.html # http://zdharma.org/Zsh-100-Commits-Club/Zsh-Native-Scripting-Handbook.html # # Completions installed on your system, e.g. for MacOSX + Homebrew users: # /usr/local/Cellar/zsh/$VERSION/share/zsh/functions # The GIT completion is quite amazing (and equally complex) # The CVS completion is much easier to grok (e.g. for function dispatch) # Entry point _dub() { # TODO: # - Handle registry URLs # - Handle multiple dub (e.g. ./bin/dub add [TAB]) # - Interactively query configuration (for -c and --override-config) # => Dub does not currently support this # - Add ability to provide version, e.g. vibe-d@0.8.6 (see dub add) # - Get registry packages if it doesn't make us lag # - Query compilers # Note that global arguments won't show up when completing commands # This is on purpose, to reduce the amount of options being shown during completion, # as users are much more likely to be looking for command-specific options. _arguments -S -C \ '(* : -)'{-h,--help}'[Display general or command specific help and exit]' \ '(* : -)--version[Print version information and exit]' \ \ '--root=[Run as if dub was started in given path]: :_directories' \ '--skip-registry=[Skips searching packages on certain repositories]:mode:(none standard configured all)' \ '--registry=[Search the given registry URL first when resolving dependencies]:registry URL:_urls' \ '--bare[Read only packages contained in the current directory]' \ '--cache=[Puts any fetched packages in the specified location]:cache location:(local|system|user)' \ '--annotate[Do not perform any action, just print what would be done]' \ \ + '(verbosity)' \ '--vquiet[Print no messages]' \ '--verror[Only print errors]' \ {-q,--quiet}'[Only print warnings and errors]' \ {-v,--verbose}'[Print diagnostic output]' \ '--vverbose[Print debug output]' \ \ '--[End of dub arguments, the following will be sent to the program]' \ '*::dub command:_command_dispatch' } # Command dispatch function _command_dispatch() { declare -a commands=( init:'Initialize a new dub package' run:'Build and run a dub package (default action)' build:'Build a dub package (by name, or in the working directory by default)' test:'Execute the tests of a dub package' generate:'Generates project files using the specified generator' describe:'Prints a JSON description of the project and its dependencies' clean:'Removes intermediate build files and cached build results' dustmite:'Create reduced test cases for build errors' fetch:'Manually retrieves and caches a package' add:'Adds dependencies to the package file' remove:'Removes a cached package' upgrade:'Forces an upgrade of the dependencies' add-path:'Adds a default package search path' remove-path:'Removes a package search path' add-local:'Adds a local package directory (e.g. a git repository)' remove-local:'Removes a local package directory' list:'Prints a list of all local packages dub is aware of' search:'Search for available packages' add-override:'Adds a new package override' remove-override:'Removes an existing package override' list-overrides:'Prints a list of all local package overrides' clean-caches:'Removes cached metadata' convert:'Converts the file format of the package recipe' ) if (( CURRENT == 1 )); then _alternative \ 'files:filename:_files -g "*.d"' \ "commands:dub command: _describe -t commands command commands" else integer ret=0 local cmd=${${(k)commands}[(r)$words[1]:*]%%:*} if [ ! -z "$cmd" ]; then _call_function ret _dub_$cmd else # Assume single file, it takes program arguments _message "Arguments for single file package $words[1]" fi return 0 fi } (( $+functions[_dub_add] )) || _dub_add() { # TODO: Make dub list more machine-readable local -a dubList=("${(@f)$(dub list)}") # First element is 'Packages present in the system...' # Last element is an empty line dubList=(${dubList[2,$#dubList-1]}) local -A pkgs # Collect versions and names for ((i = 1; i <= ${#dubList}; i++)); do pkg_name=${${=${dubList[i]}}[1]} pkg_version=${${${=${dubList[i]}}[2]}%:} # Subpackages are currently not supported by 'dub add' (see dlang/dub#1846) if [ ! -z "${pkg_name:#*:*}" ]; then pkgs[${pkg_name}]+="${pkg_version}, " fi done # Merge versions local -a packages for name ver in ${(kv)pkgs}; do packages+=${name}:"${ver%, }" done # Package list includes ':' which is used as description #_values 'local packages' ${pkgs//:/\\:} # Use the unique property to get rid of subpkgs _describe -t packages package packages } (( $+functions[_dub_init] )) || _dub_init() { _arguments -S -C \ ':package directory:_directories' \ '*:package dependency:_dub_add' \ '(-t --type)'{-t,--type}'[Set the type of project to generate]:project type:((minimal\:"simple hello world project (default)" vibe.d\:"minimal HTTP server based on vibe.d" deimos\:"skeleton for C header bindings" custom\:"custom project provided by dub package"))' \ '(-f --format)'{-f,--format}'[Sets the format to use for the manifest file]:format:(json sdl)' \ '(-n --non-iteractive)'{-n,--non-iteractive}'[Do not prompt for values and use only defaults]' \ '(* : -)'{-h,--help}'[Display general or command specific help and exit]' } (( $+functions[_dub_list] )) || _dub_list() { _arguments -S -C \ '(* : -)'{-h,--help}'[Display general or command specific help and exit]' } # dub generate, dub build, dub run... (( $+functions[_dub_generate_generic] )) || _dub_generate_generic() { _arguments -S -C \ $@ \ '::package:_dub_add' \ '(* : -)'{-h,--help}'[Display general or command specific help and exit]' \ '(-b --build)'{-b,--build=}'[Specifies the type of build to perform]:build type:("debug (default)" plain release release-debug release-nobounds unittest profile profile-gc docs ddox cov cov-ctfe unittest-cov unittest-cov-ctfe syntax)' \ '(-c --config)'{-c,--config=}'[Builds the specified configuration]:package configuration: ' \ '*--override-config=[ Uses the specified configuration for a certain dependency]:dependency/config: ' \ '--compiler=[Specifies the compiler binary to use (can be a path)]:compiler:(dmd gdc ldc gdmd ldmd)' \ '(-a --arch)'{-a,--arch=}'[Force a different architecture (e.g. x86 or x86_64)]:architecture: ' \ '(-d --debug)*'{-d,--debug=}'[Define the specified debug version identifier when building]:Debug version: ' \ '--d-version=[Define the specified version identifier when building]:Version identifier: ' \ '--nodeps[Do not resolve missing dependencies before building]' \ '--build-mode=[Specifies the way the compiler and linker are invoked]:build mode:("separate (default)" allAtOnce singleFile)' \ '--single[Treats the package name as a filename. The file must contain a package recipe comment]:file:_files -g "*.d"' \ '--filter-versions[Experimental: Filter version identifiers and debug version identifiers to improve build cache efficiency]' \ '--combined[Tries to build the whole project in a single compiler run]' \ '--print-builds[Prints the list of available build types]' \ '--print-configs[Prints the list of available configurations]' \ '--print-platform[Prints the identifiers for the current build platform as used for the manifests build field]' \ '--parallel[Runs multiple compiler instances in parallel, if possible]' } (( $+functions[_dub_generate] )) || _dub_generate() { local curcontext="$curcontext" declare -a generators=( visuald:'VisualD project files', sublimetext:'SublimeText project file' cmake:'CMake build scripts' build:'Builds the package directly (use "dub build" instead)' ) local localArgs=( ':generator: _describe -t generators generator generators' ) integer ret=0 _call_function ret _dub_generate_generic ${(@)localArgs} return ret } (( $+functions[_dub_build] )) || _dub_build() { local localArgs=( $@ '--rdmd[Use rdmd instead of directly invoking the compiler]' '(-f --force)'{-f,--force}'[Forces a recompilation even if the target is up to date]' '(-y--yes)'{-y,--yes}'[Assume "yes" as answer to all interactive prompts]' '(-n--non-interactive)'{-n,--non-interactive}'[Do not enter interactive mode]' ) integer ret=0 _call_function ret _dub_generate_generic ${(@)localArgs} return ret } (( $+functions[_dub_run] )) || _dub_run() { local localArgs=( '--[End of dub arguments, the following will be sent to the program]' '--temp-build[Builds the project in the temp folder if possible]' ) integer ret=0 _call_function ret _dub_build ${(@)localArgs} return ret } (( $+functions[_dub_test] )) || _dub_test() { local localArgs=( '--main-file=[Specifies a custom file containing the main() function to use for running the tests]:main file:_files -g "*.d"' ) integer ret=0 _call_function ret _dub_build ${(@)localArgs} return ret } (( $+functions[_dub_describe] )) || _dub_describe() { local localArgs=( '--import-paths[Shortcut for --data=import-paths --data-list]' '--string-import-paths[Shortcut for --data=string-import-paths --data-list]' '--data=[List the values of a particular build setting]:listing options: _values -s , argument main-source-file dflags lflags libs linker-files source-files versions debug-versions import-paths string-import-paths import-files options' '--data-list[Output --data information in list format (line-by-line)]' '--data-0[Output --data information using null-delimiters, rather than spaces or newlines]' ) integer ret=0 _call_function ret _dub_build ${(@)localArgs} return ret } (( $+functions[_dub_clean] )) || _dub_clean() { _arguments -S -C \ '(* : -)'{-h,--help}'[Display general or command specific help and exit]' \ + '(toclean)' \ '--all-packages[Cleans up *all* known packages (dub list)]' \ ':package:_dub_add' } (( $+functions[_dub_dustmite] )) || _dub_dustmite() { local localArgs=( ':target directory:_directories' '--compiler-status=[The expected status code of the compiler run]:status code: ' '--compiler-regex=[A regular expression used to match against the compiler output]:regex: ' '--linker-status=[The expected status code of the linker run]:status code: ' '--linker-regex=[A regular expression used to match against the linker output]:regex: ' '--program-status=[The expected status code of the built executable]:status code: ' '--program-regex=[A regular expression used to match against the program output]:regex: ' '--[End of dub arguments, the following will be sent to the program]' ) integer ret=0 _call_function ret _dub_generate_generic ${(@)localArgs} return ret } _dub