Parent directory

grunt.plugin.zsh

7157 bytes
  1#compdef grunt
  2#autoload
  3# -----------------------------------------------------------------------------
  4#  _grunt
  5#
  6#  Completion script for grunt.
  7#   - https://github.com/gruntjs/grunt
  8#   - https://github.com/gruntjs/grunt-cli
  9#
 10# -----------------------------------------------------------------------------
 11#
 12#  Version     : 0.1.2
 13#  Author      : Yonchu <yuyuchu3333@gmail.com>
 14#  License     : MIT License
 15#  Repository  : https://github.com/yonchu/grunt-zsh-completion
 16#  Last Change : 20 Aug 2014.
 17#
 18#  Copyright (c) 2013 Yonchu.
 19#
 20# -----------------------------------------------------------------------------
 21# USAGE
 22# -----
 23#
 24# Enable caching:
 25#
 26#   If you want to use the cache, set the following in your .zshrc:
 27#
 28#     zstyle ':completion:*' use-cache yes
 29#
 30#
 31# Settings:
 32#
 33#  - Show grunt file path:
 34#      zstyle ':completion::complete:grunt::options:' show_grunt_path yes
 35#
 36#  - Cache expiration days (default: 7):
 37#      zstyle ':completion::complete:grunt::options:' expire 1
 38#
 39#  - Not update options cache if target gruntfile is changed.
 40#      zstyle ':completion::complete:grunt::options:' no_update_options yes
 41#
 42#  Note that if you change the zstyle settings,
 43#  you should delete the cache file and restart zsh.
 44#
 45#    $ rm ~/.zcompcache/grunt
 46#    $ exec zsh
 47#
 48# -----------------------------------------------------------------------------
 49
 50function __grunt() {
 51    local curcontext="$curcontext" update_policy state
 52    local show_grunt_path update_msg gruntfile opts tasks
 53
 54    # Setup cache-policy.
 55    zstyle -s ":completion:${curcontext}:" cache-policy update_policy
 56    if [[ -z $update_policy ]]; then
 57        zstyle ":completion:${curcontext}:" cache-policy __grunt_caching_policy
 58    fi
 59
 60    # Check show_path option.
 61    zstyle -b ":completion:${curcontext}:options:" show_grunt_path show_grunt_path
 62
 63    # Get current gruntfile.
 64    gruntfile=$(__grunt_get_gruntfile)
 65
 66    # Initialize opts and tasks.
 67    opts=()
 68    tasks=()
 69
 70    # Add help options.
 71    opts+=('(- 1 *)'{-h,--help}'[Display this help text.]')
 72
 73    ## Complete without gruntfile.
 74    if [[ ! -f $gruntfile ]]; then
 75        _arguments "${opts[@]}"
 76        return
 77    fi
 78
 79    ## Complete with gruntfile.
 80    # Retrieve cache.
 81    if ! __grunt_update_cache "$gruntfile"; then
 82        update_msg=' (cache updated)'
 83    fi
 84
 85    # Make options completion.
 86    if [[ ${#__grunt_opts} -gt 0 ]]; then
 87        opts+=("${__grunt_opts[@]}")
 88    fi
 89
 90    # Complete arguments.
 91    _arguments \
 92        "${opts[@]}" \
 93        '*: :->tasks' \
 94        && return
 95
 96    case $state in
 97        tasks)
 98            if [[ $show_grunt_path == 'yes' ]]; then
 99                update_msg="$update_msg: ${${gruntfile/#$HOME/~}%/}"
100            fi
101            # Make tasks completion.
102            if [[ ${#__grunt_tasks} -gt 0 ]]; then
103                tasks+=("${__grunt_tasks[@]}")
104                _describe -t grunt-task "$verbose grunt task$update_msg" tasks || return 1
105            fi
106        ;;
107    esac
108
109    return 0
110}
111
112# Cache policy:
113#   The cache file name: grunt
114#   The cache variable name: __grunt_version __grunt_gruntfile __grunt_opts __grunt_tasks
115function __grunt_update_cache() {
116    # TODO
117    local version='0.1.2'
118    local is_updating=0
119    local gruntfile="$1"
120    local grunt_info no_update_options cache_path
121
122    # Check no_update_options option.
123    zstyle -b ":completion:${curcontext}:options:" no_update_options no_update_options
124
125
126    if ! ( ((  $+__grunt_gruntfile )) \
127        && (( $+__grunt_opts )) \
128        && (( $+__grunt_tasks )) ) \
129        && ! _retrieve_cache 'grunt'; then
130        is_updating=1
131    fi
132
133    if [[ $gruntfile != $__grunt_gruntfile ]]; then
134        # Except for --help options.
135        __grunt_gruntfile=$gruntfile
136        if [[ $no_update_options == 'yes' ]]; then
137            if [[ $PREFIX == ${PREFIX#-} ]]; then
138                # Not options completions.
139                is_updating=1
140            elif [[ ${#__grunt_opts} -lt 2 ]]; then
141                is_updating=1
142            else
143                unset __grunt_gruntfile
144            fi
145        else
146            is_updating=1
147        fi
148    else
149        if [[ $PREFIX != ${PREFIX#-} && ${#__grunt_opts} -gt 1 ]]; then
150            unset __grunt_gruntfile
151        fi
152    fi
153
154    if _cache_invalid 'grunt'; then
155        is_updating=1
156    fi
157
158    # Check _grunt version.
159    if [[ $__grunt_version != $version ]]; then
160        is_updating=1
161    fi
162
163    if [[ $is_updating -ne 0 ]]; then
164        # Update cache.
165        __grunt_version=$version
166        __grunt_gruntfile=$gruntfile
167        is_updating=1
168        grunt_info=$(grunt --help --no-color --gruntfile "$__grunt_gruntfile" 2>/dev/null)
169        __grunt_opts=(${(f)"$(__grunt_get_opts "$grunt_info")"})
170        __grunt_tasks=(${(f)"$(__grunt_get_tasks "$grunt_info")"})
171        _store_cache 'grunt' __grunt_version __grunt_gruntfile __grunt_opts __grunt_tasks
172    fi
173    return $is_updating
174}
175
176function __grunt_get_tasks() {
177    echo -E "$1" \
178        | grep 'Available tasks' -A 100 \
179        | grep '^ ' \
180        | sed -e 's/^[[:blank:]]*//' -e 's/[[:blank:]]*$//' \
181        | sed -e 's/:/\\:/g' \
182        | sed -e 's/  /:/'
183}
184
185function __grunt_get_opts() {
186    local opt_hunk opt_sep opt_num line opt
187    opt_hunk=$(echo -E "$1" \
188        | grep 'Options$' -A 100 \
189        | sed '1 d' \
190        | sed -e 's/[[:blank:]]*$//' \
191    )
192
193    opt_sep=()
194    opt_hunk=(${(f)opt_hunk})
195    opt_num=0
196    for line in "$opt_hunk[@]"; do
197        opt=$(echo -E "$line" | sed -e 's/^[[:blank:]]*//')
198        if [[ $line == $opt ]]; then
199            break
200        fi
201        if [[ $opt != ${opt#-} ]]; then
202            # Start with -
203            (( opt_num++ ))
204            opt=$(echo -E "$opt" | sed 's/^\(\(--[^ ]*\)\(, \(-[^ ]*\)\)*\)  */\2\\t\4\\\t/')
205        fi
206        opt_sep[$opt_num]=("${opt_sep[$opt_num]}${opt}")
207    done
208
209    for line in "$opt_sep[@]"; do
210        opt=(${(s:\t:)line})
211        if [[ ${opt[1]} == '--help' ]]; then
212            continue
213        fi
214        if [[ ${#opt} -eq 2 ]]; then
215            echo -E "(${opt[1]})${opt[1]}[${opt[2]}]"
216        else
217            echo -E "(${opt[1]},${opt[2]})${opt[1]}[${opt[3]}]"
218            echo -E "(${opt[1]},${opt[2]})${opt[2]}[${opt[3]}]"
219        fi
220    done
221}
222
223function __grunt_get_gruntfile() {
224    local gruntfile
225    local curpath="$PWD"
226    while [ "$curpath" ]; do
227        for gruntfile in "$curpath/"{G,g}runtfile.{js,coffee}; do
228            if [[ -e "$gruntfile" ]]; then
229                echo "$gruntfile"
230                return
231            fi
232        done
233        curpath=${curpath%/*}
234    done
235    return 1
236}
237
238function __grunt_caching_policy() {
239    # Returns status zero if the completions cache needs rebuilding.
240
241    # Rebuild if .agignore more recent than cache.
242    if [[ -f $__grunt_gruntfile && $__grunt_gruntfile -nt $1 ]]; then
243        # Invalid cache because gruntfile is old.
244        return 0
245    fi
246
247    local -a oldp
248    local expire
249    zstyle -s ":completion:${curcontext}:options:" expire expire || expire=7
250    # Rebuild if cache is more than $expire days.
251    oldp=( "$1"(Nm+$expire) )
252    (( $#oldp ))
253}
254
255compdef __grunt grunt