Commit 9a97880f48d57456f7bd36e82ad5f53960dff462

Authored by Shrikant Sharat

Merge branch 'master' of github.com:zsh-users/antigen

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 ls "$location" | grep -qm1 '\.zsh$'; then 248 elif ls "$location" | grep -qm1 '\.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 ls "$location" | grep -qm1 '\.sh$'; then 253 elif ls "$location" | grep -qm1 '\.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 } 341 }
342 342
343 antigen-list () { 343 antigen-list () {
344 # List all currently installed bundles. 344 # List all currently installed bundles.
345 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then 345 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then
346 echo "You don't have any bundles." >&2 346 echo "You don't have any bundles." >&2
347 return 1 347 return 1
348 else 348 else
349 -antigen-echo-record | sort -u 349 -antigen-echo-record | sort -u
350 fi 350 fi
351 } 351 }
352 352
353 antigen-snapshot () { 353 antigen-snapshot () {
354 354
355 local snapshot_file="${1:-antigen-shapshot}" 355 local snapshot_file="${1:-antigen-shapshot}"
356 356
357 # The snapshot content lines are pairs of repo-url and git version hash, in 357 # The snapshot content lines are pairs of repo-url and git version hash, in
358 # the form: 358 # the form:
359 # <version-hash> <repo-url> 359 # <version-hash> <repo-url>
360 local snapshot_content="$(-antigen-echo-record | 360 local snapshot_content="$(-antigen-echo-record |
361 grep 'true$' | 361 grep 'true$' |
362 sed 's/ .*$//' | 362 sed 's/ .*$//' |
363 sort -u | 363 sort -u |
364 while read url; do 364 while read url; do
365 local dir="$(-antigen-get-clone-dir "$url")" 365 local dir="$(-antigen-get-clone-dir "$url")"
366 local version_hash="$(cd "$dir" && git rev-parse HEAD)" 366 local version_hash="$(cd "$dir" && git rev-parse HEAD)"
367 echo "$version_hash $url" 367 echo "$version_hash $url"
368 done)" 368 done)"
369 369
370 { 370 {
371 # The first line in the snapshot file is for metadata, in the form: 371 # The first line in the snapshot file is for metadata, in the form:
372 # key='value'; key='value'; key='value'; 372 # key='value'; key='value'; key='value';
373 # Where `key`s are valid shell variable names. 373 # Where `key`s are valid shell variable names.
374 374
375 # Snapshot version. Has no relation to antigen version. If the snapshot 375 # Snapshot version. Has no relation to antigen version. If the snapshot
376 # file format changes, this number can be incremented. 376 # file format changes, this number can be incremented.
377 echo -n "version='1';" 377 echo -n "version='1';"
378 378
379 # Snapshot creation date+time. 379 # Snapshot creation date+time.
380 echo -n " created_on='$(date)';" 380 echo -n " created_on='$(date)';"
381 381
382 # Add a checksum with the md5 checksum of all the snapshot lines. 382 # Add a checksum with the md5 checksum of all the snapshot lines.
383 local checksum="$(echo "$snapshot_content" | md5sum)" 383 local checksum="$(echo "$snapshot_content" | md5sum)"
384 echo -n " checksum='${checksum%% *}';" 384 echo -n " checksum='${checksum%% *}';"
385 385
386 # A newline after the metadata and then the snapshot lines. 386 # A newline after the metadata and then the snapshot lines.
387 echo "\n$snapshot_content" 387 echo "\n$snapshot_content"
388 388
389 } > "$snapshot_file" 389 } > "$snapshot_file"
390 390
391 } 391 }
392 392
393 antigen-restore () { 393 antigen-restore () {
394 394
395 if [[ $# == 0 ]]; then 395 if [[ $# == 0 ]]; then
396 echo 'Please provide a snapshot file to restore from.' >&2 396 echo 'Please provide a snapshot file to restore from.' >&2
397 return 1 397 return 1
398 fi 398 fi
399 399
400 local snapshot_file="$1" 400 local snapshot_file="$1"
401 401
402 # TODO: Before doing anything with the snapshot file, verify its checksum. 402 # TODO: Before doing anything with the snapshot file, verify its checksum.
403 # If it fails, notify this to the user and confirm if restore should 403 # If it fails, notify this to the user and confirm if restore should
404 # proceed. 404 # proceed.
405 405
406 echo -n "Restoring from $snapshot_file..." 406 echo -n "Restoring from $snapshot_file..."
407 407
408 sed -n '1!p' "$snapshot_file" | 408 sed -n '1!p' "$snapshot_file" |
409 while read line; do 409 while read line; do
410 410
411 local version_hash="${line%% *}" 411 local version_hash="${line%% *}"
412 local url="${line##* }" 412 local url="${line##* }"
413 local clone_dir="$(-antigen-get-clone-dir "$url")" 413 local clone_dir="$(-antigen-get-clone-dir "$url")"
414 414
415 if [[ ! -d $clone_dir ]]; then 415 if [[ ! -d $clone_dir ]]; then
416 git clone "$url" "$clone_dir" > /dev/null 416 git clone "$url" "$clone_dir" > /dev/null
417 fi 417 fi
418 418
419 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null 419 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null
420 420
421 done 421 done
422 422
423 echo ' done.' 423 echo ' done.'
424 echo 'Please open a new shell to get the restored changes.' 424 echo 'Please open a new shell to get the restored changes.'
425 } 425 }
426 426
427 antigen-help () { 427 antigen-help () {
428 cat <<EOF 428 cat <<EOF
429 Antigen is a plugin management system for zsh. It makes it easy to grab awesome 429 Antigen is a plugin management system for zsh. It makes it easy to grab awesome
430 shell scripts and utilities, put up on github. For further details and complete 430 shell scripts and utilities, put up on github. For further details and complete
431 documentation, visit the project's page at 'http://antigen.sharats.me'. 431 documentation, visit the project's page at 'http://antigen.sharats.me'.
432 EOF 432 EOF
433 } 433 }
434 434
435 # A syntax sugar to avoid the `-` when calling antigen commands. With this 435 # A syntax sugar to avoid the `-` when calling antigen commands. With this
436 # function, you can write `antigen-bundle` as `antigen bundle` and so on. 436 # function, you can write `antigen-bundle` as `antigen bundle` and so on.
437 antigen () { 437 antigen () {
438 local cmd="$1" 438 local cmd="$1"
439 shift 439 shift
440 "antigen-$cmd" "$@" 440 "antigen-$cmd" "$@"
441 } 441 }
442 442
443 -antigen-parse-args () { 443 -antigen-parse-args () {
444 # An argument parsing functionality to parse arguments the *antigen* way :). 444 # An argument parsing functionality to parse arguments the *antigen* way :).
445 # Takes one first argument (called spec), which dictates how to parse and 445 # Takes one first argument (called spec), which dictates how to parse and
446 # the rest of the arguments are parsed. Outputs a piece of valid shell code 446 # the rest of the arguments are parsed. Outputs a piece of valid shell code
447 # that can be passed to `eval` inside a function which creates the arguments 447 # that can be passed to `eval` inside a function which creates the arguments
448 # and their values as local variables. Suggested use is to set the defaults 448 # and their values as local variables. Suggested use is to set the defaults
449 # to all arguments first and then eval the output of this function. 449 # to all arguments first and then eval the output of this function.
450 450
451 # Spec: Only long argument supported. No support for parsing short options. 451 # Spec: Only long argument supported. No support for parsing short options.
452 # The spec must have two sections, separated by a `;`. 452 # The spec must have two sections, separated by a `;`.
453 # '<positional-arguments>;<keyword-only-arguments>' 453 # '<positional-arguments>;<keyword-only-arguments>'
454 # Positional arguments are passed as just values, like `command a b`. 454 # Positional arguments are passed as just values, like `command a b`.
455 # Keyword arguments are passed as a `--name=value` pair, like `command 455 # Keyword arguments are passed as a `--name=value` pair, like `command
456 # --arg1=a --arg2=b`. 456 # --arg1=a --arg2=b`.
457 457
458 # Each argument in the spec is separated by a `,`. Each keyword argument can 458 # Each argument in the spec is separated by a `,`. Each keyword argument can
459 # end in a `:` to specifiy that this argument wants a value, otherwise it 459 # end in a `:` to specifiy that this argument wants a value, otherwise it
460 # doesn't take a value. (The value in the output when the keyword argument 460 # doesn't take a value. (The value in the output when the keyword argument
461 # doesn't have a `:` is `true`). 461 # doesn't have a `:` is `true`).
462 462
463 # Arguments in either section can end with a `?` (should come after `:`, if 463 # Arguments in either section can end with a `?` (should come after `:`, if
464 # both are present), means optional. FIXME: Not yet implemented. 464 # both are present), means optional. FIXME: Not yet implemented.
465 465
466 # See the test file, tests/arg-parser.t for (working) examples. 466 # See the test file, tests/arg-parser.t for (working) examples.
467 467
468 local spec="$1" 468 local spec="$1"
469 shift 469 shift
470 470
471 # Sanitize the spec 471 # Sanitize the spec
472 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')" 472 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')"
473 473
474 local code='' 474 local code=''
475 475
476 --add-var () { 476 --add-var () {
477 test -z "$code" || code="$code\n" 477 test -z "$code" || code="$code\n"
478 code="${code}local $1='$2'" 478 code="${code}local $1='$2'"
479 } 479 }
480 480
481 local positional_args="$(echo "$spec" | cut -d\; -f1)" 481 local positional_args="$(echo "$spec" | cut -d\; -f1)"
482 local positional_args_count="$(echo $positional_args | 482 local positional_args_count="$(echo $positional_args |
483 awk -F, '{print NF}')" 483 awk -F, '{print NF}')"
484 484
485 # Set spec values based on the positional arguments. 485 # Set spec values based on the positional arguments.
486 local i=1 486 local i=1
487 while ! [[ -z $1 || $1 == --* ]]; do 487 while ! [[ -z $1 || $1 == --* ]]; do
488 488
489 if (( $i > $positional_args_count )); then 489 if (( $i > $positional_args_count )); then
490 echo "Only $positional_args_count positional arguments allowed." >&2 490 echo "Only $positional_args_count positional arguments allowed." >&2
491 echo "Found at least one more: '$1'" >&2 491 echo "Found at least one more: '$1'" >&2
492 return 492 return
493 fi 493 fi
494 494
495 local name_spec="$(echo "$positional_args" | cut -d, -f$i)" 495 local name_spec="$(echo "$positional_args" | cut -d, -f$i)"
496 local name="${${name_spec%\?}%:}" 496 local name="${${name_spec%\?}%:}"
497 local value="$1" 497 local value="$1"
498 498
499 if echo "$code" | grep -qm1 "^local $name="; then 499 if echo "$code" | grep -qm1 "^local $name="; then
500 echo "Argument '$name' repeated with the value '$value'". >&2 500 echo "Argument '$name' repeated with the value '$value'". >&2
501 return 501 return
502 fi 502 fi
503 503
504 --add-var $name "$value" 504 --add-var $name "$value"
505 505
506 shift 506 shift
507 i=$(($i + 1)) 507 i=$(($i + 1))
508 done 508 done
509 509
510 local keyword_args="$( 510 local keyword_args="$(
511 # Positional arguments can double up as keyword arguments too. 511 # Positional arguments can double up as keyword arguments too.
512 echo "$positional_args" | tr , '\n' | 512 echo "$positional_args" | tr , '\n' |
513 while read line; do 513 while read line; do
514 if [[ $line == *\? ]]; then 514 if [[ $line == *\? ]]; then
515 echo "${line%?}:?" 515 echo "${line%?}:?"
516 else 516 else
517 echo "$line:" 517 echo "$line:"
518 fi 518 fi
519 done 519 done
520 520
521 # Specified keyword arguments. 521 # Specified keyword arguments.
522 echo "$spec" | cut -d\; -f2 | tr , '\n' 522 echo "$spec" | cut -d\; -f2 | tr , '\n'
523 )" 523 )"
524 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')" 524 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')"
525 525
526 # Set spec values from keyword arguments, if any. The remaining arguments 526 # Set spec values from keyword arguments, if any. The remaining arguments
527 # are all assumed to be keyword arguments. 527 # are all assumed to be keyword arguments.
528 while [[ $1 == --* ]]; do 528 while [[ $1 == --* ]]; do
529 # Remove the `--` at the start. 529 # Remove the `--` at the start.
530 local arg="${1#--}" 530 local arg="${1#--}"
531 531
532 # Get the argument name and value. 532 # Get the argument name and value.
533 if [[ $arg != *=* ]]; then 533 if [[ $arg != *=* ]]; then
534 local name="$arg" 534 local name="$arg"
535 local value='' 535 local value=''
536 else 536 else
537 local name="${arg%\=*}" 537 local name="${arg%\=*}"
538 local value="${arg#*=}" 538 local value="${arg#*=}"
539 fi 539 fi
540 540
541 if echo "$code" | grep -qm1 "^local $name="; then 541 if echo "$code" | grep -qm1 "^local $name="; then
542 echo "Argument '$name' repeated with the value '$value'". >&2 542 echo "Argument '$name' repeated with the value '$value'". >&2
543 return 543 return
544 fi 544 fi
545 545
546 # The specification for this argument, used for validations. 546 # The specification for this argument, used for validations.
547 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")" 547 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")"
548 548
549 # Validate argument and value. 549 # Validate argument and value.
550 if [[ -z $arg_line ]]; then 550 if [[ -z $arg_line ]]; then
551 # This argument is not known to us. 551 # This argument is not known to us.
552 echo "Unknown argument '$name'." >&2 552 echo "Unknown argument '$name'." >&2
553 return 553 return
554 554
555 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then 555 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then
556 # This argument needs a value, but is not provided. 556 # This argument needs a value, but is not provided.
557 echo "Required argument for '$name' not provided." >&2 557 echo "Required argument for '$name' not provided." >&2
558 return 558 return
559 559
560 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then 560 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then
561 # This argument doesn't need a value, but is provided. 561 # This argument doesn't need a value, but is provided.
562 echo "No argument required for '$name', but provided '$value'." >&2 562 echo "No argument required for '$name', but provided '$value'." >&2
563 return 563 return
564 564
565 fi 565 fi
566 566
567 if [[ -z $value ]]; then 567 if [[ -z $value ]]; then
568 value=true 568 value=true
569 fi 569 fi
570 570
571 --add-var "${name//-/_}" "$value" 571 --add-var "${name//-/_}" "$value"
572 shift 572 shift
573 done 573 done
574 574
575 echo "$code" 575 echo "$code"
576 576
577 unfunction -- --add-var 577 unfunction -- --add-var
578 578
579 } 579 }
580 580
581 # Echo the bundle specs as in the record. The first line is not echoed since it 581 # Echo the bundle specs as in the record. The first line is not echoed since it
582 # is a blank line. 582 # is a blank line.
583 -antigen-echo-record () { 583 -antigen-echo-record () {
584 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p' 584 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p'
585 } 585 }
586 586
587 -antigen-env-setup () { 587 -antigen-env-setup () {
588 # Pre-startup initializations. 588 # Pre-startup initializations.
589 -set-default ANTIGEN_DEFAULT_REPO_URL \ 589 -set-default ANTIGEN_DEFAULT_REPO_URL \
590 https://github.com/robbyrussell/oh-my-zsh.git 590 https://github.com/robbyrussell/oh-my-zsh.git
591 -set-default ADOTDIR $HOME/.antigen 591 -set-default ADOTDIR $HOME/.antigen
592 592
593 # Load the compinit module. Required for `compdef` to be defined, which is 593 # Load the compinit module. Required for `compdef` to be defined, which is
594 # used by many plugins to define completions. 594 # used by many plugins to define completions.
595 autoload -U compinit 595 autoload -U compinit
596 compinit -i 596 compinit -i
597 597
598 # Setup antigen's own completion. 598 # Setup antigen's own completion.
599 compdef _antigen antigen 599 compdef _antigen antigen
600 } 600 }
601 601
602 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is 602 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is
603 # not already set. 603 # not already set.
604 -set-default () { 604 -set-default () {
605 local arg_name="$1" 605 local arg_name="$1"
606 local arg_value="$2" 606 local arg_value="$2"
607 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'" 607 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'"
608 } 608 }
609 609
610 # Setup antigen's autocompletion 610 # Setup antigen's autocompletion
611 _antigen () { 611 _antigen () {
612 compadd \ 612 compadd \
613 bundle\ 613 bundle\
614 bundles\ 614 bundles\
615 update\ 615 update\
616 revert\ 616 revert\
617 list\ 617 list\
618 cleanup\ 618 cleanup\
619 lib\ 619 lib\
620 theme\ 620 theme\
621 apply\ 621 apply\
622 help 622 help
623 } 623 }
624 624
625 -antigen-env-setup 625 -antigen-env-setup
626 626