mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-11-04 07:21:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2017 lines
		
	
	
	
		
			62 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			2017 lines
		
	
	
	
		
			62 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
#compdef p4 -value-,P4CLIENT,-default- -value-,P4PORT,-default- -value-,P4MERGE,-default- -value-,P4USER,-default-
 | 
						|
 | 
						|
# Increasingly loosely based on _cvs version 1.17.
 | 
						|
# Completions currently based on Perforce release 2004.2.
 | 
						|
 | 
						|
# Styles, tags and contexts
 | 
						|
# =========================
 | 
						|
#
 | 
						|
# If the `verbose' style is set (it is assumed by default), verbose
 | 
						|
# descriptions are provided for many completed quantities derived
 | 
						|
# dynamically such as subcommand names, labels, changes -- in fact,
 | 
						|
# just about anything for which Perforce itself produces a verbose,
 | 
						|
# one-line description.  It may be turned off in the context of each
 | 
						|
# subcommand e.g.
 | 
						|
#   zstyle ':completion:*:p4-labelsync:*' verbose false
 | 
						|
# or for a particular tag, e.g. changes,
 | 
						|
#   zstyle ':completion:*:changes' verbose false
 | 
						|
# or just for top-level completion (i.e. up to and including completion
 | 
						|
# of the subcommand):
 | 
						|
#   zstyle ':completion:*:p4:*' verbose false
 | 
						|
# or for p4 as a whole,
 | 
						|
#   zstyle  ':completion:*:p4(-*|):*' verbose false
 | 
						|
# This is actually handled by the `_describe' function underneath the
 | 
						|
# Perforce completion system; it's mentioned here as verbosity adds
 | 
						|
# significantly to a lot of the Perforce completions.
 | 
						|
#
 | 
						|
# Note that completing change numbers is not very useful if `verbose' is
 | 
						|
# turned off.  There is no speed advantage for turning it off, either.
 | 
						|
# (Changes are also known as changelists or changesets.  The functions
 | 
						|
# and tags here all consistently use `changes'.)
 | 
						|
#
 | 
						|
# The style `max' can be set to a number which limits how many
 | 
						|
# possibilities can be shown when selecting changes or jobs.  This is
 | 
						|
# handled within Perforce, so the completion code may limit the number even
 | 
						|
# further.  If not set explicitly, the value is taken to be 20 to avoid a
 | 
						|
# huge database being output.  Set it to a larger number if necessary.
 | 
						|
# Setting it explicitly to zero removes the maximum.  Because you see only
 | 
						|
# the most recent, changes and jobs are shown in the order given by
 | 
						|
# Perforce without further sorting.
 | 
						|
#
 | 
						|
# Completion of jobs can also be controlled by the `jobview' style.
 | 
						|
# This uses the standard Perforce JobView syntax, and is applied
 | 
						|
# in connection with the `max' style.  In other words,
 | 
						|
# if you set
 | 
						|
#   zstyle ':completion:*:p4-*:jobs' max 0
 | 
						|
#   zstyle ':completion:*:p4-*:jobs' jobview 'user=pws'
 | 
						|
# then jobs to be completed will be those from the output of
 | 
						|
#   p4 jobs -e 'user=pws'
 | 
						|
# i.e. those assigned to Perforce user `pws'.
 | 
						|
#
 | 
						|
# Completion of changes can be controlled by the `changes' style.
 | 
						|
# This takes additional arguments to be passed to `p4 changes'.
 | 
						|
# An obvious example is:
 | 
						|
#   zstyle ':completion:*:p4-*:changes' changes -u $USER
 | 
						|
# to limit changes to the present user.
 | 
						|
#
 | 
						|
# The style `all-files' is used to tell the completion system to
 | 
						|
# complete any file in a given context.  This is for use in places
 | 
						|
# where it would, for example, only complete files opened for editing.
 | 
						|
# See the next section for more.
 | 
						|
#
 | 
						|
# The style `depot-files' tells the system to complete files by asking
 | 
						|
# Perforce for a list where it would otherwise complete files locally by
 | 
						|
# the standard mechanism --- basically any time you don't use // notation
 | 
						|
# and there is no restriction e.g. to opened files only.  There is likely
 | 
						|
# to be a significant speed penalty for this; it is turned off by default
 | 
						|
# in all contexts.  The advantage is that it cuts out files not maintained
 | 
						|
# by Perforce.  (Again, note this is a style, not a tag.)  Contexts
 | 
						|
# where this might be particularly useful include p4-diff or p4-diff2.
 | 
						|
#
 | 
						|
# The tags depot-files and depot-dirs also exist; they are used whenever
 | 
						|
# the system is completing files or directories by asking Perforce
 | 
						|
# to list them, rather than by using normal file completion.
 | 
						|
#
 | 
						|
# The tag subdirs is used to complete the special `...' which tells
 | 
						|
# Perforce to search all subdirectories.  Hence you can turn this
 | 
						|
# feature off by suitably manipulating your tags.
 | 
						|
#
 | 
						|
# Completion of files and their revisions
 | 
						|
# =======================================
 | 
						|
#
 | 
						|
# File completion handles @ and # suffixes.  If the filename is completed,
 | 
						|
# typing @ or # removes the space which was automatically added.
 | 
						|
# The context used has `at-suffix' or `hash-suffix' in the position
 | 
						|
# before the tag to indicate suffix completion (as always, ^Xh will
 | 
						|
# show you all possible contexts).  This makes it possible
 | 
						|
# to select changes, dates, labels and clients using the tag-order
 | 
						|
# style.  For example,
 | 
						|
#    zstyle ':completion:*:p4-*:at-suffix:*' tag-order changes '*'
 | 
						|
# will force all completion after `@' to show changes first.  Executing
 | 
						|
# _next_tags (usually ^x^n) will cycle between that and the remaining
 | 
						|
# tags (dates, labels, clients).  I recommend, at least, keeping labels
 | 
						|
# later than changes since the former are less useful and can take a long
 | 
						|
# time to complete.
 | 
						|
#
 | 
						|
# A # is automatically quoted when handled in this way; if the file is
 | 
						|
# typed by hand or the completion didn't finish (e.g. you typed a character
 | 
						|
# in the middle of menu completion), you probably need to type `\#' by
 | 
						|
# hand.  The problem is that the completion system uses extended globbing
 | 
						|
# and hence a pattern of the form `filename#' always matches `filename'
 | 
						|
# (since e# matches any number of e's including one).  Hence this can look
 | 
						|
# like an expansion which expands to `filename'.
 | 
						|
#
 | 
						|
# After @, you can complete changes (note the use of the style `max'
 | 
						|
# above), labels, clients or even dates, while after `#' you can
 | 
						|
# complete numeric revisions or the special revision names head, none,
 | 
						|
# have.  These are available whether or not you completed the filename; if
 | 
						|
# the file doesn't exist, numeric revisions won't work, but the rest will
 | 
						|
# (though what Perforce will do with the resulting command is another matter).
 | 
						|
#
 | 
						|
# In addition, when completing after `file@', only changes specific to `file'
 | 
						|
# will be shown (exactly the list of changes Perforce shows from the
 | 
						|
# command `p4 changes file').  If this doesn't work, chances are that
 | 
						|
# `file' does not exist.  Having a multi-directory match (literal `...')
 | 
						|
# in `file' should work fine, since `p4 changes' recognises all normal
 | 
						|
# Perforce file syntax.
 | 
						|
#
 | 
						|
# Some perforce commands allow you to specify a range of revisions or
 | 
						|
# changes as `file@1,@2' or `file#1,#2'.  Currently, the second part of the
 | 
						|
# revision range can always be completed (whether the command accepts them
 | 
						|
# or not), but the comma after the first part of the range is only added
 | 
						|
# automatically if the documentation suggests the command accepts ranges at
 | 
						|
# that point.  This is an auto-removable suffix, so it will disappear if
 | 
						|
# you hit space or return.  Typing a `#' at this point will insert a
 | 
						|
# backslash, as before.  The # and @ are never added automatically; you
 | 
						|
# have to select one by hand.
 | 
						|
#
 | 
						|
# Perforce allows change and revision numbers to be preceded by =, <, <=, >
 | 
						|
# or >=.  See `p4 help undoc' for details.  (In particular, `=' is
 | 
						|
# an extremely useful shortcut when integrating single changes.)
 | 
						|
# This syntax is handled, but currently the < and > must be quoted
 | 
						|
# with a backslash, not by any other mechanism.  For example,
 | 
						|
#   p4 files myfile@\>=3<TAB>
 | 
						|
# will complete a change number.  The valid syntax where the second
 | 
						|
# change or revision in a range does not have the @ or # in front
 | 
						|
# (for example `file@32183,32185') is not currently handled; the @
 | 
						|
# must be repeated.
 | 
						|
#
 | 
						|
# File completion for some functions is restricted by the Perforce
 | 
						|
# status of the file; for example, `p4 opened' only completes opened
 | 
						|
# files (surprised?)  However, you can set the style (N.B. not tag)
 | 
						|
# all-files; so, for example, you can turn off the limit in this case by
 | 
						|
#   zstyle ':completion:*:p4-opened:*' all-files true
 | 
						|
# Normally the file-patterns style would be used to control matching,
 | 
						|
# but as the file types are not selected by globbing it doesn't work here
 | 
						|
# However, if you set the all-files style, all filename completion is done
 | 
						|
# by the standard mechanism; in this case, the file-patterns style works
 | 
						|
# as usual.  The style ignored-patterns is available in any case, even
 | 
						|
# without all-files; this is therefore generally the one to use.
 | 
						|
#
 | 
						|
# With `p4 diff', the shell will spot if you have used an option that
 | 
						|
# allows you to diff unopened files (such as -f) and in that case offer
 | 
						|
# all files; otherwise, it just offers opened files.
 | 
						|
#
 | 
						|
# Completion of changes
 | 
						|
# =====================
 | 
						|
#
 | 
						|
# There is various extra magic available any time change numbers
 | 
						|
# are completed, regardless of how this was reached, i.e.
 | 
						|
# `p4 fixes -c ...' and `p4 diff filename.c@...' are treated the same way.
 | 
						|
# Note, however, these only work if you are at the point where a change
 | 
						|
# number would be completed.
 | 
						|
#
 | 
						|
# Firstly, as mentioned above there is a maximum for the number of
 | 
						|
# changes which will be shown, given by the style max, or defaulting to 20.
 | 
						|
# Only the most recent changes will be shown.  This is to avoid a speed
 | 
						|
# penalty or clumsy output.  If a positive numeric argument is given
 | 
						|
# when changes are being completed, the maximum is set (unconditionally)
 | 
						|
# to that number instead.
 | 
						|
#
 | 
						|
# It is also possible to give a negative numeric prefix to a listing widget
 | 
						|
# (i.e. typically whatever is bound to ^D).  If there is already a change
 | 
						|
# number on the line, e.g. from cycling through a menu of choices, the full
 | 
						|
# description for that change is shown in the format of a completion
 | 
						|
# listing.  [TODO: this could be made configurable with a style.]
 | 
						|
