Comment 8 for bug 84822

Revision history for this message
clemens fischer (ino-news) wrote : Re: [Bug 84822] Re: bash completion should use shell-complete

> clemens fischer:

> > Daniel Hahler:
>
> > But please create the cache on the first call, not when the
> > completion scripts get loaded (like git does it currently).
>
> i can't do this either, because completions run in a subshell.
> variables, like a cache, set in the subshell cease existing when
> that subshell terminates. this is the reason git does some of the
> completion work on loading.

this is nonsense, but i didn't see it when staring at the code.

> then again, a few seconds after sending off this reply i might find a
> way to transport results up one level of shell-invocations ...

ok, the few seconds passed. the code completes three cases:

1. options to any bzr commands. it is not feasible to cache the
    options to every command. i decided against it.

2. files coming after the (artificial) "end-of-options" token "--".
    obviously, caching these is impractical. bash handles these.

3. simple commands. this is quite easy to cache, see attached.

4. commands and topics. the commands are cached, the topics are not,
    but this could be changed. i didn't bother to go for more than the
    commands.

# scans args, returns 1st non-option or 1 if none or zero-length.
# 1st arg is the actual command to look out for, its index is returned
# in $__nonopts_start, the nonopts are returned in array ${__nonopts[]}.
#
declare -a __nonopts
__get_nonopts()
{
  local index=0
  local startcmd="$1"
  shift
  __nonopts=()
  __nonopts_start=0
  for i in "$@"
  do
    [[ "${startcmd}" == "${i}" ]] && __nonopts_start=${index}
    case "$i" in
      -*)
        ;;
      *)
        __nonopts[${index}]="$i"
        #index=$((${index}+1))
        index=$((index++))
        ;;
    esac
  done
  [[ ${#__nonopts[*]} -eq 0 ]] && return 1
  return 0
}

_bzr_opts()
{
  [[ -z "${__bzr_opts_cache}" ]] &&
    __bzr_opts_cache="$(
      bzr s-c "$1" | sed -E 's/^.+(--[[:alnum:]_-]+).*/\1/'
      bzr s-c "$1" | sed -E 's/^.+(-[[:alnum:]]+).*/\1/'|grep -v -- '-None'
    )"
  echo "${__bzr_opts_cache}"
}
__bzr_command_cache=""
_bzr()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  local prev=${COMP_WORDS[COMP_CWORD-1]}
  case ".${cur}" in
    .-*)
      __get_nonopts "bzr" "${COMP_WORDS[@]}" || : 'COMPREPLY=( $(compgen -f $cur) )'
      COMPREPLY=(
        $(compgen -W '$(_bzr_opts ${__nonopts[$((${__nonopts_start}+1))]})' -- $cur)
      )
      ;;
    .*)
      case "$prev" in
        --)
          COMPREPLY=( $(compgen -f -- $cur) )
          ;;
        bzr)
          [[ -z "${__bzr_command_cache}" ]] &&
            __bzr_command_cache="$(bzr s-c | egrep -o '^([^:]+)')"
          COMPREPLY=( $(compgen -W '${__bzr_command_cache}' -- $cur))
          ;;
        help|\?|--help|-\?|-h)
          [[ -z "${__bzr_command_cache}" ]] &&
            __bzr_command_cache="$(bzr s-c | egrep -o '^([^:]+)')"
          COMPREPLY=( $(compgen -W '${__bzr_command_cache}' -- $cur)
            $(compgen -W '$(bzr help topics | egrep -o "^([^[:space:]]+)")' -- $cur) )
          ;;
      esac
      ;;
  esac
}
complete -o filenames -F _bzr bzr

regards, clemens