Commit a6d46893a848439ba003d418a8e9dfadaba669cc

Authored by Xavier Garrido
1 parent 49dc1fb413

add a selfupdate function to update antigen itself

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

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