Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

CVS completer (Re: PATCH: Re: Completion/User functions again)



On Jul 14, 10:12pm, Tanaka Akira wrote:
} Subject: Re: PATCH: Re: Completion/User functions again
}
} > While we are at it: we still don't have completion functions for some
} > commands for which we have compctl examples, e.g. cvs and rpm.
} 
} I wrote _cvs.
} But it's ugly, not self-contained and it doesn't deal with CVS/Entries.
} And I don't have a time to implove it in this week.

Below is an improved version of Tanaka's _cvs completer.  I changed many
"compgen -[sk]" calls into compadd calls, fixed up completing of option
letters in a couple of cases, and used the explanation-printing trick
recently discussed on zsh-users in a couple of others.  And I changed
_complete_opts to take the list of options and completion actions as
commmand-line arguments rather than through a shared global association.

However, there is still much room for improvement; for example, the
explanation strings get confused after "cvs import" if there are any
intervening options between the word "import" and the repository name.
I simply don't have time to beat on it any longer.

Also, some options like -k require that there be no space between the
option and its arguments, but nothing seems to enforce that -- even if
I type "cvs add -kv <TAB>" (note space after -kv) the completions I get
are the ones for -k; it should instead act as if a new option or file
name were being completed.

Finally, there are a number of cases where "compgen -f" could be replaced
by something similar to the cvstargets function from misc/compctl-examples.

There are some fairly long lines below, so watch out for wrapping.

--- 8< --- _cvs --- 8< ---
#compdef cvs

typeset -A commands
commands=(add "ad new"            admin "adm rcs"         annotate ann
          checkout "co get"       commit "ci com"         diff "di dif"
          edit ""                 editors ""              export "exp ex"
          history "hi his"        import "im imp"         init ""
          log "lo rlog"           login "logon lgn"       logout ""
          rdiff patch             release "re rel"        remove "rm delete"
          status "st stat"        rtag "rt rfreeze"       tag "ta freeze"
          unedit ""               update "up upd"         watch ""
          watchers "")

local com="${words[(i)(${(j:|:)${(kv)=commands}})]}"

local showlist='compstate[list]=list; compstate[force_list]=yes'
local showhint="$showlist ; compstate[insert]=''"
local complete_D="compadd yesterday week\\ ago month\\ ago"
local complete_k="compadd kv kvl k o b v"
local complete_r="compadd -UX 'Enter tag name or rev number' ''; $showhint"
local complete_m="compadd -UX 'Enter log message' -n ''; $showhint"

#_view_completion_parameters "com=$com"

