Commit 3e518778228e47d131cf8a5aa9eab7284831adea

Authored by ChangZhuo Chen
1 parent 01aae9e3ba

Let antigen-selfupdate works when in submodule

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

1 # Antigen: A simple plugin manager for zsh 1 # Antigen: A simple plugin manager for zsh
2 # Authors: Shrikant Sharat Kandula 2 # Authors: Shrikant Sharat Kandula
3 # and Contributors <https://github.com/zsh-users/antigen/contributors> 3 # and Contributors <https://github.com/zsh-users/antigen/contributors>
4 # Homepage: http://antigen.sharats.me 4 # Homepage: http://antigen.sharats.me
5 # License: MIT License <mitl.sharats.me> 5 # License: MIT License <mitl.sharats.me>
6 6
7 # Each line in this string has the following entries separated by a space 7 # Each line in this string has the following entries separated by a space
8 # character. 8 # character.
9 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone> 9 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone>
10 # FIXME: Is not kept local by zsh! 10 # FIXME: Is not kept local by zsh!
11 local _ANTIGEN_BUNDLE_RECORD="" 11 local _ANTIGEN_BUNDLE_RECORD=""
12 local _ANTIGEN_INSTALL_DIR="$(cd "$(dirname "$0")" && pwd)" 12 local _ANTIGEN_INSTALL_DIR="$(cd "$(dirname "$0")" && pwd)"
13 13
14 # Used to defer compinit/compdef 14 # Used to defer compinit/compdef
15 typeset -a __deferred_compdefs 15 typeset -a __deferred_compdefs
16 compdef () { __deferred_compdefs=($__deferred_compdefs "$*") } 16 compdef () { __deferred_compdefs=($__deferred_compdefs "$*") }
17 17
18 # Syntaxes 18 # Syntaxes
19 # antigen-bundle <url> [<loc>=/] 19 # antigen-bundle <url> [<loc>=/]
20 # Keyword only arguments: 20 # Keyword only arguments:
21 # branch - The branch of the repo to use for this bundle. 21 # branch - The branch of the repo to use for this bundle.
22 antigen-bundle () { 22 antigen-bundle () {
23 23
24 # Bundle spec arguments' default values. 24 # Bundle spec arguments' default values.
25 local url="$ANTIGEN_DEFAULT_REPO_URL" 25 local url="$ANTIGEN_DEFAULT_REPO_URL"
26 local loc=/ 26 local loc=/
27 local branch= 27 local branch=
28 local no_local_clone=false 28 local no_local_clone=false
29 local btype=plugin 29 local btype=plugin
30 30
31 # Parse the given arguments. (Will overwrite the above values). 31 # Parse the given arguments. (Will overwrite the above values).
32 eval "$(-antigen-parse-args \ 32 eval "$(-antigen-parse-args \
33 'url?, loc? ; branch:?, no-local-clone?, btype:?' \ 33 'url?, loc? ; branch:?, no-local-clone?, btype:?' \
34 "$@")" 34 "$@")"
35 35
36 # Check if url is just the plugin name. Super short syntax. 36 # Check if url is just the plugin name. Super short syntax.
37 if [[ "$url" != */* ]]; then 37 if [[ "$url" != */* ]]; then
38 loc="plugins/$url" 38 loc="plugins/$url"
39 url="$ANTIGEN_DEFAULT_REPO_URL" 39 url="$ANTIGEN_DEFAULT_REPO_URL"
40 fi 40 fi
41 41
42 # Resolve the url. 42 # Resolve the url.
43 url="$(-antigen-resolve-bundle-url "$url")" 43 url="$(-antigen-resolve-bundle-url "$url")"
44 44
45 # Add the branch information to the url. 45 # Add the branch information to the url.
46 if [[ ! -z $branch ]]; then 46 if [[ ! -z $branch ]]; then
47 url="$url|$branch" 47 url="$url|$branch"
48 fi 48 fi
49 49
50 # The `make_local_clone` variable better represents whether there should be 50 # The `make_local_clone` variable better represents whether there should be
51 # a local clone made. For cloning to be avoided, firstly, the `$url` should 51 # a local clone made. For cloning to be avoided, firstly, the `$url` should
52 # be an absolute local path and `$branch` should be empty. In addition to 52 # be an absolute local path and `$branch` should be empty. In addition to
53 # these two conditions, either the `--no-local-clone` option should be 53 # these two conditions, either the `--no-local-clone` option should be
54 # given, or `$url` should not a git repo. 54 # given, or `$url` should not a git repo.
55 local make_local_clone=true 55 local make_local_clone=true
56 if [[ $url == /* && -z $branch && 56 if [[ $url == /* && -z $branch &&
57 ( $no_local_clone == true || ! -d $url/.git ) ]]; then 57 ( $no_local_clone == true || ! -d $url/.git ) ]]; then
58 make_local_clone=false 58 make_local_clone=false
59 fi 59 fi
60 60
61 # Add the theme extension to `loc`, if this is a theme. 61 # Add the theme extension to `loc`, if this is a theme.
62 if [[ $btype == theme && $loc != *.zsh-theme ]]; then 62 if [[ $btype == theme && $loc != *.zsh-theme ]]; then
63 loc="$loc.zsh-theme" 63 loc="$loc.zsh-theme"
64 fi 64 fi
65 65
66 # Add it to the record. 66 # Add it to the record.
67 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype" 67 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype"
68 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone" 68 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone"
69 69
70 # Ensure a clone exists for this repo, if needed. 70 # Ensure a clone exists for this repo, if needed.
71 if $make_local_clone; then 71 if $make_local_clone; then
72 -antigen-ensure-repo "$url" 72 -antigen-ensure-repo "$url"
73 fi 73 fi
74 74
75 # Load the plugin. 75 # Load the plugin.
76 -antigen-load "$url" "$loc" "$btype" "$make_local_clone" 76 -antigen-load "$url" "$loc" "$btype" "$make_local_clone"
77 77
78 } 78 }
79 79
80 -antigen-resolve-bundle-url () { 80 -antigen-resolve-bundle-url () {
81 # Given an acceptable short/full form of a bundle's repo url, this function 81 # Given an acceptable short/full form of a bundle's repo url, this function
82 # echoes the full form of the repo's clone url. 82 # echoes the full form of the repo's clone url.
83 83
84 local url="$1" 84 local url="$1"
85 85
86 # Expand short github url syntax: `username/reponame`. 86 # Expand short github url syntax: `username/reponame`.
87 if [[ $url != git://* && 87 if [[ $url != git://* &&
88 $url != https://* && 88 $url != https://* &&
89 $url != /* && 89 $url != /* &&
90 $url != git@github.com:*/* 90 $url != git@github.com:*/*
91 ]]; then 91 ]]; then
92 url="https://github.com/${url%.git}.git" 92 url="https://github.com/${url%.git}.git"
93 fi 93 fi
94 94
95 echo "$url" 95 echo "$url"
96 } 96 }
97 97
98 antigen-bundles () { 98 antigen-bundles () {
99 # Bulk add many bundles at one go. Empty lines and lines starting with a `#` 99 # Bulk add many bundles at one go. Empty lines and lines starting with a `#`
100 # are ignored. Everything else is given to `antigen-bundle` as is, no 100 # are ignored. Everything else is given to `antigen-bundle` as is, no
101 # quoting rules applied. 101 # quoting rules applied.
102 102
103 local line 103 local line
104 104
105 grep '^[[:space:]]*[^[:space:]#]' | while read line; do 105 grep '^[[:space:]]*[^[:space:]#]' | while read line; do
106 # Using `eval` so that we can use the shell-style quoting in each line 106 # Using `eval` so that we can use the shell-style quoting in each line
107 # piped to `antigen-bundles`. 107 # piped to `antigen-bundles`.
108 eval "antigen-bundle $line" 108 eval "antigen-bundle $line"
109 done 109 done
110 } 110 }
111 111
112 antigen-update () { 112 antigen-update () {
113 # Update your bundles, i.e., `git pull` in all the plugin repos. 113 # Update your bundles, i.e., `git pull` in all the plugin repos.
114 114
115 date > $ADOTDIR/revert-info 115 date > $ADOTDIR/revert-info
116 116
117 -antigen-echo-record | 117 -antigen-echo-record |
118 awk '$4 == "true" {print $1}' | 118 awk '$4 == "true" {print $1}' |
119 sort -u | 119 sort -u |
120 while read url; do 120 while read url; do
121 echo "**** Pulling $url" 121 echo "**** Pulling $url"
122 122
123 local clone_dir="$(-antigen-get-clone-dir "$url")" 123 local clone_dir="$(-antigen-get-clone-dir "$url")"
124 if [[ -d "$clone_dir" ]]; then 124 if [[ -d "$clone_dir" ]]; then
125 (echo -n "$clone_dir:" 125 (echo -n "$clone_dir:"
126 cd "$clone_dir" 126 cd "$clone_dir"
127 git rev-parse HEAD) >> $ADOTDIR/revert-info 127 git rev-parse HEAD) >> $ADOTDIR/revert-info
128 fi 128 fi
129 129
130 -antigen-ensure-repo "$url" --update --verbose 130 -antigen-ensure-repo "$url" --update --verbose
131 131
132 echo 132 echo
133 done 133 done
134 } 134 }
135 135
136 antigen-revert () { 136 antigen-revert () {
137 if [[ -f $ADOTDIR/revert-info ]]; then 137 if [[ -f $ADOTDIR/revert-info ]]; then
138 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do 138 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do
139 dir="$(echo "$line" | cut -d: -f1)" 139 dir="$(echo "$line" | cut -d: -f1)"
140 git --git-dir="$dir/.git" --work-tree="$dir" \ 140 git --git-dir="$dir/.git" --work-tree="$dir" \
141 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null 141 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null
142 142
143 done 143 done
144 144
145 echo "Reverted to state before running -update on $( 145 echo "Reverted to state before running -update on $(
146 cat $ADOTDIR/revert-info | sed -n 1p)." 146 cat $ADOTDIR/revert-info | sed -n 1p)."
147 147
148 else 148 else
149 echo 'No revert information available. Cannot revert.' >&2 149 echo 'No revert information available. Cannot revert.' >&2
150 fi 150 fi
151 151
152 152
153 } 153 }
154 154
155 -antigen-get-clone-dir () { 155 -antigen-get-clone-dir () {
156 # Takes a repo url and gives out the path that this url needs to be cloned 156 # Takes a repo url and gives out the path that this url needs to be cloned
157 # to. Doesn't actually clone anything. 157 # to. Doesn't actually clone anything.
158 echo -n $ADOTDIR/repos/ 158 echo -n $ADOTDIR/repos/
159 159
160 if [[ "$1" == "https://github.com/sorin-ionescu/prezto.git" ]]; then 160 if [[ "$1" == "https://github.com/sorin-ionescu/prezto.git" ]]; then
161 # Prezto's directory *has* to be `.zprezto`. 161 # Prezto's directory *has* to be `.zprezto`.
162 echo .zprezto 162 echo .zprezto
163 163
164 else 164 else
165 echo "$1" | sed \ 165 echo "$1" | sed \
166 -e 's./.-SLASH-.g' \ 166 -e 's./.-SLASH-.g' \
167 -e 's.:.-COLON-.g' \ 167 -e 's.:.-COLON-.g' \
168 -e 's.|.-PIPE-.g' 168 -e 's.|.-PIPE-.g'
169 169
170 fi 170 fi
171 } 171 }
172 172
173 -antigen-get-clone-url () { 173 -antigen-get-clone-url () {
174 # Takes a repo's clone dir and gives out the repo's original url that was 174 # Takes a repo's clone dir and gives out the repo's original url that was
175 # used to create the given directory path. 175 # used to create the given directory path.
176 176
177 if [[ "$1" == ".zprezto" ]]; then 177 if [[ "$1" == ".zprezto" ]]; then
178 # Prezto's (in `.zprezto`), is assumed to be from `sorin-ionescu`'s 178 # Prezto's (in `.zprezto`), is assumed to be from `sorin-ionescu`'s
179 # remote. 179 # remote.
180 echo https://github.com/sorin-ionescu/prezto.git 180 echo https://github.com/sorin-ionescu/prezto.git
181 181
182 else 182 else
183 echo "$1" | sed \ 183 echo "$1" | sed \
184 -e "s:^$ADOTDIR/repos/::" \ 184 -e "s:^$ADOTDIR/repos/::" \
185 -e 's.-SLASH-./.g' \ 185 -e 's.-SLASH-./.g' \
186 -e 's.-COLON-.:.g' \ 186 -e 's.-COLON-.:.g' \
187 -e 's.-PIPE-.|.g' 187 -e 's.-PIPE-.|.g'
188 188
189 fi 189 fi
190 } 190 }
191 191
192 -antigen-ensure-repo () { 192 -antigen-ensure-repo () {
193 193
194 # Ensure that a clone exists for the given repo url and branch. If the first 194 # Ensure that a clone exists for the given repo url and branch. If the first
195 # argument is `--update` and if a clone already exists for the given repo 195 # argument is `--update` and if a clone already exists for the given repo
196 # and branch, it is pull-ed, i.e., updated. 196 # and branch, it is pull-ed, i.e., updated.
197 197
198 # Argument defaults. 198 # Argument defaults.
199 # The url. No sane default for this, so just empty. 199 # The url. No sane default for this, so just empty.
200 local url= 200 local url=
201 # Check if we have to update. 201 # Check if we have to update.
202 local update=false 202 local update=false
203 # Verbose output. 203 # Verbose output.
204 local verbose=false 204 local verbose=false
205 205
206 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")" 206 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")"
207 shift $# 207 shift $#
208 208
209 # Get the clone's directory as per the given repo url and branch. 209 # Get the clone's directory as per the given repo url and branch.
210 local clone_dir="$(-antigen-get-clone-dir $url)" 210 local clone_dir="$(-antigen-get-clone-dir $url)"
211 211
212 # A temporary function wrapping the `git` command with repeated arguments. 212 # A temporary function wrapping the `git` command with repeated arguments.
213 --plugin-git () { 213 --plugin-git () {
214 (cd "$clone_dir" && git --no-pager "$@") 214 (cd "$clone_dir" && git --no-pager "$@")
215 } 215 }
216 216
217 # Clone if it doesn't already exist. 217 # Clone if it doesn't already exist.
218 if [[ ! -d $clone_dir ]]; then 218 if [[ ! -d $clone_dir ]]; then
219 git clone --recursive "${url%|*}" "$clone_dir" 219 git clone --recursive "${url%|*}" "$clone_dir"
220 elif $update; then 220 elif $update; then
221 # Save current revision. 221 # Save current revision.
222 local old_rev="$(--plugin-git rev-parse HEAD)" 222 local old_rev="$(--plugin-git rev-parse HEAD)"
223 # Pull changes if update requested. 223 # Pull changes if update requested.
224 --plugin-git pull 224 --plugin-git pull
225 # Update submodules. 225 # Update submodules.
226 --plugin-git submodule update --recursive 226 --plugin-git submodule update --recursive
227 # Get the new revision. 227 # Get the new revision.
228 local new_rev="$(--plugin-git rev-parse HEAD)" 228 local new_rev="$(--plugin-git rev-parse HEAD)"
229 fi 229 fi
230 230
231 # If its a specific branch that we want, checkout that branch. 231 # If its a specific branch that we want, checkout that branch.
232 if [[ $url == *\|* ]]; then 232 if [[ $url == *\|* ]]; then
233 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/} 233 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/}
234 local requested_branch="${url#*|}" 234 local requested_branch="${url#*|}"
235 # Only do the checkout when we are not already on the branch. 235 # Only do the checkout when we are not already on the branch.
236 [[ $requested_branch != $current_branch ]] && 236 [[ $requested_branch != $current_branch ]] &&
237 --plugin-git checkout $requested_branch 237 --plugin-git checkout $requested_branch
238 fi 238 fi
239 239
240 if [[ -n $old_rev && $old_rev != $new_rev ]]; then 240 if [[ -n $old_rev && $old_rev != $new_rev ]]; then
241 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}. 241 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}.
242 if $verbose; then 242 if $verbose; then
243 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..' 243 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..'
244 fi 244 fi
245 fi 245 fi
246 246
247 # Remove the temporary git wrapper function. 247 # Remove the temporary git wrapper function.
248 unfunction -- --plugin-git 248 unfunction -- --plugin-git
249 249
250 } 250 }
251 251
252 -antigen-load () { 252 -antigen-load () {
253 253
254 local url="$1" 254 local url="$1"
255 local loc="$2" 255 local loc="$2"
256 local btype="$3" 256 local btype="$3"
257 local make_local_clone="$4" 257 local make_local_clone="$4"
258 258
259 # The full location where the plugin is located. 259 # The full location where the plugin is located.
260 local location 260 local location
261 if $make_local_clone; then 261 if $make_local_clone; then
262 location="$(-antigen-get-clone-dir "$url")/$loc" 262 location="$(-antigen-get-clone-dir "$url")/$loc"
263 else 263 else
264 location="$url" 264 location="$url"
265 fi 265 fi
266 266
267 if [[ $btype == theme ]]; then 267 if [[ $btype == theme ]]; then
268 268
269 # Of course, if its a theme, the location would point to the script 269 # Of course, if its a theme, the location would point to the script
270 # file. 270 # file.
271 source "$location" 271 source "$location"
272 272
273 else 273 else
274 274
275 # Source the plugin script. 275 # Source the plugin script.
276 # FIXME: I don't know. Looks very very ugly. Needs a better 276 # FIXME: I don't know. Looks very very ugly. Needs a better
277 # implementation once tests are ready. 277 # implementation once tests are ready.
278 local script_loc="$(ls "$location" | grep '\.plugin\.zsh$' | head -n1)" 278 local script_loc="$(ls "$location" | grep '\.plugin\.zsh$' | head -n1)"
279 279
280 if [[ -f $location/$script_loc ]]; then 280 if [[ -f $location/$script_loc ]]; then
281 # If we have a `*.plugin.zsh`, source it. 281 # If we have a `*.plugin.zsh`, source it.
282 source "$location/$script_loc" 282 source "$location/$script_loc"
283 283
284 elif [[ -f $location/init.zsh ]]; then 284 elif [[ -f $location/init.zsh ]]; then
285 # If we have a `init.zsh` 285 # If we have a `init.zsh`
286 if (( $+functions[pmodload] )); then 286 if (( $+functions[pmodload] )); then
287 # If pmodload is defined pmodload the module. Remove `modules/` 287 # If pmodload is defined pmodload the module. Remove `modules/`
288 # from loc to find module name. 288 # from loc to find module name.
289 pmodload "${loc#modules/}" 289 pmodload "${loc#modules/}"
290 else 290 else
291 # Otherwise source it. 291 # Otherwise source it.
292 source "$location/init.zsh" 292 source "$location/init.zsh"
293 fi 293 fi
294 294
295 elif ls "$location" | grep -l '\.zsh$' &> /dev/null; then 295 elif ls "$location" | grep -l '\.zsh$' &> /dev/null; then
296 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh` 296 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh`
297 # files. 297 # files.
298 for script ($location/*.zsh(N)) source "$script" 298 for script ($location/*.zsh(N)) source "$script"
299 299
300 elif ls "$location" | grep -l '\.sh$' &> /dev/null; then 300 elif ls "$location" | grep -l '\.sh$' &> /dev/null; then
301 # If there are no `*.zsh` files either, we look for and source any 301 # If there are no `*.zsh` files either, we look for and source any
302 # `*.sh` files instead. 302 # `*.sh` files instead.
303 for script ($location/*.sh(N)) source "$script" 303 for script ($location/*.sh(N)) source "$script"
304 304
305 fi 305 fi
306 306
307 # Add to $fpath, for completion(s). 307 # Add to $fpath, for completion(s).
308 fpath=($location $fpath) 308 fpath=($location $fpath)
309 309
310 fi 310 fi
311 311
312 } 312 }
313 313
314 # Update (with `git pull`) antigen itself. 314 # Update (with `git pull`) antigen itself.
315 # TODO: Once update is finished, show a summary of the new commits, as a kind of 315 # TODO: Once update is finished, show a summary of the new commits, as a kind of
316 # "what's new" message. 316 # "what's new" message.
317 antigen-selfupdate () { 317 antigen-selfupdate () {
318 ( cd $_ANTIGEN_INSTALL_DIR 318 ( cd $_ANTIGEN_INSTALL_DIR
319 if [[ ! -d .git ]]; then 319 if [[ ! ( -d .git || -f .git ) ]]; then
320 echo "Your copy of antigen doesn't appear to be a git clone. " \ 320 echo "Your copy of antigen doesn't appear to be a git clone. " \
321 "The 'selfupdate' command cannot work in this case." 321 "The 'selfupdate' command cannot work in this case."
322 return 1 322 return 1
323 fi 323 fi
324 local head="$(git rev-parse --abbrev-ref HEAD)"
325 if [[ $head == "HEAD" ]]; then
326 # If current head is detached HEAD, checkout to master branch.
327 git checkout master
328 fi
324 git pull 329 git pull
325 ) 330 )
326 } 331 }
327 332
328 antigen-cleanup () { 333 antigen-cleanup () {
329 334
330 # Cleanup unused repositories. 335 # Cleanup unused repositories.
331 336
332 local force=false 337 local force=false
333 if [[ $1 == --force ]]; then 338 if [[ $1 == --force ]]; then
334 force=true 339 force=true
335 fi 340 fi
336 341
337 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then 342 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then
338 echo "You don't have any bundles." 343 echo "You don't have any bundles."
339 return 0 344 return 0
340 fi 345 fi
341 346
342 # Find directores in ADOTDIR/repos, that are not in the bundles record. 347 # Find directores in ADOTDIR/repos, that are not in the bundles record.
343 local unused_clones="$(comm -13 \ 348 local unused_clones="$(comm -13 \
344 <(-antigen-echo-record | 349 <(-antigen-echo-record |
345 awk '$4 == "true" {print $1}' | 350 awk '$4 == "true" {print $1}' |
346 while read line; do 351 while read line; do
347 -antigen-get-clone-dir "$line" 352 -antigen-get-clone-dir "$line"
348 done | 353 done |
349 sort -u) \ 354 sort -u) \
350 <(ls -d "$ADOTDIR/repos/"* | sort -u))" 355 <(ls -d "$ADOTDIR/repos/"* | sort -u))"
351 356
352 if [[ -z $unused_clones ]]; then 357 if [[ -z $unused_clones ]]; then
353 echo "You don't have any unidentified bundles." 358 echo "You don't have any unidentified bundles."
354 return 0 359 return 0
355 fi 360 fi
356 361
357 echo 'You have clones for the following repos, but are not used.' 362 echo 'You have clones for the following repos, but are not used.'
358 echo "$unused_clones" | 363 echo "$unused_clones" |
359 while read line; do 364 while read line; do
360 -antigen-get-clone-url "$line" 365 -antigen-get-clone-url "$line"
361 done | 366 done |
362 sed -e 's/^/ /' -e 's/|/, branch /' 367 sed -e 's/^/ /' -e 's/|/, branch /'
363 368
364 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then 369 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then
365 echo 370 echo
366 echo 371 echo
367 echo "$unused_clones" | while read line; do 372 echo "$unused_clones" | while read line; do
368 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..." 373 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..."
369 rm -rf "$line" 374 rm -rf "$line"
370 echo ' done.' 375 echo ' done.'
371 done 376 done
372 else 377 else
373 echo 378 echo
374 echo Nothing deleted. 379 echo Nothing deleted.
375 fi 380 fi
376 } 381 }
377 382
378 antigen-use () { 383 antigen-use () {
379 if [[ $1 == oh-my-zsh ]]; then 384 if [[ $1 == oh-my-zsh ]]; then
380 -antigen-use-oh-my-zsh 385 -antigen-use-oh-my-zsh
381 elif [[ $1 == prezto ]]; then 386 elif [[ $1 == prezto ]]; then
382 -antigen-use-prezto 387 -antigen-use-prezto
383 else 388 else
384 echo 'Usage: antigen-use <library-name>' >&2 389 echo 'Usage: antigen-use <library-name>' >&2
385 echo 'Where <library-name> is any one of the following:' >&2 390 echo 'Where <library-name> is any one of the following:' >&2
386 echo ' * oh-my-zsh' >&2 391 echo ' * oh-my-zsh' >&2
387 echo ' * prezto' >&2 392 echo ' * prezto' >&2
388 return 1 393 return 1
389 fi 394 fi
390 } 395 }
391 396
392 -antigen-use-oh-my-zsh () { 397 -antigen-use-oh-my-zsh () {
393 if [[ -z "$ZSH" ]]; then 398 if [[ -z "$ZSH" ]]; then
394 export ZSH="$(-antigen-get-clone-dir "$ANTIGEN_DEFAULT_REPO_URL")" 399 export ZSH="$(-antigen-get-clone-dir "$ANTIGEN_DEFAULT_REPO_URL")"
395 fi 400 fi
396 antigen-bundle --loc=lib 401 antigen-bundle --loc=lib
397 } 402 }
398 403
399 -antigen-use-prezto () { 404 -antigen-use-prezto () {
400 antigen-bundle sorin-ionescu/prezto 405 antigen-bundle sorin-ionescu/prezto
401 export ZDOTDIR=$ADOTDIR/repos/ 406 export ZDOTDIR=$ADOTDIR/repos/
402 } 407 }
403 408
404 # For backwards compatibility. 409 # For backwards compatibility.
405 antigen-lib () { 410 antigen-lib () {
406 -antigen-use-oh-my-zsh 411 -antigen-use-oh-my-zsh
407 echo '`antigen-lib` is deprecated and will soon be removed.' 412 echo '`antigen-lib` is deprecated and will soon be removed.'
408 echo 'Use `antigen-use oh-my-zsh` instead.' 413 echo 'Use `antigen-use oh-my-zsh` instead.'
409 } 414 }
410 415
411 # For backwards compatibility. 416 # For backwards compatibility.
412 antigen-prezto-lib () { 417 antigen-prezto-lib () {
413 -antigen-use-prezto 418 -antigen-use-prezto
414 echo '`antigen-prezto-lib` is deprecated and will soon be removed.' 419 echo '`antigen-prezto-lib` is deprecated and will soon be removed.'
415 echo 'Use `antigen-use prezto` instead.' 420 echo 'Use `antigen-use prezto` instead.'
416 } 421 }
417 422
418 antigen-theme () { 423 antigen-theme () {
419 424
420 if [[ "$1" != */* && "$1" != --* ]]; then 425 if [[ "$1" != */* && "$1" != --* ]]; then
421 # The first argument is just a name of the plugin, to be picked up from 426 # The first argument is just a name of the plugin, to be picked up from
422 # the default repo. 427 # the default repo.
423 local name="${1:-robbyrussell}" 428 local name="${1:-robbyrussell}"
424 antigen-bundle --loc=themes/$name --btype=theme 429 antigen-bundle --loc=themes/$name --btype=theme
425 430
426 else 431 else
427 antigen-bundle "$@" --btype=theme 432 antigen-bundle "$@" --btype=theme
428 433
429 fi 434 fi
430 435
431 } 436 }
432 437
433 antigen-apply () { 438 antigen-apply () {
434 439
435 # Initialize completion. 440 # Initialize completion.
436 local cdef 441 local cdef
437 442
438 # Load the compinit module. This will readefine the `compdef` function to 443 # Load the compinit module. This will readefine the `compdef` function to
439 # the one that actually initializes completions. 444 # the one that actually initializes completions.
440 autoload -U compinit 445 autoload -U compinit
441 compinit -i 446 compinit -i
442 447
443 # Apply all `compinit`s that have been deferred. 448 # Apply all `compinit`s that have been deferred.
444 eval "$(for cdef in $__deferred_compdefs; do 449 eval "$(for cdef in $__deferred_compdefs; do
445 echo compdef $cdef 450 echo compdef $cdef
446 done)" 451 done)"
447 452
448 unset __deferred_compdefs 453 unset __deferred_compdefs
449 454
450 } 455 }
451 456
452 antigen-list () { 457 antigen-list () {
453 # List all currently installed bundles. 458 # List all currently installed bundles.
454 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then 459 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then
455 echo "You don't have any bundles." >&2 460 echo "You don't have any bundles." >&2
456 return 1 461 return 1
457 else 462 else
458 -antigen-echo-record | sort -u 463 -antigen-echo-record | sort -u
459 fi 464 fi
460 } 465 }
461 466
462 antigen-snapshot () { 467 antigen-snapshot () {
463 468
464 local snapshot_file="${1:-antigen-shapshot}" 469 local snapshot_file="${1:-antigen-shapshot}"
465 470
466 # The snapshot content lines are pairs of repo-url and git version hash, in 471 # The snapshot content lines are pairs of repo-url and git version hash, in
467 # the form: 472 # the form:
468 # <version-hash> <repo-url> 473 # <version-hash> <repo-url>
469 local snapshot_content="$(-antigen-echo-record | 474 local snapshot_content="$(-antigen-echo-record |
470 grep 'true$' | 475 grep 'true$' |
471 sed 's/ .*$//' | 476 sed 's/ .*$//' |
472 sort -u | 477 sort -u |
473 while read url; do 478 while read url; do
474 local dir="$(-antigen-get-clone-dir "$url")" 479 local dir="$(-antigen-get-clone-dir "$url")"
475 local version_hash="$(cd "$dir" && git rev-parse HEAD)" 480 local version_hash="$(cd "$dir" && git rev-parse HEAD)"
476 echo "$version_hash $url" 481 echo "$version_hash $url"
477 done)" 482 done)"
478 483
479 { 484 {
480 # The first line in the snapshot file is for metadata, in the form: 485 # The first line in the snapshot file is for metadata, in the form:
481 # key='value'; key='value'; key='value'; 486 # key='value'; key='value'; key='value';
482 # Where `key`s are valid shell variable names. 487 # Where `key`s are valid shell variable names.
483 488
484 # Snapshot version. Has no relation to antigen version. If the snapshot 489 # Snapshot version. Has no relation to antigen version. If the snapshot
485 # file format changes, this number can be incremented. 490 # file format changes, this number can be incremented.
486 echo -n "version='1';" 491 echo -n "version='1';"
487 492
488 # Snapshot creation date+time. 493 # Snapshot creation date+time.
489 echo -n " created_on='$(date)';" 494 echo -n " created_on='$(date)';"
490 495
491 # Add a checksum with the md5 checksum of all the snapshot lines. 496 # Add a checksum with the md5 checksum of all the snapshot lines.
492 local checksum="$(echo "$snapshot_content" | md5sum)" 497 local checksum="$(echo "$snapshot_content" | md5sum)"
493 echo -n " checksum='${checksum%% *}';" 498 echo -n " checksum='${checksum%% *}';"
494 499
495 # A newline after the metadata and then the snapshot lines. 500 # A newline after the metadata and then the snapshot lines.
496 echo "\n$snapshot_content" 501 echo "\n$snapshot_content"
497 502
498 } > "$snapshot_file" 503 } > "$snapshot_file"
499 504
500 } 505 }
501 506
502 antigen-restore () { 507 antigen-restore () {
503 508
504 if [[ $# == 0 ]]; then 509 if [[ $# == 0 ]]; then
505 echo 'Please provide a snapshot file to restore from.' >&2 510 echo 'Please provide a snapshot file to restore from.' >&2
506 return 1 511 return 1
507 fi 512 fi
508 513
509 local snapshot_file="$1" 514 local snapshot_file="$1"
510 515
511 # TODO: Before doing anything with the snapshot file, verify its checksum. 516 # TODO: Before doing anything with the snapshot file, verify its checksum.
512 # If it fails, notify this to the user and confirm if restore should 517 # If it fails, notify this to the user and confirm if restore should
513 # proceed. 518 # proceed.
514 519
515 echo -n "Restoring from $snapshot_file..." 520 echo -n "Restoring from $snapshot_file..."
516 521
517 sed -n '1!p' "$snapshot_file" | 522 sed -n '1!p' "$snapshot_file" |
518 while read line; do 523 while read line; do
519 524
520 local version_hash="${line%% *}" 525 local version_hash="${line%% *}"
521 local url="${line##* }" 526 local url="${line##* }"
522 local clone_dir="$(-antigen-get-clone-dir "$url")" 527 local clone_dir="$(-antigen-get-clone-dir "$url")"
523 528
524 if [[ ! -d $clone_dir ]]; then 529 if [[ ! -d $clone_dir ]]; then
525 git clone "$url" "$clone_dir" > /dev/null 530 git clone "$url" "$clone_dir" > /dev/null
526 fi 531 fi
527 532
528 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null 533 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null
529 534
530 done 535 done
531 536
532 echo ' done.' 537 echo ' done.'
533 echo 'Please open a new shell to get the restored changes.' 538 echo 'Please open a new shell to get the restored changes.'
534 } 539 }
535 540
536 antigen-help () { 541 antigen-help () {
537 cat <<EOF 542 cat <<EOF
538 Antigen is a plugin management system for zsh. It makes it easy to grab awesome 543 Antigen is a plugin management system for zsh. It makes it easy to grab awesome
539 shell scripts and utilities, put up on github. For further details and complete 544 shell scripts and utilities, put up on github. For further details and complete
540 documentation, visit the project's page at 'http://antigen.sharats.me'. 545 documentation, visit the project's page at 'http://antigen.sharats.me'.
541 EOF 546 EOF
542 } 547 }
543 548
544 # A syntax sugar to avoid the `-` when calling antigen commands. With this 549 # A syntax sugar to avoid the `-` when calling antigen commands. With this
545 # function, you can write `antigen-bundle` as `antigen bundle` and so on. 550 # function, you can write `antigen-bundle` as `antigen bundle` and so on.
546 antigen () { 551 antigen () {
547 local cmd="$1" 552 local cmd="$1"
548 if [[ -z "$cmd" ]]; then 553 if [[ -z "$cmd" ]]; then
549 echo 'Antigen: Please give a command to run.' >&2 554 echo 'Antigen: Please give a command to run.' >&2
550 return 1 555 return 1
551 fi 556 fi
552 shift 557 shift
553 558
554 if functions "antigen-$cmd" > /dev/null; then 559 if functions "antigen-$cmd" > /dev/null; then
555 "antigen-$cmd" "$@" 560 "antigen-$cmd" "$@"
556 else 561 else
557 echo "Antigen: Unknown command: $cmd" >&2 562 echo "Antigen: Unknown command: $cmd" >&2
558 fi 563 fi
559 } 564 }
560 565
561 -antigen-parse-args () { 566 -antigen-parse-args () {
562 # An argument parsing functionality to parse arguments the *antigen* way :). 567 # An argument parsing functionality to parse arguments the *antigen* way :).
563 # Takes one first argument (called spec), which dictates how to parse and 568 # Takes one first argument (called spec), which dictates how to parse and
564 # the rest of the arguments are parsed. Outputs a piece of valid shell code 569 # the rest of the arguments are parsed. Outputs a piece of valid shell code
565 # that can be passed to `eval` inside a function which creates the arguments 570 # that can be passed to `eval` inside a function which creates the arguments
566 # and their values as local variables. Suggested use is to set the defaults 571 # and their values as local variables. Suggested use is to set the defaults
567 # to all arguments first and then eval the output of this function. 572 # to all arguments first and then eval the output of this function.
568 573
569 # Spec: Only long argument supported. No support for parsing short options. 574 # Spec: Only long argument supported. No support for parsing short options.
570 # The spec must have two sections, separated by a `;`. 575 # The spec must have two sections, separated by a `;`.
571 # '<positional-arguments>;<keyword-only-arguments>' 576 # '<positional-arguments>;<keyword-only-arguments>'
572 # Positional arguments are passed as just values, like `command a b`. 577 # Positional arguments are passed as just values, like `command a b`.
573 # Keyword arguments are passed as a `--name=value` pair, like `command 578 # Keyword arguments are passed as a `--name=value` pair, like `command
574 # --arg1=a --arg2=b`. 579 # --arg1=a --arg2=b`.
575 580
576 # Each argument in the spec is separated by a `,`. Each keyword argument can 581 # Each argument in the spec is separated by a `,`. Each keyword argument can
577 # end in a `:` to specifiy that this argument wants a value, otherwise it 582 # end in a `:` to specifiy that this argument wants a value, otherwise it
578 # doesn't take a value. (The value in the output when the keyword argument 583 # doesn't take a value. (The value in the output when the keyword argument
579 # doesn't have a `:` is `true`). 584 # doesn't have a `:` is `true`).
580 585
581 # Arguments in either section can end with a `?` (should come after `:`, if 586 # Arguments in either section can end with a `?` (should come after `:`, if
582 # both are present), means optional. FIXME: Not yet implemented. 587 # both are present), means optional. FIXME: Not yet implemented.
583 588
584 # See the test file, tests/arg-parser.t for (working) examples. 589 # See the test file, tests/arg-parser.t for (working) examples.
585 590
586 local spec="$1" 591 local spec="$1"
587 shift 592 shift
588 593
589 # Sanitize the spec 594 # Sanitize the spec
590 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')" 595 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')"
591 596
592 local code='' 597 local code=''
593 598
594 --add-var () { 599 --add-var () {
595 test -z "$code" || code="$code\n" 600 test -z "$code" || code="$code\n"
596 code="${code}local $1='$2'" 601 code="${code}local $1='$2'"
597 } 602 }
598 603
599 local positional_args="$(echo "$spec" | cut -d\; -f1)" 604 local positional_args="$(echo "$spec" | cut -d\; -f1)"
600 local positional_args_count="$(echo $positional_args | 605 local positional_args_count="$(echo $positional_args |
601 awk -F, '{print NF}')" 606 awk -F, '{print NF}')"
602 607
603 # Set spec values based on the positional arguments. 608 # Set spec values based on the positional arguments.
604 local i=1 609 local i=1
605 while [[ -n $1 && $1 != --* ]]; do 610 while [[ -n $1 && $1 != --* ]]; do
606 611
607 if (( $i > $positional_args_count )); then 612 if (( $i > $positional_args_count )); then
608 echo "Only $positional_args_count positional arguments allowed." >&2 613 echo "Only $positional_args_count positional arguments allowed." >&2
609 echo "Found at least one more: '$1'" >&2 614 echo "Found at least one more: '$1'" >&2
610 return 615 return
611 fi 616 fi
612 617
613 local name_spec="$(echo "$positional_args" | cut -d, -f$i)" 618 local name_spec="$(echo "$positional_args" | cut -d, -f$i)"
614 local name="${${name_spec%\?}%:}" 619 local name="${${name_spec%\?}%:}"
615 local value="$1" 620 local value="$1"
616 621
617 if echo "$code" | grep -l "^local $name=" &> /dev/null; then 622 if echo "$code" | grep -l "^local $name=" &> /dev/null; then
618 echo "Argument '$name' repeated with the value '$value'". >&2 623 echo "Argument '$name' repeated with the value '$value'". >&2
619 return 624 return
620 fi 625 fi
621 626
622 --add-var $name "$value" 627 --add-var $name "$value"
623 628
624 shift 629 shift
625 i=$(($i + 1)) 630 i=$(($i + 1))
626 done 631 done
627 632
628 local keyword_args="$( 633 local keyword_args="$(
629 # Positional arguments can double up as keyword arguments too. 634 # Positional arguments can double up as keyword arguments too.
630 echo "$positional_args" | tr , '\n' | 635 echo "$positional_args" | tr , '\n' |
631 while read line; do 636 while read line; do
632 if [[ $line == *\? ]]; then 637 if [[ $line == *\? ]]; then
633 echo "${line%?}:?" 638 echo "${line%?}:?"
634 else 639 else
635 echo "$line:" 640 echo "$line:"
636 fi 641 fi
637 done 642 done
638 643
639 # Specified keyword arguments. 644 # Specified keyword arguments.
640 echo "$spec" | cut -d\; -f2 | tr , '\n' 645 echo "$spec" | cut -d\; -f2 | tr , '\n'
641 )" 646 )"
642 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')" 647 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')"
643 648
644 # Set spec values from keyword arguments, if any. The remaining arguments 649 # Set spec values from keyword arguments, if any. The remaining arguments
645 # are all assumed to be keyword arguments. 650 # are all assumed to be keyword arguments.
646 while [[ $1 == --* ]]; do 651 while [[ $1 == --* ]]; do
647 # Remove the `--` at the start. 652 # Remove the `--` at the start.
648 local arg="${1#--}" 653 local arg="${1#--}"
649 654
650 # Get the argument name and value. 655 # Get the argument name and value.
651 if [[ $arg != *=* ]]; then 656 if [[ $arg != *=* ]]; then
652 local name="$arg" 657 local name="$arg"
653 local value='' 658 local value=''
654 else 659 else
655 local name="${arg%\=*}" 660 local name="${arg%\=*}"
656 local value="${arg#*=}" 661 local value="${arg#*=}"
657 fi 662 fi
658 663
659 if echo "$code" | grep -l "^local $name=" &> /dev/null; then 664 if echo "$code" | grep -l "^local $name=" &> /dev/null; then
660 echo "Argument '$name' repeated with the value '$value'". >&2 665 echo "Argument '$name' repeated with the value '$value'". >&2
661 return 666 return
662 fi 667 fi
663 668
664 # The specification for this argument, used for validations. 669 # The specification for this argument, used for validations.
665 local arg_line="$(echo "$keyword_args" | 670 local arg_line="$(echo "$keyword_args" |
666 egrep "^$name:?\??" | head -n1)" 671 egrep "^$name:?\??" | head -n1)"
667 672
668 # Validate argument and value. 673 # Validate argument and value.
669 if [[ -z $arg_line ]]; then 674 if [[ -z $arg_line ]]; then
670 # This argument is not known to us. 675 # This argument is not known to us.
671 echo "Unknown argument '$name'." >&2 676 echo "Unknown argument '$name'." >&2
672 return 677 return
673 678
674 elif (echo "$arg_line" | grep -l ':' &> /dev/null) && 679 elif (echo "$arg_line" | grep -l ':' &> /dev/null) &&
675 [[ -z $value ]]; then 680 [[ -z $value ]]; then
676 # This argument needs a value, but is not provided. 681 # This argument needs a value, but is not provided.
677 echo "Required argument for '$name' not provided." >&2 682 echo "Required argument for '$name' not provided." >&2
678 return 683 return
679 684
680 elif (echo "$arg_line" | grep -vl ':' &> /dev/null) && 685 elif (echo "$arg_line" | grep -vl ':' &> /dev/null) &&
681 [[ -n $value ]]; then 686 [[ -n $value ]]; then
682 # This argument doesn't need a value, but is provided. 687 # This argument doesn't need a value, but is provided.
683 echo "No argument required for '$name', but provided '$value'." >&2 688 echo "No argument required for '$name', but provided '$value'." >&2
684 return 689 return
685 690
686 fi 691 fi
687 692
688 if [[ -z $value ]]; then 693 if [[ -z $value ]]; then
689 value=true 694 value=true
690 fi 695 fi
691 696
692 --add-var "${name//-/_}" "$value" 697 --add-var "${name//-/_}" "$value"
693 shift 698 shift
694 done 699 done
695 700
696 echo "$code" 701 echo "$code"
697 702
698 unfunction -- --add-var 703 unfunction -- --add-var
699 704
700 } 705 }
701 706
702 # Echo the bundle specs as in the record. The first line is not echoed since it 707 # Echo the bundle specs as in the record. The first line is not echoed since it
703 # is a blank line. 708 # is a blank line.
704 -antigen-echo-record () { 709 -antigen-echo-record () {
705 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p' 710 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p'
706 } 711 }
707 712
708 -antigen-env-setup () { 713 -antigen-env-setup () {
709 714
710 # Helper function: Same as `export $1=$2`, but will only happen if the name 715 # Helper function: Same as `export $1=$2`, but will only happen if the name
711 # specified by `$1` is not already set. 716 # specified by `$1` is not already set.
712 -set-default () { 717 -set-default () {
713 local arg_name="$1" 718 local arg_name="$1"
714 local arg_value="$2" 719 local arg_value="$2"
715 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'" 720 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'"
716 } 721 }
717 722
718 # Pre-startup initializations. 723 # Pre-startup initializations.
719 -set-default ANTIGEN_DEFAULT_REPO_URL \ 724 -set-default ANTIGEN_DEFAULT_REPO_URL \
720 https://github.com/robbyrussell/oh-my-zsh.git 725 https://github.com/robbyrussell/oh-my-zsh.git
721 -set-default ADOTDIR $HOME/.antigen 726 -set-default ADOTDIR $HOME/.antigen
722 727
723 # Setup antigen's own completion. 728 # Setup antigen's own completion.
724 compdef _antigen antigen 729 compdef _antigen antigen
725 730
726 # Remove private functions. 731 # Remove private functions.
727 unfunction -- -set-default 732 unfunction -- -set-default
728 } 733 }
729 734
730 # Setup antigen's autocompletion 735 # Setup antigen's autocompletion
731 _antigen () { 736 _antigen () {
732 compadd \ 737 compadd \
733 bundle \ 738 bundle \
734 bundles \ 739 bundles \
735 update \ 740 update \
736 revert \ 741 revert \
737 list \ 742 list \
738 cleanup \ 743 cleanup \
739 use \ 744 use \
740 selfupdate \ 745 selfupdate \
741 theme \ 746 theme \
742 apply \ 747 apply \
743 snapshot \ 748 snapshot \
744 restore \ 749 restore \
745 help 750 help
746 } 751 }
747 752
748 -antigen-env-setup 753 -antigen-env-setup
749 754