Commit a58b694d9d5e0a6418b7c66aded44c400c78de8e

Authored by Shrikant Sharat
1 parent e8a2b3a63c

Formatting.

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

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