🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.unix.shell
2 messages
2 total messages Started by Cyrille Lefevre Thu, 22 Feb 2007 00:05
emacs style completion in ksh93
#3980
Author: 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.
Re: emacs style completion in ksh93
#3981
Author: bsh
Date: Fri, 23 Feb 2007 01:50
39 lines
2761 bytes
Cyrille Lefevre wrote:
> this should be rewritten using a state machine...

Oh no you shouldn't! Or perhaps I should instead say that,
having had much experience in writing state machines, they
are always problematic to debug and maintain. Their use is
almost always a case of having not used the appropriate
software tool, or justified by the primacy of execution speed.

> function comp_emacs {

Thank you! I wish that I could show you my own keybind
example implementing generalized autocompletion, but it's
stuck on another machine's harddrive. It's almost as
complex, and (if I understand your code sufficiently) shows
a design variation that allows binding of (multiple) keystrokes
to the output of a user-specified function. I've attempted a
different algorithm to map character sequences utilizing
hashes with a base 64 numerical radix, instead of the usual
associative array technique, which has limitations, but is
very fast.

I wonder, was this code written in regard to the issue
described in:
https://mailman.research.att.com/pipermail/ast-users/2004q1/000457.html

Obviously, you have seen DGK's keybind example, but
for those in C.U.S. who wish a demonstration example,
see:
http://www.kornshell.com/examples/keybind

A question: have you done GUI coding on dtksh?

Once again, thanks for submitting your code to C.U.S.
I thought _someone_ should respond to this contribution,
but I wanted to resolve the problem of the above keybind
URL being temporarily unavailable, before I posted.

=Brian
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads