Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Various completion contributions



Hi All,

Let me start by thanking the wonderful wonderful zsh devs! I've been
using tcsh for the last 10 years, and recently switched over to zsh. I'm
completely awestruck! Thanks a ton.

I updated/modified a couple of default completion scripts, and wrote a
couple of new ones. I'm attaching them to this message in case they
would be useful. (Please let me know the "official" way to submit
patches / bugs, and I will do so in future).

Here's a brief description of the changes:

    _gv		Added --monochrome, and options for --orientation

    _lp		Added support for completion of printer options (e.g.
		after lpr -o), and values (as provided by lpoptions).

    _modultils	Added caching for module names. Added -i, --ignore-*
		options. Restricted module names to those ending in *.o
		or *.ko (otherwise too many false positives were
		generated on my system). I'm not sure if *.o is
		necessary. [Also -- some zsh guru should look at my
		caching code. If you put it in the "standard" form, I'll
		use it in future]

    _okular	Added non-qt/kde options, and complete all files which
		okular can view. (I got the list from /etc/mailcap on my
		system, so I'm not sure if the list is complete or not)

    _pdftk	New completion file

    _pgrep	New completion file (which I downloaded from the mailing
		list archives). I guess it's pointless to attach here.
		However, the completion file is quite good, and it might
		be helpful to new users if it was distributed by
		default.

    _subversion	Added caching support. (Completion of svn is quite quite
		slow by default. This makes things a little faster,
		though things are still quite slow...) [I would call the
		changes I made here an "ugly hack". If someone knows a
		better way to speed this up, please let me know]

    _tex	New completion file

    _unison	New completion file

    _vnc	Added -via option

    _wpa_cli	New completion file

    _xournal	New completion file (only completes filenames).

    _xrandr	Added new options. Also made some options repeatable
		(e.g. --output). Completed values for displays, modes,
		--set and properties. (I took the completion values from
		my system. One may want to make these user configurable
		styles instead).

Thanks,

GI

-- 
The 10 Commandments of DOS:
6. Thou shall edit and shuffle the sacred lines of CONFIG.SYS and
AUTOEXEC.BAT until DOS functions adequately for the likes of you. Giving
up in disgust is not allowed.
#compdef gv

_arguments \
  '-geometry:geometry:_x_geometry' \
  '(--nosafer)--safer' \
  '(--safer)--nosafer' \
  '(--noquiet)--quiet' \
  '(--quiet)--noquiet' \
  '(--nocenter)--center' \
  '(--center)--nocenter' \
  '(--noswap)--swap' \
  '(--swap)--noswap' \
  '(--noantialias)--antialias' \
  '(--antialias)--noantialias' \
  '(--nodsc)--dsc' \
  '(--dsc)--nodsc' \
  '(--noeof)--eof' \
  '(--eof)--noeof' \
  '(--nopixmap)--pixmap' \
  '(--pixmap)--nopixmap' \
  '(--nowatch)--watch' \
  '(--watch)--nowatch' \
  '(--noresize)--resize' \
  '(--resize)--noresize' \
  '(--monochrome --color)--grayscale' \
  '(--grayscale --color)--monochrome' \
  '(--landscape --seascape --upsidedown)--portrait' \
  '(--portrait --seascape --upsidedown)--landscape' \
  '(--portrait --landscape --upsidedown)--seascape' \
  '(--portrait --landscape --seascape)--upsidedown' \
  --{help,spartan} \
  -{h,v} \
  '--arguments=:ghostscript arguments:' \
  '--page=:label of first page:' \
  '--media=:page size:(Letter Legal Statement Tabloid Ledger Folio Quarto 10x14 Executive A3 A4 A5 B4 B5)' \
  '--orientation=:orientation:(landscape seascape upsidedown portrait)' \
  '--scale=:scale entry:' \
  '--scalebase=:scale base:' \
  '--ad=:resource file:_files' \
  '--style=:resource file:_files' \
  '*:file: _pspdf -z'
#compdef lp lpr lpq lprm lpoptions lpstat

local expl ret=1 printer list disp strs shown

function _lp_get_printer()
{
  # No reason to call _lp_get_printer when service == lpstat. Others matched
  # below.
  case $service in
    (lpr|lpq|lprm)
      [[ "$words" == (#I)*-P* ]] && printer="${${words##*(#I)-P( |)}%% *}"
      ;;
    (lp)
      [[ "$words" == (#I)*-d* ]] && printer="${${words##*(#I)-d( |)}%% *}"
      ;;
    (lpoptions)
      [[ "$words" == (#I)*-(d|p)* ]] && \
	printer="${${words##*(#I)-(d|p)( |)}%% *}"
      ;;
  esac
}

function _lp_job_options()
{
  local -a lopts_with_args lopts_no_args

  # Generic options (from lp manual page)
  lopts_with_args=( media orientation-requested sides number-up scaling cpi lpi
    page-{bottom,left,right,top} )

  lopts_no_args=(fitplot landscape)

  _lp_get_printer
  [[ -n "$printer" ]] && printer=(-p $printer)

  # The program specified by the style list-printer-options should list jobs in
  # the same style as lpoptions -l.
  if compset -P '*='; then
    # List values for the option
    case ${IPREFIX%=} in
      (media)
	compadd "$@" a4 letter legal
	;;
      (orientation-requested)
	compadd "$@" 4
	;;
      (sides)
	compadd "$@" one-sided two-sided-{long,short}-edge
	;;
      (number-up)
	_description -V option-o-1 expl "pages per sheet"
	compadd "$expl[@]" 2 4 6 9 16
	;;
      (scaling|cpi|lpi|page-(bottom|left|right|top))
	return 0; # Don't complete anything
	;;
      (*)
	compadd "$@" \
	  $(_call_program list-printer-options lpoptions $printer -l | \
	    grep "^${IPREFIX%=}" | cut -d: -f2 | tr -d \* )
	;;
    esac
  else
    # List options
    local eq_suffix

    # Don't add an '=' suffix when completing lpoptions -r
    if [[ $service == lpoptions && $words[CURRENT-1] == "-r" ]]; then
      eq_suffix=()
    else
      eq_suffix=(-S '=')
    fi

    _description lpopts expl "generic printer options"
    compadd "$expl[@]" $eq_suffix $lopts_with_args
    compadd "$expl[@]" $lopts_no_args

    _description printeropts expl "printer specific options"
    compadd "$expl[@]" $eq_suffix \
      $(_call_program list-printer-options \
	lpoptions $printer -l | cut -d/ -f1)
  fi
}

function _lp_list_jobs()
{
  _lp_get_printer
  [[ -n "$printer" ]] && printer=(-P $printer)

  list=( ${(M)"${(f@)$(_call_program jobs lpq $printer 2> /dev/null)}":#[0-9]*} )

  if (( $#list )); then
    _tags users jobs

    while _tags; do
      if _requested users; then
	strs=( "${(@)${(@)list##[^ 	]##[ 	]##[^ 	]##[ 	]##}%%[ 	]*}" )
	if [[ -z "$shown" ]] &&
	   zstyle -T ":completion:${curcontext}:users" verbose;
	then
	  disp=(-ld list)
	  shown=yes
	else
	  disp=()
	fi
	_all_labels users expl user compadd "$disp[@]" -a strs ||
	    _users && ret=0
      fi
      if _requested jobs; then
	strs=( "${(@)${(@)list##[^ 	]##[ 	]##[^ 	]##[ 	]##[^ 	]##[ 	]##}%%[ 	]*}" )
	if [[ -z "$shown" ]] &&
	   zstyle -T ":completion:${curcontext}:jobs" verbose; then
	  disp=(-ld list)
	shown=yes
	else
	disp=()
	fi
	_all_labels jobs expl job compadd "$disp[@]" -a strs && ret=0
      fi
      (( ret )) || return 0
    done
  else
    _message 'no print jobs'
  fi
  return 1
}

case $service in
  (lpq)
    _arguments \
      '-E[Force encryption]' \
      '-U:username (for connection to server):_users' \
      '-h:alternate server:_hosts' \
      '(-a)-P+[destination printer]:printers:_printers' \
      '(-P)-a[all printers]' \
      '-l[long listing]' \
      '*:poll interval (+seconds):'
    ;;

  (lprm)
    _arguments \
      '-E[Force encryption]' \
      '-U:username (for connection to server):_users' \
      '-h:alternate server:_hosts' \
      '-P+[destination printer]:printers:_printers' \
      '*:job ids:_lp_list_jobs'
    ;;

  (lpoptions)
    _arguments \
      '-E[Force encryption]' \
      '-U:username (for connection to server):_users' \
      '-h:alternate server:_hosts' \
      '(-p -l -r -x)-d[set default printer]:printers:_printers' \
      '(-l -x)*-o:job options:_lp_job_options' \
      '(-d -x)-p[destination printer for options]:printers:_printers' \
      '(-d -o -r -x)-l[list options]' \
      '(-d -l -x)*-r:remove option:_lp_job_options' \
      '(-d -l -r -o)-x[remove all options]:printers:_printers'
    ;;

  (lpstat)
    _arguments \
      '-E[Force encryption]' \
      '-R[Shows print job ranking]' \
      '-U:username (for connection to server):_users' \
      '-W:which jobs:(completed not-completed)' \
      '-a[Show accepting state]:printers:_printers' \
      '-c:printer classes:' \
      '-d[Show current default destination]' \
      '-h:hostname (alternate server):_hosts' \
      '-l[long listing]' \
      '-o[destinations]:printers:_printers' \
      '-p:printers:_printers' \
      '-r[CUPS server running status]' \
      '-s[Status summary]' \
      '-t[All status info]' \
      '-u[list jobs by users]:users:_users' \
      '-v[show devices]:printers:_printers'
    ;;

  (lpr)
    _arguments \
      '-E[Force encryption]' \
      '-H:hostname (alternate server):_hosts' \
      '(-C -J -T)'-{C,J,T}':job name:' \
      '-P+[destination printer]:printers:_printers' \
      '-U:username (for connection to server):_users' \
      '-#[Copies]:copies (1--100):' \
      '-h[Disables banner printing]' \
      '-l[raw file]' \
      '-m[Send an email on job completion]' \
      '*-o:print job options:_lp_job_options' \
      '-p[format with shaded header incl. date, time etc.]' \
      '-q[Hold job for printing.]' \
      '-r[delete files after printing]' \
      '*:PS/PDF files:_pspdf'
    ;;

  (lp)
    _arguments \
      '-E[Force encryption]' \
      '-U[username (for connection to server)]:username:_users' \
      '-c[(OBSOLETE) copy to spool dir before printing]' \
      '-d[destination printer]:printers:_printers' \
      '-h:hostname (alternate server):_hosts' \
      '-i[job id to modify]:job id:' \
      '-m[Send an email on job completion]' \
      '-n[Copies]:copies (1--100):' \
      '*-o:print job options:_lp_job_options' \
      '-q[Job priority -- 1 (lowest) to 100 (highest)]:priority:' \
      '-s[Dont report resulting job IDs]' \
      '-t[Sets the job name]:job name:' \
      '-u[job submission username]:username:_users' \
      '-H[Time to print]:print time (or enter hh\:mm):(hold immediate restart resume)' \
      '-P:page range list:' \
      '*:PS/PDF files:_pspdf'
    ;;
esac
#compdef lsmod modinfo modprobe rmmod insmod

function _modules_caching_policy()
{
  # Rebuild every week, or if $modules_dir is newer than the cache
  local -a oldp

  oldp=( "$1"(Nmw+1) )
  (( $#oldp )) || [[ $modules_dir -nt $1 ]]
}

local curcontext="$curcontext" expl state line modules ign args ret=1
local -r modules_dir=/lib/modules

local update_policy
zstyle -s ":completion:*:*:$service:*" cache-policy update_policy
if [[ -z "$update_policy" ]]; then
  zstyle ":completion:*:*:$service:*" cache-policy _modules_caching_policy
fi

args=(
  '(-)'{-V,--version}'[print version]'
  '(-)'{-h,--help}'[print help text]'
)

case "$service" in
  lsmod) _arguments -s "$args[@]" && return ;;
  
  modinfo)
    _arguments -s -C "$args[@]" \
      '(-)'{-a,--author}"[display the module's author]" \
      '(-)'{-d,--description}"[display the module's description]" \
      '(-)'{-l,--license}"[display the module's license]" \
      '(-)'{-n,--filename}"[display the module's filename]" \
      '(-)'{-p,--parameters}'[display the typed parameters that a module may support]' \
      '(-)'{-F,--field}"[display only selected module's information]:module_field:(
        alias author depends description filename license parm)" \
      '(-)-k[use modules from a different kernel version]:kernel_version:(
        $(echo $modules_dir/*(/\:t)))' \
      '1:module file:->all_modules' && ret=0
  ;;

  modprobe)
    ign='-h --help -V --version -c --showconfig'
    _arguments -s -C "$args[@]" \
      "(-a --all $ign)"{-a,--all}'[load all matching modules]' \
      '(-)'{-c,--showconfig}'[show current configuration]' \
      "(-d --debug $ign)"{-d,--debug}'[print debug info]' \
      "(-k --autoclean $ign)"{-k,--autoclean}'[set autoclean]' \
      "(-n --show $ign)"{-n,--show}"[don't actually perform action]" \
      "(-q --quiet $ign)"{-q,--quiet}"[don't complain about insmod failures]" \
      "(-s --syslog $ign)"{-s,--syslog}'[report via syslog instead of stderr]' \
      "(* -t --type $ign)"{-t,--type}'[module type]:module type' \
      "(-v --verbose $ign)"{-v,--verbose}'[print all commands as executed]' \
      '(-C --config)'{-C,--config}'[specify config file]:config file:_files' \
      "(-r --remove -l --list -t --type -a --all $ign)"{-r,--remove}'[remove module (stacks)]' \
      "(-l --list -t --type -a --all $ign)"{'-i[ignore install/remove commands in config file]','--ignore-install[ignore install commands in config file]','--ignore-remove[ignore remove commands in config file]'} \
      "(* -l --list -r --remove $ign)"{-l,--list}'[list matching modules]' \
      "(-c $ign)1:modules:->loadable_modules" \
      "(-c -l --list -t --type $ign)*:params:->params" && ret=0
      
      [[ -n $state ]] && (( $+opt_args[-r] )) && state=loaded_modules        
  ;;

  rmmod)
    _arguments -s -C "$args[@]" \
      '(-a --all)'{-a,--all}'[remove all unused autocleanable modules]' \
      '(-e --persist)'{-e,--persist}'[save persistent data]' \
      '(-r --stacks)'{-r,--stacks}'[remove a module stack]' \
      '(-s --syslog)'{-s,--syslog}'[output to syslog]' \
      '(-v --verbose)'{-v,--verbose}'[be verbose]' \
      '*:loaded module:->loaded_modules' && ret=0
  ;;

  insmod)
    _arguments \
      '1:module file:_files' \
      '*:module parameters:' && ret=0
  ;;
esac 

case "$state" in
  loaded_modules|loadable_modules)
    if [[ -r /proc/modules ]]; then
     loaded_modules=(${${(f)"$(</proc/modules)"}%% *})
    elif [[ -x /sbin/lsmod ]]; then
     loaded_modules=(${${(f)"$(/sbin/lsmod)"}[2,-1]%% *})
    else
     return 1
    fi

    if [[ $state = loaded_modules ]]; then
        _wanted modules expl 'loaded module' compadd -a loaded_modules && return
        return ret
    fi
  ;&

  all_modules)
    local kver
    integer kver_idx
    if (( kver_idx=${words[(I)-k]} )); then
      kver=${words[kver_idx+1]}
    else
      kver=$(uname -r)
    fi
    if [[ -z $modules ]] && ! _cache_invalid modules-$kver && \
      ! _retrieve_cache modules-$kver;
    then 
      # 2011-01-02 gi1242: Do we need .o files? Or is .ko enough?
      modules=( $modules_dir/$kver/(*~(source|build))/**/*.(o|ko)(.:t:r) )
      _store_cache modules-$kver modules
    fi

    if [[ $state = loadable_modules ]]; then
        modules=( ${modules:#(${(j:|:)~${=loaded_modules//_/-}})} )
    fi

    _tags files modules
    while _tags; do
      _requested files expl "module file"  _files -g '*.ko' && ret=0
      _requested modules expl module compadd -a modules && ret=0
    done
  ;;

  params)
    if compset -P '*='; then
      _message -e value 'parameter value'
    else
      local params
      params=( ${${(M)${(f)"$(_call_program module_parameter modinfo "$words[2]" 2>/dev/null)"}:#parm:*}##parm:[[:space:]]##} )
      if [[ $#params -eq 0 ]]; then
        _message -e parameter "This modules doesn't have parameters"
      else
        typeset -A val_args

        _values -S = -C -w 'module parameter' \
          ${${${(M)params:#*(:bool|\(bool\))}/:/[}/(bool| \(bool\))/]} \
          ${^${params:#*(:bool|\(bool\))}/:/[}"]:auto added argument: " && ret=0
      fi
    fi
  ;;
esac

return ret
#compdef okular
local extns

extns="{pdf,ps,eps,dvi}(.gz|.bz2)(#c,1)|djvu|tiff|chm|cbr|cbz"

_arguments \
  '(-p --page)'{-p,--page}'[Page of the document to be shown]:page: ' \
  '--presentation[Start the document in presentation mode]' \
  '--unique[Unique instance control]' \
  "*:Okular documents:_files -g '*.(#i)($extns)(-.)'"
#compdef pdftk

function _pdfwithhandle()
{
    compset -P '(#I)[A-Z]='
    _files "$@" -g '(#i)*.pdf'
}

local expl
local -a opts operations

opts=(output encrypt_40bit encrypt_128bit allow owner_pw user_pw flatten
	compress uncompress keep_first_id keep_final_id drop_xfa verbose
	dont_ask do_ask)
operations=(cat attach_files unpack_files burst fill_form background stamp
	generate_fdf multibackground multistamp dump_data dump_data_fields
	update_info)

case $words[CURRENT-1] in
    ((input|owner|user)_pw)
	_message "password, or PROMPT"
	;;

    (allow)
	#_description permissions expl "permission"
	#compadd $expl \
	_values -s , permissions \
	    Printing DegradedPrinting ModifyContents Assembly CopyContents \
	    ScreenReaders ModifyAnnotations FillIn AllFeatures
	;;

    (attach_files)
	_files "$@"
	;;

    (fill_form)
	_description files expl 'FDF and XFDF files'
	_files "$@" $expl -g '(#i)*.(fdf|xfdf)'
	;;

    ((multibackground|background|stamp|multistamp|output))
	_description files expl 'PDF files'
	_files "$@" $expl -g '(#i)*.pdf'
	;;

    (update_info)
	_files
	;;

    (*)
	false
	;;
esac && return 0

if [[ -n $words[(r)(${(j:|:)operations})] ]]; then
    _description options expl "options"
    compadd $@ $expl $opts
else
    _tags files operations
    _alternative \
	'files:PDF files:_pdfwithhandle' \
	"operations:operations:($operations)"
fi
#compdef pgrep pkill 

local context state line
typeset -A opt_args
typeset -a arguments

arguments=('-P[parent process id]:parent process id:->ppid' 
	   '-g[match only in process group ids]:group:->pgid' 
	   '-G[match only real group id]:group:->group' 
	   '-s[match only session id]:session id:->sid' 
	   '-t[match only controlled by terminal]:terminal device:->tty'
	   '-u[match only effective user id]:user:->user' 
	   '-U[match only real user id]:user:->user' 
           '(-n)-o[oldest process]' 
	   '(-o)-n[newest process]' 
	   '-f[match against full command line]' 
	   '-v[negate matching]' 
	   '-x[match exactly]' 
	   '*:process name:->pname')

if [[ $service == 'pkill' ]]
then
	arguments+=('-'${^signals}'[signal]')
elif [[ $service == 'pgrep' ]]
then
	arguments+=('-d[output delimiter]:delimiter:compadd ${(s\:\:)IFS}'
		    '-l[list name in addition to id]')
fi

_arguments -s -w $arguments

case $state in
	(tty)
		compset -P '*,'

		local -a used
		used=(${(s:,:)IPREFIX})

		compadd -S ',' -q -F used /dev/tty*(:t)
		;;
		
	(sid)
		compset -P '*,'

		local -a used sid
		used=(${(s:,:)IPREFIX})
		sid=(${(uon)$(ps -A o sid=)})

		compadd -S ',' -q -F used $sid
		;;
	
	(ppid)
		compset -P '*,'

		local -a used ppid
		used=(${(s:,:)IPREFIX})
		ppid=(${(uon)$(ps -A o ppid=)})

		compadd -S ',' -q -F used $ppid
		;;

	(pgid)
		compset -P '*,'

		local -a used pgid
		used=(${(s:,:)IPREFIX})
		pgid=(${(uon)$(ps -A o pgid=)})

		compadd -S ',' -q -F used $pgid
		;;
	
	(pname)
		if (( ${+opt_args[-x]} )) && (( ${+opt_args[-f]} ))
		then
			compadd ${(u)${(f)"$(ps -A o cmd=)"}}
		else
			compadd ${(u)${(f)"$(ps -A co cmd=)"}}
		fi
		;;
	
	(group)
		compset -P '*,'

		local group
		group=$(getent group)

		local -a groups ids
		groups=(${${(f)group}%%:*})
		ids=(${${${(f)group}#*:*:}%%:*})

		local -a used
		used=(${(s:,:)IPREFIX})

		compadd -S ',' -q -F used -d ids $groups $groups
		;;

	(user)
		compset -P '*,'

		local passwd
		passwd=$(getent passwd)

		local -a users ids
		users=(${${(f)passwd}%%:*})
		ids=(${${${(f)passwd}#*:*:}%%:*})
		
		local -a used
		used=(${(s:,:)IPREFIX})

		compadd -S ',' -q -F used -d ids $users $users
		;;
esac
#compdef svn svnadmin svnadmin-static=svnadmin

_svn () {
  local curcontext="$curcontext" state line expl ret=1
  typeset -A opt_args

  local update_policy
  zstyle -s ":completion:*:*:$service:*" cache-policy update_policy
  if [[ -z "$update_policy" ]]; then
    zstyle ":completion:*:*:$service:*" cache-policy _svn_caching_policy
  fi

  _arguments -C \
    '(-)--help[print help information]' \
    '(- *)--version[print client version information]' \
    '1: :->cmds' \
    '*:: :->args' && ret=0

  if [[ -n $state ]] && (( ! $+_svn_cmds )); then
    typeset -gHA _svn_cmds
    if ! _cache_invalid svn_cmds && ! _retrieve_cache svn_cmds; then 
      _svn_cmds=(
	${=${(f)${${"$(LC_ALL=C _call_program commands svn help)"#l#*Available subcommands:}%%Subversion is a tool*}}/(#s)[[:space:]]#(#b)([a-z]##)[[:space:]]#(\([a-z, ?]##\))#/$match[1] :$match[1]${match[2]:+:${${match[2]//[(),]}// /:}}:}
      )
      _store_cache svn_cmds _svn_cmds
    fi
  fi

  case $state in
    cmds)
      _wanted commands expl 'svn command' _svn_commands && ret=0
    ;;
    args)
      local cmd args usage
      typeset -gHA _cache_svn_status _cache_svn_mtime

      cmd="${${(k)_svn_cmds[(R)*:$words[1]:*]}:-${(k)_svn_cmds[(i):$words[1]:]}}"
      if (( $#cmd )); then
        curcontext="${curcontext%:*:*}:svn-${cmd}:"

	if ! _cache_invalid svn-${cmd}-usage && \
	    ! _retrieve_cache svn-${cmd}-usage;
	then
	  usage=${${(M)${(f)"$(LC_ALL=C _call_program options svn help $cmd)"}:#usage:*}#usage:*$cmd] }
	  _store_cache svn-${cmd}-usage usage
	fi
	if ! _cache_invalid svn-${cmd}-usage && \
	    ! _retrieve_cache svn-${cmd}-args;
	then
	  args=(
	    ${=${${${(M)${(f)"$(LC_ALL=C _call_program options svn help $cmd)"#(*Valid options:|(#e))}:#* :*}%% #:*}/ (arg|ARG)/:arg:}/(#b)-([[:alpha:]]) \[--([a-z-]##)\](:arg:)#/(--$match[2])-$match[1]$match[3] (-$match[1])--$match[2]$match[3]}
	  )
	  _store_cache svn-${cmd}-args args
	fi

        case $cmd in;
          (add)
            args+=(
              '*:file:_files -g "*(^e:_svn_controlled:)"'
            )
          ;;
          (commit)
            args=(
	      ${args/(#b)(*--file*):arg:/$match[1]:file:_files}
              '*:file:_files -g "*(e:_svn_status:)"'
            )
          ;;
          (delete)
            args+=(
              '*:file:_files -g ".svn(/e:_svn_deletedfiles:)"'
            )
          ;;
          (diff)
            args+=(
	      '*: : _alternative "files:file:_files -g \*\(e:_svn_status:\)" "urls:URL:_svn_urls"'
	    )
          ;;
          (help)
            args+=(
              '*::sub command:_svn_commands'
            )
	  ;;
	  (import)
	    args+=(
		'1:project directory or import location: _alternative "files:file:_files" "urls:URL:_svn_urls"'
		'2:import location: _alternative "files:file:_files" "urls:URL:_svn_urls"'
	    )
          ;;
          (log)
            args+=(
              '1: : _alternative "files:file:_files -g \*\(e:_svn_controlled:\)" "urls:URL:_svn_urls"'
	      '*:file:_files -g "*(e:_svn_controlled:)"'
            )
          ;;
	  (propget|propedit)
	    args+=(
		'1:property name:_svn_props'
		'2:target: _alternative "files:file:_files" "urls:URL:_svn_urls"'
	    )
	  ;;
	  (propset)
	    args=(
	    ':propname:(svn:ignore svn:keywords svn:executable svn:eol-style svn:mime-type svn:externals svn:needs-lock)'
	    ${args/(#b)(*--file*):arg:/$match[1]:file:_files}
	    '*:path or url: _alternative "files:file:_files" "urls:URL:_svn_urls"'
	    )
	  ;;
          (resolved)
            args+=(
              '*:file:_files -g "*(e:_svn_conflicts:)"'
            )
          ;;
          (revert)
            args+=(
              '*:file:_files -g "(.svn|*)(/e:_svn_deletedfiles:,e:_svn_status:)"'
            )
          ;;
          (*)
            case $usage in
              *(SRC|DST|TARGET|URL*PATH)*)
                args+=(
	          '*: : _alternative "files:file:_files" "urls:URL:_svn_urls"'
	        )
	      ;;
              *URL*) args+=( ':URL:_svn_urls' ) ;;
              *PATH*) args+=( '*:file:_files' ) ;;
            esac
          ;;
        esac

        _arguments "$args[@]" && ret=0

      else
        _message "unknown svn command: $words[1]"
      fi
    ;;
  esac

  return ret
}

_svnadmin () {
  local curcontext="$curcontext" state line ret=1

  _arguments -C \
    '(-)--help[print help information]' \
    '(- *)--version[print client version information]' \
    '1: :->cmds' \
    '*:: :->args' && ret=0

  if [[ -n $state ]] && (( ! $+_svnadmin_cmds )); then
    typeset -gHA _svnadmin_cmds
    _svnadmin_cmds=(
      ${=${(f)${${"$(LC_ALL=C _call_program commands svnadmin help)"#l#*Available subcommands:}}}/(#s)[[:space:]]#(#b)([-a-z]##)[[:space:]]#(\([a-z, ?]##\))#/$match[1] :$match[1]${match[2]:+:${${match[2]//[(),]}// /:}}:}
    )
  fi

  case $state in
    cmds)
      _wanted commands expl 'svnadmin command' _svnadmin_commands && ret=0
    ;;
    args)
      local cmd args usage

      cmd="${${(k)_svnadmin_cmds[(R)*:$words[1]:*]}:-${(k)_svnadmin_cmds[(i):$words[1]:]}}"
      if (( $#cmd )); then
        curcontext="${curcontext%:*:*}:svnadmin-${cmd}:"

        usage=${${(M)${(f)"$(LC_ALL=C _call_program options svnadmin help $cmd)"}:#$cmd: usage:*}#$cmd: usage: svnadmin $cmd }
        args=(
          ${=${${${(M)${(f)"$(LC_ALL=C _call_program options svnadmin help $cmd)"#(*Valid options:|(#e))}:#* :*}%% #:*}/ (arg|ARG)/:arg:}/(#b)-([[:alpha:]]) \[--([a-z-]##)\](:arg:)#/(--$match[2])-$match[1]$match[3] (-$match[1])--$match[2]$match[3]}
        )
        if [[ $usage == *REPOS_PATH* ]]; then
          args+=( ":path:_files -/" )
        elif [[ $cmd = help ]]; then
          args+=( "*:subcommand:_svnadmin_commands" )
        fi

        _arguments "$args[@]" && ret=0
      else
        _message "unknown svnadmin command: $words[1]"
      fi
    ;;
  esac

  return ret
}

(( $+functions[_svn_controlled] )) ||
_svn_controlled() {
  [[ -f ${(M)REPLY##*/}.svn/text-base/${REPLY##*/}.svn-base ]]
}

(( $+functions[_svn_conflicts] )) ||
_svn_conflicts() {
  [ -n $REPLY.(mine|r<->)(N[1]) ]
}

(( $+functions[_svn_deletedfiles] )) ||
_svn_deletedfiles() {
  # Typical usage would be _files -g '.svn(/e:_svn_deletedfiles:)'
  local cont controlled
  reply=( )
  [[ $REPLY = (*/|).svn ]] || return
  controlled=( $REPLY/text-base/*.svn-base(N:r:t) )
  for cont in ${controlled}; do
    [[ -e $REPLY:h/$cont ]] || reply+=( ${REPLY%.svn}$cont )
  done
}

(( $+functions[_svn_status] )) ||
_svn_status() {
  local dir=$REPLY:h
  local pat="${1:-([ADMR~]|?M)}"

  zmodload -F zsh/stat b:zstat 2>/dev/null
  local key="$(zstat +device $dir):$(zstat +inode $dir)"
  local mtime="$(zstat +mtime $dir/.svn/entries)"

  if (( ! $+_cache_svn_status[$key] || _cache_svn_mtime[$key] != mtime )); then
    _cache_svn_status[$key]="$(_call_program files svn status -N $dir)"
    _cache_svn_mtime[$key]="$mtime"
  fi

  (( ${(M)#${(f)_cache_svn_status[$key]}:#(#s)${~pat}*$REPLY} ))
}

(( $+functions[_svn_remote_paths] )) ||
_svn_remote_paths() {
  local expl remfiles remdispf remdispd suf ret=1 pfx='\^/' sub='^/'

  # prefix must match a valid repository path format, either standard style
  # schema://host/path/.. or ^/path/.. specifying a path relative to the
  # root of the working directory repository.  In the second form, allow the
  # leading '^' be escaped in case the user has the extendedglob option set.
  [[ -prefix *://*/ ]] ||
  [[ -f .svn/entries && ( -prefix '^/' || -prefix '\^/' ) ]] ||
  return 1

  # return if remote access is not permitted
  zstyle -T ":completion:${curcontext}:" remote-access || return 1

  remfiles=( ${(f)"$(svn list $IPREFIX${${PREFIX%%[^/]#}/#$pfx/$sub} 2>/dev/null)"} )
  (( $? == 0 )) || return 1

  # you might consider trying to return early if $#remfiles is zero,
  # but for whatever reason remfiles will always contain at least a
  # single empty string; that case is handled correctly below.

  compset -P '*/'
  compset -S '/*' || suf=file
  remdispf=(${remfiles:#*/})
  remdispd=(${(M)remfiles:#*/})
  _tags files
  while _tags; do
    while _next_label files expl ${suf:-directory}; do
      # add files, unless there is a '/' immediately to the right
      [[ -n $suf ]] &&
      compadd -S ' ' -q "$@" "$expl[@]" -d remdispf $remdispf && ret=0
      # add directories; use empty suffix if there is a '/' immediately to the right
      compadd -S "${suf:+/}" -q "$@" "$expl[@]" -d remdispd ${remdispd%/} && ret=0
    done
    (( ret )) || return 0
  done

  return 1
}

(( $+functions[_svn_urls] )) ||
_svn_urls() {
  local urlsch expl ret=1

  # first try completing a remote path; if successful, we are all done..
  _svn_remote_paths && return 0

  # allow configuring svn repository locations using the 'urls' zstyle.
  # always attempt completion of these because then matcher-list styles
  # which do substring matching will work correctly.
  _urls -S/ && ret=0

  if [[ ! -prefix *://? ]] ; then
    zstyle -a ":completion:${curcontext}:" url-schemas urlsch \
     || urlsch=( file:// http:// https:// svn:// svn+ssh:// )
    
    if (( $#urlsch )) ; then
      compset -S '[^:]*'
      _wanted url-schemas expl 'URL schema' compadd -S '' - $urlsch[@] && ret=0
    fi
  fi

  return ret
}

(( $+functions[_svn_commands] )) ||
_svn_commands() {
  compadd "$@" -k _svn_cmds || compadd "$@" ${(s.:.)_svn_cmds}
}

(( $+functions[_svnadmin_command] )) ||
_svnadmin_commands() {
  compadd "$@" -k _svnadmin_cmds || compadd "$@" ${(s.:.)_svnadmin_cmds}
}

(( $+functions[_svn_props] )) ||
_svn_props() {
  local properties

  properties=( ${${(M)${(f)"$(svn proplist 2>/dev/null)"}:#  [^ ]*}#  } )
  compadd "$@" -a properties && return 0
}

_subversion () {
  case $service in
    (svn) _svn "$@" ;;
    (svnadmin) _svnadmin "$@" ;;
  esac
}

_svn_caching_policy() {
  # Rebuild every week
  local -a oldp

  oldp=( "$1"(Nmw+1) )
  (( $#oldp ))
}


_subversion "$@"
#compdef tex latex pdftex pdflatex

_arguments : \
    '-enc[enable encTeX extensions]' \
    '(-no-file-line-error -file-line-error)'{-no,}'-file-line-error[enable/disable file\:line\:error style messages]' \
    '-fmt=-[use FMTNAME instead of program name or a %& line]:FMTNAME:' \
    '-halt-on-error[stop processing at the first error]' \
    '-ini[be initex, for dumping formats]' \
    '-interaction[set interaction mode]:STRING:(batchmode nonstopmode  scrollmode errorstopmode)' \
    '-ipc[send DVI output to a socket as well as the usual output file]' \
    '-ipc-start[as -ipc, and also start the server at the other end]' \
    '-jobname=-[set the job name]:STRING:' \
    '-kpathsea-debug=-[set path searching debugging flags according to the bits of NUMBER]:NUMBER:' \
    '(-no-mktex -mktex)'{-no,}'-mktex=-[enable/disable mktexFMT generation]:FMT:(tex tfm)' \
    '-mltex[enable MLTeX extensions]' \
    '-output-comment=-[DVI file comment]:STRING:' \
    '-output-directory=-[directory to write files to]:DIR:' \
    '(-no-parse-first-line -parse-first-line)'{-no,}'-parse-first-line[disable/enable parsing of the first line of the input file]' \
    '-progname=-[set program (and fmt) name]:STRING:' \
    '-recorder[enable filename recorder]' \
    '(-no-shell-escape -shell-escape)'{-no,}-shell-escape'[enable/disable \\write18{SHELL COMMAND}]' \
    '-shell-restricted[enable restricted \\write18]' \
    '-src-specials[insert source specials into the DVI file]' \
    '-src-specials=-[insert source specials in certain places of the DVI file]:WHERE:_values -s , WHERE cr display hbox math par parend vbox' \
    '-translate-file=-[use the TCX file TCXNAME]:TCXNAME:' \
    '-8bit[make all characters printable by default]' \
    '-help[display this help and exit]' \
    '-version[output version information and exit]' \
    '*:TeX file:_files -g "*.tex"'
#compdef unison

local context state line
typeset -A opt_args

_arguments \
    '-auto[automatically accept default (nonconflicting) actions]' \
    '-batch[batch mode\: ask no questions at all]' \
    '-doc[show documentation]:topics:(about people lists status copying ack install tutorial basics failures running ssh news all topics)' \
    '-follow[add a pattern to the follow list]:pattern:' \
    '-force[force changes from this replica to the other]:replica:' \
    '-group[synchronize group attributes]' \
    '-ignore[add a pattern to the ignore list]:pattern:' \
    '-ignorenot[add a pattern to the ignorenot list]:pattern:' \
    '-owner[synchronize owner]' \
    '-path[path to synchronize]:path:_files' \
    '-perms[part of the permissions which is synchronized]:perms:' \
    '-prefer[choose this replicas version for conflicting changes]:replica:' \
    '-root[root of a replica (should be used exactly twice)]:path:_files -/' \
    '-silent[print nothing except error messages]' \
    '-terse[suppress status messages]' \
    '-testserver[exit immediately after the connection to the server]' \
    '-times[synchronize modification times]' \
    '-version[print version and exit]' \
    '-addprefsto[add new prefs to]:file:_files' \
    '-addversionno[add version number to name of unison on server]' \
    '-backup[add a pattern to the backup list]:pattern:' \
    '-backupcurr[add a pattern to the backupcurr list]:pattern:' \
    '-backupcurrnot[add a pattern to the backupcurrnot list]:pattern:' \
    '-backupdir[directory for storing centralized backups]:directory:_files -/' \
    '-backuploc[where backups are stored]:backup location:(local central)' \
    '-backupnot[add a pattern to the backupnot list]:pattern:' \
    '-backupprefix[prefix for the names of backup files]:prefix:' \
    '-backups[keep backup copies of all files]' \
    '-backupsuffix[a suffix to be added to names of backup files]:suffix:' \
    '-confirmbigdel[ask about whole-replica (or path) deletes (default true)]' \
    '-confirmmerge[ask for confirmation before commiting results of a merge]' \
    '-contactquietly[suppress the "contacting server" message during startup]' \
    '-copyprog[external program for copying large files]:program:_files -g "*(-x)"' \
    '-copyprogrest[variant of copyprog for resuming partial transfers]:program:_files -g "*(-x)"' \
    '-copyquoterem[add quotes to remote file name for copyprog]:quote style:(true false default)]' \
    '-copythreshold[use copyprog on files bigger than this]:size (kb):' \
    '-debug:debug module:(all verbose)' \
    '-diff[command for showing differences between files]:program:_files -g "*(-x)"' \
    '-dontchmod[When set, never use the chmod system call]' \
    '-dumbtty[do not change terminal settings in text UI]' \
    '-fastcheck:fast update detection:(true false default)' \
    '-forcepartial[add a pattern to the forcepartial list]:pattern:' \
    '-height[height of main window in graphical interface]:number (lines):' \
    '-host[bind the socket to this host name in server socket mode]:host:_hosts' \
    '-ignorecase[identify upper/lowercase filenames]:ignorecase:(true false default)' \
    '-ignorelocks[ignore locks left over from previous run (dangerous!)]' \
    '-immutable[add a pattern to the immutable list]:pattern:' \
    '-immutablenot[add a pattern to the immutablenot list]:pattern:' \
    '-key[define a keyboard shortcut for this profile (in some UIs)]:shortcut:' \
    '-killserver[kill server when done (even when using sockets)]' \
    '-label[provide a descriptive string label for this profile]:label:' \
    '-log[record actions in logfile (default true)]' \
    '-logfile:logfile name:_files' \
    '-maxbackups[number of backed up versions of a file]:number:' \
    '-maxthreads[maximum number of simultaneous file transfers]:number:' \
    '-merge[add a pattern to the merge list]:pattern:' \
    '-mountpoint[abort if this path does not exist]:mountpoint:_files -/' \
    '-numericids[dont map uid/gid values by user/group names]' \
    '-preferpartial[add a pattern to the preferpartial list]:pattern:' \
    '-pretendwin[Use creation times for detecting updates]' \
    '-repeat[synchronize repeatedly (text interface only)]:repeat:' \
    '-retry[re-try failed synchronizations N times (text ui only)]:retry times:' \
    '-rootalias[register alias for canonical root names]:root alias:' \
    '-rsrc:synchronize resource forks:(true false default)' \
    '-rsync[activate the rsync transfer mode (default true)]' \
    '-selftest[run internal tests and exit]' \
    '-servercmd[name of unison executable on remote server]:program:_files -g "*(-x)"' \
    '-showarchive[show "true names" (for rootalias) of roots and archive]' \
    '-socket[act as a server on a socket]:socket:_files -g "*(-=)"' \
    '-sortbysize[list changed files by size, not name]' \
    '-sortfirst[add a pattern to the sortfirst list]:pattern:' \
    '-sortlast[add a pattern to the sortlast list]:pattern:' \
    '-sortnewfirst[list new before changed files]' \
    '-sshargs[other arguments (if any) for remote shell command]:ssh args:' \
    '-sshcmd[path to the ssh executable]:program:_files -g "*(-x)"' \
    '-ui:user interface:(text graphic)' \
    '-xferbycopying[optimize transfers using local copies (default true)]' \
    '*:profile:->profile'

if [[ $state == profile ]]; then
    local -a profiles

    profiles=( ~/.unison/*.prf(N) )
    (( $#profiles )) && \
	compadd "$@" - ${${profiles#~/.unison/}%.prf}
fi
#compdef vncserver vncviewer xvncviewer xtightvncviewer xvnc4viewer

local displays args
displays=( ~/.vnc/$HOST:<->.pid(N:r:t:s/$HOST//) )
displays=( \\${^displays} ) 

case $service in
  vncserver)
    # currently lacking Xvnc arguments
    _arguments \
      - start \
	'-name:desktop name:_x_name' \
	'-geometry:geometry:(1600x1200 1280x1024 1152x864 1024x768 800x600 640x480)' \
	'-depth:pixel depth:(8 16 24 32)' \
	'-pixelformat:pixel format' \
	'1:: :_guard "(|:[0-9]#)" "display number"' \
      - kill \
	"-kill:display number:($displays)" \
      - help \
	'-help'
  ;;
  *vncviewer) 
    _xt_arguments -shared -viewonly -fullscreen -bgr233 -owncmap -truecolour \
      '-encodings:encodings:_values -s " " encoding copyrect hextile corre rre raw' \
      '-depth:depth' \
      '-passwd:file:_files' \
      '(1)-listen:display number' \
      '-via:host:_hosts' \
      '(-listen)1::display:_x_display'
  ;;
esac
    
#compdef wpa_cli

_arguments \
    '-p:path to ctrl sockets:_files -g "*(=)"' \
    '-i:ifname:_net_interfaces' \
    '-h[help]' \
    '-v[shown version information]' \
    '-B[run a daemon in the background]' \
    '-a[run in daemon mode]:action file:_files' \
    '-P:pid file:_files' \
    '-g:global ctrl:_files -g "*(=)"' \
    '-G:ping interval:' \
    ':command:(status ping mib help interface level license quit set logon logoff pmksa reassociate preauthenticate identity password new_password pin otp passphrase bssid list_networks select_network enable_network disable_network add_network remove_network set_network get_network save_config disconnect reconnect scan scan_results bss get_capability reconfigure terminate interface_add interface_remove interface_list ap_scan stkstart ft_ds wps_pbc wps_pin wps_reg)'
#compdef xournal

local expl

_description files expl 'PDF and Xournal files'
_files "$@" "$expl[@]" -g '*.(#i){xoj,pdf}(-.)'
#compdef xrandr
local context state line
typeset -A opt_args
local outputs modes expl

# User configurable. TODO -- styles?
outputs=(LVDS1 TV1 VGA1)
modes=(1280x800 1024x768 800x600 640x480)

_arguments \
  '(-d -display)'{-d,-display}':X display:_x_display' \
  '-help[display help]' \
  '(-o --orientation)'{-o,--orientation}':rotation:(normal inverted left right 0 1 2 3)' \
  '(-q --query)'{-q,--query}'[display current state]' \
  '(-s --size)'{-s,--size}':size:' \
  '(-r --rate --refresh)'{*-r,*--rate,*--refresh}':target refresh rate:' \
  '(-v --version)'{-v,--version}'[display version]' \
  '-x[reflect across X axis]' \
  '-y[reflect across Y axis]' \
  '--screen:X screen number' \
  '--verbose[be more verbose]' \
  '--dryrun' \
  '--nograb' \
  '(--prop --properties)'{--prop,--properties}'[display the contents of properties for each output]' \
  '--fb:size:' \
  '--fbmm:size:' \
  '--dpi:dpi:' \
  "*--output:output to reconfigure:($outputs)" \
  '*--auto' \
  "*--mode:mode:($modes)" \
  '*--preferred' \
  '*--pos:position:' \
  '*--reflect:axes:(normal x y xy)' \
  '*--rotate:rotation:(normal inverted left right)' \
  "*--left-of:relative position to:($outputs)" \
  "*--right-of:relative position to:($outputs)" \
  "*--above:relative position to:($outputs)" \
  "*--below:relative position to:($outputs)" \
  "*--same-as:relative position to:($outputs)" \
  '*--set:property:(Backlight scaling\ mode):value:->value' \
  '*--scale:output scaling:' \
  '*--transform:transformation matrix:' \
  '*--off[disable the output]' \
  '*--crtc:crtc to use:' \
  '*--panning:panning:' \
  '*--gamma:r\:g\:b:' \
  '*--primary' \
  '--noprimary' \
  '*--newmode:name: :clock MHz: :hdisp: :hsync-start: :hsync-end: :htotal: :vdisp: :vsync-start: :vsync-end: :vtotal:' \
  '*--rmmode:Mode name:' \
  "*--addmode:output:($outputs):name:" \
  "*--delmode:output:($outputs):name:" \
  && return 0

if [[ $state == value ]]; then
    case $words[CURRENT-1] in
	(scaling* mode)
	    _description value expl "output property 'scaling mode'"
	    compadd "$@" "$expl[@]" None Full Center Full\ aspect && return 0
	    ;;
    esac
fi


Messages sorted by: Reverse Date, Date, Thread, Author