Commit 40deb795bddd2fddb6b9c5db0bb0fa782b4c2954

Authored by Shrikant Sharat
1 parent b69ad8866a

Add completion definition after compinit is run.

Showing 1 changed file with 2 additions and 2 deletions Inline Diff

1 #!/bin/zsh 1 #!/bin/zsh
2 2
3 # Each line in this string has the following entries separated by a space 3 # Each line in this string has the following entries separated by a space
4 # character. 4 # character.
5 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone> 5 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone>
6 # FIXME: Is not kept local by zsh! 6 # FIXME: Is not kept local by zsh!
7 local _ANTIGEN_BUNDLE_RECORD="" 7 local _ANTIGEN_BUNDLE_RECORD=""
8 8
9 # Syntaxes 9 # Syntaxes
10 # antigen-bundle <url> [<loc>=/] 10 # antigen-bundle <url> [<loc>=/]
11 # Keyword only arguments: 11 # Keyword only arguments:
12 # branch - The branch of the repo to use for this bundle. 12 # branch - The branch of the repo to use for this bundle.
13 antigen-bundle () { 13 antigen-bundle () {
14 14
15 # Bundle spec arguments' default values. 15 # Bundle spec arguments' default values.
16 local url="$ANTIGEN_DEFAULT_REPO_URL" 16 local url="$ANTIGEN_DEFAULT_REPO_URL"
17 local loc=/ 17 local loc=/
18 local branch= 18 local branch=
19 local no_local_clone=false 19 local no_local_clone=false
20 local btype=plugin 20 local btype=plugin
21 21
22 # Parse the given arguments. (Will overwrite the above values). 22 # Parse the given arguments. (Will overwrite the above values).
23 eval "$(-antigen-parse-args \ 23 eval "$(-antigen-parse-args \
24 'url?, loc? ; branch:?, no-local-clone?, btype:?' \ 24 'url?, loc? ; branch:?, no-local-clone?, btype:?' \
25 "$@")" 25 "$@")"
26 26
27 # Check if url is just the plugin name. Super short syntax. 27 # Check if url is just the plugin name. Super short syntax.
28 if [[ "$url" != */* ]]; then 28 if [[ "$url" != */* ]]; then
29 loc="plugins/$url" 29 loc="plugins/$url"
30 url="$ANTIGEN_DEFAULT_REPO_URL" 30 url="$ANTIGEN_DEFAULT_REPO_URL"
31 fi 31 fi
32 32
33 # Resolve the url. 33 # Resolve the url.
34 url="$(-antigen-resolve-bundle-url "$url")" 34 url="$(-antigen-resolve-bundle-url "$url")"
35 35
36 # Add the branch information to the url. 36 # Add the branch information to the url.
37 if [[ ! -z $branch ]]; then 37 if [[ ! -z $branch ]]; then
38 url="$url|$branch" 38 url="$url|$branch"
39 fi 39 fi
40 40
41 # The `make_local_clone` variable better represents whether there should be 41 # The `make_local_clone` variable better represents whether there should be
42 # a local clone made. For cloning to be avoided, firstly, the `$url` should 42 # a local clone made. For cloning to be avoided, firstly, the `$url` should
43 # be an absolute local path and `$branch` should be empty. In addition to 43 # be an absolute local path and `$branch` should be empty. In addition to
44 # these two conditions, either the `--no-local-clone` option should be 44 # these two conditions, either the `--no-local-clone` option should be
45 # given, or `$url` should not a git repo. 45 # given, or `$url` should not a git repo.
46 local make_local_clone=true 46 local make_local_clone=true
47 if [[ $url == /* && -z $branch && 47 if [[ $url == /* && -z $branch &&
48 ( $no_local_clone == true || ! -d $url/.git ) ]]; then 48 ( $no_local_clone == true || ! -d $url/.git ) ]]; then
49 make_local_clone=false 49 make_local_clone=false
50 fi 50 fi
51 51
52 # Add it to the record. 52 # Add it to the record.
53 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype" 53 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype"
54 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone" 54 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone"
55 55
56 # Ensure a clone exists for this repo, if needed. 56 # Ensure a clone exists for this repo, if needed.
57 if $make_local_clone; then 57 if $make_local_clone; then
58 -antigen-ensure-repo "$url" 58 -antigen-ensure-repo "$url"
59 fi 59 fi
60 60
61 # Load the plugin. 61 # Load the plugin.
62 -antigen-load "$url" "$loc" "$btype" "$make_local_clone" 62 -antigen-load "$url" "$loc" "$btype" "$make_local_clone"
63 63
64 } 64 }
65 65
66 -antigen-resolve-bundle-url () { 66 -antigen-resolve-bundle-url () {
67 # Given an acceptable short/full form of a bundle's repo url, this function 67 # Given an acceptable short/full form of a bundle's repo url, this function
68 # echoes the full form of the repo's clone url. 68 # echoes the full form of the repo's clone url.
69 69
70 local url="$1" 70 local url="$1"
71 71
72 # Expand short github url syntax: `username/reponame`. 72 # Expand short github url syntax: `username/reponame`.
73 if [[ $url != git://* && 73 if [[ $url != git://* &&
74 $url != https://* && 74 $url != https://* &&
75 $url != /* && 75 $url != /* &&
76 $url != git@github.com:*/* 76 $url != git@github.com:*/*
77 ]]; then 77 ]]; then
78 url="https://github.com/${url%.git}.git" 78 url="https://github.com/${url%.git}.git"
79 fi 79 fi
80 80
81 echo "$url" 81 echo "$url"
82 } 82 }
83 83
84 antigen-bundles () { 84 antigen-bundles () {
85 # Bulk add many bundles at one go. Empty lines and lines starting with a `#` 85 # Bulk add many bundles at one go. Empty lines and lines starting with a `#`
86 # are ignored. Everything else is given to `antigen-bundle` as is, no 86 # are ignored. Everything else is given to `antigen-bundle` as is, no
87 # quoting rules applied. 87 # quoting rules applied.
88 88
89 local line 89 local line
90 90
91 grep -v '^\s*$\|^#' | while read line; do 91 grep -v '^\s*$\|^#' | while read line; do
92 # Using `eval` so that we can use the shell-style quoting in each line 92 # Using `eval` so that we can use the shell-style quoting in each line
93 # piped to `antigen-bundles`. 93 # piped to `antigen-bundles`.
94 eval "antigen-bundle $line" 94 eval "antigen-bundle $line"
95 done 95 done
96 } 96 }
97 97
98 antigen-update () { 98 antigen-update () {
99 # Update your bundles, i.e., `git pull` in all the plugin repos. 99 # Update your bundles, i.e., `git pull` in all the plugin repos.
100 100
101 date > $ADOTDIR/revert-info 101 date > $ADOTDIR/revert-info
102 102
103 -antigen-echo-record | 103 -antigen-echo-record |
104 awk '{print $1}' | 104 awk '{print $1}' |
105 sort -u | 105 sort -u |
106 while read url; do 106 while read url; do
107 echo "**** Pulling $url" 107 echo "**** Pulling $url"
108 (dir="$(-antigen-get-clone-dir "$url")" 108 (dir="$(-antigen-get-clone-dir "$url")"
109 echo -n "$dir:" 109 echo -n "$dir:"
110 cd "$dir" 110 cd "$dir"
111 git rev-parse HEAD) >> $ADOTDIR/revert-info 111 git rev-parse HEAD) >> $ADOTDIR/revert-info
112 -antigen-ensure-repo "$url" --update --verbose 112 -antigen-ensure-repo "$url" --update --verbose
113 echo 113 echo
114 done 114 done
115 } 115 }
116 116
117 antigen-revert () { 117 antigen-revert () {
118 if ! [[ -f $ADOTDIR/revert-info ]]; then 118 if ! [[ -f $ADOTDIR/revert-info ]]; then
119 echo 'No revert information available. Cannot revert.' >&2 119 echo 'No revert information available. Cannot revert.' >&2
120 fi 120 fi
121 121
122 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do 122 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do
123 dir="$(echo "$line" | cut -d: -f1)" 123 dir="$(echo "$line" | cut -d: -f1)"
124 git --git-dir="$dir/.git" --work-tree="$dir" \ 124 git --git-dir="$dir/.git" --work-tree="$dir" \
125 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null 125 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null
126 done 126 done
127 127
128 echo "Reverted to state before running -update on $( 128 echo "Reverted to state before running -update on $(
129 cat $ADOTDIR/revert-info | sed -n 1p)." 129 cat $ADOTDIR/revert-info | sed -n 1p)."
130 } 130 }
131 131
132 -antigen-get-clone-dir () { 132 -antigen-get-clone-dir () {
133 # Takes a repo url and gives out the path that this url needs to be cloned 133 # Takes a repo url and gives out the path that this url needs to be cloned
134 # to. Doesn't actually clone anything. 134 # to. Doesn't actually clone anything.
135 echo -n $ADOTDIR/repos/ 135 echo -n $ADOTDIR/repos/
136 echo "$1" | sed \ 136 echo "$1" | sed \
137 -e 's./.-SLASH-.g' \ 137 -e 's./.-SLASH-.g' \
138 -e 's.:.-COLON-.g' \ 138 -e 's.:.-COLON-.g' \
139 -e 's.|.-PIPE-.g' 139 -e 's.|.-PIPE-.g'
140 } 140 }
141 141
142 -antigen-get-clone-url () { 142 -antigen-get-clone-url () {
143 # Takes a repo's clone dir and gives out the repo's original url that was 143 # Takes a repo's clone dir and gives out the repo's original url that was
144 # used to create the given directory path. 144 # used to create the given directory path.
145 echo "$1" | sed \ 145 echo "$1" | sed \
146 -e "s:^$ADOTDIR/repos/::" \ 146 -e "s:^$ADOTDIR/repos/::" \
147 -e 's.-SLASH-./.g' \ 147 -e 's.-SLASH-./.g' \
148 -e 's.-COLON-.:.g' \ 148 -e 's.-COLON-.:.g' \
149 -e 's.-PIPE-.|.g' 149 -e 's.-PIPE-.|.g'
150 } 150 }
151 151
152 -antigen-ensure-repo () { 152 -antigen-ensure-repo () {
153 153
154 # Ensure that a clone exists for the given repo url and branch. If the first 154 # Ensure that a clone exists for the given repo url and branch. If the first
155 # argument is `--update` and if a clone already exists for the given repo 155 # argument is `--update` and if a clone already exists for the given repo
156 # and branch, it is pull-ed, i.e., updated. 156 # and branch, it is pull-ed, i.e., updated.
157 157
158 # Argument defaults. 158 # Argument defaults.
159 # The url. No sane default for this, so just empty. 159 # The url. No sane default for this, so just empty.
160 local url= 160 local url=
161 # Check if we have to update. 161 # Check if we have to update.
162 local update=false 162 local update=false
163 # Verbose output. 163 # Verbose output.
164 local verbose=false 164 local verbose=false
165 165
166 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")" 166 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")"
167 shift $# 167 shift $#
168 168
169 # Get the clone's directory as per the given repo url and branch. 169 # Get the clone's directory as per the given repo url and branch.
170 local clone_dir="$(-antigen-get-clone-dir $url)" 170 local clone_dir="$(-antigen-get-clone-dir $url)"
171 171
172 # A temporary function wrapping the `git` command with repeated arguments. 172 # A temporary function wrapping the `git` command with repeated arguments.
173 --plugin-git () { 173 --plugin-git () {
174 eval git --git-dir=$clone_dir/.git --work-tree=$clone_dir "$@" 174 eval git --git-dir=$clone_dir/.git --work-tree=$clone_dir "$@"
175 } 175 }
176 176
177 # Clone if it doesn't already exist. 177 # Clone if it doesn't already exist.
178 if [[ ! -d $clone_dir ]]; then 178 if [[ ! -d $clone_dir ]]; then
179 git clone "${url%|*}" "$clone_dir" 179 git clone "${url%|*}" "$clone_dir"
180 elif $update; then 180 elif $update; then
181 # Save current revision. 181 # Save current revision.
182 local old_rev="$(--plugin-git rev-parse HEAD)" 182 local old_rev="$(--plugin-git rev-parse HEAD)"
183 # Pull changes if update requested. 183 # Pull changes if update requested.
184 --plugin-git pull 184 --plugin-git pull
185 # Get the new revision. 185 # Get the new revision.
186 local new_rev="$(--plugin-git rev-parse HEAD)" 186 local new_rev="$(--plugin-git rev-parse HEAD)"
187 fi 187 fi
188 188
189 # If its a specific branch that we want, checkout that branch. 189 # If its a specific branch that we want, checkout that branch.
190 if [[ $url == *\|* ]]; then 190 if [[ $url == *\|* ]]; then
191 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/} 191 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/}
192 local requested_branch="${url#*|}" 192 local requested_branch="${url#*|}"
193 # Only do the checkout when we are not already on the branch. 193 # Only do the checkout when we are not already on the branch.
194 [[ $requested_branch != $current_branch ]] && 194 [[ $requested_branch != $current_branch ]] &&
195 --plugin-git checkout $requested_branch 195 --plugin-git checkout $requested_branch
196 fi 196 fi
197 197
198 if ! [[ -z $old_rev || $old_rev == $new_rev ]]; then 198 if ! [[ -z $old_rev || $old_rev == $new_rev ]]; then
199 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}. 199 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}.
200 if $verbose; then 200 if $verbose; then
201 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..' 201 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..'
202 fi 202 fi
203 fi 203 fi
204 204
205 # Remove the temporary git wrapper function. 205 # Remove the temporary git wrapper function.
206 unfunction -- --plugin-git 206 unfunction -- --plugin-git
207 207
208 } 208 }
209 209
210 -antigen-load () { 210 -antigen-load () {
211 211
212 local url="$1" 212 local url="$1"
213 local loc="$2" 213 local loc="$2"
214 local btype="$3" 214 local btype="$3"
215 local make_local_clone="$4" 215 local make_local_clone="$4"
216 216
217 # The full location where the plugin is located. 217 # The full location where the plugin is located.
218 local location 218 local location
219 if $make_local_clone; then 219 if $make_local_clone; then
220 location="$(-antigen-get-clone-dir "$url")/$loc" 220 location="$(-antigen-get-clone-dir "$url")/$loc"
221 else 221 else
222 location="$url" 222 location="$url"
223 fi 223 fi
224 224
225 if [[ $btype == theme ]]; then 225 if [[ $btype == theme ]]; then
226 226
227 # Of course, if its a theme, the location would point to the script 227 # Of course, if its a theme, the location would point to the script
228 # file. 228 # file.
229 source "$location" 229 source "$location"
230 230
231 else 231 else
232 232
233 # Source the plugin script. 233 # Source the plugin script.
234 # FIXME: I don't know. Looks very very ugly. Needs a better 234 # FIXME: I don't know. Looks very very ugly. Needs a better
235 # implementation once tests are ready. 235 # implementation once tests are ready.
236 local script_loc="$(ls "$location" | grep -m1 '\.plugin\.zsh$')" 236 local script_loc="$(ls "$location" | grep -m1 '\.plugin\.zsh$')"
237 237
238 if [[ -f $script_loc ]]; then 238 if [[ -f $script_loc ]]; then
239 # If we have a `*.plugin.zsh`, source it. 239 # If we have a `*.plugin.zsh`, source it.
240 source "$script_loc" 240 source "$script_loc"
241 241
242 elif [[ ! -z "$(ls "$location" | grep -m1 '\.zsh$')" ]]; then 242 elif [[ ! -z "$(ls "$location" | grep -m1 '\.zsh$')" ]]; then
243 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh` 243 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh`
244 # files. 244 # files.
245 for script ($location/*.zsh(N)) source "$script" 245 for script ($location/*.zsh(N)) source "$script"
246 246
247 elif [[ ! -z "$(ls "$location" | grep -m1 '\.sh$')" ]]; then 247 elif [[ ! -z "$(ls "$location" | grep -m1 '\.sh$')" ]]; then
248 # If there are no `*.zsh` files either, we look for and source any 248 # If there are no `*.zsh` files either, we look for and source any
249 # `*.sh` files instead. 249 # `*.sh` files instead.
250 for script ($location/*.sh(N)) source "$script" 250 for script ($location/*.sh(N)) source "$script"
251 251
252 fi 252 fi
253 253
254 # Add to $fpath, for completion(s). 254 # Add to $fpath, for completion(s).
255 fpath=($location $fpath) 255 fpath=($location $fpath)
256 256
257 fi 257 fi
258 258
259 } 259 }
260 260
261 antigen-cleanup () { 261 antigen-cleanup () {
262 262
263 # Cleanup unused repositories. 263 # Cleanup unused repositories.
264 264
265 local force=false 265 local force=false
266 if [[ $1 == --force ]]; then 266 if [[ $1 == --force ]]; then
267 force=true 267 force=true
268 fi 268 fi
269 269
270 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then 270 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then
271 echo "You don't have any bundles." 271 echo "You don't have any bundles."
272 return 0 272 return 0
273 fi 273 fi
274 274
275 # Find directores in ADOTDIR/repos, that are not in the bundles record. 275 # Find directores in ADOTDIR/repos, that are not in the bundles record.
276 local unused_clones="$(comm -13 \ 276 local unused_clones="$(comm -13 \
277 <(-antigen-echo-record | 277 <(-antigen-echo-record |
278 awk '$4 == "true" {print $1}' | 278 awk '$4 == "true" {print $1}' |
279 while read line; do 279 while read line; do
280 -antigen-get-clone-dir "$line" 280 -antigen-get-clone-dir "$line"
281 done | 281 done |
282 sort -u) \ 282 sort -u) \
283 <(ls -d "$ADOTDIR/repos/"* | sort -u))" 283 <(ls -d "$ADOTDIR/repos/"* | sort -u))"
284 284
285 if [[ -z $unused_clones ]]; then 285 if [[ -z $unused_clones ]]; then
286 echo "You don't have any unidentified bundles." 286 echo "You don't have any unidentified bundles."
287 return 0 287 return 0
288 fi 288 fi
289 289
290 echo 'You have clones for the following repos, but are not used.' 290 echo 'You have clones for the following repos, but are not used.'
291 echo "$unused_clones" | 291 echo "$unused_clones" |
292 while read line; do 292 while read line; do
293 -antigen-get-clone-url "$line" 293 -antigen-get-clone-url "$line"
294 done | 294 done |
295 sed -e 's/^/ /' -e 's/|/, branch /' 295 sed -e 's/^/ /' -e 's/|/, branch /'
296 296
297 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then 297 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then
298 echo 298 echo
299 echo 299 echo
300 echo "$unused_clones" | while read line; do 300 echo "$unused_clones" | while read line; do
301 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..." 301 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..."
302 rm -rf "$line" 302 rm -rf "$line"
303 echo ' done.' 303 echo ' done.'
304 done 304 done
305 else 305 else
306 echo 306 echo
307 echo Nothing deleted. 307 echo Nothing deleted.
308 fi 308 fi
309 } 309 }
310 310
311 antigen-lib () { 311 antigen-lib () {
312 antigen-bundle --loc=lib 312 antigen-bundle --loc=lib
313 } 313 }
314 314
315 antigen-theme () { 315 antigen-theme () {
316 local name="${1:-robbyrussell}" 316 local name="${1:-robbyrussell}"
317 antigen-bundle --loc=themes/$name.zsh-theme --btype=theme 317 antigen-bundle --loc=themes/$name.zsh-theme --btype=theme
318 } 318 }
319 319
320 antigen-apply () { 320 antigen-apply () {
321 # Initialize completion. 321 # Initialize completion.
322 # TODO: Only load completions if there are any changes to the bundle 322 # TODO: Only load completions if there are any changes to the bundle
323 # repositories. 323 # repositories.
324 compinit -i 324 compinit -i
325 } 325 }
326 326
327 antigen-list () { 327 antigen-list () {
328 # List all currently installed bundles. 328 # List all currently installed bundles.
329 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then 329 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then
330 echo "You don't have any bundles." >&2 330 echo "You don't have any bundles." >&2
331 return 1 331 return 1
332 else 332 else
333 -antigen-echo-record | sort -u 333 -antigen-echo-record | sort -u
334 fi 334 fi
335 } 335 }
336 336
337 antigen-help () { 337 antigen-help () {
338 cat <<EOF 338 cat <<EOF
339 Antigen is a plugin management system for zsh. It makes it easy to grab awesome 339 Antigen is a plugin management system for zsh. It makes it easy to grab awesome
340 shell scripts and utilities, put up on github. For further details and complete 340 shell scripts and utilities, put up on github. For further details and complete
341 documentation, visit the project's page at 'http://antigen.sharats.me'. 341 documentation, visit the project's page at 'http://antigen.sharats.me'.
342 EOF 342 EOF
343 } 343 }
344 344
345 # A syntax sugar to avoid the `-` when calling antigen commands. With this 345 # A syntax sugar to avoid the `-` when calling antigen commands. With this
346 # function, you can write `antigen-bundle` as `antigen bundle` and so on. 346 # function, you can write `antigen-bundle` as `antigen bundle` and so on.
347 antigen () { 347 antigen () {
348 local cmd="$1" 348 local cmd="$1"
349 shift 349 shift
350 "antigen-$cmd" "$@" 350 "antigen-$cmd" "$@"
351 } 351 }
352 352
353 -antigen-parse-args () { 353 -antigen-parse-args () {
354 # An argument parsing functionality to parse arguments the *antigen* way :). 354 # An argument parsing functionality to parse arguments the *antigen* way :).
355 # Takes one first argument (called spec), which dictates how to parse and 355 # Takes one first argument (called spec), which dictates how to parse and
356 # the rest of the arguments are parsed. Outputs a piece of valid shell code 356 # the rest of the arguments are parsed. Outputs a piece of valid shell code
357 # that can be passed to `eval` inside a function which creates the arguments 357 # that can be passed to `eval` inside a function which creates the arguments
358 # and their values as local variables. Suggested use is to set the defaults 358 # and their values as local variables. Suggested use is to set the defaults
359 # to all arguments first and then eval the output of this function. 359 # to all arguments first and then eval the output of this function.
360 360
361 # Spec: Only long argument supported. No support for parsing short options. 361 # Spec: Only long argument supported. No support for parsing short options.
362 # The spec must have two sections, separated by a `;`. 362 # The spec must have two sections, separated by a `;`.
363 # '<positional-arguments>;<keyword-only-arguments>' 363 # '<positional-arguments>;<keyword-only-arguments>'
364 # Positional arguments are passed as just values, like `command a b`. 364 # Positional arguments are passed as just values, like `command a b`.
365 # Keyword arguments are passed as a `--name=value` pair, like `command 365 # Keyword arguments are passed as a `--name=value` pair, like `command
366 # --arg1=a --arg2=b`. 366 # --arg1=a --arg2=b`.
367 367
368 # Each argument in the spec is separated by a `,`. Each keyword argument can 368 # Each argument in the spec is separated by a `,`. Each keyword argument can
369 # end in a `:` to specifiy that this argument wants a value, otherwise it 369 # end in a `:` to specifiy that this argument wants a value, otherwise it
370 # doesn't take a value. (The value in the output when the keyword argument 370 # doesn't take a value. (The value in the output when the keyword argument
371 # doesn't have a `:` is `true`). 371 # doesn't have a `:` is `true`).
372 372
373 # Arguments in either section can end with a `?` (should come after `:`, if 373 # Arguments in either section can end with a `?` (should come after `:`, if
374 # both are present), means optional. FIXME: Not yet implemented. 374 # both are present), means optional. FIXME: Not yet implemented.
375 375
376 # See the test file, tests/arg-parser.t for (working) examples. 376 # See the test file, tests/arg-parser.t for (working) examples.
377 377
378 local spec="$1" 378 local spec="$1"
379 shift 379 shift
380 380
381 # Sanitize the spec 381 # Sanitize the spec
382 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')" 382 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')"
383 383
384 local code='' 384 local code=''
385 385
386 --add-var () { 386 --add-var () {
387 test -z "$code" || code="$code\n" 387 test -z "$code" || code="$code\n"
388 code="${code}local $1='$2'" 388 code="${code}local $1='$2'"
389 } 389 }
390 390
391 local positional_args="$(echo "$spec" | cut -d\; -f1)" 391 local positional_args="$(echo "$spec" | cut -d\; -f1)"
392 local positional_args_count="$(echo $positional_args | 392 local positional_args_count="$(echo $positional_args |
393 awk -F, '{print NF}')" 393 awk -F, '{print NF}')"
394 394
395 # Set spec values based on the positional arguments. 395 # Set spec values based on the positional arguments.
396 local i=1 396 local i=1
397 while ! [[ -z $1 || $1 == --* ]]; do 397 while ! [[ -z $1 || $1 == --* ]]; do
398 398
399 if (( $i > $positional_args_count )); then 399 if (( $i > $positional_args_count )); then
400 echo "Only $positional_args_count positional arguments allowed." >&2 400 echo "Only $positional_args_count positional arguments allowed." >&2
401 echo "Found at least one more: '$1'" >&2 401 echo "Found at least one more: '$1'" >&2
402 return 402 return
403 fi 403 fi
404 404
405 local name_spec="$(echo "$positional_args" | cut -d, -f$i)" 405 local name_spec="$(echo "$positional_args" | cut -d, -f$i)"
406 local name="${${name_spec%\?}%:}" 406 local name="${${name_spec%\?}%:}"
407 local value="$1" 407 local value="$1"
408 408
409 if echo "$code" | grep -qm1 "^local $name="; then 409 if echo "$code" | grep -qm1 "^local $name="; then
410 echo "Argument '$name' repeated with the value '$value'". >&2 410 echo "Argument '$name' repeated with the value '$value'". >&2
411 return 411 return
412 fi 412 fi
413 413
414 --add-var $name "$value" 414 --add-var $name "$value"
415 415
416 shift 416 shift
417 i=$(($i + 1)) 417 i=$(($i + 1))
418 done 418 done
419 419
420 local keyword_args="$( 420 local keyword_args="$(
421 # Positional arguments can double up as keyword arguments too. 421 # Positional arguments can double up as keyword arguments too.
422 echo "$positional_args" | tr , '\n' | 422 echo "$positional_args" | tr , '\n' |
423 while read line; do 423 while read line; do
424 if [[ $line == *\? ]]; then 424 if [[ $line == *\? ]]; then
425 echo "${line%?}:?" 425 echo "${line%?}:?"
426 else 426 else
427 echo "$line:" 427 echo "$line:"
428 fi 428 fi
429 done 429 done
430 430
431 # Specified keyword arguments. 431 # Specified keyword arguments.
432 echo "$spec" | cut -d\; -f2 | tr , '\n' 432 echo "$spec" | cut -d\; -f2 | tr , '\n'
433 )" 433 )"
434 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')" 434 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')"
435 435
436 # Set spec values from keyword arguments, if any. The remaining arguments 436 # Set spec values from keyword arguments, if any. The remaining arguments
437 # are all assumed to be keyword arguments. 437 # are all assumed to be keyword arguments.
438 while [[ $1 == --* ]]; do 438 while [[ $1 == --* ]]; do
439 # Remove the `--` at the start. 439 # Remove the `--` at the start.
440 local arg="${1#--}" 440 local arg="${1#--}"
441 441
442 # Get the argument name and value. 442 # Get the argument name and value.
443 if [[ $arg != *=* ]]; then 443 if [[ $arg != *=* ]]; then
444 local name="$arg" 444 local name="$arg"
445 local value='' 445 local value=''
446 else 446 else
447 local name="${arg%\=*}" 447 local name="${arg%\=*}"
448 local value="${arg#*=}" 448 local value="${arg#*=}"
449 fi 449 fi
450 450
451 if echo "$code" | grep -qm1 "^local $name="; then 451 if echo "$code" | grep -qm1 "^local $name="; then
452 echo "Argument '$name' repeated with the value '$value'". >&2 452 echo "Argument '$name' repeated with the value '$value'". >&2
453 return 453 return
454 fi 454 fi
455 455
456 # The specification for this argument, used for validations. 456 # The specification for this argument, used for validations.
457 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")" 457 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")"
458 458
459 # Validate argument and value. 459 # Validate argument and value.
460 if [[ -z $arg_line ]]; then 460 if [[ -z $arg_line ]]; then
461 # This argument is not known to us. 461 # This argument is not known to us.
462 echo "Unknown argument '$name'." >&2 462 echo "Unknown argument '$name'." >&2
463 return 463 return
464 464
465 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then 465 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then
466 # This argument needs a value, but is not provided. 466 # This argument needs a value, but is not provided.
467 echo "Required argument for '$name' not provided." >&2 467 echo "Required argument for '$name' not provided." >&2
468 return 468 return
469 469
470 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then 470 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then
471 # This argument doesn't need a value, but is provided. 471 # This argument doesn't need a value, but is provided.
472 echo "No argument required for '$name', but provided '$value'." >&2 472 echo "No argument required for '$name', but provided '$value'." >&2
473 return 473 return
474 474
475 fi 475 fi
476 476
477 if [[ -z $value ]]; then 477 if [[ -z $value ]]; then
478 value=true 478 value=true
479 fi 479 fi
480 480
481 --add-var "${name//-/_}" "$value" 481 --add-var "${name//-/_}" "$value"
482 shift 482 shift
483 done 483 done
484 484
485 echo "$code" 485 echo "$code"
486 486
487 unfunction -- --add-var 487 unfunction -- --add-var
488 488
489 } 489 }
490 490
491 # Echo the bundle specs as in the record. The first line is not echoed since it 491 # Echo the bundle specs as in the record. The first line is not echoed since it
492 # is a blank line. 492 # is a blank line.
493 -antigen-echo-record () { 493 -antigen-echo-record () {
494 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p' 494 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p'
495 } 495 }
496 496
497 -antigen-env-setup () { 497 -antigen-env-setup () {
498 # Pre-startup initializations. 498 # Pre-startup initializations.
499 -set-default ANTIGEN_DEFAULT_REPO_URL \ 499 -set-default ANTIGEN_DEFAULT_REPO_URL \
500 https://github.com/robbyrussell/oh-my-zsh.git 500 https://github.com/robbyrussell/oh-my-zsh.git
501 -set-default ADOTDIR $HOME/.antigen 501 -set-default ADOTDIR $HOME/.antigen
502 502
503 # Load the compinit module. 503 # Load the compinit module.
504 autoload -U compinit 504 autoload -U compinit
505 505
506 # Without the following, `compdef` function is not defined. 506 # Without the following, `compdef` function is not defined.
507 compinit -i 507 compinit -i
508
509 compdef _antigen antigen
508 } 510 }
509 511
510 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is 512 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is
511 # not already set. 513 # not already set.
512 -set-default () { 514 -set-default () {
513 local arg_name="$1" 515 local arg_name="$1"
514 local arg_value="$2" 516 local arg_value="$2"
515 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'" 517 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'"
516 } 518 }
517 519
518 # Setup antigen's autocompletion 520 # Setup antigen's autocompletion
519 _antigen () { 521 _antigen () {
520 compadd \ 522 compadd \
521 bundle\ 523 bundle\
522 bundles\ 524 bundles\
523 update\ 525 update\
524 revert\ 526 revert\
525 list\ 527 list\
526 cleanup\ 528 cleanup\
527 lib\ 529 lib\
528 theme\ 530 theme\
529 apply\ 531 apply\
530 help 532 help
531 } 533 }
532 534
533 compdef _antigen antigen
534