Article View: comp.unix.shell
Article #3980emacs style completion in ksh93
From: Cyrille Lefevre
Date: Thu, 22 Feb 2007 00:05
Date: Thu, 22 Feb 2007 00:05
162 lines
5625 bytes
5625 bytes
hi,
this should be rewritten using a state machine, but, for instance, this
satisfy my needs...
handle tab => complete => list [=> esc # => select]
handle esc [ # ~ and esc [[ # as key binding
handle esc # as numeric prefix
ksh93 d (dtksh) vs. ksh93 q/s :
* esc [ # ~ is received as esc [, then #, then ~ under ksh93 d (dtksh)
while it is received as esc [ # ~ under ksh93 q/s
* .sh.edtext is always empty under ksh93 d (dtksh)
so hitting DEL (^D) at first pos does nothing
* esc [[ # is received as esc [[, then # under both ksh93 d/q/s
* cd /path/to esc = esc # esc = is buggy under ksh93 d
admit that the first esc = propose 1) lib/ 2) lib, then
esc 2 esc = replace /path/to by lib/ instead of /path/to/lib/
#!/bin/echo error: only source
#ident @(#) $Header:
/package/cvs/exploitation/util/san/libksh/Attic/ksh93rc,v 1.1.2.4
2007/02/19 17:29:50 cle Exp $
# [[ ${SECONDS} = *[.,]* ]] && . ./.ksh93rc
comp=(
ff=$'\f'
tab=$'\t'
list=$'\E='
comp=$'\E\E'
integer count=0
esc=$'\E'
ednum=
tilde='~'
esc2=$'\E\[\['
edchar=
eof=$'\004'
map=( []= )
)
function comp_emacs {
#printf "<%q-%q:%q:%q>" "${.sh.edchar}" "${.sh.edcol}"
"${#.sh.edtext}" "${.sh.edtext}"
if [[ ${.sh.edchar} == ${comp.tab} ]]; then
if [[ -n ${comp.ednum} ]]; then
comp.count=1
fi
if (( ++comp.count == 1 )); then
.sh.edchar=${comp.comp}; return
elif (( comp.count > 1 )); then
.sh.edchar=${comp.ednum}${comp.list}
comp.ednum=; return
fi
# notreached
elif [[ ${.sh.edchar} != ${comp.ff} ]]
comp.count=0
# fallthrough
fi
if [[ ${.sh.edchar} == ${comp.esc}[0-9] ]]; then
typeset ednum=${comp.ednum}
comp.ednum=${.sh.edchar}
.sh.edchar=${ednum}${comp.edchar}
comp.edchar=; return
elif [[ ${.sh.edchar} == [0-9] ]]; then
# dtksh hack
if [[ -n ${comp.edchar} ]]; then
comp.edchar=${comp.edchar}${.sh.edchar}
.sh.edchar=; return
elif [[ -n ${comp.ednum} ]]; then
comp.ednum=${comp.ednum}${.sh.edchar}
.sh.edchar=; return
fi
# fallthrough
elif [[ ${.sh.edchar} = [A-E] ]]; then
# cygwin hack
if [[ -n ${comp.edchar} ]]; then
.sh.edchar=${comp.edchar}${.sh.edchar}
# fallthrough
fi
fi
# dtksh hack
if [[ ${.sh.edchar} == ${comp.tilde} ]]; then
if [[ -n ${comp.edchar} ]]; then
typeset edmap=${comp.map[${comp.edchar}${comp.tilde}]}
if [[ ${edmap} != ${comp.eof} ]] || \
(( .sh.edcol || ( ! .sh.edcol && ${#.sh.edtext} ) )); then
.sh.edchar=${comp.ednum}${edmap}
comp.ednum= comp.edchar=; return
elif [[ ${edmap} == ${comp.eof} ]] && (( ! .sh.edcol )); then
.sh.edchar=
comp.ednum= comp.edchar=; return
fi
# fallthrough
fi
# cygwin hack
elif [[ ${.sh.edchar} == "${comp.esc2}" ]]; then
comp.edchar=${.sh.edchar}
.sh.edchar=; return
elif [[ -n ${comp.map[${.sh.edchar}]} ]]; then
typeset edmap=${comp.map[${.sh.edchar}]}
if [[ ${edmap} != ${comp.eof} ]] || \
(( .sh.edcol || ( ! .sh.edcol && ${#.sh.edtext} ) )); then
.sh.edchar=${comp.ednum}${edmap}
comp.ednum=; return
elif [[ ${edmap} == ${comp.eof} ]] && (( ! .sh.edcol )); then
.sh.edchar=
comp.ednum=; return
fi
# fallthrough
# dtksh hack
elif [[ -n ${comp.map[${.sh.edchar}${comp.tilde}]} ]]; then
comp.edchar=${.sh.edchar}
.sh.edchar=; return
fi
.sh.edchar=${comp.ednum}${.sh.edchar}
comp.ednum=; return
}
trap comp_emacs KEYBD
function keybind {
typeset c= act=a
while getopts pu c; do act=${c}; done
shift OPTIND-1
case ${act} in
a)
while (( $# > 1 )); do
comp.map[$(printf "$1")]=$(printf "$2")
shift 2
done
;;
p)
for c in ${!comp.map[@]}; do
printf "%-8q => %q\n" "${c}" "${comp.map[${c}]}"
done
;;
u)
if (( $# > 0 )); then
for c; do
unset ${comp.map[$(printf "${c}")]}
done
else
unset comp.map
comp.map=( []= )
fi
;;
esac
}
keybind "\E[A" "\020" "\E[B" "\016" "\E[C" "\006" "\E[D" "\002"
keybind "\EOA" "\020" "\EOB" "\016" "\EOC" "\006" "\EOD" "\002"
keybind "\E[2~" " " "\E[3~" "\004" "\E[1~" "\001" "\E[4~" "\005"
keybind "\E[L" " " "\177" "\004" "\E[H" "\001" "\E[F" "\005"
keybind "\E[5~" "\Eb" "\E[6~" "\Ef" "\E[I" "\Eb" "\E[G" "\Ef"
keybind "\E[11~" "\001man " "\E[[A" "\001man " "\EOP" "\001man "
#keybind -p
Regards, Cordialement,
Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%nospam@laposte.net.invalid
supprimer "%nospam% et ".invalid" pour me repondre.
remove "%nospam" and ".invalid" to answer me.
Technical Details
Message-ID:
<45dcde5b$1@news.stben.net>Path:
arc1-ca.pugleaf.net!g2news2.google.com!news2.google.com!news.germany.com!feed.xsnews.nl!border-1.ams.xsnews.nl!217.145.39.3.MISMATCH!talisker.lacave.net!lacave.net!news.stben.net!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Thread: 1012a6,ad528e2892f5c01c,start X-Google-Thread: 110f2c,ad528e2892f5c01c,start X-Google-Attributes: gid1012a6,gid110f2c,public X-Google-Language: ENGLISH,ASCII-7-bit Date: Thu, 22 Feb 2007 01:05:35 +0100 From: Cyrille Lefevre <clefevre-news%nospam@9online.fr.invalid> Organization: ACME User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.9) Gecko/20061207 Thunderbird/1.5.0.9 Mnenhy/0.7.4.666 MIME-Version: 1.0 Newsgroups: comp.unix.shell,fr.comp.os.unix Subject: emacs style completion in ksh93 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: news.stben.net Message-ID: <45dcde5b$1@news.stben.net> Lines: 162 X-Authenticated-User: clef X-Complaints-To: abuse@stben.net Path: arc1-ca.pugleaf.net!g2news2.google.com!news2.google.com!news.germany.com!feed.xsnews.nl!border-1.ams.xsnews.nl!217.145.39.3.MISMATCH!talisker.lacave.net!lacave.net!news.stben.net!not-for-mail