#
 | 
						|
# It may be necessary to abandon the current completion attempt before
 | 
						|
# typing this to force the completion system to display the new text.
 | 
						|
# Replacing delete-char-or-list with the following user defined widget
 | 
						|
# (create with `zle -N ...') will force this for any negative prefix argument.
 | 
						|
#    (( ${NUMERIC:-0} < 0 )) && (( CURSOR = CURSOR ))
 | 
						|
#    zle delete-char-or-list
 | 
						|
#
 | 
						|
# Completion of jobs
 | 
						|
# =================
 | 
						|
#
 | 
						|
# Completing jobs uses the same logic for the numeric prefix as completing
 | 
						|
# changes: a positive prefix changes the maximum number of jobs which
 | 
						|
# will be shown, and a negative prefix when listing shows the full
 | 
						|
# text for the job whose name is currently inserted on the command line.
 | 
						|
# In this case, the entire text of the word being completed is assumed
 | 
						|
# to constitute the job name (which is almost certainly correct).
 | 
						|
#
 | 
						|
# Completion of dates
 | 
						|
# ===================
 | 
						|
#
 | 
						|
# In a file revision specification it is possible to give a date
 | 
						|
# in the form file@YYYY/MM/DD:hh:mm:ss, which may be completed.  This
 | 
						|
# is ever so slightly less silly than it sounds.  Any component entered
 | 
						|
# by hand with the appropriate suffix will be ignored; any component
 | 
						|
# completed will be set to the current value.  Hence you can easily
 | 
						|
# specify, say, one month ago by using the completed value for all
 | 
						|
# components except the month and setting that to one less.  The shell
 | 
						|
# will also happily append the appropriate suffix if you try to complete
 | 
						|
# after anything which is already the appropriate width.  (Perforce
 | 
						|
# supports two-digit years, but these are confusing and no longer
 | 
						|
# particularly useful as they refer to the twentieth century, so
 | 
						|
# the shell does not.)
 | 
						|
#
 | 
						|
# Calls to p4
 | 
						|
# ===========
 | 
						|
#
 | 
						|
# Much of the information from Perforce is provided by calls to p4
 | 
						|
# commands.  This is done via the _call_program interface, as described
 | 
						|
# in the zshcompsys manual page.  Hence a suitable context with the
 | 
						|
# `command' style allows the user to take control of this call.
 | 
						|
# The tags used are the name of the p4 command, or in the case of
 | 
						|
# calls to help subcommands, `help-<subcommand>'.  Note that if the
 | 
						|
# value of the style begins with `-', the arguments to the perforce
 | 
						|
# command are appended to the remaining words of the style before calling
 | 
						|
# the command.
 | 
						|
#
 | 
						|
# Programmes taking p4-style arguments
 | 
						|
# ====================================
 | 
						|
#
 | 
						|
# It is possible to use the _perforce completion with other commands
 | 
						|
# which behave like a subcommand of p4 by setting the service type
 | 
						|
# to p4-<subcommand>.  For example,
 | 
						|
#   compdef _perforce p4cvsmap=p4-files
 | 
						|
# says that the command `p4cvsmap' takes arguments like `p4 files'.
 | 
						|
# Often the options will be different; if this is a problem, you
 | 
						|
# will need to write your own completer which loads _perforce and
 | 
						|
# calls its functions directly.  You can add -global to the end
 | 
						|
# of the service to say that the command also handles global
 | 
						|
# Perforce options, comme ca:
 | 
						|
#   compdef _perforce p4reopen=p4-job-global
 | 
						|
#
 | 
						|
# Anything more complicated should be modelled on one of the
 | 
						|
# _perforce_cmd_* handlers below.  To get this to work, the full
 | 
						|
# set of _perforce functions must be loaded; because of the way
 | 
						|
# autoloading works, a trick is required:  call "_perforce -l" which
 | 
						|
# causes the function to be executed, loading all the associated
 | 
						|
# functions as a side effect, but tells _perforce to return without
 | 
						|
# generating any completions.  For example, here is the completion
 | 
						|
# for my `p4desc' function which is an enhanced version of `p4 describe'
 | 
						|
# (without any handling for global Perforce arguments):
 | 
						|
#
 | 
						|
#  #compdef p4desc
 | 
						|
#
 | 
						|
#  _perforce -l
 | 
						|
#
 | 
						|
#  _arguments -s : \
 | 
						|
#    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context d\:basic\ diff n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
 | 
						|
#    '-s[short form]' \
 | 
						|
#    '-j[select by job]:job:_perforce_jobs' \
 | 
						|
#    '*::change:_perforce_changes'
 | 
						|
#
 | 
						|
# To add handling of global options to this, see the end of the _perforce
 | 
						|
# function below.  Something like:
 | 
						|
#
 | 
						|
#   local -a _perforce_global_options _perforce_option_dispatch
 | 
						|
#   if _perforce_global_options; then
 | 
						|
#     _arguments -s : $_perforce_option_dispatch \
 | 
						|
#       '<other stuff>'
 | 
						|
#   fi
 | 
						|
#
 | 
						|
# TODO
 | 
						|
# ====
 | 
						|
#
 | 
						|
# No mechanism is provided for completely ignoring certain files not
 | 
						|
# handled by Perforce as with .cvsignore.  This could be done ad hoc.
 | 
						|
# However, the ignored-patterns style and the parameter $fignore are
 | 
						|
# of course applied as usual, so setting ignored-patterns for the
 | 
						|
# context `:completion:*:p4[-:]*' should work.
 | 
						|
 | 
						|
