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