Commit 297f0f733e0a8834ccbf64296f402f6bf4feb634

Authored by Shrikant Sharat
1 parent 27bf3ceefe

The `-n` in url/dir functions screws up things.

This was messing with `-cleanup`. The fix needs to add blank `echo`s after each
call to `-antigen-get-clone-url` and `-antigen-get-clone-dir` in `-cleanup`
function, or this. I think this is better.

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