_perforce() {
 | 
						|
  # rely on localoptions
 | 
						|
  setopt nonomatch
 | 
						|
  local p4cmd==p4 match mbegin mend
 | 
						|
  integer _perforce_cmd_ind
 | 
						|
 | 
						|
  if [[ $1 = -l ]]; then
 | 
						|
    # Run to load _perforce and associated functions but do
 | 
						|
    # nothing else.
 | 
						|
    return
 | 
						|
  fi
 | 
						|
 | 
						|
  if [[ $service = -value-* ]]; then
 | 
						|
    # Completing parameter value.
 | 
						|
    # Some of these --- in particular P4PORT --- don't need
 | 
						|
    # the perforce server.
 | 
						|
    case $compstate[parameter] in
 | 
						|
      (P4PORT)
 | 
						|
      _perforce_hosts_ports
 | 
						|
      ;;
 | 
						|
 | 
						|
      (P4CLIENT)
 | 
						|
      _perforce_clients
 | 
						|
      ;;
 | 
						|
 | 
						|
      (P4MERGE)
 | 
						|
      _command_names -e
 | 
						|
      ;;
 | 
						|
 | 
						|
      (P4USER)
 | 
						|
      _perforce_users
 | 
						|
      ;;
 | 
						|
    esac
 | 
						|
    # We do not handle values anywhere else.
 | 
						|
    return
 | 
						|
  fi
 | 
						|
 | 
						|
  if [[ $p4cmd = '=p4' ]]; then
 | 
						|
    _message "p4 executable not found: completion not available"
 | 
						|
    return
 | 
						|
  fi
 | 
						|
 | 
						|
  # If we are at or after the command word, remember the
 | 
						|
  # global arguments to p4 as we will need to pass these down
 | 
						|
  # when generating completion lists.
 | 
						|
  # This is both an array and a function, but luckily I never
 | 
						|
  # get confused...
 | 
						|
  local -a _perforce_global_options
 | 
						|
  local -a _perforce_option_dispatch
 | 
						|
 | 
						|
  # If we are given a service of the form p4-cmd, treat this
 | 
						|
  # as if it was after `p4 cmd'.  This provides an easy way in
 | 
						|
  # for scripts and functions that emulate the behaviour of
 | 
						|
  # p4 subcommands.  Note we don't shorten the command line arguments.
 | 
						|
  if [[ $service = p4-(#b)(*) ]]; then
 | 
						|
    local curcontext="$curcontext"
 | 
						|
    local p4cmd=$words[1] cmd=$match[1] gbl
 | 
						|
 | 
						|
    if [[ $cmd = (#b)(*)-global ]]; then
 | 
						|
      # Handles global options.
 | 
						|
      cmd=$match[1]
 | 
						|
      _perforce_global_options && gbl=1
 | 
						|
    fi
 | 
						|
    if (( $+functions[_perforce_cmd_$cmd] )); then
 | 
						|
      curcontext="${curcontext%:*:*}:p4-${cmd}:"
 | 
						|
      if [[ -n $gbl ]]; then
 | 
						|
	# We are handling global Perforce options as well as the
 | 
						|
	# arguments to the specific command.
 | 
						|
	# To handle the latter, we need the command name, plus
 | 
						|
	# all the arguments for the command with the global options
 | 
						|
	# removed.  The function _perforce_service_dispatch handles
 | 
						|
	# this by unshifting the command ($p4cmd) into words,
 | 
						|
	# then dispatching for the Perforce subcommand $cmd.
 | 
						|
	#
 | 
						|
	# Has anyone noticed this is getting rather complicated?
 | 
						|
	_arguments -s : $_perforce_option_dispatch \
 | 
						|
	"*::p4-$cmd arguments: _perforce_service_dispatch $p4cmd $cmd"
 | 
						|
      else
 | 
						|
	_perforce_cmd_$cmd
 | 
						|
      fi
 | 
						|
      # Don't try to do full command handling.
 | 
						|
      return
 | 
						|
    else
 | 
						|
      _message "unhandled _perforce service: $service"
 | 
						|
      return 1
 | 
						|
    fi
 | 
						|
  fi
 | 
						|
 | 
						|
  if _perforce_global_options; then
 | 
						|
    _arguments -s : $_perforce_option_dispatch \
 | 
						|
    '1:perforce command:_perforce_commands'
 | 
						|
  else
 | 
						|
    (( _perforce_cmd_ind-- ))
 | 
						|
    (( CURRENT -= _perforce_cmd_ind ))
 | 
						|
    shift $_perforce_cmd_ind words
 | 
						|
    _perforce_command_args
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Command and argument dispatchers
 | 
						|
#
 | 
						|
 | 
						|
# Front end to _call_program to add in the global arguments
 | 
						|
# passed to p4.  The first argument is the tag, the remaining
 | 
						|
# arguments are passed to p4.  Typically the tag is the same
 | 
						|
# as the first p4 argument.
 | 
						|
(( $+functions[_perforce_call_p4] )) ||
 | 
						|
_perforce_call_p4() {
 | 
						|
  local cp_tag=$1
 | 
						|
  shift
 | 
						|
  # This is for our own use for parsing, and we need English output,
 | 
						|
  # so...
 | 
						|
  local +x P4LANGUAGE
 | 
						|
  _call_program $cp_tag p4 "${_perforce_global_options[@]}" "$@"
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# The list of commands is cached in _perforce_cmd_list, but we
 | 
						|
# only generate it via this function when we need it.
 | 
						|
(( $+functions[_perforce_gen_cmd_list] )) ||
 | 
						|
_perforce_gen_cmd_list() {
 | 
						|
  (( ${+_perforce_cmd_list} )) || typeset -ga _perforce_cmd_list
 | 
						|
  local hline
 | 
						|
  # Output looks like <tab>command-name<space>description in words...
 | 
						|
  # Ignore blank lines and the heading line beginning `Perforce...'
 | 
						|
  # Just gets run once, then cached, so don't bother optimising
 | 
						|
  # this to a grossly unreadable parameter substitution.
 | 
						|
  _perforce_call_p4 help-commands help commands | while read -A hline; do
 | 
						|
    (( ${#hline} < 2 )) && continue
 | 
						|
    [[ $hline[1] = (#i)perforce ]] && continue
 | 
						|
    _perforce_cmd_list+=("${hline[1]}:${hline[2,-1]}")
 | 
						|
  done
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_commands] )) ||
 | 
						|
_perforce_commands() {
 | 
						|
  (( ${#_perforce_cmd_list} )) || _perforce_gen_cmd_list
 | 
						|
  _describe -t p4-commands 'Perforce command' _perforce_cmd_list
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_command_args] )) ||
 | 
						|
_perforce_command_args() {
 | 
						|
  local curcontext="$curcontext" cmd=${words[1]}
 | 
						|
  if (( $+functions[_perforce_cmd_$cmd] )); then
 | 
						|
    curcontext="${curcontext%:*:*}:p4-${cmd}:"
 | 
						|
    _perforce_cmd_$cmd
 | 
						|
  else
 | 
						|
    _message "unhandled perforce command: $cmd"
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_service_dispatch] )) ||
 | 
						|
_perforce_service_dispatch() {
 | 
						|
  # Put the original command name back, then dispatch for
 | 
						|
  # our Perforce handler.
 | 
						|
  words=($1 "$words[@]")
 | 
						|
  (( CURRENT++ ))
 | 
						|
  _perforce_cmd_$2
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Helper functions
 | 
						|
#
 | 
						|
 | 
						|
(( $+functions[_perforce_global_options] )) ||
 | 
						|
_perforce_global_options() {
 | 
						|
  # Options with arguments we need to pass down when calling
 | 
						|
  # p4 from completers.  There are no options without arguments
 | 
						|
  # we need to pass.  (Don't pass down -L language since we
 | 
						|
  # parse based on English output.)
 | 
						|
  local argopts_pass="cCdHpPu"
 | 
						|
  # Other options which have arguments but we shouldn't pass down.
 | 
						|
  # There are some debugging options, but they tend to get used
 | 
						|
  # with the argument in the same word as the option, in which
 | 
						|
  # case they will be handled OK anyway.
 | 
						|
  local argopts_ignore="Lx"
 | 
						|
 | 
						|
  # The options we support in the form for _arguments.
 | 
						|
  # This is here for modularity and convenience, but note that since the
 | 
						|
  # actual dispatch takes place later, this is not local to this
 | 
						|
  # function and so must be made local in the caller.
 | 
						|
  _perforce_option_dispatch=(
 | 
						|
    '-c+[client]:client:_perforce_clients' \
 | 
						|
    '-C+[charset]:charset:_perforce_charsets' \
 | 
						|
    '-d+[current directory]:directory:_path_files -g "*(/)"' \
 | 
						|
    '-H+[hostname]:host:_perforce_hosts' \
 | 
						|
    '-G[python output]' \
 | 
						|
    '-L+[message language]:language: ' \
 | 
						|
    '-p+[server port]:port:_perforce_hosts_ports' \
 | 
						|
    '-P+[password on server]:password: ' \
 | 
						|
    '-s[output script tags]' \
 | 
						|
    '-u+[user]:user name:_perforce_users' \
 | 
						|
    '-x+[filename or -]:file:_perforce_files_or_minus' \
 | 
						|
  )
 | 
						|
 | 
						|
  integer i
 | 
						|
 | 
						|
  # We need to try and check if we are before or after the
 | 
						|
  # subcommand, since some of the options with arguments, in particular -c,
 | 
						|
  # work differently.  It didn't work if I just added '*::...' to the
 | 
						|
  # end of the arguments list, anyway.
 | 
						|
  for (( i = 2; i < CURRENT; i++ )); do
 | 
						|
    if [[ $words[i] = -[$argopts_pass$argopts_ignore] ]]; then
 | 
						|
      # word with following argument --- check this
 | 
						|
      # is less than the current word, else we are completing
 | 
						|
      # this and shouldn't pass it down
 | 
						|
      if [[ $(( i + 1 )) -lt $CURRENT && \
 | 
						|
	$words[i] = -[$argopts_pass] ]]; then
 | 
						|
	_perforce_global_options+=(${words[i,i+1]})
 | 
						|
      fi
 | 
						|
      (( i++ ))
 | 
						|
    elif [[ $words[i] = -[$argopts_pass]* ]]; then
 | 
						|
      # word including argument which we want to keep
 | 
						|
      _perforce_global_options+=(${words[i]})
 | 
						|
    elif [[ $words[i] != -* ]]; then
 | 
						|
      break
 | 
						|
    fi
 | 
						|
  done
 | 
						|
 | 
						|
  (( _perforce_cmd_ind = i ))
 | 
						|
  (( _perforce_cmd_ind >= CURRENT ))
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_branches] )) ||
 | 
						|
_perforce_branches() {
 | 
						|
  local bline match mbegin mend
 | 
						|
  local -a bl
 | 
						|
  bl=(${${${(f)"$(_perforce_call_p4 branches branches 2>/dev/null)"}##Branch }/ /:})
 | 
						|
  [[ $#bl -eq 1 && $bl[1] = '' ]] && bl=()
 | 
						|
  (( $#bl )) && _describe -t branches 'Perforce branch' bl
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_changes] )) ||
 | 
						|
_perforce_changes() {
 | 
						|
  local cline match mbegin mend max ctype num comma file
 | 
						|
  local -a cl cstatus amax xargs
 | 
						|
 | 
						|
  zstyle -s ":completion:${curcontext}:changes" max max || max=20
 | 
						|
  zstyle -a ":completion:${curcontext}:changes" changes xargs
 | 
						|
  if [[ ${NUMERIC:-0} -lt 0 && -z $compstate[insert] ]]; then
 | 
						|
    # Not inserting (i.e. just listing) and given a negative
 | 
						|
    # prefix argument.  Instead of listing possible completions,
 | 
						|
    # show the full description for the change number on the line at
 | 
						|
    # the moment.
 | 
						|
    [[ $PREFIX = (|*[^[:digit:]])(#b)(<->) ]] && num+=$match[1]
 | 
						|
    [[ $SUFFIX = (#b)(<->)* ]] && num+=$match[1]
 | 
						|
    if [[ -n $num ]]; then
 | 
						|
      _message -r "$(_perforce_call_p4 describe describe $num)"
 | 
						|
      return 0
 | 
						|
    fi
 | 
						|
  elif [[ ${NUMERIC:-0} -gt 0 ]]; then
 | 
						|
    max=$NUMERIC
 | 
						|
  fi
 | 
						|
 | 
						|
  (( max )) && amax=(-m $max)
 | 
						|
 | 
						|
  # Hack: assume the arguments we want are at the end.
 | 
						|
  while [[ $argv[-1] = -t? ]]; do
 | 
						|
    case $argv[-1] in
 | 
						|
      # Change embedded in filename; extract that and remove
 | 
						|
      # the corresponding prefix.  Remove possible `#'s, too,
 | 
						|
      # in case we are looking at a range.
 | 
						|
      (-tf)
 | 
						|
      file=${${(Q)PREFIX}%%[\#@]*}
 | 
						|
      compset -P '*@(|\\\<|\\\>)(|=)'
 | 
						|
      ;;
 | 
						|
 | 
						|
      # Changes already submitted
 | 
						|
      (-ts)
 | 
						|
      cstatus=(-s submitted)
 | 
						|
      ctype="submitted "
 | 
						|
      ;;
 | 
						|
 | 
						|
      # Changes still pending
 | 
						|
      (-tp)
 | 
						|
      cstatus=(-s pending)
 | 
						|
      ctype="pending "
 | 
						|
      ;;
 | 
						|
 | 
						|
      # Range allowed: append comma and supply rules for
 | 
						|
      # removing and handling subsequent `#'.
 | 
						|
      (-tR)
 | 
						|
      comma=(-S, -R _perforce_file_suffix)
 | 
						|
    esac
 | 
						|
    argv=($argv[1,-2])
 | 
						|
  done
 | 
						|
  # Limit to the 20 most recent changes by default to avoid huge
 | 
						|
  # output.
 | 
						|
  cl=(
 | 
						|
${${${${(f)"$(_perforce_call_p4 changes changes $amax $xargs $cstatus \$file)"}##Change\ }//\ on\ /:}/\ by\ /\ }
 | 
						|
"default:change not yet numbered")
 | 
						|
  [[ $#cl -eq 1 && $cl[1] = '' ]] && cl=()
 | 
						|
  _describe -t changes "${ctype}change" cl -V changes-unsorted $comma
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_charsets] )) ||
 | 
						|
_perforce_charsets() {
 | 
						|
  local expl
 | 
						|
  _wanted charset expl 'character set' \
 | 
						|
    compadd eucjp iso8859-1 shiftjis utf8 winansi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_clients] )) ||
 | 
						|
_perforce_clients() {
 | 
						|
  local -a slash cl
 | 
						|
 | 
						|
  # Are we completing after an @, or a client view in a filespec?
 | 
						|
  if ! compset -P '*@'; then
 | 
						|
    compset -P '//' && slash=(-S/ -q)
 | 
						|
  fi
 | 
						|
 | 
						|
  cl=(${${${(f)"$(_perforce_call_p4 clients clients)"}##Client\ }/\ /:})
 | 
						|
  [[ $#cl -eq 1 && $cl[1] = '' ]] && cl=()
 | 
						|
  _describe -t clients 'Perforce client' cl $slash
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_counters] )) ||
 | 
						|
_perforce_counters() {
 | 
						|
  local cline match mbegin mend
 | 
						|
  local -a cl
 | 
						|
 | 
						|
  cl=(${${${(f)"$(_perforce_call_p4 counters counters)"}/\ /:}/\=/current value})
 | 
						|
  [[ $#cl -eq 1 && $cl[1] = '' ]] && cl=()
 | 
						|
  _describe -t counters 'Perforce counter' cl
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_counter_values] )) ||
 | 
						|
_perforce_counter_values() {
 | 
						|
  if [[ -n $words[CURRENT-1] ]]; then
 | 
						|
    local value="$(_perforce_call_p4 counter counter $words[CURRENT-1] 2>/dev/null)"
 | 
						|
    if [[ -n $value ]]; then
 | 
						|
      # No space.  This allows stuff like incarg and decarg.
 | 
						|
      compstate[insert]=1
 | 
						|
      _wanted value expl 'counter value' compadd $value
 | 
						|
    fi
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_dates] )) ||
 | 
						|
_perforce_dates() {
 | 
						|
  # Only useful in a file spec after `@'.
 | 
						|
  compset -P '*@'
 | 
						|
 | 
						|
  # Date/time now in format required by Perforce.
 | 
						|
  local now="$(date +%Y:%m:%d:%T)" name prefix
 | 
						|
  local -a nowarray offer opts matchpats suffixes names
 | 
						|
  nowarray=(${(s.:.)now})
 | 
						|
 | 
						|
  names=(   year month day\ of\ month hour minute second)
 | 
						|
  suffixes=(  /    /    :               :     :     ''  )
 | 
						|
 | 
						|
  integer i
 | 
						|
  prefix=${(Q)PREFIX}
 | 
						|
  for (( i = 6; i >= 1; i-- )); do
 | 
						|
    # Match from the most specific back.
 | 
						|
    # The following is one of those occasions where zsh
 | 
						|
    # substitution skips to the right answer without ever
 | 
						|
    # passing through the real world on the way.
 | 
						|
    if [[ $prefix = *${(j.*.)~suffixes[1,i-1]}* ]]; then
 | 
						|
      (( i > 1 )) && compset -P "*$suffixes[i-1]"
 | 
						|
      # If what's there already is the right length,
 | 
						|
      # just accept it and add the suffix.
 | 
						|
      prefix=${(Q)PREFIX}
 | 
						|
      if [[ ${#prefix} = ${#nowarray[i]} ]]; then
 | 
						|
	offer=($prefix)
 | 
						|
      else
 | 
						|
	offer=($nowarray[i])
 | 
						|
      fi
 | 
						|
      [[ -n $suffixes[i] ]] && opts=(-S $suffixes[i] -q)
 | 
						|
      name=$names[i]
 | 
						|
      break
 | 
						|
    fi
 | 
						|
  done
 | 
						|
 | 
						|
  _describe -t dates $name offer $opts
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_depots] )) ||
 | 
						|
_perforce_depots() {
 | 
						|
  local dline match mbegin mend
 | 
						|
  local -a dl
 | 
						|
 | 
						|
  dl=(${${${(f)"$(_perforce_call_p4 depots depots)"}##Depot\ }/\ /:})
 | 
						|
  [[ $#dl -eq 1 && $dl[1] = '' ]] && dl=()
 | 
						|
  _describe -t depots 'depot name' dl
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_files_or_minus] )) ||
 | 
						|
_perforce_files_or_minus() {
 | 
						|
  _alternative 'minus:minus sign:(-)' 'files:file name:_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_file_suffix] )) ||
 | 
						|
_perforce_file_suffix() {
 | 
						|
  # Used with compadd -R to handle @ or # after a file name.
 | 
						|
  # Differs from compadd -r '...' in that it quotes `#' if typed.
 | 
						|
  [[ $1 = 1 ]] || return
 | 
						|
 | 
						|
  if [[ $LBUFFER[-1] = [\ ,] ]]; then
 | 
						|
    if [[ $KEYS = '#' ]]; then
 | 
						|
      if [[ $LBUFFER[-1] = , ]]; then
 | 
						|
	# Range: no suffix removal but add a backslash
 | 
						|
	LBUFFER+=\\
 | 
						|
	  else
 | 
						|
	# Suffix removal with an added backslash
 | 
						|
	LBUFFER="$LBUFFER[1,-2]\\"
 | 
						|
      fi
 | 
						|
    elif [[ $KEYS = (*[^[:print:]]*|[[:blank:]\;\&\|]) || \
 | 
						|
      ( $KEYS = @ && $LBUFFER[-1] = ' ' ) ]] ; then
 | 
						|
      # Normal suffix removal
 | 
						|
      LBUFFER="$LBUFFER[1,-2]"
 | 
						|
    fi
 | 
						|
  elif [[ $LBUFFER[-1] = / ]]; then
 | 
						|
    # Normal suffix removal for directories.
 | 
						|
    if [[ $KEYS = (*[^[:print:]]*|[[:blank:]\;\&\|/]) ]]; then
 | 
						|
      LBUFFER="$LBUFFER[1,-2]"
 | 
						|
    fi
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Helper functions for the helper function _perforce_files.  These files
 | 
						|
# are low-level enough that they don't handle tags; this is done
 | 
						|
# by the _alternative handler in _perforce_files.
 | 
						|
#
 | 
						|
 | 
						|
(( $+functions[_perforce_integrated_files] )) ||
 | 
						|
_perforce_integrated_files() {
 | 
						|
  local pfx=${(Q)PREFIX} type
 | 
						|
  local -a files
 | 
						|
 | 
						|
  compset -P '*/'
 | 
						|
  files=(${${${(f)"$(_perforce_call_p4 integrated integrated \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/})
 | 
						|
  [[ $#files -eq 1 && $files[1] = '' ]] && files=()
 | 
						|
  compadd "$@" -a files
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_opened_files] )) ||
 | 
						|
_perforce_opened_files() {
 | 
						|
  local pfx=${(Q)PREFIX} type
 | 
						|
  local -a files
 | 
						|
 | 
						|
  compset -P '*/'
 | 
						|
  files=(${${${(f)"$(_perforce_call_p4 opened opened \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/})
 | 
						|
  [[ $#files -eq 1 && $files[1] = '' ]] && files=()
 | 
						|
  compadd "$@" -a files
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_resolved_files] )) ||
 | 
						|
_perforce_resolved_files() {
 | 
						|
  local pfx=${(Q)PREFIX} type
 | 
						|
  local -a files
 | 
						|
 | 
						|
  compset -P '*/'
 | 
						|
  files=(${${${(f)"$(_perfroce_call_p4 resolved resolved \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/})
 | 
						|
  [[ $#files -eq 1 && $files[1] = '' ]] && files=()
 | 
						|
  compadd "$@" -a files
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_subdirs] )) ||
 | 
						|
_perforce_subdirs() {
 | 
						|
  # This has no other function than to offer to add the `...' used
 | 
						|
  # by Perforce to indicate a recursive search of directories.
 | 
						|
  # Bit pathetic, really.
 | 
						|
  compset -P '*/'
 | 
						|
  compadd "$@" '...'
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_depot_dirs] )) ||
 | 
						|
_perforce_depot_dirs() {
 | 
						|
  # Normal completion of directories in depots
 | 
						|
  local pfx=${(Q)PREFIX} expl
 | 
						|
  local -a files
 | 
						|
 | 
						|
  compset -P '*/'
 | 
						|
  files=(${"${(f)$(_perforce_call_p4 dirs dirs \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)}"##*/})
 | 
						|
  [[ $#files -eq 1 && $files[1] = '' ]] && files=()
 | 
						|
  compadd "$@" -S / -q -a files
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_depot_files] )) ||
 | 
						|
_perforce_depot_files() {
 | 
						|
  # Normal completion of files in depots
 | 
						|
  local pfx=${(Q)PREFIX} expl
 | 
						|
  local -a files
 | 
						|
 | 
						|
  compset -P '*/'
 | 
						|
  files=(${${${(f)"$(_perforce_call_p4 files files \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/})
 | 
						|
  [[ $#files -eq 1 && $files[1] = '' ]] && files=()
 | 
						|
  compadd "$@" -R _perforce_file_suffix -a files
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_client_dirs] )) ||
 | 
						|
_perforce_client_dirs() {
 | 
						|
  # This is a slightly odd addition which isn't often necessary.
 | 
						|
  # When completing directories in a client specification, Perforce
 | 
						|
  # doesn't tell you about intermediate directories which are in
 | 
						|
  # the client, but not in the depot.  (Well... sometimes.  I've
 | 
						|
  # had some odd results with this.  I suspect there may be a bug
 | 
						|
  # but I don't really know enough to be sure.)
 | 
						|
  #
 | 
						|
  # For example, if my view contains
 | 
						|
  #   //depot/branches/rev1.2/...   //pws_client/branches/rev1.2/...
 | 
						|
  # then `p4 dirs "//pws_client/*"' won't mention the `branches'
 | 
						|
  # directory because the view actually starts lower down.  So
 | 
						|
  # we add it by hand when necessary.
 | 
						|
  #
 | 
						|
  # We don't want to waste time on this, since it's not the usual
 | 
						|
  # case, so we cache the results where necessary.  This means
 | 
						|
  # recording all the clients that we can later ask about if necessary.
 | 
						|
  # To flush the cache, `unset _perforce_client_list _perforce_client_dirs'.
 | 
						|
  if (( ! ${+_perforce_client_list} )); then
 | 
						|
    # Retrieve the list of clients.
 | 
						|
    typeset -gA _perforce_client_list
 | 
						|
    local -a tmplist
 | 
						|
    local tmpelt
 | 
						|
    tmplist=(${${${(f)"$(_perforce_call_p4 clients clients)"}##Client\ }%%\ *})
 | 
						|
    [[ $#tmplist -eq 1 && $tmplist[1] = '' ]] && tmplist=()
 | 
						|
    for tmpelt in $tmplist; do
 | 
						|
      _perforce_client_list[$tmpelt]=1
 | 
						|
    done
 | 
						|
  fi
 | 
						|
 | 
						|
  # See if the first path element is a client.  Very often it
 | 
						|
  # will actually be a depot, so we test this as quickly as possible.
 | 
						|
  local client=${${PREFIX##//}%%/*}
 | 
						|
  [[ -z ${_perforce_client_list[$client]} ]] && return 1
 | 
						|
 | 
						|
  local oldifs=$IFS IFS= type dir line dirs
 | 
						|
 | 
						|
  (( ${+_perforce_client_dirs} )) || typeset -gA _perforce_client_dirs
 | 
						|
 | 
						|
  if (( ${+_perforce_client_dirs[$client]} )); then
 | 
						|
    # Already cached, although may be empty.
 | 
						|
    dirs=${_perforce_client_dirs[$client]}
 | 
						|
  else
 | 
						|
    # We need to look at the View stanza of the client record
 | 
						|
    # to see what directories exist in the client view.
 | 
						|
    _perforce_call_p4 client "client -o $client" 2>/dev/null | while read line
 | 
						|
    do
 | 
						|
      case $line in
 | 
						|
	([[:blank:]]##)
 | 
						|
	type=
 | 
						|
	;;
 | 
						|
 | 
						|
	((#b)([[:alpha:]]##):*)
 | 
						|
	type=${match[1]}
 | 
						|
	;;
 | 
						|
 | 
						|
	(*)
 | 
						|
	if [[ $type = View ]]; then
 | 
						|
	  dir=${${line##[[:blank:]]##//*[[:blank:]]//$client}%%/...(/*|)}
 | 
						|
	  if [[ $#dir -gt 1 ]]; then
 | 
						|
	    dirs+="${dirs:+ }${(q)dir##/}"
 | 
						|
	  fi
 | 
						|
	fi
 | 
						|
	;;
 | 
						|
      esac
 | 
						|
    done
 | 
						|
  fi
 | 
						|
 | 
						|
  (( ${#dirs} )) || return 1
 | 
						|
 | 
						|
  # Turn our string of space-separated backquoted elements into an array.
 | 
						|
  dirs=(${(z)dirs})
 | 
						|
  # Get the current prefix also as an array of elements
 | 
						|
  compset -P '//[^/]##/'
 | 
						|
  pfx=(${(s./.)${(Q)PREFIX}})
 | 
						|
 | 
						|
  local -a ndirs
 | 
						|
  local match mbegin mend
 | 
						|
  # Check matching path segments
 | 
						|
  while (( ${#pfx} > 1 )); do
 | 
						|
    ndirs=()
 | 
						|
    for dir in $dirs; do
 | 
						|
      if [[ $dir = $pfx/(#b)(*) ]]; then
 | 
						|
	ndirs+=($match[1])
 | 
						|
      fi
 | 
						|
    done
 | 
						|
    (( ${#ndirs} )) || return 1
 | 
						|
    dirs=($ndirs)
 | 
						|
    shift pfx
 | 
						|
    compset -P '[^/]'
 | 
						|
  done
 | 
						|
  compadd -S / -q "$@" -- ${dirs%%/*}
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_files] )) ||
 | 
						|
_perforce_files() {
 | 
						|
  local pfx fline expl opt match mbegin mend range type
 | 
						|
  local -a files types
 | 
						|
 | 
						|
  local dodirs unmaintained
 | 
						|
  # Suffix operations can modify context
 | 
						|
  local curcontext="$curcontext"
 | 
						|
 | 
						|
  while (( $# )); do
 | 
						|
    if [[ $1 = -t(#b)(?) ]]; then
 | 
						|
      case $match[1] in
 | 
						|
	(d)
 | 
						|
	dodirs=-/
 | 
						|
	;;
 | 
						|
 | 
						|
	(u)
 | 
						|
	unmaintained=1
 | 
						|
	;;
 | 
						|
 | 
						|
	(i)
 | 
						|
	types+=(integrated)
 | 
						|
	;;
 | 
						|
 | 
						|
	(o)
 | 
						|
	types+=(opened)
 | 
						|
	;;
 | 
						|
 | 
						|
	(r)
 | 
						|
	types+=(resolved)
 | 
						|
	;;
 | 
						|
 | 
						|
	(R)
 | 
						|
	range="-tR"
 | 
						|
	;;
 | 
						|
      esac
 | 
						|
    fi
 | 
						|
    shift
 | 
						|
  done
 | 
						|
 | 
						|
  # Remove the quotes present in the word on the command line,
 | 
						|
  # since we will treat this as a literal string from now on.
 | 
						|
  # We might get into problems with characters recognised as
 | 
						|
  # special by p4 files and p4 dirs, but worry about that later.
 | 
						|
  pfx=${(Q)PREFIX}
 | 
						|
  if [[ -prefix *@ ]]; then
 | 
						|
    # Modify context to indicate we are in a suffix.
 | 
						|
    curcontext="${curcontext%:*}:at-suffix"
 | 
						|
    # Check for existing range syntax
 | 
						|
    [[ $PREFIX = *[@\#]*,* ]] && range=
 | 
						|
    # After @ you can specify changes, clients, labels or dates.
 | 
						|
    # Note we don't remove the prefix here; we leave it to the
 | 
						|
    # subcommand.  This is in case it needs information from
 | 
						|
    # the prefix; _perforce_changes uses this to limit the
 | 
						|
    # output to relevant changes.
 | 
						|
    _alternative \
 | 
						|
      "changes:change:_perforce_changes $range -tf" \
 | 
						|
      clients:client:_perforce_clients \
 | 
						|
      "labels:label:_perforce_labels -tf" \
 | 
						|
      'dates:date (+ time):_perforce_dates'
 | 
						|
  elif [[ -prefix *\# ]]; then
 | 
						|
    # Modify context to indicate we are in a suffix.
 | 
						|
    curcontext="${curcontext%:*}:hash-suffix"
 | 
						|
    # Check for existing range syntax
 | 
						|
    [[ $PREFIX = *[@\#]*,* ]] && range=
 | 
						|
    # Remove longest possible tail match to get name --- this
 | 
						|
    # automatically handles filenames in ranges e.g. `foo#1,#3'.
 | 
						|
    # (Note the compset removes the maximum possible head match,
 | 
						|
    # so we only complete the second part of the range in that case.)
 | 
						|
    _perforce_revisions $range
 | 
						|
  elif [[ $PREFIX = //* ]]; then
 | 
						|
    # This specifies files already handled by Perforce, so there's
 | 
						|
    # no point trying to look for unmaintained files.  Assume
 | 
						|
    # the user knows what they're doing.
 | 
						|
    local -a altfiles
 | 
						|
 | 
						|
    if [[ $PREFIX = //[^/]# ]]; then
 | 
						|
      # Complete //clientname spec.  Don't complete non-directories...
 | 
						|
      # I don't actually know if they are valid here.
 | 
						|
      altfiles+=("clients:Perforce client:_perforce_clients")
 | 
						|
    else
 | 
						|
      local donefiles=1
 | 
						|
      if [[ -z $dodirs ]]; then
 | 
						|
	if [[ ${#types} -gt 0 ]] &&
 | 
						|
	  ! zstyle -t ":completion:${curcontext}:" all-files; then
 | 
						|
	  for type in $types; do
 | 
						|
	    altfiles+=("$type-files:$type file:_perforce_${type}_files")
 | 
						|
	  done
 | 
						|
	else
 | 
						|
	  altfiles+=("depot-files:file in depot:_perforce_depot_files")
 | 
						|
	fi
 | 
						|
      fi
 | 
						|
      # Intermediate directories in a client view.
 | 
						|
      # See function for notes.
 | 
						|
      altfiles+=("client-dirs:client directory:_perforce_client_dirs")
 | 
						|
    fi
 | 
						|
    altfiles+=("depot-dirs:directory in depot:_perforce_depot_dirs"
 | 
						|
      "subdirs:subdirectory search:_perforce_subdirs")
 | 
						|
    _alternative $altfiles
 | 
						|
  elif [[ -n $unmaintained && -z $dodirs ]]; then
 | 
						|
    # a la _cvs_nonentried_files: directories are never maintained,
 | 
						|
    # so skip 'em.  Unmaintained files can't be integrated, opened
 | 
						|
    # or resolved, so treat as exclusive (just as well, since
 | 
						|
    # this bit's messy).
 | 
						|
    local MATCH MBEGIN MEND
 | 
						|
    local -a omitpats
 | 
						|
 | 
						|
    match=()
 | 
						|
    : ${PREFIX:#(#b)(*/)(*)}
 | 
						|
    pfx="$match[1]"
 | 
						|
    pfx=${(e)~pfx}
 | 
						|
    # Exclude both files already known to perforce, plus
 | 
						|
    # those opened.  There will be some overlap but we need
 | 
						|
    # to exclude files that are already opened for add.
 | 
						|
    omitpats=(
 | 
						|
      ${${${${(f)"$(_perforce_call_p4 files files \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/}//(#m)[][*?()<|^~#\\]/\\$MATCH}
 | 
						|
      ${${${${(f)"$(_perforce_call_p4 opened opened \"\$pfx\*\$\{\(Q\)SUFFIX\}\" 2>/dev/null)"}%\#*}##*/}//(#m)[][*?()<|^~#\\]/\\$MATCH}
 | 
						|
	)
 | 
						|
 | 
						|
    [[ $#omitpats -eq 1 && $omitpats[1] = '' ]] && omitpats=()
 | 
						|
    if (( ${#omitpats} )); then
 | 
						|
      _path_files -g "*~(*/|)(${(j:|:)~omitpats})(D.)"
 | 
						|
    else
 | 
						|
      _path_files
 | 
						|
    fi
 | 
						|
    # Don't handle suffixes for non-entried files
 | 
						|
  elif (( ${#types} )) && ! zstyle -t ":completion:${curcontext}:" all-files
 | 
						|
    then
 | 
						|
    local -a altfiles
 | 
						|
 | 
						|
    for type in $types; do
 | 
						|
      altfiles+=("$type-files:$type file:_perforce_${type}_files")
 | 
						|
    done
 | 
						|
 | 
						|
    altfiles+=("subdirs:subdirectory search:_perforce_subdirs")
 | 
						|
    if zstyle -t ":completion:${curcontext}:" depot-files; then
 | 
						|
      altfiles+=("depot-dirs:directory in depot:_perforce_depot_dirs")
 | 
						|
    else
 | 
						|
      altfiles+=("directories:directory:_path_files -/")
 | 
						|
    fi
 | 
						|
    _alternative $altfiles
 | 
						|
  elif zstyle -t ":completion:${curcontext}:" depot-files; then
 | 
						|
    local -a altfiles
 | 
						|
    if [[ -z $dodirs ]]; then
 | 
						|
      altfiles+=("depot-files:file in depot:_perforce_depot_files")
 | 
						|
    fi
 | 
						|
    altfiles+=("depot-dirs:directory in depot:_perforce_depot_dirs"
 | 
						|
      "subdirs:subdirectory search:_perforce_subdirs")
 | 
						|
    _alternative $altfiles
 | 
						|
  else
 | 
						|
    # Look locally.
 | 
						|
    _alternative \
 | 
						|
      "files:file:_path_files -R _perforce_file_suffix $dodirs" \
 | 
						|
      "subdirs:subdirectory search:_perforce_subdirs"
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Remaining helpers for other types of Perforce metadata.
 | 
						|
#
 | 
						|
 | 
						|
(( $+functions[_perforce_filetypes] )) ||
 | 
						|
_perforce_filetypes() {
 | 
						|
  local -a values
 | 
						|
  if compset -P '*+*'; then
 | 
						|
    # That second `*' is deliberate --- only complete the last
 | 
						|
    # letter since we can have a whole string of them.
 | 
						|
    values=(
 | 
						|
      "m:always set modtime on client"
 | 
						|
      "w:always writeable on client"
 | 
						|
      "x:set exec bit on client"
 | 
						|
      "k:full RCS keyword expansion"
 | 
						|
      "k:RCS expansion only for Id, Header"
 | 
						|
      "l:exclusive open, disallow multiple opens"
 | 
						|
      "C:server stores compress file per revision"
 | 
						|
      "D:server stores deltas in RCS format"
 | 
						|
      "F:server stores full file per revision"
 | 
						|
      "S:server stores only head revision")
 | 
						|
    _describe -t file-modifiers 'Perforce file modifier' values
 | 
						|
  else
 | 
						|
    values=(
 | 
						|
      "text:text, translate newlines"
 | 
						|
      "binary:raw bytes"
 | 
						|
      "symlink:symbolic link"
 | 
						|
      "apple:Mac resource + data"
 | 
						|
      "unicode:text, translate newlines, store as UTF-8")
 | 
						|
    _describe -t file-types 'Perforce file type' values -S+ -q
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_groups] )) ||
 | 
						|
_perforce_groups() {
 | 
						|
  local -a values
 | 
						|
  values=($(_perforce_call_p4 groups groups))
 | 
						|
  _describe -t groups 'Perforce group' values
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_hosts] )) ||
 | 
						|
_perforce_hosts() {
 | 
						|
  local expl host
 | 
						|
  # Completion for p4 -H; other forms of host completion
 | 
						|
  # go through _perforce_hosts_ports.
 | 
						|
  # From Felix: if the client specifies a hostname, there's
 | 
						|
  # no point using any other host, since it won't work.
 | 
						|
  host=$(_perforce_call_p4 client client -o |
 | 
						|
    awk '$1 ~ /^Host:/ {print $2}' )
 | 
						|
  if [[ -n $host ]]; then
 | 
						|
    _wanted hosts expl host compadd "$@" $host
 | 
						|
  else
 | 
						|
    _hosts
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_hosts_ports] )) ||
 | 
						|
_perforce_hosts_ports() {
 | 
						|
  if compset -P '*:'; then
 | 
						|
    _ports
 | 
						|
    local expl
 | 
						|
    _wanted ports expl port compadd "$@" 1666
 | 
						|
  else
 | 
						|
    # is this -q-able?
 | 
						|
    _hosts -S :
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_jobs] )) ||
 | 
						|
_perforce_jobs() {
 | 
						|
  local jline match mbegin mend max jobview
 | 
						|
  local -a jl amax ajobview
 | 
						|
 | 
						|
  zstyle -s ":completion:${curcontext}:jobs" max max || max=20
 | 
						|
  zstyle -s ":completion:${curcontext}:jobs" jobview jobview &&
 | 
						|
  ajobview=(-e $jobview)
 | 
						|
  if [[ ${NUMERIC:-0} -lt 0 && -z $compstate[insert] ]]; then
 | 
						|
  # Not inserting (i.e. just listing) and given a negative
 | 
						|
  # prefix argument.  Instead of listing possible completions,
 | 
						|
  # show the full description for the job which is on the line at
 | 
						|
  # the moment.
 | 
						|
    _message -r "$(_perforce_call_p4 jobs jobs -e \"Job=\$PREFIX\$SUFFIX\" -l 2>/dev/null)"
 | 
						|
    return 0
 | 
						|
  elif [[ ${NUMERIC:-0} -gt 0 ]]; then
 | 
						|
    max=$NUMERIC
 | 
						|
  fi
 | 
						|
 | 
						|
  (( max )) && amax=(-m $max)
 | 
						|
 | 
						|
  _perforce_call_p4 jobs jobs $ajobview $amax | while read jline; do
 | 
						|
    if [[ $jline = (#b)([^[:blank:]]##)' '[^[:blank:]]##' '(*) ]]; then
 | 
						|
      jl+=("${match[1]}:${match[2]}")
 | 
						|
    fi
 | 
						|
  done
 | 
						|
  _describe -t jobs 'Perforce job' jl -V jobs-unsorted
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_jobviews] )) ||
 | 
						|
_perforce_jobviews() {
 | 
						|
  # Jobviews (see `p4 help jobview') are ways of interrogating the
 | 
						|
  # jobs/fixes database.  It's basically either a set of strings,
 | 
						|
  # or a set of key=value pairs, or some combination, separated
 | 
						|
  # by various logical operators.  The `=' could be a comparison,
 | 
						|
  # but we don't currently bother with that here; it's a bit cumbersome
 | 
						|
  # to complete.
 | 
						|
  local line type oldifs=$IFS IFS= key value slash=/
 | 
						|
  local match mbegin mend
 | 
						|
  # This is simply to split out two space-delimited words a backreferences.
 | 
						|
  local m2words
 | 
						|
  m2words='(#b)[[:blank:]]##([[:alnum:]]##)[[:blank:]]##([^[:blank:]]##)'
 | 
						|
 | 
						|
  local -a valuespec
 | 
						|
  local -A p4fields p4values
 | 
						|
 | 
						|
  # All the characters which can separate multiple match attempts.
 | 
						|
  # Ignore up to the last one.  We don't try to complete these.
 | 
						|
  compset -P '*[[:blank:]\^\&\|\(\)]'
 | 
						|
 | 
						|
  # According to the manual, `p4 jobspec' requires admin privileges.
 | 
						|
  # If this is true even of `p4 jobspec -o', we are a bit screwed.
 | 
						|
  _perforce_call_p4 jobspec jobspec -o 2>/dev/null | while read line; do
 | 
						|
    case $line in
 | 
						|
      ([[:blank:]]##)
 | 
						|
      type=
 | 
						|
      ;;
 | 
						|
 | 
						|
      ((#b)([[:alpha:]]##):*)
 | 
						|
      type=${match[1]}
 | 
						|
      ;;
 | 
						|
 | 
						|
      (*)
 | 
						|
      case $type in
 | 
						|
	# This stanza tells us all the allowed fields.
 | 
						|
	(Fields)
 | 
						|
	if [[ $line = [[:blank:]]##<->${~m2words}* ]]; then
 | 
						|
	  p4fields[${(L)match[1]}]=${match[2]}
 | 
						|
	fi
 | 
						|
	;;
 | 
						|
 | 
						|
	# This stanza gives allowed values for the `select' types.
 | 
						|
	(Values)
 | 
						|
	if [[ $line = ${~m2words}* ]]; then
 | 
						|
	  p4values[${(L)match[1]}]=${match[2]}
 | 
						|
	fi
 | 
						|
	;;
 | 
						|
      esac
 | 
						|
 | 
						|
      ;;
 | 
						|
    esac
 | 
						|
  done
 | 
						|
 | 
						|
  IFS=$oldifs
 | 
						|
 | 
						|
  if (( ! ${#p4fields} )); then
 | 
						|
    # We didn't get anything; add the defaults.
 | 
						|
    p4fields=(
 | 
						|
      date		date
 | 
						|
      description	text
 | 
						|
      job		word
 | 
						|
      status		select
 | 
						|
      user		word
 | 
						|
    )
 | 
						|
    p4values=(
 | 
						|
	    status	open/suspended/closed
 | 
						|
	)
 | 
						|
  fi
 | 
						|
 | 
						|
  for key in ${(k)p4fields}; do
 | 
						|
    if [[ -n ${p4values[$key]} ]]; then
 | 
						|
      valuespec+=("${key}:${p4fields[$key]}:(${p4values[$key]//$slash/ })")
 | 
						|
    elif [[ $key = job ]]; then
 | 
						|
      # Nothing special for jobs; add our own completion.
 | 
						|
      valuespec+=("${key}:Perforce job:_perforce_jobs")
 | 
						|
    elif [[ $key = user ]]; then
 | 
						|
      # Nothing provided for user; add our own completion.
 | 
						|
      valuespec+=("${key}:user:_perforce_users")
 | 
						|
    else
 | 
						|
      valuespec+=("${key}:${p4fields[$key]}: ")
 | 
						|
    fi
 | 
						|
  done
 | 
						|
 | 
						|
  _values 'Job specification parameter' $valuespec
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_labels] )) ||
 | 
						|
_perforce_labels() {
 | 
						|
    local lline file
 | 
						|
    local -a ll match mbegin mend
 | 
						|
 | 
						|
    if [[ $argv[-1] = -tf ]]; then
 | 
						|
      argv=($argv[1,-2])
 | 
						|
      # Completing after `@'.
 | 
						|
      file=${${(Q)PREFIX}%%@*}
 | 
						|
      compset -P '*@'
 | 
						|
    fi
 | 
						|
 | 
						|
    ll=(${${(f)"$(_perforce_call_p4 labels labels ${file:+\$file})"}//(#b)Label\ ([^[:blank:]]##)\ (*)/$match[1]:$match[2]})
 | 
						|
    _describe -t labels 'Perforce label' ll
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_revisions] )) ||
 | 
						|
_perforce_revisions() {
 | 
						|
  # Doesn't handle standard completion options; requires space
 | 
						|
  # in front if used as action in _arguments.
 | 
						|
 | 
						|
  local rline match mbegin mend comma expl pfx
 | 
						|
  local -a rl
 | 
						|
 | 
						|
  if [[ $1 = -tR ]]; then
 | 
						|
    # handle ranges
 | 
						|
    comma=(-S, -R _perforce_file_suffix)
 | 
						|
	shift
 | 
						|
  fi
 | 
						|
 | 
						|
  # Beware of @foo,#bar; stupid but valid.
 | 
						|
  pfx=${${(Q)PREFIX}%%[\#@]*}
 | 
						|
  compset -P '*\#(|\\\<|\\\>)(|=)'
 | 
						|
 | 
						|
  # Numerical revision numbers, possibly with text.
 | 
						|
  if [[ -z $PREFIX || $PREFIX = <-> ]]; then
 | 
						|
    # always allowed (same as none)
 | 
						|
    rl+=(0)
 | 
						|
    _perforce_call_p4 filelog 'filelog $pfx' 2>/dev/null | while read rline; do
 | 
						|
      if [[ $rline = (#b)'... #'(<->)' change '(*) ]]; then
 | 
						|
	rl+=("${match[1]}:${match[2]}")
 | 
						|
      fi
 | 
						|
    done
 | 
						|
  fi
 | 
						|
  # Non-numerical (special) revision names.
 | 
						|
  if [[ -z $PREFIX || $PREFIX != <-> ]]; then
 | 
						|
    rl+=('head:head revision' 'none:empty revision'
 | 
						|
      'have:current synced revision')
 | 
						|
  fi
 | 
						|
  _describe -t revisions 'revision' rl -V revisions-unsorted $comma
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_statuses] )) ||
 | 
						|
_perforce_statuses() {
 | 
						|
  # Perforce statuses are usually limited to a set of values
 | 
						|
  # given by the jobspec.
 | 
						|
  local jline match mbegin mend
 | 
						|
  local -a statuses
 | 
						|
 | 
						|
  _perforce_call_p4 jobspec jobspec -o | while read jline; do
 | 
						|
    if [[ $jline = (#b)Status[[:blank:]]##(*/*) ]]; then
 | 
						|
      statuses=(${(s./.)match[1]})
 | 
						|
      break
 | 
						|
    fi
 | 
						|
  done
 | 
						|
  if (( !${#statuses} )); then
 | 
						|
    # Couldn't find anything from the jobspec; add defaults.
 | 
						|
    statuses=(closed open suspended)
 | 
						|
  fi
 | 
						|
  _describe -t statuses 'job status' statuses
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_users] )) ||
 | 
						|
_perforce_users() {
 | 
						|
  local -a ul
 | 
						|
 | 
						|
  ul=(${${(f)"$(_perforce_call_p4 users users)"}/\ /:})
 | 
						|
  [[ $#ul -eq 1 && $ul[1] = '' ]] && ul=()
 | 
						|
  _describe -t users 'Perforce user' ul
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_variables] )) ||
 | 
						|
_perforce_variables() {
 | 
						|
  local line match mbegin mend expl
 | 
						|
  local -a vars
 | 
						|
 | 
						|
  _perforce_call_p4 help-environment help environment | while IFS= read line
 | 
						|
  do
 | 
						|
    if [[ $line = $'\t'(#b)([A-Z][A-Z0-9_]##)* ]]; then
 | 
						|
      vars+=($match[1])
 | 
						|
    fi
 | 
						|
  done
 | 
						|
 | 
						|
  _wanted variable expl 'environment variable' compadd -S= -q $vars
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Completions for p4 commands
 | 
						|
#
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_add] )) ||
 | 
						|
_perforce_cmd_add() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c+[select by change]:change:_perforce_changes -tp' \
 | 
						|
    '-t+[set file type]:file type:_perforce_filetypes' \
 | 
						|
    '*:file:_perforce_files -tu'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_admin] )) ||
 | 
						|
_perforce_cmd_admin() {
 | 
						|
  if (( CURRENT == 2 )); then
 | 
						|
    local -a adcmds
 | 
						|
    adcmds=(
 | 
						|
      "checkpoint:checkpoint, save copy of journal file"
 | 
						|
      "journal:save and truncate journal file"
 | 
						|
      "stop:stop the server")
 | 
						|
    _describe -t commands 'Perforce admin command' adcmds
 | 
						|
  elif [[ $words[2] == (checkpoint|journal) ]]; then
 | 
						|
    shift words
 | 
						|
    (( CURRENT-- ))
 | 
						|
    _arguments -s : \
 | 
						|
      '-z[gzip journal file]' \
 | 
						|
      '1::journal file prefix: '
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_annotate] )) ||
 | 
						|
_perforce_cmd_annotate() {
 | 
						|
  # New in release 2002.2.
 | 
						|
  # -c was new in about 2003.2.
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[all, show both added and deleted lines]' \
 | 
						|
    '-c[output change numbers instead of revisions]' \
 | 
						|
    '-q[quiet, suppress one-line file header]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_branch] )) ||
 | 
						|
_perforce_cmd_branch() {
 | 
						|
  _arguments -s : \
 | 
						|
    '(-o)-f[force operation by superuser]' \
 | 
						|
    '(-o -i)-d[delete branch]' \
 | 
						|
    '(-d -i -f)-o[write specification to standard output]' \
 | 
						|
    '(-d -o)-i[read specification from standard input]' \
 | 
						|
    '(-i)*::branch name:_perforce_branches'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_branches] )) ||
 | 
						|
_perforce_cmd_branches() {
 | 
						|
  # No arguments.
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_change] )) ||
 | 
						|
_perforce_cmd_change() {
 | 
						|
  local ctype
 | 
						|
  # Unless forcing or outputting, we don't
 | 
						|
  # complete committed changes since they can't be altered.
 | 
						|
  [[ ${words[(I)-*(f|o)*]} -eq 0 ]] && ctype=" -tp"
 | 
						|
  _arguments -s : \
 | 
						|
    '(-o)-f[allow force by superuser]' \
 | 
						|
    '-s[joblist includes the fix status]' \
 | 
						|
    '(-o -i)-d[discard newly created pending change]' \
 | 
						|
    '(-d -i -f)-o[output specification to standard output]' \
 | 
						|
    '(-d -o)-i[read specification from standard input]' \
 | 
						|
    "(-i)1::change:_perforce_changes$ctype"
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_changes] )) ||
 | 
						|
_perforce_cmd_changes() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-i[include integrated changes]' \
 | 
						|
    '-t[output time as well as date]' \
 | 
						|
    '-l[long output]' \
 | 
						|
    '-c+[select by client]:client:_perforce_clients' \
 | 
						|
    '-m+[most recent N changes]:max changes: ' \
 | 
						|
    '-s+[select by status]:status:(pending submitted)' \
 | 
						|
    '-u+[select by user]:user:_perforce_users' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_client] )) ||
 | 
						|
_perforce_cmd_client() {
 | 
						|
  _arguments -s : \
 | 
						|
    '(-o)-f[force modification by superuser]' \
 | 
						|
    '-t[use template]:template client:_perforce_clients' \
 | 
						|
    '(-o -i -t)-d[delete client]' \
 | 
						|
    '(-d -i -f)-o[print to standard output]' \
 | 
						|
    '(-d -o -t)-i[read from standard input]' \
 | 
						|
    '1::file:_perforce_clients'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_clients] )) ||
 | 
						|
_perforce_cmd_clients() {
 | 
						|
  # No arguments.
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_counter] )) ||
 | 
						|
_perforce_cmd_counter() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d[delete counter]' \
 | 
						|
    '-f[force setting of internal counter]' \
 | 
						|
    '1:counter:_perforce_counters' \
 | 
						|
    '(-d)2::numeric value:_perforce_counter_values'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_counters] )) ||
 | 
						|
_perforce_cmd_counters() {
 | 
						|
  # No arguments
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_delete] )) ||
 | 
						|
_perforce_cmd_delete() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[select change for deletion]:change:_perforce_changes -tp' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_depot] )) ||
 | 
						|
_perforce_cmd_depot() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d[delete depot]' \
 | 
						|
    '-o[print to stdout]' \
 | 
						|
    '-i[read name from stdin]' \
 | 
						|
    '(-i)*::depot name:_perforce_depots'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_depots] )) ||
 | 
						|
_perforce_cmd_depots() {
 | 
						|
  # No arguments
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_describe] )) ||
 | 
						|
_perforce_cmd_describe() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
 | 
						|
    '-s[short form]' \
 | 
						|
    '*::change:_perforce_changes'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_diff] )) ||
 | 
						|
_perforce_cmd_diff() {
 | 
						|
  local limit
 | 
						|
  [[ ${words[(I)-(f|sd|se)]} -eq 0 ]] && limit=" -to"
 | 
						|
  _arguments -s : \
 | 
						|
    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context l\:ignore\ line\ endings n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
 | 
						|
    '-f[diff every file]' \
 | 
						|
    '(-sd -se -sr)-sa[opened files, different or missing]' \
 | 
						|
    '(-sa -se -sr)-sd[unopened files, missing]' \
 | 
						|
    '(-sa -sd -sr)-se[unopened files, different]' \
 | 
						|
    '(-sa -sd -se)-sr[opened files, same as depot]' \
 | 
						|
    '-t[include non-text files]' \
 | 
						|
    "*::file:_perforce_files$limit"
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_diff2] )) ||
 | 
						|
_perforce_cmd_diff2() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-b[specify branch view]:branch name:_perforce_branches' \
 | 
						|
    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
 | 
						|
    '-q[only list different files]' \
 | 
						|
    '-t[include non-text files]' \
 | 
						|
    '-u[use patch-friendly output]' \
 | 
						|
    '1::first file:_perforce_files' \
 | 
						|
    '2::second file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_dirs] )) ||
 | 
						|
_perforce_cmd_dirs() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-C[only dirs on current client]' \
 | 
						|
    '-D[include dirs with deleted files]' \
 | 
						|
    '-H[only dirs on the `have'\'' list]' \
 | 
						|
    '*::directory:_perforce_files -td'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_edit] )) ||
 | 
						|
_perforce_cmd_edit() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[set change for edit]:change:_perforce_changes -tp' \
 | 
						|
    '-t[set filetype]:filetype:_perforce_filetypes' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_filelog] )) ||
 | 
						|
_perforce_cmd_filelog() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-i[follow branches]' \
 | 
						|
    '-l[long output, full change text]' \
 | 
						|
    '-m[set maximum number of revisions to show]:max revisions: ' \
 | 
						|
    '-t[include time with date]' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_files] )) ||
 | 
						|
_perforce_cmd_files() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[display all revisions in given range]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_fix] )) ||
 | 
						|
_perforce_cmd_fix() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d[delete the fix]' \
 | 
						|
    '-s[set job status]:status:_perforce_statuses' \
 | 
						|
    '1::-c required:(-c)' \
 | 
						|
    '2::change:_perforce_changes' \
 | 
						|
    '3::job:_perforce_jobs'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_fixes] )) ||
 | 
						|
_perforce_cmd_fixes() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-i[include integrated changes]' \
 | 
						|
    '-j[select by job]:job:_perforce_jobs' \
 | 
						|
    '-c[select by change]:change:_perforce_changes' \
 | 
						|
    '*::fixed file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_flush] )) ||
 | 
						|
_perforce_cmd_flush() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-f[force resynchronisation]' \
 | 
						|
    '-n[show operations but don'\''t perform them]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_fstat] )) ||
 | 
						|
_perforce_cmd_fstat() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c+[affected since change]:change:_perforce_changes -ts' \
 | 
						|
    '-e+[affected by change]:change:_perforce_changes -ts' \
 | 
						|
    '-C[select mapped files (-Rc)]' \
 | 
						|
    '-H[select synced files (-Rh)]' \
 | 
						|
    '-W[select opened files (-Ro)]' \
 | 
						|
    '-l[include fileSize, possibly slow (-Ol)]' \
 | 
						|
    '-O-[select output type]:output type:((l\:fileSize p\:client\ path\ format r\:pending\ integrations s\:exclude\ local\ path))' \
 | 
						|
    '-P[output clientFile in full Perforce syntax (-Op)]' \
 | 
						|
    '-R-[restrict selected files]:restriction:((c\:mapped\ in\ client h\:synced\ to\ client n\:not\ synced\ to\ head o\:opened r\:resolved u\:unresolved))' \
 | 
						|
    '-s[shorten, no client-related data (-Os)]' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_group] )) ||
 | 
						|
_perforce_cmd_group() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d[delete group]' \
 | 
						|
    '-o[output to stdout]' \
 | 
						|
    '-i[read from stdin]' \
 | 
						|
    '1::perforce group:_perforce_groups'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_groups] )) ||
 | 
						|
_perforce_cmd_groups() {
 | 
						|
  _arguments -s : \
 | 
						|
    '1::user name:_perforce_users'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_have] )) ||
 | 
						|
_perforce_cmd_have() {
 | 
						|
  _perforce_files
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_help] )) ||
 | 
						|
_perforce_cmd_help() {
 | 
						|
  local hline
 | 
						|
  if (( ! ${#_perforce_help_list} )); then
 | 
						|
    (( ${+_perforce_help_list} )) || typeset -ga _perforce_help_list
 | 
						|
    # All commands have help.
 | 
						|
    (( ${#_perforce_cmd_list} )) || _perforce_gen_cmd_list
 | 
						|
    _perforce_help_list=($_perforce_cmd_list)
 | 
						|
    _perforce_call_p4 help help | while read -A hline; do
 | 
						|
      if [[ $hline[1] = p4 && $hline[2] = help ]]; then
 | 
						|
	_perforce_help_list+=("$hline[3]:${hline[4,-1]}")
 | 
						|
      fi
 | 
						|
    done
 | 
						|
  fi
 | 
						|
  _describe -t help-options 'Perforce help option' _perforce_help_list
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_info] )) ||
 | 
						|
_perforce_cmd_info() {
 | 
						|
  # No arguments
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_integrate] )) ||
 | 
						|
_perforce_cmd_integrate() {
 | 
						|
  local range
 | 
						|
  # If -s is present, the first normal argument can't have revRange.
 | 
						|
  [[ ${words[(I)-s]} -eq 0 ]] && range=" -tR"
 | 
						|
  _arguments -s : \
 | 
						|
    '-b[select branch]:branch:_perforce_branches' \
 | 
						|
    '-c[select change for integration]:change:_perforce_changes -tp' \
 | 
						|
    '-f[force reintegration]' \
 | 
						|
    '-d[reintegrate deleted files]' \
 | 
						|
    '-D-[specify allowed deletions]:deletion type:((
 | 
						|
t\:rebranch\ on\ deleted\ file
 | 
						|
s\:delete\ modified\ target\ file
 | 
						|
i\:ignore\ readded\ source\ file
 | 
						|
))' \
 | 
						|
    '-h[integrate to revision had on client]' \
 | 
						|
    '-i[integrate if no common file base]' \
 | 
						|
    '-I[same as -i from 2004.2]' \
 | 
						|
    '-n[no action, dummy run]' \
 | 
						|
    '-o[display base file name for subsequent resolve]' \
 | 
						|
    '-r[reverse direction of integration with branch]' \
 | 
						|
    '-s[select source with -b]:source file:_perforce_files -tR' \
 | 
						|
    '-t[propagate type changes]' \
 | 
						|
    '-v[leave newly branched files uncopied till sync]' \
 | 
						|
    "1:file:_perforce_files$range" \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_integrated] )) ||
 | 
						|
_perforce_cmd_integrated() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-r[reverse mapping in branch view with -b]' \
 | 
						|
    '-b[select files integrated via branch]:branch:_perforce_branches' \
 | 
						|
    '*::file:_perforce_files -ti'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_job] )) ||
 | 
						|
_perforce_cmd_job() {
 | 
						|
  _arguments -s : \
 | 
						|
    '(-d -o -i)-f[force setting of readonly fields]' \
 | 
						|
    '(-f -o -i)-d[delete job]' \
 | 
						|
    '(-f -d -i)-o[print to stdout]' \
 | 
						|
    '(-d -o)-i[read from stdin]' \
 | 
						|
    '(-i)1::job:_perforce_jobs'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_jobs] )) ||
 | 
						|
_perforce_cmd_jobs() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-e[select by jobview]:jobview:_perforce_jobviews' \
 | 
						|
    '-i[included integrated changes]' \
 | 
						|
    '-l[long output, full job descriptions]' \
 | 
						|
    '-r[reverse order of job names]' \
 | 
						|
    '-m[limit to most recent N jobs]:number of most recent jobs: ' \
 | 
						|
    '(-e -i -l -m)-R[rebuild jobs table on upgrade]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_jobspec] )) ||
 | 
						|
_perforce_cmd_jobspec() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-i[read form from stdin]' \
 | 
						|
    '-o[write form from to stdout]'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_label] )) ||
 | 
						|
_perforce_cmd_label() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-f[force operation]' \
 | 
						|
    '-t+[copy template]:template: ' \
 | 
						|
    '(-o -i -t)-d[delete label]' \
 | 
						|
    '(-d -f -i)-o[write to standard output]' \
 | 
						|
    '(-o -d -t)-i[read from standard input]' \
 | 
						|
    '*::label:_perforce_labels'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_labels] )) ||
 | 
						|
_perforce_cmd_labels() {
 | 
						|
  _arguments -s : \
 | 
						|
    '1::file or revisions which must contain label:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_labelsync] )) ||
 | 
						|
_perforce_cmd_labelsync() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[add files to label]' \
 | 
						|
    '-d[delete files from label]' \
 | 
						|
    '-n[no effect, dummy run]' \
 | 
						|
    '-l[specify label]:label:_perforce_labels' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_lock] )) ||
 | 
						|
_perforce_cmd_lock() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[select by change]:change:_perforce_changes -tp' \
 | 
						|
    '*::file:_perforce_files -to'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_logger] )) ||
 | 
						|
_perforce_cmd_logger() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[limit by counter no]:number: ' \
 | 
						|
    '-t[use counter instead of logger]:counter:_perforce_counters'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_login] )) ||
 | 
						|
_perforce_cmd_login() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[ticket valid on all machines]' \
 | 
						|
    '-p[display ticket, do not store]' \
 | 
						|
    '-s[show status of ticket]' \
 | 
						|
    '(-s)1::user:_perforce_users'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_logout] )) ||
 | 
						|
_perforce_cmd_logout() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[invalidate ticket on server]'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_monitor] )) ||
 | 
						|
_perforce_cmd_monitor() {
 | 
						|
  if (( CURRENT > 2 )); then
 | 
						|
    case $words[2] in
 | 
						|
      (show)
 | 
						|
      shift words
 | 
						|
      (( CURRENT-- ))
 | 
						|
      _arguments -s : \
 | 
						|
        '-a[show command arguments]' \
 | 
						|
        '-e[show command environment]' \
 | 
						|
        '-l[long output format]'
 | 
						|
      ;;
 | 
						|
 | 
						|
      (terminate|clear)
 | 
						|
      _message "process ID"
 | 
						|
      ;;
 | 
						|
 | 
						|
      (*)
 | 
						|
      _message "no such monitor command: $words[1]"
 | 
						|
      ;;
 | 
						|
    esac
 | 
						|
  else
 | 
						|
    local expl
 | 
						|
    _wanted monitor-command expl 'monitor command' compadd show terminate clear
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_obliterate] )) ||
 | 
						|
_perforce_cmd_obliterate() {
 | 
						|
  _message "obliterate is dangerous: you're on your own here."
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_opened] )) ||
 | 
						|
_perforce_cmd_opened() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[list for all clients]' \
 | 
						|
    '-c+[select by change]:change:_perforce_changes -tp' \
 | 
						|
    '*::file:_perforce_files -to'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_passwd] )) ||
 | 
						|
_perforce_cmd_passwd() {
 | 
						|
  _arguments -s : : \
 | 
						|
    '-O[explicit old password]:old password: ' \
 | 
						|
    '-P[explicit new password]:new password: ' \
 | 
						|
    '1::user name:_perforce_users'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_print] )) ||
 | 
						|