if (( $com < $CURRENT )); then
  case "$words[$com]" in
    add|ad|new) # "+k:m:"
      _complete_opts k: "$complete_k" m: "$complete_m" || compgen -f
      ;;
    admin|adm|rcs) # "+ib::c:a:A:e:l::u::LUn:N:m:o:s:t::IqxV:k:"
      _complete_opts i '' b:: '' c: '' a: '' A: '' e: '' l:: '' u:: '' L '' U '' n: '' N: '' m: "$complete_m" o: '' s: '' t:: '' I '' q '' x '' V: '' k: "$complete_k" || compgen -f
      ;;
    annotate|ann) # "+lr:D:fR"
      _complete_opts l '' r: '' D: '' f '' R '' || compgen -f
      ;;
    checkout|co|get) # "+ANnk:d:flRpQqcsr:D:j:P"
      _complete_opts A '' N '' n '' k: "$complete_k" d: '' f '' l '' R '' p '' Q '' q '' c '' s '' r: "$complete_r" D: "$complete_D" j: '' P '' || compadd MODULE
      ;;
    commit|ci|com) # "+nlRm:fF:r:"
      _complete_opts n '' l '' R '' m: "$complete_m" f '' F: '' r: "$complete_r" || compgen -f
      ;;
    diff|di|dif) # "+abcdefhilnpstuw0123456789BHNRC:D:F:I:L:U:V:W:k:r:"
      _complete_opts a '' b '' c '' d '' e '' f '' h '' i '' l '' n '' p '' s '' t '' u '' w '' 0 '' 1 '' 2 '' 3 '' 4 '' 5 '' 6 '' 7 '' 8 '' 9 '' B '' H '' N '' R '' C: '' D: "$complete_D" F: '' I: '' L: '' U: '' V: '' W: '' k: "$complete_k" r: "$complete_r" || compgen -f
      ;;
    edit) # "+lRa:"
      _complete_opts l '' R '' a: '' || compgen -f
      ;;
    editors) # "+lR"
      _complete_opts l '' R '' || compgen -f
      ;;
    export|exp|ex) # "+ANnk:d:flRpQqcsr:D:j:P"
      _complete_opts A '' N '' n '' k: "$complete_k" d: '' f '' l '' R '' p '' Q '' q '' c '' s '' r: "$complete_r" D: "$complete_D" j: '' P '' || compadd MODULE
      ;;
    history|hi|his) # "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:"
      _complete_opts T '' a '' c '' e '' l '' o '' w '' \? '' D: "$complete_D" b: '' f: '' m: "$complete_m" n: '' p: '' r: '' t: '' u: '' x: '' X: '' z: '' || compgen -f
      ;;
    import|im|imp) # "+Qqdb:m:I:k:W:"
      _complete_opts Q '' q '' d '' b: '' m: "$complete_m" I: '' k: "$complete_k" W: '' || case $[CURRENT-com] in
	1) compgen -X "Enter repository name" -W $CVSROOT -g '*~*CVSROOT(/)' -s '';;
	2) compadd -UX "Enter vendor tag name" -n '' && eval "$showhint";;
	3) compadd -UX "Enter release tag name" -n '' && eval "$showhint";;
	*) compadd -UX "No futher arguments used" -n '' && eval "$showhint";;
	esac
      ;;
    init)
      break
      ;;
    login|logon|lgn)
      _complete_opts || compgen -f
      ;;
    logout)
      _complete_opts || compgen -f
      ;;
    rdiff|patch|pa) # "+V:k:cuftsQqlRD:r:"
      _complete_opts V: '' k: "$complete_k" c '' u '' f '' t '' s '' Q '' q '' l '' R '' D: "$complete_D" r: "$complete_r" || compgen -f
      ;;
    release|re|rel) # "+Qdq"
      _complete_opts Q '' d '' q '' || compgen -/
      ;;
    remove|rm|delete) # "+flR"
      _complete_opts f '' l '' R '' || compgen -f
      ;;
    status|st|stat) # "+vlR"
      _complete_opts v '' l '' R '' || compgen -f
      ;;
    tag|ta|freeze) # "+FQqlRcdr:D:bf"
      _complete_opts F '' Q '' q '' l '' R '' c '' d '' r: "$complete_r" D: "$complete_D" b '' f '' || compgen -f
      ;;
    unedit) # "+lR"
      _complete_opts l '' R '' || compgen -f
      ;;
    update|up|upd) # "+ApPflRQqduk:r:D:j:I:W:"
      _complete_opts A '' p '' P '' f '' l '' R '' Q '' q '' d '' u '' k: "$complete_k" r: "$complete_r" D: "$complete_D" j: '' I: '' W: '' || compgen -f
      ;;
    watch)
      if (( CURRENT == com + 1 )); then
        compadd on off add remove
      else
        case "$words[com+1]" in
          on|off) # "+lR"
            _complete_opts l '' R '' || compgen -f
            ;;
          add|remove) # "+lRa:"
            _complete_opts l '' R '' a: '' || compgen -f
            ;;
        esac
      fi
      ;;
    watchers) # "+lR"
      _complete_opts l '' R '' || compgen -f
      ;;
    *) compgen -f;;
  esac
  return
fi

