Commit a54264963745656e6d4d7b71847af3f4c47360e6

Authored by Shrikant Sharat
1 parent 3e92539689

Refactorings on the selfupdate function.

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