_perforce_cmd_print() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[display all revisions in a range]' \
 | 
						|
    '-o[select output file]:output file:_files' \
 | 
						|
    '-q[suppress header]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_protect] )) ||
 | 
						|
_perforce_cmd_protect() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-o[write spec to stdout]' \
 | 
						|
    '-i[read spec from stdin]'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_reopen] )) ||
 | 
						|
_perforce_cmd_reopen() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c+[select change to reopen on]:change:_perforce_changes -tp' \
 | 
						|
    '-t+[set file type]:file type:_perforce_filetypes' \
 | 
						|
    '*::file:_perforce_files -to'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_resolve] )) ||
 | 
						|
_perforce_cmd_resolve() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a-[select automatic merge type]:automation type:((f\:force\ acceptance m\:skip\ conflicts s\:safe t\:use\ theirs y\:use\ yours))' \
 | 
						|
    '-d-[select diff option]:diff option:((b\:ignore\ blanks w\:ignore\ all\ whitespace))' \
 | 
						|
    '-f[force re-resolution]' \
 | 
						|
    '-n[no action, just list]' \
 | 
						|
    '-o[display base file name and revision for merge]' \
 | 
						|
    '-t[force textual merge on binary files]' \
 | 
						|
    '-v[verbose, mark all changes]' \
 | 
						|
    '*::file:_perforce_files -to'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_resolved] )) ||
 | 
						|