case ${+cvs_roots} in
  0)
    cvs_roots=()
    if [[ -f ~/.cvspass ]]; then
      cvs_roots=(
	$(cut -d ' ' -f 1 ~/.cvspass)
      )
    fi
    ;;
esac

_complete_opts \
  H '' Q '' q '' r '' w '' l '' n '' t '' v '' f '' a '' \
  b: "compadd /usr/local/bin" \
  T: "compadd $TMPPREFIX:h $TMPDIR /tmp" \
  e: "compadd vi" \
  d: "compadd $cvs_roots || compgen -/" \
  z: "compadd 9'" \
  s: "_cvs_user_variable" \
 || 
compadd ${(k)commands} ||
compadd ${(kv)=commands}

--- 8< --- end of _cvs --- 8< ---
--- 8< --- _complete_opts --- 8< ---

#autoload

# Usage:
#  _complete_opts H '' f 'compgen -f'

emulate -L zsh
setopt extendedglob

typeset -A option_pairs
option_pairs=("$@")
typeset -a no_arg with_arg opt_arg
no_arg=($option_pairs[(I)?])
opt_arg=($option_pairs[(I)?::]:s/:://)
with_arg=($option_pairs[(I)?:]:s/:// $opt_arg)

case "${#no_arg}-${#with_arg}" in
  0-0)
    if [[ x$PREFIX = x-* ]]; then
      compgen -k '()'			# What does this accomplish?
    else
      false
    fi
    ;;

  0-*)
    if [[ x$PREFIX = x- ]]; then
      IPREFIX="$IPREFIX$PREFIX"
      PREFIX=
      compadd $with_arg
    elif [[ x$PREFIX = x-[${(j::)with_arg}] ]]; then
      IPREFIX="$IPREFIX$PREFIX"
      PREFIX=
      eval $option_pairs[$IPREFIX[-1]:]
    elif [[ x$PREFIX = x-[${(j::)with_arg}]* ]]; then
      local p="$PREFIX[1,(r)[${(j::)with_arg}]]"
      IPREFIX="$IPREFIX$p"
      PREFIX="$PREFIX[$#p + 1,-1]"
      eval $option_pairs[$IPREFIX[-1]:]
    elif [[ x$words[$CURRENT-1] = x-[${(j::)with_arg}] ]]; then
      local p="$words[$CURRENT - 1]"
      eval $option_pairs[$p[-1]:]
    else
      false
    fi
    ;;

  *-0)
    if [[ x$PREFIX = x-[${(j::)no_arg}]# ]]; then
      IPREFIX="$IPREFIX$PREFIX"
      PREFIX=
      compadd $no_arg
    else
      false
    fi
    ;;

  *-*)
    if [[ x$PREFIX = x-[${(j::)no_arg}]# ]]; then
      IPREFIX="$IPREFIX$PREFIX"
      PREFIX=
      compadd $no_arg
      compadd $with_arg
    elif [[ x$PREFIX = x-[${(j::)no_arg}]#[${(j::)with_arg}] ]]; then
      IPREFIX="$IPREFIX$PREFIX"
      PREFIX=
      eval $option_pairs[$IPREFIX[-1]:]
    elif [[ x$PREFIX = x-[${(j::)no_arg}]#[${(j::)with_arg}]* ]]; then
      local p="$PREFIX[1,(r)[${(j::)with_arg}]]"
      IPREFIX="$IPREFIX$p"
      PREFIX="$PREFIX[$#p + 1,-1]"
      eval $option_pairs[$IPREFIX[-1]:]
    elif [[ x$words[$CURRENT-1] = x-[${(j::)no_arg}]#[${(j::)with_arg}] ]]; then
      local p="$words[$CURRENT - 1]"
      eval $option_pairs[$p[-1]:]
    else
      false
    fi
    ;;
esac || { compadd - -${(k)^option_pairs:gs/://} && false }

--- 8< --- end of _complete_opts --- 8< ---

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com



Messages sorted by: Reverse Date, Date, Thread, Author