1#compdef tla
2
3autoload -z is-at-least
4local TLA=$words[1]
5local tla_version
6local hide_short
7
8# ask the user which version of tla this is
9if ! zstyle -s ":completion:${curcontext}" tla-version tla_version; then
10  # ask tla instead
11  tla_version="$($TLA --version)"
12  if [[ "${${(f)tla_version}[1]}" == The\ GNU\ Arch\ Revision\ Control\ System\ \(tla\)\ (#b)([0-9.]##) ]]; then
13    tla_version="$match[1]"
14  else
15    tla_version="${${$($TLA --version)#tla tla-}%% from regexps.com*}"
16    [[ $tla_version == *[a-zA-Z]* ]] && tla_version=1.3 # tla doesn't know
17  fi
18fi
19
20# test whether to hide short options from completion
21if zstyle -s ":completion:${curcontext}" hide-shortopts hide_short; then
22  case $hide_short in
23    true|yes|on|1) hide_short='!' ;;
24    *) hide_short='' ;;
25  esac
26fi
27
28# completion functions
29
30(( $+functions[_tla_archives] )) ||
31_tla_archives () { _arch_archives tla "$@" }
32
33(( $+functions[_tla_categories] )) ||
34_tla_categories () { _arch_namespace tla 1 "$argv[@]" }
35
36(( $+functions[_tla_branches] )) ||
37_tla_branches () {_arch_namespace tla 2 "$argv[@]" }
38
39(( $+functions[_tla_versions] )) ||
40_tla_versions () { _arch_namespace tla 3 "$argv[@]" }
41
42(( $+functions[_tla_revisions] )) ||
43_tla_revisions () { _arch_namespace tla 4 "$argv[@]" }
44
45(( $+functions[_tla_local_revisions] )) ||
46_tla_local_revisions () {
47  local expl1 expl2 tree_version=`$TLA tree-version`
48  _description -V applied-patches expl1 "patches from this version"
49  _description -V other-patches expl2 "patches from other versions"
50  compadd "$expl1[@]" `$TLA logs`
51  compadd "$expl2[@]" `$TLA logs --full $($TLA log-versions | grep -v $tree_version)`
52  # This is incredibly slow.
53  # Should complete based on -A, -R, -d
54}
55
56(( $+functions[_tla_config] )) ||
57_tla_config () {
58
59  # zsh 4.1.1+ is recommended; 4.0.6 gives the error below when doing
60  # tla build-config e<TAB>
61  # _path_files:322: no matches found: configs//e/.(/)
62  # whereas 4.1.1 completes correctly
63
64  local configdir root ret=1 n expl
65
66  n=$opt_args[(i)(-d|--dir)]
67  [[ -n "$n" ]] && configdir=$opt_args[$n]
68  root="$(_call_program tla $TLA tree-root ${configdir} 2>&1)"
69  if (( $? )); then
70    _message -e messages "Error: $root"
71    return $ret
72  fi
73
74  if [[ -d "$root/configs" ]]; then
75    configdir=("$root/configs")
76    _description files expl '%Bconfig file%b'
77    _files -W configdir "$expl[@]" && ret=0
78  else
79    _message -e messages "No configs/ directory in tree whose root is $root"
80  fi
81  return $ret
82}
83
84(( $+functions[_tla_limit] )) ||
85_tla_limit () { #presently only does push-mirror style limits
86  [[ $words[$CURRENT] == *@* ]] && return 1
87
88  local expl archive
89  archive=${words[(r)*@*]:-$($TLA my-default-archive 2> /dev/null)}
90  if [ $archive ]; then
91
92    if [[ $PREFIX != *--* ]]; then
93      _description -V categories expl "categories in $archive"
94      compadd -q -S -- "$expl[@]" `$TLA categories -A $archive`
95    else
96      _tla_namespace_branches 3
97    fi
98  fi
99}
100
101(( $+functions[_tla_tree_or_rev] )) ||
102_tla_tree_or_rev () {
103  _alternative 'trees:tree:_files -/' 'revisions:revision:_tla_revisions'
104}
105
106(( $+functions[_tla_libraries] )) ||
107_tla_libraries () {
108  local libraries expl
109  libraries=($(_call_program tla $TLA my-revision-library))
110  _description -V libraries expl "revision libraries"
111  compadd "$expl[@]" -a libraries
112}
113
114(( $+functions[_tla_my_revision_library] )) ||
115_tla_my_revision_library () {
116  if [[ -n $words[(r)-d] ]] || [[ -n $words[(r)--delete] ]]; then
117    _tla_libraries
118  else
119    _files -/
120  fi
121}
122
123(( $+functions[_tla_log_versions] )) ||
124_tla_log_versions () {
125  local logs expl
126  if is-at-least 1.1 $tla_version; then
127    logs=($(_call_program tla $TLA log-versions))
128  else
129    logs=($(_call_program tla $TLA logs))
130  fi
131  _description -V versions expl "log versions"
132  compadd "$expl[@]" -a logs
133}
134
135# command argument definitions
136# commands with different versions
137
138local cmd_register_archive cmd_archives cmd_ls_archives cmd_redo
139local cmd_redo_changes cmd_changes cmd_what_changed cmd_categories
140local cmd_branches cmd_versions cmd_cacherev cmd_logs cmd_log_versions
141local cmd_log_ls cmd_update cmd_join_branch cmd_replay cmd_deltapatch
142local cmd_delta_patch cmd_apply_delta cmd_sync_tree cmd_make_sync_tree
143local cmd_delta cmd_revdelta cmd_library_categories cmd_library_branches
144local cmd_library_versions cmd_library_revisions
145local cmd_archive_register
146
147cmd_log_ls=('*:version:_tla_log_versions')
148cmd_log_versions=()
149# the options should only complete items that are in the tree
150
151if is-at-least 1.1 $tla_version; then
152  cmd_register_archive=('::archive:_tla_archives' ':location:_files -/')
153  cmd_archive_register=($cmd_register_archive)
154  cmd_archives=('::regex:')
155  cmd_redo=('::changeset:_files -/')
156  cmd_changes=('::revision:_tla_revisions'
157    #  ':separator:(--)' '*::limit:_files'
158    #don't understand the limit usage
159  )
160  cmd_categories=('::archive:_tla_archives')
161  cmd_branches=('::category:_tla_categories')
162  cmd_versions=('::branch:_tla_branches')
163  cmd_cacherev=('::revision:_tla_revisions')
164  #should only complete non-cached revisions
165
166  cmd_logs=($cmd_log_ls)
167  cmd_update=('::revision:_tla_revisions')
168  cmd_join_branch=(':revision:_tla_revisions')
169  #should only complete continuation revisions
170
171  cmd_replay=('*::revision:_tla_revisions')
172  cmd_deltapatch=(':FROM:_tla_tree_or_rev' ':TO:_tla_tree_or_rev')
173  cmd_sync_tree=(':revision:_tla_revisions')
174  cmd_delta=(':FROM:_tla_tree_or_rev' ':TO:_tla_tree_or_rev' '::DEST:_files -/')
175  cmd_library_categories=('::archive:_tla_archives --library')
176  cmd_library_branches=('::category:_tla_categories --library')
177  cmd_library_versions=('::branch:_tla_branches --library')
178  cmd_library_revisions=('::version:_tla_versions --library')
179else
180  cmd_register_archive=(':archive:_tla_archives' ':location:_files -/')
181  cmd_archives=()
182  cmd_redo=()
183  cmd_changes=('::revision:_tla_revisions')
184  cmd_categories=()
185  cmd_branches=(':category:_tla_categories')
186  cmd_versions=(':branch:_tla_branches')
187  cmd_cacherev=(':revision:_tla_revisions' '::dir:_files -/')
188  cmd_logs=($cmd_log_versions)
189  cmd_update=(':dir:_files -/' '::newdir:_files -/'
190    '::revision:_tla_revisions')
191  cmd_join_branch=(':dir:_files -/' '::newdir:_files -/'
192    ':revision:_tla_revisions')
193  cmd_replay=(':dir:_files -/' '::newdir:_files -/' '::revision:_tla_revisions')
194  cmd_deltapatch=(':FROM:_tla_tree_or_rev' ':TO:_tla_tree_or_rev'
195    ':UPON:_tla_tree_or_rev' '::DEST:_files -/')
196  cmd_sync_tree=(':dir:_files -/' '::newdir:_files -/'
197    ':revision:_tla_revisions')
198  cmd_delta=(':FROM:_tla_tree_or_rev' ':TO:_tla_tree_or_rev')
199  cmd_library_categories=()
200  cmd_library_branches=(':category:_tla_categories --library')
201  cmd_library_versions=(':branch:_tla_branches --library')
202  cmd_library_revisions=(':version:_tla_versions --library')
203fi
204
205cmd_ls_archives=($cmd_archives)
206cmd_redo_changes=($cmd_redo)
207cmd_what_changed=($cmd_changes)
208cmd_delta_patch=($cmd_deltapatch)
209cmd_apply_delta=($cmd_deltapatch)
210cmd_make_sync_tree=($cmd_sync_tree)
211cmd_revdelta=($cmd_delta)
212
213# commands the same in all versions
214
215local cmd_help
216cmd_help=()
217
218local cmd_my_id
219cmd_my_id=('::id-string:')
220
221local cmd_my_default_archive
222cmd_my_default_archive=('::archive:_tla_archives')
223
224local cmd_whereis_archive
225cmd_whereis_archive=(':archive:_tla_archives')
226
227local cmd_init_tree
228cmd_init_tree=('::version:_tla_versions')
229
230local cmd_tree_root
231cmd_tree_root=('::directory:_files -/')
232
233local cmd_tree_version
234cmd_tree_version=('::directory:_files -/')
235
236local cmd_set_tree_version
237cmd_set_tree_version=(':version:_tla_versions')
238
239local cmd_build_config cmd_buildcfg
240cmd_build_config=(':config:_tla_config')
241cmd_buildcfg=($cmd_build_config)
242
243local cmd_cat_config cmd_catcfg cmd_cfgcat
244cmd_cat_config=(':config:_tla_config')
245cmd_catcfg=($cmd_cat_config)
246cmd_cfgcat=($cmd_cat_config)
247
248local cmd_undo cmd_undo_changes
249cmd_undo=('::revision:_tla_revisions')
250cmd_undo_changes=($cmd_undo)
251
252local cmd_file_diffs
253cmd_file_diffs=(':file:_files' '::revision:_tla_revisions')
254
255local cmd_file_find
256cmd_file_find=(':file:_files' '::revision:_tla_revisions')
257
258local cmd_inventory cmd_srcfind
259cmd_inventory=('::separator:(--)' '*:directory:_files -/')
260cmd_srcfind=($cmd_inventory)
261
262local cmd_tree_lint cmd_lint
263cmd_tree_lint=('::directory:_files -/')
264cmd_lint=($cmd_tree_lint)
265
266local cmd_id cmd_invtag
267cmd_id=('*:file:_files')
268cmd_invtag=($cmd_id)
269
270local cmd_id_tagging_method cmd_tagging_method methods
271cmd_id_tagging_method=('::tagging method:(($methods))')
272methods=(
273  'names:use naming conventions only'
274  'implicit:use naming conventions but permit for inventory tags'
275  'tagline:use naming conventions but permit for inventory tags'
276  'explicit:require explicit designation of source'
277)
278cmd_tagging_method=($cmd_id_tagging_method)
279
280local cmd_add cmd_add_id cmd_add_tag
281cmd_add=('*:files to add:_files')
282cmd_add_id=($cmd_add)
283cmd_add_tag=($cmd_add)
284
285local cmd_delete cmd_delete_id cmd_delete_tag
286cmd_delete=('*:files to delete:_files')
287cmd_delete_id=($cmd_delete)
288cmd_delete_tag=($cmd_delete)
289
290local cmd_move cmd_move_id cmd_move_tag
291cmd_move_id=(':old name:_files' ':new name:_files')
292cmd_move_id=($cmd_move)
293cmd_move_tag=($cmd_move)
294#would be nice not to offer dirs for newname if oldname is a file, and
295#vice versa
296
297local cmd_mv
298cmd_mv=('*:file:_files')
299# not really right, but close enough
300
301local cmd_default_id cmd_explicit_default cmd_default_tag
302cmd_default_id=('::TAG-PREFIX:')
303cmd_explicit_default=($cmd_default_id)
304cmd_default_tag=($cmd_default_id)
305
306local cmd_tagging_defaults cmd_id_tagging_defaults
307cmd_tagging_defaults=()
308cmd_id_tagging_defaults=($cmd_tagging_defaults)
309
310local cmd_changeset cmd_mkpatch
311cmd_changeset=(
312  ':ORIG:_files -/'
313  ':MOD:_files -/'
314  ':DEST:_files -/'
315  '*:files:_files'
316)
317cmd_mkpatch=("$cmd_changeset[@]")
318
319local cmd_dopatch cmd_do_changeset cmd_apply_changeset
320cmd_dopatch=(':changeset:_files -/' ':target:_files -/')
321cmd_do_changeset=($cmd_dopatch)
322cmd_apply_changeset=($cmd_dopatch)
323
324local cmd_show_changeset
325cmd_show_changeset=('::changeset:_files -/')
326
327local cmd_make_archive
328cmd_make_archive=('::name:' ':location:_files -/')
329
330local cmd_archive_setup
331cmd_archive_setup=('*:versions:_tla_branches --trailing-dashes')
332
333local cmd_make_category
334cmd_make_category=(':category:_tla_archives -S /')
335
336local cmd_make_branch
337cmd_make_branch=(':branch:_tla_categories --trailing-dashes')
338
339local cmd_make_version
340cmd_make_version=(':version:_tla_branches --trailing-dashes')
341
342local cmd_import cmd_imprev
343cmd_import=('::version:_tla_versions')
344cmd_imprev=($cmd_import)
345
346local cmd_commit cmd_cmtrev
347cmd_commit=('::version:_tla_versions' ':separator:(--)' '*:files:_files')
348cmd_cmtrev=($cmd_commit)
349
350local cmd_get cmd_getrev
351cmd_get=(':revision:_tla_revisions' '::directory:_files -/')
352cmd_getrev=($cmd_get)
353
354local cmd_get_patch cmd_get_changeset
355cmd_get_patch=(':revision:_tla_revisions' '::dir:_files -/')
356cmd_get_changeset=($cmd_get_patch)
357
358local cmd_lock_revision
359cmd_lock_revision=(':revision:_tla_revisions')
360
361local cmd_push_mirror cmd_archive_mirror
362cmd_push_mirror=(
363  '::FROM or MINE:_tla_archives'
364  '::TO:_tla_archives'
365  '::LIMIT:_tla_limit'
366)
367cmd_archive_mirror=($cmd_push_mirror)
368
369local cmd_revisions
370cmd_revisions=('::version:_tla_versions')
371
372local cmd_ancestry
373cmd_ancestry=('::revision:_tla_revisions')
374
375local cmd_ancestry_graph
376cmd_ancestry_graph=('::revision:_tla_revisions')
377
378local cmd_cat_archive_log
379cmd_cat_archive_log=(':revision:_tla_revisions')
380
381local cmd_cachedrevs
382cmd_cachedrevs=(':version:_tla_versions')
383
384local cmd_uncacherev
385cmd_uncacherev=(':revision:_tla_revisions' '::dir:_files -/')
386
387local cmd_archive_meta_info
388cmd_archive_meta_info=(':item-name:((name\:foo mirror\:bar))')
389
390local cmd_archive_snapshot
391cmd_archive_snapshot=(':dir:_files -/' '::limit:_tla_revisions')
392
393local cmd_archive_version
394cmd_archive_version=()
395
396local cmd_archive_fixup
397cmd_archive_fixup=()
398
399local cmd_make_log
400cmd_make_log=('::version:_tla_versions')
401
402local cmd_add_log cmd_add_log_version
403cmd_add_log=(':version:_tla_versions')
404cmd_add_log_version=($cmd_add_log)
405
406local cmd_remove_log cmd_remove_log_version
407cmd_remove_log=(':version:_tla_log_versions')
408cmd_remove_log_version=($cmd_remove_log)
409
410local cmd_abrowse
411cmd_abrowse=('::LIMIT:_tla_revisions')
412
413local cmd_cat_log
414cmd_cat_log=(':revision-spec:_tla_local_revisions')
415
416local cmd_changelog
417cmd_changelog=('::version:_tla_versions')
418
419local cmd_log_for_merge
420cmd_log_for_merge=('::version:_tla_versions')
421
422local cmd_merges
423cmd_merges=(':INTO:_tla_revisions' '::FROM:_tla_revisions')
424
425local cmd_new_merges
426cmd_new_merges=('::version:_tla_versions')
427
428local cmd_tag cmd_tagrev cmd_branch
429cmd_tag=(':SOURCE-REVISION:_tla_revisions' ':TAG-VERSION:_tla_versions')
430cmd_tagrev=($cmd_tag)
431cmd_branch=($cmd_tag)
432
433local cmd_star_merge
434cmd_star_merge=(':FROM:_tla_revisions')
435
436local cmd_missing cmd_whats_missing
437cmd_missing=('::revision:_tla_revisions')
438cmd_whats_missing=($cmd_missing)
439
440local cmd_pristines cmd_ls_pristines
441cmd_pristines=('::limit:_tla_revisions')
442cmd_ls_pristines=($cmd_pristines)
443
444local cmd_lock_pristine
445cmd_lock_pristine=(':revision:_tla_revisions')
446
447local cmd_add_pristine
448cmd_add_pristine=(':revision:_tla_revisions')
449
450local cmd_find_pristine
451cmd_find_pristine=(':revision:_tla_revisions')
452
453local cmd_my_revision_library cmd_library_dir
454cmd_my_revision_library=(':library:_tla_my_revision_library')
455cmd_library_dir=($my_revision_library)
456
457local cmd_library_find
458cmd_library_find=(':revision:_tla_revisions --library')
459
460local cmd_library_add
461cmd_library_add=(':revision:_tla_revisions --exclude-library-revisions')
462
463local cmd_library_remove
464cmd_library_remove=(':revision:_tla_revisions --library')
465
466local cmd_library_archives
467cmd_library_archives=()
468
469local cmd_library_log
470cmd_library_log=(':revision:_tla_revisions --library')
471
472local cmd_library_file
473cmd_library_file=(':file:_files' ':revision:_tla_revisions --library')
474
475local cmd_grab
476cmd_grab=(':location:_files')
477
478local cmd_parse_package_name
479cmd_parse_package_name=(':name:')
480
481local cmd_valid_package_name
482cmd_valid_package_name=(':name:')
483
484local cmd_library_config
485cmd_library_config=(':library:_tla_libraries')
486
487local cmd_rbrowse
488cmd_rbrowse=('::regular expression:')
489
490local cmd_rm
491cmd_rm=('*:file:_files')
492
493local cmd_escape
494cmd_escape=(':string:')
495
496local cmd_diff
497cmd_diff=('::revision:_tla_revisions')
498
499local cmd_export
500cmd_export=(':revision:_tla_revisions' ':dir:_files -/')
501
502#mutually exclusive options
503
504local -A excludes
505excludes=(
506# This first line means that if --output was given, don't complete
507# --no-output or --keep. The converse is not true.
508--output '--no-output --keep'
509--no-output --output
510
511--silent  '         --quiet --report --verbose --debug'
512--quiet   '--silent         --report --verbose --debug'
513--report  '--silent --quiet          --verbose --debug'
514--verbose '--silent --quiet --report           --debug'
515--debug   '--silent --quiet --report --verbose        '
516
517--sparse --non-sparse
518--non-sparse --sparse
519
520--files       '        --directories --both'
521--directories '--files               --both'
522--both        '--files --directories       '
523
524--mirror --mirror-from
525--mirror-from --mirror
526
527--no-cached --cached-tags
528--cached-tags --no-cached
529
530--non-greedy --greedy
531--greedy --non-greedy
532)
533
534_tla_main () {
535  typeset -A opt_args
536  local arguments
537  if (( CURRENT > 2 )); then
538    local cmd=${words[2]}
539    local var_cmd=cmd_${cmd//-/_}
540    curcontext="${curcontext%:*:*}:tla-$cmd:"
541    (( CURRENT-- ))
542    shift words
543
544    arguments=()
545    local input
546    input=(${${(M)${(f)"$($TLA $cmd -h)"}:#  *}#  })
547
548    local i j=1
549    local short long arg desc action
550    short=()
551    long=()
552    arg=()
553    desc=()
554    action=()
555    for (( i=1 ; i <= ${#input} ; i++ )); do
556      [[ "$input[i]" != *[^\ ]* ]] && continue # stupid blank lines
557      short[j]="${${${input[i]}[1,2]}#--}"
558      long[j]="${${input[i]#-?, }%% *}"
559
560      arg[j]="${${${input[i]%%  *}##* }##-*}"
561      [[ $long[j] == --archive ]] && arg[j]=ARCHIVE # tla doesn't mention this
562
563      desc[j]="${input[i]##*  }"
564      if [[ "$input[i+1]" == \ *[^\ ]* ]]; then # description continues
565        (( i++ ))
566        desc[j]="$desc[j] ${input[i]##*  }"
567      fi
568      [[ "$short[j]" == -[hHV] ]] && continue
569      desc[j]="${${desc[j]//\[/\\[}//\]/\\]}" # escape brackets
570
571      case $arg[j] in
572      DIR|PATCH-DIR|DEST|OUTPUT|PATH)
573        action[j]='_files -/' ;;
574      FILES|FILE|SNAP-FILE)
575        action[j]='_files' ;;
576      MASTER|MASTER-SOURCE|ARCHIVE)
577        action[j]='_tla_archives' ;;
578      CATEGORY)
579        action[j]='_tla_categories' ;;
580      BRANCH)
581        action[j]='_tla_branches' ;;
582      VERSION)
583        action[j]='_tla_versions' ;;
584      CFG)
585        action[j]='_tla_configs' ;;
586      LIB)
587        action[j]='_tla_libraries' ;;
588#      PATCH,FILE) # not sure how to complete this
589#        action[j]='_tla_patch_file' ;;
590      *)
591        action[j]='' ;;
592      esac
593
594      (( j++ ))
595
596    done
597
598    local excluded k
599    for (( i = 1 ; i < j ; i++ )); do
600      excluded=($short[i] $long[i])
601      foreach opt (${=excludes[$long[i]]})
602        k=$long[(i)$opt]
603        excluded=($excluded $short[k] $long[k])
604        #excludes matching short options too :-)
605      end
606
607
608      # generate arguments to _arguments ;-)
609      # make long and short options mutually exclusive
610      [ $short[i] ] && arguments=("$arguments[@]"
611        "${hide_short}(${excluded})${short[i]}[${desc[i]}]${arg[i]:+:$arg[i]:$action[i]}")
612      [ $long[i] ] && arguments=("$arguments[@]"
613        "(${excluded})${long[i]}[${desc[i]}]${arg[i]:+:$arg[i]:$action[i]}")
614    done
615
616    arguments=("$arguments[@]" "${(@P)var_cmd-*:FILE:_files}")
617  else
618    local help
619    local -U cmds
620    help=(${(f)"$($TLA help)"})
621    cmds=(${${${${(M)help:#* :*}/ #: #/:}%% ##}## #})
622    arguments=(':commands:(($cmds))')
623  fi
624  _arguments -S -A '-*' \
625    {"${hide_short}(: -)-V",'(: -)--version'}'[display version]' \
626    {"${hide_short}(: -)-h",'(: -)--help'}'[display help]' \
627    '(: -)-H[display verbose help]' \
628    "$arguments[@]"
629}
630
631_tla_main "$@"
632