_perforce_cmd_resolved() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-o[report revision used as base for resolve]' \
 | 
						|
    '*::file:_perforce_files -tr'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_revert] )) ||
 | 
						|
_perforce_cmd_revert() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-a[revert unaltered files]' \
 | 
						|
    '-c[limit reversions to change]:change:_perforce_changes -tp' \
 | 
						|
    '-n[no action, show effect only]' \
 | 
						|
    '*::file:_perforce_files -to'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_review] )) ||
 | 
						|
_perforce_cmd_review() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[select change for counter]:change:_perforce_changes -ts' \
 | 
						|
    '-t[limit change number by counter]:counter:_perforce_counters'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_reviews] )) ||
 | 
						|
_perforce_cmd_reviews() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[show users by change]:change:_perforce_changes -ts' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_set] )) ||
 | 
						|
_perforce_cmd_set() {
 | 
						|
  # Only works under Windoze but maybe we are on Cygwin.
 | 
						|
  _arguments -s : \
 | 
						|
    '-s[set for whole system]' \
 | 
						|
    '-S[set for specified service]:service: ' \
 | 
						|
    "*::environment variable:_perforce_variables"
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_submit] )) ||
 | 
						|
_perforce_cmd_submit() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-r[files open for add or edit remain open]' \
 | 
						|
    '-s[include fix status in list]' \
 | 
						|
    '(-s -i)-c[submit specific change]:change:_perforce_changes -tp' \
 | 
						|
    '(-c)-i[read change spec from stdin]' \
 | 
						|
    '*::file:_perforce_files -to -tr'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_sync] )) ||
 | 
						|
