My pdksh project is mainly focusing on interactive shells. I use vi editing mode, so I will try to fix any bug found in it. I added supports for arrow keys and Home, End, PgUp, PgDn, so the cursor can be moved easier.
I also added programmed tab-completion, just like bash. It's kind of complicated, though, and there still may be bugs. OK, let me introduce the programmed tab-completion to you.
First of all, you may need to edit your $HOME/.kshrc to setup your tab-completion configuration. Some lines of mine look like:
# interactive shell only
[[ "$-" == *i* ]] || return
PS1='$USER@${PWD}$ '
# list of alias and predefined function/variable.
#...
#...
#...
[[ "$KSH_VERSION" == *PD* ]] || return
# command completions
complete 'sudo=C'
complete 'git=S:add,:status,:commit,clone,:diff,:log'
complete 'svn=S:add,:status,:commit,checkout,@--diff-cmd,:diff,:log'
function _systemctl {
typeset ACT="enable disable start stop restart status reload"
case $# in
0)
_COMPLETE=$ACT
;;
1)
if [[ -z "$1" ]]; then
_COMPLETE=$ACT
else
typeset -i i=0
typeset outs
typeset a
for a in $ACT; do
if [[ ${a#$1} != $a ]]; then
outs[$((i++))]=$a
fi
done
_COMPLETE="${outs[@]}"
fi
;;
*)
shift $(($# - 1))
_COMPLETE=$(cd /lib/systemd/system;
if [ -z "$1" ];then
echo *
elif echo $1* |grep -F '*' > /dev/null 2>&1;then
:
else
echo $1*
fi)
;;
esac
}
complete 'systemctl=F_systemctl'
function _modprobe {
if [[ $# -le 0 ]]; then return; fi
while [[ x$1 = x-* ]]; do
shift
done
_COMPLETE=$(find /lib/modules/$(uname -r) -type f -name "$1*.ko" -printf '%f\n'|sed 's/\.ko//g')
}
complete 'modprobe=F_modprobe'
function _manpage {
typeset manid='*'
typeset search=x
typeset ACT='-a -f -k -K -l 1 2 3 4 5 6 7 8 9'
_COMPLETE=
if [[ $# -gt 1 ]]; then
case "$1" in
([0-9]?(p|n))
manid=$1
shift
;;
(-[af])
shift
;;
(-[kK])
search=a
shift
;;
(-l)
search=l
shift
;;
esac
else
case z$1 in
z[0-9])
_COMPLETE=$1
;;
z-)
_COMPLETE='-a -f -k -K -l'
;;
z)
_COMPLETE=$ACT
;;
esac
fi
if [[ -z $_COMPLETE ]]; then
if [[ ${1##*/} != $1 || $search = l ]]; then
_COMPLETE=$(echo $1*)
elif [[ $search = a ]]; then
_COMPLETE="$@"
else
_COMPLETE=$(find /usr/share/man/man$manid -name "$1*" -printf '%f\n'|sed 's/\.[0-9]\..*//g'|sort|uniq)
fi
fi
}
complete 'man=F_manpage'
#key bindings
bind '\033[A=up'
bind '\033[B=down'
bind '\033[C=right'
bind '\033[D=left'
bind '\033[H=home' '\033[F=end' '\033[5~=up' '\033[6~=down'
bind '\033[3~=del' '\033[2~=ins'
As you may already figure it out. There is a new builtin command complete. We use the command to make customized tab-completion work as expected.
The builtin complete has three kinds of arguments. listed below:
-
COMMAND_NAME=C indicates that the word following COMMAND_NAME should be a command.
-
COMMAND_NAME=SARG_LIST indicates that the word following COMMAND_NAME should be a customized ARG joined by "," and may be prefixed by ":" or "@" in ARG_LIST.
The prefix ":" means the ARG needs a file name argument, while "@" means the ARG needs a command name argument.
-
COMMAND_NAME=FFUNC indicates that the word following COMMAND_NAME should be generated by calling shell function FUNC.
Arguments passed to function FUNC is all what you have already typed in the current command line.
In function FUNC, generated candidate-string list, should be assigned to _COMPLETE variable. Do NOT print anything out, unless you know what you are doing.
All variable except _COMPLETE within FUNC, should be declared with typeset or local keyword, making them exist only within the function.
Support for bind built-in now available! It's usage is similar to emacs editing mode. Currently supported binding name include up, down, right, left, home, end, del, ins.