#compdef mvn mvnDebug # ------------------------------------------------------------------------------ # Copyright (c) 2010-2011 zsh-users # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the zsh-users nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ------------------------------------------------------------------------------ # Description # ----------- # # Completion script for Maven (http://maven.apache.org). # # Status: Incomplete, see FIXME and TODO tags. # # ------------------------------------------------------------------------------ # Authors # ------- # # * Julien Nicoulaud # # ------------------------------------------------------------------------------ # How to tweak # ------------ # # * By default only a few common utility plugins are displayed. To define your # own list of plugins: # # maven_plugins=( # 'jboss' # 'tomcat' # 'gwt:Maven plugin for the Google Web Toolkit' # 'android:Maven Plugin for Android' # ) # zstyle ':completion:*:mvn:*' plugins $maven_plugins # # * By default advanced phases are not displayed. To have them displayed: # # zstyle ':completion:*:mvn:*' show-advanced-phases true # # * To have a better presentation of completions: # # zstyle ':completion:*:*:mvn:*:matches' group 'yes' # zstyle ':completion:*:*:mvn:*:options' description 'yes' # zstyle ':completion:*:*:mvn:*:options' auto-description '%d' # zstyle ':completion:*:*:mvn:*:descriptions' format $'\e[1m -- %d --\e[22m' # zstyle ':completion:*:*:mvn:*:messages' format $'\e[1m -- %d --\e[22m' # zstyle ':completion:*:*:mvn:*:warnings' format $'\e[1m -- No matches found --\e[22m' # # ------------------------------------------------------------------------------ # -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- # vim: ft=zsh sw=2 ts=2 et # ------------------------------------------------------------------------------ typeset -A opt_args local context state line _mvn() { local curcontext="$curcontext" maven_version excl_opts excl_opts=(-h --help -v --version -ep --encrypt-password -emp --encrypt-master-password) _pick_variant -r maven_version maven3='Maven 3' maven2='Maven 2' unknown --version if [[ $maven_version == 'maven3' ]]; then opts=( "($excl_opts -T --threads)"{-T,--threads}'[thread count, for instance 2.0C where C is core multiplied]:thread count:_mvn_thread_counts' "($excl_opts -t --toolchains)"{-t,--toolchains}'[alternate path for the user toolchains file]:toolchains file:_mvn_toolchains_files' "($excl_opts -l --log-file)"{-l,--log-file}'[log file to where all build output will go]:log file:_mvn_log_files' ) elif [[ $maven_version == 'maven2' ]]; then opts=( "($excl_opts -cpu --check-plugin-updates -up --update-plugins -npu --no-plugin-updates -o --offline)"{-cpu,--check-plugin-updates,-up,--update-plugins}'[force upToDate check for any relevant registered plugins]' "($excl_opts -npr --no-plugin-registry)"{-npr,--no-plugin-registry}'[don'\''t use plugin-registry.xml for plugin versions]' "($excl_opts -npu --no-plugin-updates -cpu --check-plugin-updates -up --update-plugins)"{-npu,--no-plugin-updates}'[suppress upToDate check for any relevant registered plugins]' "($excl_opts -r --reactor)"{-r,--reactor}'[dynamically build reactor from subdirectories]:reactor:_mvn_reactors' ) else return 1 fi [[ -n ${(M)words:#"-pl"} || -n ${(M)words:#"--projects"} ]] && opts+=( "($excl_opts -am --also-make)"{-am,--also-make}'[if project list is specified, also build projects required by the list]' "($excl_opts -amd --also-make-dependents)"{-amd,--also-make-dependents}'[if project list is specified, also build projects that depend on projects on the list]' ) _arguments -C \ "(- : *)"{-h,--help}'[display help information]' \ "(- : *)"{-v,--version}'[display version information]' \ "(- : *)"{-emp,--encrypt-master-password}'[encrypt master security password]:master password:_mvn_passwords' \ "(- : *)"{-ep,--encrypt-password}'[encrypt server password]:password:_mvn_passwords' \ "($excl_opts -B --batch-mode)"{-B,--batch-mode}'[run in non-interactive (batch) mode]' \ "($excl_opts -V --show-version)"{-V,--show-version}'[display version information without stopping build]' \ "($excl_opts -q --quiet -X --debug)"{-q,--quiet}'[quiet output, only show errors]' \ "($excl_opts -X --debug -q --quiet)"{-X,--debug}'[produce execution debug output]' \ "($excl_opts -N --non-recursive)"{-N,--non-recursive}'[do not recurse into sub-projects]' \ "($excl_opts -C --strict-checksums -c --lax-checksums)"{-C,--strict-checksums}'[fail the build if checksums don'\''t match]' \ "($excl_opts -c --lax-checksums -C --strict-checksums)"{-c,--lax-checksums}'[warn if checksums don'\''t match]' \ "($excl_opts -e --errors)"{-e,--errors}'[produce execution error messages]' \ "($excl_opts -f --file)"{-f,--file}'[force the use of an alternate POM file]:POM file:_mvn_pom_files' \ "($excl_opts -s --settings)"{-s,--settings}'[alternate path for the user settings file]:settings file:_mvn_settings_files' \ "($excl_opts -gs --global-settings)"{-gs,--global-settings}'[alternate path for the global settings file]:global settings file:_mvn_settings_files' \ "($excl_opts -fae --fail-at-end -ff --fail-fast -fn --fail-never)"{-fae,--fail-at-end}'[only fail the build afterwards, allow all non-impacted builds to continue]' \ "($excl_opts -ff --fail-fast -fae --fail-at-end -fn --fail-never)"{-ff,--fail-fast}'[stop at first failure in reactorized builds]' \ "($excl_opts -fn --fail-never -fae --fail-at-end -ff --fail-fast)"{-fn,--fail-never}'[nerver fail the build, regardless of project result]' \ "($excl_opts -P --activate-profiles)"{-P,--activate-profiles}'[comma-delimited list of profiles to activate]:profile:_mvn_profiles' \ "($excl_opts -pl --projects)"{-pl,--projects}'[build specified reactor projects instead of all projects]:project list:_mvn_projects -s ,' \ "($excl_opts -rf --resume-from)"{-rf,--resume-from}'[resume reactor from specified project]:project:_mvn_projects' \ "($excl_opts -o --offline -U --update-snapshots -cpu --check-plugin-updates -up --update-plugins)"{-o,--offline}'[work offline]' \ "($excl_opts -U --update-snapshots -nsu --no-snapshot-updates -o --offline)"{-U,--update-snapshots}'[force a check for updated releases and snapshots on remote repositories]' \ "($excl_opts -nsu --no-snapshot-updates -U --update-snapshots -o --offline)"{-nsu,--no-snapshot-updates}'[Supress SNAPSHOT updates]' \ {-D-,--define}'[define a system property]:property:_mvn_properties' \ "$opts[@]" \ "($excl_opts)*: :_mvn_args" } (( $+functions[_mvn_args] )) || _mvn_args() { _alternative \ 'phases:phase:_mvn_phases' \ 'goals:goal:_mvn_plugin_goals' } (( $+functions[_mvn_phases] )) || _mvn_phases() { local phases phases=( 'clean:remove all files generated by the previous build' 'compile:compile the source code of the project' 'test:run tests using a suitable unit testing framework' 'package:take the compiled code and package it in its distributable format, such as a JAR' 'integration-test:process and deploy the package if necessary into an environment where integration tests can be run' 'verify:run any checks to verify the package is valid and meets quality criteria' 'install:install the package into the local repository, for use as a dependency in other projects locally' 'deploy:done in an integration or release environment, copies the final package to the remote repository' 'site:generates the projects site documentation' 'site-deploy:deploys the generated site documentation to the specified web server' ) if zstyle -t ":completion:${curcontext}:" show-advanced-phases || [[ $#PREFIX -gt 0 ]]; then phases+=( 'pre-clean:executes processes needed prior to the actual project cleaning' 'post-clean:executes processes needed to finalize the project cleaning' 'validate:validate the project is correct and all necessary information is available' 'initialize:initialize build state, e.g. set properties or create directories' 'generate-sources:generate any source code for inclusion in compilation' 'process-sources:process the source code, for example to filter any values' 'generate-resources:generate resources for inclusion in the package' 'process-resources:copy and process the resources into the destination directory, ready for packaging' 'process-classes:post-process the generated files from compilation' 'generate-test-sources:generate any test source code for inclusion in compilation' 'process-test-sources:process the test source code, for example to filter any values' 'generate-test-resources:create resources for testing' 'process-test-resources:copy and process the resources into the test destination directory' 'test-compile:compile the test source code into the test destination directory' 'process-test-classes:post-process the generated files from test compilation' 'prepare-package:perform any operations necessary to prepare a package before the actual packaging' 'pre-integration-test:perform actions required before integration tests are executed' 'post-integration-test:perform actions required after integration tests have been executed' 'pre-site:executes processes needed prior to the actual project site generation.' 'post-site:executes processes needed to finalize the site generation, and to prepare for site deployment' ) fi _describe -t 'phases' "phase" phases } (( $+functions[_mvn_plugin_goals] )) || _mvn_plugin_goals() { local ret=1 # TODO Plugin goals can also have the form groupId:artifactId:version:goal if compset -P '*:'; then _mvn_goals "${IPREFIX%:}" && ret=0 else _mvn_plugins && ret=0 fi return ret } (( $+functions[_mvn_plugins] )) || _mvn_plugins() { local plugins zstyle -a ":completion:${curcontext}:" plugins plugins [[ $#plugins -gt 0 ]] || plugins=( 'assembly:create archives of your projects sources, classes, dependencies etc. from flexible assembly descriptors' 'release:release a project with Maven, saving a lot of repetitive, manual work' 'help:provides goals aimed at helping to make sense out of the build environment.' 'versions:diagnose and update the versions of components in the POM' 'deploy:add your artifact(s) to a remote repository for sharing with other developers and project' 'dependency:provides the capability to manipulate artifacts' 'archetype:create a Maven project from an existing template called an archetype' 'site:generate a site for the project' ) _describe -t 'plugin' "plugin" plugins -S ':' } (( $+functions[_mvn_goals] )) || _mvn_goals() { local ret=1 plugin="$@" update_policy zstyle -s ":completion:${curcontext}:" cache-policy update_policy [[ -z "$update_policy" ]] && zstyle ":completion:${curcontext}:" cache-policy _mvn_goals_caching_policy unset goals if ( [[ ${+goals} -eq 0 ]] || _cache_invalid "mvn/plugins/$plugin" ) && ! _retrieve_cache "mvn/plugins/$plugin"; then setopt localoptions extendedglob goals=(${(s:,,,:)${${${(f)${${${(f)${${${${(F)${(S)${(f)"$(_call_program goals $words[1] -N org.apache.maven.plugins:maven-help-plugin:2.1.1:describe -Dplugin=$plugin)"}//#$plugin:/,,,}}:#*BUILD FAILURE*}#*This plugin has*goals#:}%For more information, run \'mvn help:describe*}}//:/\\:}}}// ##/ }// Description\\: /:}}) [[ $#goals -gt 0 ]] && _store_cache "mvn/plugins/$plugin" goals fi [[ $#goals -gt 0 ]] && _describe -t "plugin-$plugin-goals" "$plugin plugin goal" goals && ret=0 return ret } # FIXME No idea what kind of value the "--reactor" option is supposed to take (( $+functions[_mvn_reactors] )) || _mvn_reactors() { _message -e reactors 'reactor' } (( $+functions[_mvn_passwords] )) || _mvn_passwords() { _message -e passwords 'password' } (( $+functions[_mvn_thread_counts] )) || _mvn_thread_counts() { local thread_counts thread_counts=( '1:build with 1 thread' '1C:build with 1 thread per CPU core' '2:build with 2 threads' '2C:build with 2 threads per CPU core' '3:build with 3 threads' '3C:build with 3 threads per CPU core' '4:build with 4 threads' '4C:build with 4 threads per CPU core' '5:build with 5 threads' '5C:build with 5 threads per CPU core' '6:build with 6 threads' '6C:build with 6 threads per CPU core' '7:build with 7 threads' '7C:build with 7 threads per CPU core' '8:build with 8 threads' '8C:build with 8 threads per CPU core' ) _describe -t 'thread-counts' "thread count" thread_counts } (( $+functions[_mvn_pom_files] )) || _mvn_pom_files() { _files -g '*pom*\.xml*' } (( $+functions[_mvn_toolchains_files] )) || _mvn_toolchains_files() { _files } (( $+functions[_mvn_settings_files] )) || _mvn_settings_files() { _files -g '*settings*\.xml*' } (( $+functions[_mvn_log_files] )) || _mvn_log_files() { _files } (( $+functions[_mvn_profiles] )) || _mvn_profiles() { # FIXME Use "mvn help:all-profiles" output instead of parsing... # Blocked on http://jira.codehaus.org/browse/MPH-82 and http://jira.codehaus.org/browse/MPH-83 local ret=1 profs update_policy settings_file files parent_pom_file cache_name profiles_section zstyle -s ":completion:${curcontext}:" cache-policy update_policy [[ -z "$update_policy" ]] && zstyle ":completion:${curcontext}:" cache-policy _mvn_profiles_caching_policy profs=() # Resolve profiles from settings.xml settings_file=${~opt_args[-s]:-${opt_args[--settings]:-~/.m2/settings.xml}} if [[ -f $settings_file ]]; then unset profiles cache_name="mvn/profiles${settings_file:A}" if ( [[ ${+profiles} -eq 0 ]] || _cache_invalid "$cache_name" ) && ! _retrieve_cache "$cache_name"; then profiles=() profiles_section="${(M)${(f)$(<$settings_file)}:#**}" if [[ -n "$profiles_section" ]]; then for profile in ${(s:,,,:)${${${(S)${(S)${(S)${(S)${${profiles_section#*}%*}//*<\/repositories>}//*<\/pluginRepositories>}//*<\/build>}//<\/id>*/,,,}##*}%%*}}; do [[ -z ${(M)profiles:#"$profile"*} ]] && profiles+=("$profile"'['"in settings file"']') done fi [[ $#profiles -gt 0 ]] && _store_cache "$cache_name" profiles fi profs+=($profiles) fi # Resolve project profiles parent_pom_file=${~opt_args[-f]:-${opt_args[--file]:-pom.xml}} while [[ -f ${parent_pom_file:a:h:h}/pom.xml ]]; do parent_pom_file=${parent_pom_file:a:h:h}/pom.xml; done if [[ -f $parent_pom_file ]]; then unset profiles cache_name="mvn/profiles${parent_pom_file:A}" if ( [[ ${+profiles} -eq 0 ]] || _cache_invalid "$cache_name" ) && ! _retrieve_cache "$cache_name"; then profiles=() setopt localoptions extendedglob for file in ${parent_pom_file:h}/**/pom.xml~*target\/*; do profiles_section="${(M)${(f)$(<$file)}:#**}" if [[ -n "$profiles_section" ]]; then for profile in ${(s:,,,:)${${${(S)${(S)${(S)${(S)${${profiles_section#*}%*}//*<\/repositories>}//*<\/pluginRepositories>}//*<\/build>}//<\/id>*/,,,}##*}%%*}}; do [[ -z ${(M)profiles:#"$profile"*} ]] && profiles+=("$profile"'['"in ${file#${parent_pom_file:h}\/}"']') done fi done [[ $#profiles -gt 0 ]] && _store_cache "$cache_name" profiles fi profs+=($profiles) fi [[ $#profs -gt 0 ]] && _values -s ',' 'profile' "$profs[@]" && ret=0 return ret } (( $+functions[_mvn_projects] )) || _mvn_projects() { # TODO projects can also be given in the form [groupId:]artifactId. local pom_file ret=1 pom_file=${~opt_args[-f]:-${opt_args[--file]:-pom.xml}} while [[ -f ${pom_file:a:h:h}/pom.xml ]]; do pom_file=${pom_file:a:h:h}/pom.xml; done if [[ -f $pom_file ]]; then setopt localoptions extendedglob local projects; projects=(${pom_file:h}/*/**/pom.xml~*target\/*) projects=(${${projects#.\/}:h}) [[ $#projects -gt 0 ]] && _values "$@" 'project' "${projects[@]}" && ret=0 fi return ret } (( $+functions[_mvn_properties] )) || _mvn_properties() { local ret=1 if compset -P '*='; then # TODO Add callback for plugin specific handlers _default && ret=0 else # TODO Split in several functions + _alternatives local properties plugin_colon_goal properties=( 'skipTests:skip tests execution' 'maven.test.skip=:skip tests compilation and execution' 'gpg.passphrase=:gpg passphrase' ) for plugin_colon_goal in ${(M)words:#*:*}; do # FIXME pretty sure this matches more than just plugin:goals # TODO Extract descriptions too # FIXME Output seems to be truncated (eg release:prepare) properties+=(${${${(M)${(f)"$(_call_program goals $words[1] -N org.apache.maven.plugins:maven-help-plugin:2.1.1:describe -Dplugin=${plugin_colon_goal%:*} -Dgoal=${plugin_colon_goal#*:} -Ddetail)"}:#*Expression: *}#*\{}%\}*}"=:$plugin_colon_goal parameter") done _describe -t 'property-names' "property name" properties && ret=0 # FIXME Don't add a space prefix fi return ret } _mvn_goals_caching_policy() { # Rebuild if cache is older than one month. local -a oldp oldp=( "$1"(NmM+1) ) (( $#oldp )) } _mvn_profiles_caching_policy() { # Resolve the cache directory. local cache_dir zstyle -s ":completion:${curcontext}:" cache-path cache_dir : ${cache_dir:=${ZDOTDIR:-$HOME}/.zcompcache} # Rebuild if cached file more recent than cache. local cached_file="${1#$cache_dir}" [[ -f $cached_file && $cached_file -nt "$1" ]] && return 0 # Rebuild if cache is older than one week. local -a oldp oldp=( "$1"(Nmw+1) ) (( $#oldp )) && return 0 return 1 } _mvn "$@"