_perforce_cmd_sync() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-f[force resynchronisation]' \
 | 
						|
    '-n[show operations but don'\''t perform them]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_tag] )) ||
 | 
						|
_perforce_cmd_tag() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-d[delete association between label and files]' \
 | 
						|
    '-n[show what files would be tagged]' \
 | 
						|
    '-l[specify label]:label:_perforce_labels' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_triggers] )) ||
 | 
						|
_perforce_cmd_triggers() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-o[output form to stdout]' \
 | 
						|
    '-i[read from from stdin]'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_tickets] )) ||
 | 
						|
_perforce_cmd_tickets() {
 | 
						|
  # No arguments.
 | 
						|
  _arguments -s :
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_typemap] )) ||
 | 
						|
_perforce_cmd_typemap() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-o[output table to stdout]' \
 | 
						|
    '-i[read table from stdin]'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_unlock] )) ||
 | 
						|
_perforce_cmd_unlock() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-c[non-default change to unlock]:change:_perforce_changes -tp' \
 | 
						|
    '-f[allow superuser to unlock any file]' \
 | 
						|
    '*::file:_perforce_files'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_user] )) ||
 | 
						|
_perforce_cmd_user() {
 | 
						|
  _arguments -s : \
 | 
						|
    '(-o)-f[force edit by superuser]' \
 | 
						|
    '(-o -i)-d[delete user]' \
 | 
						|
    '(-o -d)-i[read form from stdin]' \
 | 
						|
    '(-f -i -d)-o[write form to stdout]' \
 | 
						|
    '(-i)1::username:_perforce_users'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_users] )) ||
 | 
						|
_perforce_cmd_users() {
 | 
						|
  _arguments -s : \
 | 
						|
    '*::username:_perforce_users'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_verify] )) ||
 | 
						|
_perforce_cmd_verify() {
 | 
						|
  _arguments -s : \
 | 
						|
    '-q[operate quietly]' \
 | 
						|
    '-u[compute and save digest if missing]' \
 | 
						|
    '-v[compute and save all digets]' \
 | 
						|
    '*::file:_perforce_files -tR'
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(( $+functions[_perforce_cmd_where] )) ||
 | 
						|
_perforce_cmd_where() {
 | 
						|
  _perforce_files
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
_perforce "$@"
 |