1#compdef hg
2
3# Zsh completion script for mercurial.  Rename this file to _hg and copy
4# it into your zsh function path (/usr/share/zsh/site-functions for
5# instance)
6#
7# If you do not want to install it globally, you can copy it somewhere
8# else and add that directory to $fpath. This must be done before
9# compinit is called. If the file is copied to ~/.zsh.d, your ~/.zshrc
10# file could look like this:
11#
12# fpath=("$HOME/.zsh.d" $fpath)
13# autoload -U compinit
14# compinit
15#
16# Copyright (C) 2005, 2006 Steve Borho <steve@borho.org>
17# Copyright (C) 2006-9 Brendan Cully <brendan@kublai.com>
18#
19# Permission is hereby granted, without written agreement and without
20# licence or royalty fees, to use, copy, modify, and distribute this
21# software and to distribute modified versions of this software for any
22# purpose, provided that the above copyright notice and the following
23# two paragraphs appear in all copies of this software.
24#
25# In no event shall the authors be liable to any party for direct,
26# indirect, special, incidental, or consequential damages arising out of
27# the use of this software and its documentation, even if the authors
28# have been advised of the possibility of such damage.
29#
30# The authors specifically disclaim any warranties, including, but not
31# limited to, the implied warranties of merchantability and fitness for
32# a particular purpose.  The software provided hereunder is on an "as
33# is" basis, and the authors have no obligation to provide maintenance,
34# support, updates, enhancements, or modifications.
35
36emulate -LR zsh
37setopt extendedglob
38
39local curcontext="$curcontext" state line
40typeset -A _hg_cmd_globals
41
42_hg() {
43  local cmd _hg_root
44  integer i=2
45  _hg_cmd_globals=()
46
47  while (( i < $#words ))
48  do
49    case "$words[$i]" in
50      -R|--repository)
51        eval _hg_root="$words[$i+1]"
52        _hg_cmd_globals+=("$words[$i]" "$_hg_root")
53        (( i += 2 ))
54        continue
55      ;;
56      -R*)
57        _hg_cmd_globals+="$words[$i]"
58        eval _hg_root="${words[$i]#-R}"
59       (( i++ ))
60       continue
61      ;;
62      --cwd|--config)
63        # pass along arguments to hg completer
64        _hg_cmd_globals+=("$words[$i]" "$words[$i+1]")
65        (( i += 2 ))
66        continue
67      ;;
68      -*)
69        # skip option
70        (( i++ ))
71        continue
72      ;;
73    esac
74    if [[ -z "$cmd" ]]
75    then
76      cmd="$words[$i]"
77      words[$i]=()
78      (( CURRENT-- ))
79    fi
80    (( i++ ))
81  done
82
83  if [[ -z "$cmd" ]]
84  then
85    _arguments -s -w : $_hg_global_opts \
86    ':mercurial command:_hg_commands'
87    return
88  fi
89
90  # resolve abbreviations and aliases
91  if ! (( $+functions[_hg_cmd_${cmd}] ))
92  then
93    local cmdexp
94    (( $#_hg_cmd_list )) || _hg_get_commands
95
96    cmdexp=$_hg_cmd_list[(r)${cmd}*]
97    if [[ $cmdexp == $_hg_cmd_list[(R)${cmd}*] ]]
98    then
99      # might be nice to rewrite the command line with the expansion
100      cmd="$cmdexp"
101    fi
102    if [[ -n $_hg_alias_list[$cmd] ]]
103    then
104      cmd=$_hg_alias_list[$cmd]
105    fi
106  fi
107
108  curcontext="${curcontext%:*:*}:hg-${cmd}:"
109
110  zstyle -s ":completion:$curcontext:" cache-policy update_policy
111
112  if [[ -z "$update_policy" ]]
113  then
114    zstyle ":completion:$curcontext:" cache-policy _hg_cache_policy
115  fi
116
117  if (( $+functions[_hg_cmd_${cmd}] ))
118  then
119    _hg_cmd_${cmd}
120  else
121    # complete unknown commands normally
122    _arguments -s -w : $_hg_global_opts \
123      '*:files:_hg_files'
124  fi
125}
126
127_hg_cache_policy() {
128  typeset -a old
129
130  # cache for a minute
131  old=( "$1"(mm+10) )
132  (( $#old )) && return 0
133
134  return 1
135}
136
137_hg_get_commands() {
138  typeset -ga _hg_cmd_list
139  typeset -gA _hg_alias_list
140  local hline cmd cmdalias
141
142  _call_program hg hg debugcomplete -v | while read -A hline
143  do
144    cmd=$hline[1]
145    _hg_cmd_list+=($cmd)
146
147    for cmdalias in $hline[2,-1]
148    do
149      _hg_cmd_list+=($cmdalias)
150      _hg_alias_list+=($cmdalias $cmd)
151    done
152  done
153}
154
155_hg_commands() {
156  (( $#_hg_cmd_list )) || _hg_get_commands
157  _describe -t commands 'mercurial command' _hg_cmd_list
158}
159
160_hg_revrange() {
161  compset -P 1 '*:'
162  _hg_tags "$@"
163}
164
165_hg_tags() {
166  typeset -a tags
167  local tag rev
168
169  _hg_cmd tags 2> /dev/null | while read tag
170  do
171    tags+=(${tag/ #    [0-9]#:*})
172  done
173  (( $#tags )) && _describe -t tags 'tags' tags
174}
175
176# likely merge candidates
177_hg_mergerevs() {
178  typeset -a heads
179  local myrev
180
181  heads=(${(f)"$(_hg_cmd heads --template '{rev}\\n')"})
182  # exclude own revision
183  myrev=$(_hg_cmd log -r . --template '{rev}\\n')
184  heads=(${heads:#$myrev})
185
186  (( $#heads )) && _describe -t heads 'heads' heads
187}
188
189_hg_files() {
190  if [[ -n "$_hg_root" ]]
191  then
192    [[ -d "$_hg_root/.hg" ]] || return
193    case "$_hg_root" in
194      /*)
195        _files -W $_hg_root
196      ;;
197      *)
198        _files -W $PWD/$_hg_root
199      ;;
200    esac
201  else
202    _files
203  fi
204}
205
206_hg_status() {
207  [[ -d $PREFIX ]] || PREFIX=$PREFIX:h
208  status_files=(${(ps:\0:)"$(_hg_cmd status -0n$1 ./$PREFIX 2>/dev/null)"})
209}
210
211_hg_unknown() {
212  typeset -a status_files
213  _hg_status u
214  _wanted files expl 'unknown files' _multi_parts / status_files
215}
216
217_hg_missing() {
218  typeset -a status_files
219  _hg_status d
220  _wanted files expl 'missing files' _multi_parts / status_files
221}
222
223_hg_modified() {
224  typeset -a status_files
225  _hg_status m
226  _wanted files expl 'modified files' _multi_parts / status_files
227}
228
229_hg_resolve() {
230  local rstate rpath
231
232  [[ -d $PREFIX ]] || PREFIX=$PREFIX:h
233
234  _hg_cmd resolve -l ./$PREFIX 2> /dev/null | while read rstate rpath
235  do
236    [[ $rstate == 'R' ]] && resolved_files+=($rpath)
237    [[ $rstate == 'U' ]] && unresolved_files+=($rpath)
238  done
239}
240
241_hg_resolved() {
242  typeset -a resolved_files unresolved_files
243  _hg_resolve
244  _wanted files expl 'resolved files' _multi_parts / resolved_files
245}
246
247_hg_unresolved() {
248  typeset -a resolved_files unresolved_files
249  _hg_resolve
250  _wanted files expl 'unresolved files' _multi_parts / unresolved_files
251}
252
253_hg_config() {
254    typeset -a items
255    items=(${${(%f)"$(_call_program hg hg showconfig)"}%%\=*})
256    (( $#items )) && _describe -t config 'config item' items
257}
258
259_hg_addremove() {
260  _alternative 'files:unknown files:_hg_unknown' \
261    'files:missing files:_hg_missing'
262}
263
264_hg_ssh_urls() {
265  if [[ -prefix */ ]]
266  then
267    if zstyle -T ":completion:${curcontext}:files" remote-access
268    then
269      local host=${PREFIX%%/*}
270      typeset -a remdirs
271      compset -p $(( $#host + 1 ))
272      local rempath=${(M)PREFIX##*/}
273      local cacheid="hg:${host}-${rempath//\//_}"
274      cacheid=${cacheid%[-_]}
275      compset -P '*/'
276      if _cache_invalid "$cacheid" || ! _retrieve_cache "$cacheid"
277      then
278        remdirs=(${${(M)${(f)"$(_call_program files ssh -a -x $host ls -1FL "${(q)rempath}" 2> /dev/null)"}##*/}%/})
279        _store_cache "$cacheid" remdirs
280      fi
281      _describe -t directories 'remote directory' remdirs -S/
282    else
283      _message 'remote directory'
284    fi
285  else
286    if compset -P '*@'
287    then
288      _hosts -S/
289    else
290      _alternative 'hosts:remote host name:_hosts -S/' \
291        'users:user:_users -S@'
292    fi
293  fi
294}
295
296_hg_urls() {
297  if compset -P bundle://
298  then
299    _files
300  elif compset -P ssh://
301  then
302    _hg_ssh_urls
303  elif [[ -prefix *: ]]
304  then
305    _urls
306  else
307    local expl
308    compset -S '[^:]*'
309    _wanted url-schemas expl 'URL schema' compadd -S '' - \
310      http:// https:// ssh:// bundle://
311  fi
312}
313
314_hg_paths() {
315  typeset -a paths pnames
316  _hg_cmd paths 2> /dev/null | while read -A pnames
317  do
318    paths+=($pnames[1])
319  done
320  (( $#paths )) && _describe -t path-aliases 'repository alias' paths
321}
322
323_hg_remote() {
324  _alternative 'path-aliases:repository alias:_hg_paths' \
325    'directories:directory:_files -/' \
326    'urls:URL:_hg_urls'
327}
328
329_hg_clone_dest() {
330  _alternative 'directories:directory:_files -/' \
331    'urls:URL:_hg_urls'
332}
333
334# Common options
335_hg_global_opts=(
336    '(--repository -R)'{-R+,--repository}'[repository root directory]:repository:_files -/'
337    '--cwd[change working directory]:new working directory:_files -/'
338    '(--noninteractive -y)'{-y,--noninteractive}'[do not prompt, assume yes for any required answers]'
339    '(--verbose -v)'{-v,--verbose}'[enable additional output]'
340    '*--config[set/override config option]:defined config items:_hg_config'
341    '(--quiet -q)'{-q,--quiet}'[suppress output]'
342    '(--help -h)'{-h,--help}'[display help and exit]'
343    '--debug[debug mode]'
344    '--debugger[start debugger]'
345    '--encoding[set the charset encoding (default: UTF8)]'
346    '--encodingmode[set the charset encoding mode (default: strict)]'
347    '--lsprof[print improved command execution profile]'
348    '--traceback[print traceback on exception]'
349    '--time[time how long the command takes]'
350    '--profile[profile]'
351    '--version[output version information and exit]'
352)
353
354_hg_pat_opts=(
355  '*'{-I+,--include}'[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/'
356  '*'{-X+,--exclude}'[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/')
357
358_hg_diff_opts=(
359  '(--text -a)'{-a,--text}'[treat all files as text]'
360  '(--git -g)'{-g,--git}'[use git extended diff format]'
361  "--nodates[don't include dates in diff headers]")
362
363_hg_dryrun_opts=(
364  '(--dry-run -n)'{-n,--dry-run}'[do not perform actions, just print output]')
365
366_hg_style_opts=(
367  '--style[display using template map file]:'
368  '--template[display with template]:')
369
370_hg_commit_opts=(
371  '(-m --message -l --logfile --edit -e)'{-e,--edit}'[edit commit message]'
372  '(-e --edit -l --logfile --message -m)'{-m+,--message}'[use <text> as commit message]:message:'
373  '(-e --edit -m --message --logfile -l)'{-l+,--logfile}'[read the commit message from <file>]:log file:_files')
374
375_hg_remote_opts=(
376  '(--ssh -e)'{-e+,--ssh}'[specify ssh command to use]:'
377  '--remotecmd[specify hg command to run on the remote side]:')
378
379_hg_cmd() {
380  _call_program hg hg --config ui.verbose=0 --config defaults."$1"= \
381    "$_hg_cmd_globals[@]" "$@" 2> /dev/null
382}
383
384_hg_cmd_add() {
385  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
386  '*:unknown files:_hg_unknown'
387}
388
389_hg_cmd_addremove() {
390  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
391  '(--similarity -s)'{-s+,--similarity}'[guess renamed files by similarity (0<=s<=100)]:' \
392  '*:unknown or missing files:_hg_addremove'
393}
394
395_hg_cmd_annotate() {
396  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
397  '(--rev -r)'{-r+,--rev}'[annotate the specified revision]:revision:_hg_tags' \
398  '(--follow -f)'{-f,--follow}'[follow file copies and renames]' \
399  '(--text -a)'{-a,--text}'[treat all files as text]' \
400  '(--user -u)'{-u,--user}'[list the author]' \
401  '(--date -d)'{-d,--date}'[list the date]' \
402  '(--number -n)'{-n,--number}'[list the revision number (default)]' \
403  '(--changeset -c)'{-c,--changeset}'[list the changeset]' \
404  '*:files:_hg_files'
405}
406
407_hg_cmd_archive() {
408  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
409  '--no-decode[do not pass files through decoders]' \
410  '(--prefix -p)'{-p+,--prefix}'[directory prefix for files in archive]:' \
411  '(--rev -r)'{-r+,--rev}'[revision to distribute]:revision:_hg_tags' \
412  '(--type -t)'{-t+,--type}'[type of distribution to create]:archive type:(files tar tbz2 tgz uzip zip)' \
413  '*:destination:_files'
414}
415
416_hg_cmd_backout() {
417  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
418    '--merge[merge with old dirstate parent after backout]' \
419    '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \
420    '--parent[parent to choose when backing out merge]' \
421    '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \
422    '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \
423    '(--message -m)'{-m+,--message}'[specify commit message]:text' \
424    '(--logfile -l)'{-l+,--logfile}'[read commit message from specified file]:log file:_files'
425}
426
427_hg_cmd_bisect() {
428  _arguments -s -w : $_hg_global_opts \
429  '(-)'{-r,--reset}'[reset bisect state]' \
430  '(--good -g --bad -b --skip -s --reset -r)'{-g,--good}'[mark changeset good]'::revision:_hg_tags \
431  '(--good -g --bad -b --skip -s --reset -r)'{-b,--bad}'[mark changeset bad]'::revision:_hg_tags \
432  '(--good -g --bad -b --skip -s --reset -r)'{-s,--skip}'[skip testing changeset]' \
433  '(--command -c --noupdate -U)'{-c+,--command}'[use command to check changeset state]':commands:_command_names \
434  '(--command -c --noupdate -U)'{-U,--noupdate}'[do not update to target]'
435}
436
437_hg_cmd_branch() {
438  _arguments -s -w : $_hg_global_opts \
439  '(--force -f)'{-f,--force}'[set branch name even if it shadows an existing branch]' \
440  '(--clean -C)'{-C,--clean}'[reset branch name to parent branch name]'
441}
442
443_hg_cmd_branches() {
444  _arguments -s -w : $_hg_global_opts \
445  '(--active -a)'{-a,--active}'[show only branches that have unmerge heads]'
446}
447
448_hg_cmd_bundle() {
449  _arguments -s -w : $_hg_global_opts $_hg_remote_opts \
450  '(--force -f)'{-f,--force}'[run even when remote repository is unrelated]' \
451  '(2)*--base[a base changeset to specify instead of a destination]:revision:_hg_tags' \
452  ':output file:_files' \
453  ':destination repository:_files -/'
454}
455
456_hg_cmd_cat() {
457  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
458  '(--output -o)'{-o+,--output}'[print output to file with formatted name]:filespec:' \
459  '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \
460  '*:file:_hg_files'
461}
462
463_hg_cmd_clone() {
464  _arguments -s -w : $_hg_global_opts $_hg_remote_opts \
465  '(--noupdate -U)'{-U,--noupdate}'[do not update the new working directory]' \
466  '(--rev -r)'{-r+,--rev}'[a changeset you would like to have after cloning]:' \
467  '--uncompressed[use uncompressed transfer (fast over LAN)]' \
468  ':source repository:_hg_remote' \
469  ':destination:_hg_clone_dest'
470}
471
472_hg_cmd_commit() {
473  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
474  '(--addremove -A)'{-A,--addremove}'[mark new/missing files as added/removed before committing]' \
475  '(--message -m)'{-m+,--message}'[specify commit message]:text' \
476  '(--logfile -l)'{-l+,--logfile}'[read commit message from specified file]:log file:_files' \
477  '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \
478  '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \
479  '*:file:_hg_files'
480}
481
482_hg_cmd_copy() {
483  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
484  '(--after -A)'{-A,--after}'[record a copy that has already occurred]' \
485  '(--force -f)'{-f,--force}'[forcibly copy over an existing managed file]' \
486  '*:file:_hg_files'
487}
488
489_hg_cmd_diff() {
490  typeset -A opt_args
491  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_diff_opts \
492  '*'{-r,--rev}'+[revision]:revision:_hg_revrange' \
493  '(--show-function -p)'{-p,--show-function}'[show which function each change is in]' \
494  '(--ignore-all-space -w)'{-w,--ignore-all-space}'[ignore white space when comparing lines]' \
495  '(--ignore-space-change -b)'{-b,--ignore-space-change}'[ignore changes in the amount of white space]' \
496  '(--ignore-blank-lines -B)'{-B,--ignore-blank-lines}'[ignore changes whose lines are all blank]' \
497  '*:file:->diff_files'
498
499  if [[ $state == 'diff_files' ]]
500  then
501    if [[ -n $opt_args[-r] ]]
502    then
503      _hg_files
504    else
505      _hg_modified
506    fi
507  fi
508}
509
510_hg_cmd_export() {
511  _arguments -s -w : $_hg_global_opts $_hg_diff_opts \
512  '(--outout -o)'{-o+,--output}'[print output to file with formatted name]:filespec:' \
513  '--switch-parent[diff against the second parent]' \
514  '*:revision:_hg_tags'
515}
516
517_hg_cmd_grep() {
518  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
519  '(--print0 -0)'{-0,--print0}'[end filenames with NUL]' \
520  '--all[print all revisions with matches]' \
521  '(--follow -f)'{-f,--follow}'[follow changeset or file history]' \
522  '(--ignore-case -i)'{-i,--ignore-case}'[ignore case when matching]' \
523  '(--files-with-matches -l)'{-l,--files-with-matches}'[print only filenames and revs that match]' \
524  '(--line-number -n)'{-n,--line-number}'[print matching line numbers]' \
525  '*'{-r+,--rev}'[search in given revision range]:revision:_hg_revrange' \
526  '(--user -u)'{-u,--user}'[print user who committed change]' \
527  '1:search pattern:' \
528  '*:files:_hg_files'
529}
530
531_hg_cmd_heads() {
532  _arguments -s -w : $_hg_global_opts $_hg_style_opts \
533  '(--rev -r)'{-r+,--rev}'[show only heads which are descendants of rev]:revision:_hg_tags'
534}
535
536_hg_cmd_help() {
537  _arguments -s -w : $_hg_global_opts \
538  '*:mercurial command:_hg_commands'
539}
540
541_hg_cmd_identify() {
542  _arguments -s -w : $_hg_global_opts \
543  '(--rev -r)'{-r+,--rev}'[identify the specified rev]:revision:_hg_tags' \
544  '(--num -n)'{-n+,--num}'[show local revision number]' \
545  '(--id -i)'{-i+,--id}'[show global revision id]' \
546  '(--branch -b)'{-b+,--branch}'[show branch]' \
547  '(--tags -t)'{-t+,--tags}'[show tags]'
548}
549
550_hg_cmd_import() {
551  _arguments -s -w : $_hg_global_opts \
552  '(--strip -p)'{-p+,--strip}'[directory strip option for patch (default: 1)]:count:' \
553  '(--message -m)'{-m+,--message}'[use <text> as commit message]:text:' \
554  '(--force -f)'{-f,--force}'[skip check for outstanding uncommitted changes]' \
555  '*:patch:_files'
556}
557
558_hg_cmd_incoming() {
559  _arguments -s -w : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \
560  '(--no-merges -M)'{-M,--no-merges}'[do not show merge revisions]' \
561  '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \
562  '(--patch -p)'{-p,--patch}'[show patch]' \
563  '(--rev -r)'{-r+,--rev}'[a specific revision up to which you would like to pull]:revision:_hg_tags' \
564  '(--newest-first -n)'{-n,--newest-first}'[show newest record first]' \
565  '--bundle[file to store the bundles into]:bundle file:_files' \
566  ':source:_hg_remote'
567}
568
569_hg_cmd_init() {
570  _arguments -s -w : $_hg_global_opts $_hg_remote_opts \
571  ':dir:_files -/'
572}
573
574_hg_cmd_locate() {
575  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
576  '(--rev -r)'{-r+,--rev}'[search repository as it stood at revision]:revision:_hg_tags' \
577  '(--print0 -0)'{-0,--print0}'[end filenames with NUL, for use with xargs]' \
578  '(--fullpath -f)'{-f,--fullpath}'[print complete paths]' \
579  '*:search pattern:_hg_files'
580}
581
582_hg_cmd_log() {
583  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_style_opts \
584  '(--follow --follow-first -f)'{-f,--follow}'[follow changeset or history]' \
585  '(-f --follow)--follow-first[only follow the first parent of merge changesets]' \
586  '(--copies -C)'{-C,--copies}'[show copied files]' \
587  '(--keyword -k)'{-k+,--keyword}'[search for a keyword]:' \
588  '(--limit -l)'{-l+,--limit}'[limit number of changes displayed]:' \
589  '*'{-r,--rev}'[show the specified revision or range]:revision:_hg_revrange' \
590  '(--no-merges -M)'{-M,--no-merges}'[do not show merges]' \
591  '(--only-merges -m)'{-m,--only-merges}'[show only merges]' \
592  '(--patch -p)'{-p,--patch}'[show patch]' \
593  '(--prune -P)'{-P+,--prune}'[do not display revision or any of its ancestors]:revision:_hg_tags' \
594  '*:files:_hg_files'
595}
596
597_hg_cmd_manifest() {
598  _arguments -s -w : $_hg_global_opts \
599  ':revision:_hg_tags'
600}
601
602_hg_cmd_merge() {
603  _arguments -s -w : $_hg_global_opts \
604  '(--force -f)'{-f,--force}'[force a merge with outstanding changes]' \
605  '(--rev -r 1)'{-r,--rev}'[revision to merge]:revision:_hg_mergerevs' \
606  '(--preview -P)'{-P,--preview}'[review revisions to merge (no merge is performed)]' \
607  ':revision:_hg_mergerevs'
608}
609
610_hg_cmd_outgoing() {
611  _arguments -s -w : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \
612  '(--no-merges -M)'{-M,--no-merges}'[do not show merge revisions]' \
613  '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \
614  '(--patch -p)'{-p,--patch}'[show patch]' \
615  '(--rev -r)'{-r+,--rev}'[a specific revision you would like to push]' \
616  '(--newest-first -n)'{-n,--newest-first}'[show newest record first]' \
617  ':destination:_hg_remote'
618}
619
620_hg_cmd_parents() {
621  _arguments -s -w : $_hg_global_opts $_hg_style_opts \
622  '(--rev -r)'{-r+,--rev}'[show parents of the specified rev]:revision:_hg_tags' \
623  ':last modified file:_hg_files'
624}
625
626_hg_cmd_paths() {
627  _arguments -s -w : $_hg_global_opts \
628  ':path:_hg_paths'
629}
630
631_hg_cmd_pull() {
632  _arguments -s -w : $_hg_global_opts $_hg_remote_opts \
633  '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \
634  '(--update -u)'{-u,--update}'[update to new tip if changesets were pulled]' \
635  '(--rev -r)'{-r+,--rev}'[a specific revision up to which you would like to pull]:revision:' \
636  ':source:_hg_remote'
637}
638
639_hg_cmd_push() {
640  _arguments -s -w : $_hg_global_opts $_hg_remote_opts \
641  '(--force -f)'{-f,--force}'[force push]' \
642  '(--rev -r)'{-r+,--rev}'[a specific revision you would like to push]:revision:_hg_tags' \
643  ':destination:_hg_remote'
644}
645
646_hg_cmd_remove() {
647  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
648  '(--after -A)'{-A,--after}'[record remove that has already occurred]' \
649  '(--force -f)'{-f,--force}'[remove file even if modified]' \
650  '*:file:_hg_files'
651}
652
653_hg_cmd_rename() {
654  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
655  '(--after -A)'{-A,--after}'[record a rename that has already occurred]' \
656  '(--force -f)'{-f,--force}'[forcibly copy over an existing managed file]' \
657  '*:file:_hg_files'
658}
659
660_hg_cmd_resolve() {
661  local context state line
662  typeset -A opt_args
663
664  _arguments -s -w : $_hg_global_opts \
665  '(--list -l --mark -m --unmark -u)'{-l,--list}'[list state of files needing merge]:*:merged files:->resolve_files' \
666  '(--mark -m --list -l --unmark -u)'{-m,--mark}'[mark files as resolved]:*:unresolved files:_hg_unresolved' \
667  '(--unmark -u --list -l --mark -m)'{-u,--unmark}'[unmark files as resolved]:*:resolved files:_hg_resolved' \
668  '*:file:_hg_unresolved'
669
670  if [[ $state == 'resolve_files' ]]
671  then
672    _alternative 'files:resolved files:_hg_resolved' \
673      'files:unresolved files:_hg_unresolved'
674  fi
675}
676
677_hg_cmd_revert() {
678  local context state line
679  typeset -A opt_args
680
681  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
682  '(--all -a :)'{-a,--all}'[revert all changes when no arguments given]' \
683  '(--rev -r)'{-r+,--rev}'[revision to revert to]:revision:_hg_tags' \
684  '--no-backup[do not save backup copies of files]' \
685  '*:file:->diff_files'
686
687  if [[ $state == 'diff_files' ]]
688  then
689    if [[ -n $opt_args[-r] ]]
690    then
691      _hg_files
692    else
693      typeset -a status_files
694      _hg_status mard
695      _wanted files expl 'modified, added, removed or deleted file' _multi_parts / status_files
696    fi
697  fi
698}
699
700_hg_cmd_serve() {
701  _arguments -s -w : $_hg_global_opts \
702  '(--accesslog -A)'{-A+,--accesslog}'[name of access log file]:log file:_files' \
703  '(--errorlog -E)'{-E+,--errorlog}'[name of error log file]:log file:_files' \
704  '(--daemon -d)'{-d,--daemon}'[run server in background]' \
705  '(--port -p)'{-p+,--port}'[listen port]:listen port:' \
706  '(--address -a)'{-a+,--address}'[interface address]:interface address:' \
707  '(--name -n)'{-n+,--name}'[name to show in web pages]:repository name:' \
708  '(--templates -t)'{-t,--templates}'[web template directory]:template dir:_files -/' \
709  '--style[web template style]:style' \
710  '--stdio[for remote clients]' \
711  '(--ipv6 -6)'{-6,--ipv6}'[use IPv6 in addition to IPv4]'
712}
713
714_hg_cmd_showconfig() {
715  _arguments -s -w : $_hg_global_opts \
716  '(--untrusted -u)'{-u+,--untrusted}'[show untrusted configuration options]' \
717  ':config item:_hg_config'
718}
719
720_hg_cmd_status() {
721  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
722  '(--all -A)'{-A,--all}'[show status of all files]' \
723  '(--modified -m)'{-m,--modified}'[show only modified files]' \
724  '(--added -a)'{-a,--added}'[show only added files]' \
725  '(--removed -r)'{-r,--removed}'[show only removed files]' \
726  '(--deleted -d)'{-d,--deleted}'[show only deleted (but tracked) files]' \
727  '(--clean -c)'{-c,--clean}'[show only files without changes]' \
728  '(--unknown -u)'{-u,--unknown}'[show only unknown files]' \
729  '(--ignored -i)'{-i,--ignored}'[show ignored files]' \
730  '(--no-status -n)'{-n,--no-status}'[hide status prefix]' \
731  '(--copies -C)'{-C,--copies}'[show source of copied files]' \
732  '(--print0 -0)'{-0,--print0}'[end filenames with NUL, for use with xargs]' \
733  '--rev[show difference from revision]:revision:_hg_tags' \
734  '*:files:_files'
735}
736
737_hg_cmd_tag() {
738  _arguments -s -w : $_hg_global_opts \
739  '(--local -l)'{-l,--local}'[make the tag local]' \
740  '(--message -m)'{-m+,--message}'[message for tag commit log entry]:message:' \
741  '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \
742  '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \
743  '(--rev -r)'{-r+,--rev}'[revision to tag]:revision:_hg_tags' \
744  ':tag name:'
745}
746
747_hg_cmd_tip() {
748  _arguments -s -w : $_hg_global_opts $_hg_style_opts \
749  '(--patch -p)'{-p,--patch}'[show patch]'
750}
751
752_hg_cmd_unbundle() {
753  _arguments -s -w : $_hg_global_opts \
754  '(--update -u)'{-u,--update}'[update to new tip if changesets were unbundled]' \
755  ':files:_files'
756}
757
758_hg_cmd_update() {
759  _arguments -s -w : $_hg_global_opts \
760  '(--clean -C)'{-C,--clean}'[overwrite locally modified files]' \
761  '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \
762  ':revision:_hg_tags'
763}
764
765# HGK
766_hg_cmd_view() {
767  _arguments -s -w : $_hg_global_opts \
768  '(--limit -l)'{-l+,--limit}'[limit number of changes displayed]:' \
769  ':revision range:_hg_tags'
770}
771
772# MQ
773_hg_qseries() {
774  typeset -a patches
775  patches=(${(f)"$(_hg_cmd qseries 2> /dev/null)"})
776  (( $#patches )) && _describe -t hg-patches 'patches' patches
777}
778
779_hg_qapplied() {
780  typeset -a patches
781  patches=(${(f)"$(_hg_cmd qapplied 2> /dev/null)"})
782  if (( $#patches ))
783  then
784    patches+=(qbase qtip)
785    _describe -t hg-applied-patches 'applied patches' patches
786  fi
787}
788
789_hg_qunapplied() {
790  typeset -a patches
791  patches=(${(f)"$(_hg_cmd qunapplied 2> /dev/null)"})
792  (( $#patches )) && _describe -t hg-unapplied-patches 'unapplied patches' patches
793}
794
795# unapplied, including guarded patches
796_hg_qdeletable() {
797  typeset -a unapplied
798  unapplied=(${(f)"$(_hg_cmd qseries 2> /dev/null)"})
799  for p in $(_hg_cmd qapplied)
800  do
801    unapplied=(${unapplied:#$p})
802  done
803
804  (( $#unapplied )) && _describe -t hg-allunapplied-patches 'all unapplied patches' unapplied
805}
806
807_hg_qguards() {
808  typeset -a guards
809  local guard
810  compset -P "+|-"
811  _hg_cmd qselect -s 2> /dev/null | while read guard
812  do
813    guards+=(${guard#(+|-)})
814  done
815  (( $#guards )) && _describe -t hg-guards 'guards' guards
816}
817
818_hg_qseries_opts=(
819  '(--summary -s)'{-s,--summary}'[print first line of patch header]')
820
821_hg_cmd_qapplied() {
822  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts
823}
824
825_hg_cmd_qdelete() {
826  _arguments -s -w : $_hg_global_opts \
827  '(--keep -k)'{-k,--keep}'[keep patch file]' \
828  '*'{-r+,--rev}'[stop managing a revision]:applied patch:_hg_revrange' \
829  '*:unapplied patch:_hg_qdeletable'
830}
831
832_hg_cmd_qdiff() {
833  _arguments -s -w : $_hg_global_opts $_hg_pat_opts \
834  '*:pattern:_hg_files'
835}
836
837_hg_cmd_qfold() {
838  _arguments -s -w : $_hg_global_opts $_h_commit_opts \
839  '(--keep,-k)'{-k,--keep}'[keep folded patch files]' \
840  '*:unapplied patch:_hg_qunapplied'
841}
842
843_hg_cmd_qgoto() {
844  _arguments -s -w : $_hg_global_opts \
845  '(--force -f)'{-f,--force}'[overwrite any local changes]' \
846  ':patch:_hg_qseries'
847}
848
849_hg_cmd_qguard() {
850  _arguments -s -w : $_hg_global_opts \
851  '(--list -l)'{-l,--list}'[list all patches and guards]' \
852  '(--none -n)'{-n,--none}'[drop all guards]' \
853  ':patch:_hg_qseries' \
854  '*:guards:_hg_qguards'
855}
856
857_hg_cmd_qheader() {
858  _arguments -s -w : $_hg_global_opts \
859  ':patch:_hg_qseries'
860}
861
862_hg_cmd_qimport() {
863  _arguments -s -w : $_hg_global_opts \
864  '(--existing -e)'{-e,--existing}'[import file in patch dir]' \
865  '(--name -n 2)'{-n+,--name}'[patch file name]:name:' \
866  '(--force -f)'{-f,--force}'[overwrite existing files]' \
867  '*'{-r+,--rev}'[place existing revisions under mq control]:revision:_hg_revrange' \
868  '*:patch:_files'
869}
870
871_hg_cmd_qnew() {
872  _arguments -s -w : $_hg_global_opts $_hg_commit_opts \
873  '(--force -f)'{-f,--force}'[import uncommitted changes into patch]' \
874  ':patch:'
875}
876
877_hg_cmd_qnext() {
878  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts
879}
880
881_hg_cmd_qpop() {
882  _arguments -s -w : $_hg_global_opts \
883  '(--all -a :)'{-a,--all}'[pop all patches]' \
884  '(--name -n)'{-n+,--name}'[queue name to pop]:' \
885  '(--force -f)'{-f,--force}'[forget any local changes]' \
886  ':patch:_hg_qapplied'
887}
888
889_hg_cmd_qprev() {
890  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts
891}
892
893_hg_cmd_qpush() {
894  _arguments -s -w : $_hg_global_opts \
895  '(--all -a :)'{-a,--all}'[apply all patches]' \
896  '(--list -l)'{-l,--list}'[list patch name in commit text]' \
897  '(--merge -m)'{-m+,--merge}'[merge from another queue]:' \
898  '(--name -n)'{-n+,--name}'[merge queue name]:' \
899  '(--force -f)'{-f,--force}'[apply if the patch has rejects]' \
900  ':patch:_hg_qunapplied'
901}
902
903_hg_cmd_qrefresh() {
904  _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_commit_opts \
905  '(--git -g)'{-g,--git}'[use git extended diff format]' \
906  '(--short -s)'{-s,--short}'[short refresh]' \
907  '*:files:_hg_files'
908}
909
910_hg_cmd_qrename() {
911  _arguments -s -w : $_hg_global_opts \
912  ':patch:_hg_qseries' \
913  ':destination:'
914}
915
916_hg_cmd_qselect() {
917  _arguments -s -w : $_hg_global_opts \
918  '(--none -n :)'{-n,--none}'[disable all guards]' \
919  '(--series -s :)'{-s,--series}'[list all guards in series file]' \
920  '--pop[pop to before first guarded applied patch]' \
921  '--reapply[pop and reapply patches]' \
922  '*:guards:_hg_qguards'
923}
924
925_hg_cmd_qseries() {
926  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts \
927  '(--missing -m)'{-m,--missing}'[print patches not in series]'
928}
929
930_hg_cmd_qunapplied() {
931  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts
932}
933
934_hg_cmd_qtop() {
935  _arguments -s -w : $_hg_global_opts $_hg_qseries_opts
936}
937
938_hg_cmd_strip() {
939  _arguments -s -w : $_hg_global_opts \
940  '(--force -f)'{-f,--force}'[force multi-head removal]' \
941  '(--backup -b)'{-b,--backup}'[bundle unrelated changesets]' \
942  '(--nobackup -n)'{-n,--nobackup}'[no backups]' \
943  ':revision:_hg_tags'
944}
945
946_hg "$@"
947