killでプロセスIDかプロセス名を補完する
[zsh] killコマンドでpidやコマンド名の補完 〜Just another Ruby porter,
に触発されてbashで同じようなことをしてみる。
$ kill 224<TAB> 22421 hirose31 pts/15 00:00:06 emacs 22491 hirose31 tty1 00:00:01 kterm 22493 hirose31 pts/16 00:00:00 /bin/bash $ kill su<TAB> su - 21928 root pts/14 00:00:00 sudo xconsole -fg red -bg g 21653 root tty1 00:00:00 supervise log 2267 root ? 00:00:00 supervise log 2269 root ? 00:00:00 supervise qmail-send 2268 root ? 00:00:00 supervise smtpd 2266 root ? 00:00:00
コードはこんな感じ。元はbash-completionからパクりました。
## kill
_signals() {
local i
# standard signal completion is rather braindead, so we need
# to hack around to get what we want here, which is to
# complete on a dash, followed by the signal name minus
# the SIG prefix
COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
COMPREPLY[i]=-${COMPREPLY[i]#SIG}
done
}
_pids() {
case $cur in
[a-zA-Z]*)
c=$( compgen -W '$( ps axo cmd | sed 1d )' -- $cur | wc -l)
if [ $c -eq 1 ]; then
# compgenを使ってないので不安…
COMPREPLY=( $(ps axo pid,cmd | awk "\$2 ~ /^${cur}/{print \$1}") )
else
IFS='
' COMPREPLY=( $( compgen -W '$( ps axo cmd,pid,user,tty,time | sed 1d | cut -c 1-76 )' -- $cur) )
fi
;;
*)
c=$( compgen -W '$( ps axo pid | sed 1d )' -- $cur | wc -l)
if [ $c -eq 1 ]; then
COMPREPLY=( $( compgen -W '$( ps axo pid | sed 1d )' -- $cur) )
else
IFS='
' COMPREPLY=( $( compgen -W '$( ps axo pid,user,tty,time,cmd | sed 1d | cut -c 1-76 )' -- $cur) )
fi
;;
esac
}
_kill() {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then
# return list of available signals
_signals
else
# return list of available PIDs
_pids
fi
}
complete -F _kill kill