Commit 687012615d40c96d482b1c3b8ef7d5aa8529e79f

Authored by Shrikant Sharat

Merge pull request #35 from kamipo/master

Fix `*.plugin.zsh` file loading.

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