🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.unix.shell
Article #3980

emacs style completion in ksh93

#3980
From: Cyrille Lefevre
Date: Thu, 22 Feb 2007 00:05
162 lines
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-mail

Show 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