1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-17 02:51:01 +02:00
zsh/Completion/Unix/Command/_pgrep
dana 6fe0c24fdb 43105: Improve pgrep/pkill completion
Contains minor changes to signal completion compared to the patch as originally
posted
2018-07-03 20:04:59 -05:00

244 lines
8 KiB
Text

#compdef pgrep pkill
# Notes:
# - We assume that Linux systems use procps-ng — specifically, procps-ng >=3.3.4
# (which changed the behaviour of -f and added -a)
# - We don't really need to keep pgopts and pkopts separate, but it seems like
# it should make things a bit easier to follow
# - @todo We could complete log-in classes given to -c
# - @todo We could complete routing tables given to -T
local curcontext="$curcontext" state line ret=1 expl pgopts pkopts no
typeset -A opt_args
typeset -a arguments sig_arguments aopts
# These arguments (a) are common to all variants (like -x), (b) are the most
# common amongst all variants (like -a), or (c) have a single unambiguous
# meaning amongst all variants (like --help). Many of them are filtered out or
# overridden below
arguments=(
'-a[include process ancestors in match list]'
'-c+[match only on specified login class]:login class'
'(-F --pidfile)'{-F+,--pidfile=}'[match only processes in specified PID file]:PID file:_files'
'(-f --full)'{-f,--full}'[match against full command line]'
'(-G --group)'{-G+,--group=}'[match only on specified real group IDs]: :_sequence _groups'
'(-g --pgroup)'{-g+,--pgroup=}'[match only on specified process group IDs]: :->pgid'
'(: * -)'{-h,--help}'[display help information]'
'-I[request confirmation before signalling each process]'
'-i[ignore case distinctions]'
'-J+[match only on specified project IDs]: :->projid'
'-j+[match only on specified jail IDs]:jail:_sequence _jails -0 -o jid'
'(-L --logpidfile)'{-L,--logpidfile}'[fail if PID file not locked (with -F)]'
'(-N)-M+[extract name list from specified core]:core file:_files'
'(-M)-N+[extract name list from specified system]:system file:_files'
'(-o -n --oldest --newest)'{-n,--newest}'[match newest process]'
'(-o -n --oldest --newest)'{-o,--oldest}'[match oldest process]'
'(-P --parent)'{-P+,--parent=}'[match only on specified parent process IDs]: :->ppid'
'(-l)-q[suppress normal output]'
'-S[search also in system processes (kernel threads)]'
'(-s --session)'{-s+,--session=}'[match only on specified process session IDs]: :->sid'
# _signals is OK here — we do it differently below
'(ss)--signal=[specify signal to send to process]: :_signals -s'
'-T+[match only on specified routing table]:routing table'
'(-t --terminal)'{-t+,--terminal=}'[match only on specified controlling terminals]:terminal device:_sequence _ttys -d'
'(-U --uid)'{-U+,--uid=}'[match only on specified real user IDs]: :_sequence _users'
'(-u --euid)'{-u+,--euid=}'[match only on specified effective user IDs]: :_sequence _users'
'(-v --inverse)'{-v,--inverse}'[negate matching]'
'(-x --exact)'{-x,--exact}'[match process name or command line (with -f) exactly]'
'--ns=[match only on same namespaces as specified PID]: :_pids'
'--nslist=[match only on specified namespaces (with --ns)]:namespace:(ipc mnt net pid user uts)'
'(: * -)'{-V,--version}'[display version information]'
'-z+[match only on specified zone IDs]:zone:_sequence _zones'
)
[[ $service == pgrep ]] && arguments+=(
'(-d --delimiter)'{-d+,--delimiter=}'[specify output delimiter]:delimiter:compadd ${(s<>)IFS}'
'(-q)-l[display process name (and arguments with -f)]'
'(-w --lightweight)'{-w,--lightweight}'[show all thread IDs instead of PID]'
)
[[ $service == pkill ]] && arguments+=(
'(-e --echo)'{-e,--echo}'[display signalled process]'
'-l[display kill command]'
)
case $OSTYPE in
linux*)
# Note: We deliberately exclude -v but not --inverse from pkill
pgopts=acdFfGghLlnoPstUuVvwx-
pkopts=ceFfGghLnoPstUuVx-
arguments=(
${arguments:#((#s)|*\))(\*|)-[acl]*}
'(-c --count)'{-c,--count}'[display count of matching processes]'
)
[[ $service == pgrep ]] && arguments+=(
'(-a -l --list-full --list-name)'{-a,--list-full}'[display full command line]'
'(-a -l --list-full --list-name)'{-l,--list-name}'[display process name]'
)
;;
dragonfly*|freebsd*)
pgopts=acdFfGgijLlMNnoPqSstUuvx
pkopts=acFfGgIijLlMNnoPstUuvx
;;
openbsd*)
pgopts=dfGglnoPqsTtUuvx
pkopts=fGgIlnoPqsTtUuvx
;;
darwin*)
pgopts=adFfGgiLlnoPqtUuvx
pkopts=aFfGgIiLlnoPtUuvx
;;
solaris*)
pgopts=cdfGgJlnoPsTtUuvxz
pkopts=cfGgJnoPsTtUuvxz
arguments=(
${arguments:#((#s)|*\))(\*|)-[cT]*}
'-c+[match only on specified contract IDs]: :->contract'
'-T+[match only on specified task IDs]: :->task'
)
;;
*)
pgopts=dfGgilnPstUuvx
pkopts=fGgilnPstUuvx
;;
esac
if [[ $service == pgrep ]]; then
arguments=( ${(M)arguments:#((#s)|*\))(\*|)-[$pgopts]*} )
else
arguments=( ${(M)arguments:#((#s)|*\))(\*|)-[$pkopts]*} )
# Signals on non-Linux systems can only be completed as the first argument
(( CURRENT != 2 )) && [[ $OSTYPE != linux* ]] && no='!'
# This is used for exclusion with --signal
sig_arguments=( + '(ss)' )
# This is very similar to _signals, but i've avoided it here because it
# doesn't behave the way i want it to
sig_arguments+=( $no'(--signal)-'${^signals[2,-3]} )
sig_arguments+=( '!(--signal)-'{0..$(( $#signals - 3 ))} )
# Complete the -SIG* variant if it's requested
if [[ $PREFIX$SUFFIX == -S* ]]; then
sig_arguments+=( '(--signal)-SIG'${^${(@)signals[2,-3]:#<->}} )
else
sig_arguments+=( '!(--signal)-SIG'${^${(@)signals[2,-3]:#<->}} )
fi
fi
arguments+=( $sig_arguments + o '*: :->pname' )
[[ $OSTYPE == linux* ]] || aopts+=( -A '*-' )
_arguments -C -s -S $aopts : $arguments && ret=0
case $state in
(sid)
if [[ $OSTYPE == openbsd* ]]; then
break
fi
compset -P '*,'
local -a used sid
used=(${(s:,:)IPREFIX})
if [[ $OSTYPE == freebsd* ]]; then
sid=(${(uon)$(ps -ax -o sid=)})
else
sid=(${(uon)$(ps -A -o sid=)})
fi
_wanted sid expl 'session ID' compadd -S ',' -q -F used $sid
;;
(ppid)
compset -P '*,'
local -a used ppid
used=(${(s:,:)IPREFIX})
if [[ $OSTYPE == (freebsd|openbsd|darwin)* ]]; then
ppid=(${(uon)$(ps -ax -o ppid=)})
else
ppid=(${(uon)$(ps -A -o ppid=)})
fi
_wanted ppid expl 'parent process ID' compadd -S ',' -q -F used $ppid
;;
(pgid)
compset -P '*,'
local -a used pgid
used=(${(s:,:)IPREFIX})
if [[ $OSTYPE == (freebsd|openbsd|darwin)* ]]; then
pgid=(${(uon)$(ps -ax -o pgid=)})
else
pgid=(${(uon)$(ps -A -o pgid=)})
fi
_wanted pgid expl 'process group ID' compadd -S ',' -q -F used $pgid
;;
(projid)
compset -P '*,'
local -a used projid
used=(${(s:,:)IPREFIX})
projid=(${(uon)$(ps -A -o project=)})
_wanted projid expl 'project ID' compadd -S ',' -q -F used $projid
;;
(contract)
compset -P '*,'
local -a used ctid
used=(${(s:,:)IPREFIX})
ctid=(${(uon)$(ps -A -o ctid=)})
_wanted ctid expl 'contract ID' compadd -S ',' -q -F used $ctid
;;
(task)
compset -P '*,'
local -a used taskid
used=(${(s:,:)IPREFIX})
taskid=(${(uon)$(ps -A -o project=)})
_wanted taskid expl 'task ID' compadd -S ',' -q -F used $taskid
;;
(pname)
local ispat="pattern matching "
if (( ${+opt_args[-x]} )); then
ispat=""
fi
local command
if (( ${+opt_args[-f]} )); then
if [[ "$OSTYPE" == freebsd* ]] && (( ${+opt_args[-S]} )); then
command="$(ps -axH -o command=)"
elif [[ "$OSTYPE" == (freebsd|openbsd|darwin)* ]]; then
command="$(ps -ax -o command=)"
elif [[ "$OSTYPE" == solaris* ]]; then
command="$(ps -A -o args=)"
else
command="$(ps -A o cmd=)"
fi
_wanted pname expl $ispat'process command line' compadd ${(u)${(f)${command}}}
else
if [[ "$OSTYPE" == freebsd* ]] && (( ${+opt_args[-S]} )); then
command="$(ps -axcH -o command=)"
elif [[ "$OSTYPE" == (freebsd|openbsd|darwin)* ]]; then
command="$(ps -axc -o command=)"
elif [[ "$OSTYPE" == solaris* ]]; then
command="$(ps -A -o comm=)"
else
command="$(ps -A co cmd=)"
fi
_wanted pname expl $ispat'process name' compadd ${(u)${(f)${command}}}
fi
;;
esac && ret=0
return ret