Mailinglist Archive: opensuse-buildservice (193 mails)

< Previous Next >
Re: [opensuse-buildservice] Zsh completion for osc
  • From: "Dr. Peter Poeml" <poeml@xxxxxxx>
  • Date: Mon, 23 Apr 2007 15:39:38 +0200
  • Message-id: <20070423133938.GF4538@xxxxxxx>
On Sun, Apr 22, 2007 at 03:30:09PM +0200, Christian Boltz wrote:
> Hello,
> 
> I just thought that bash completion for osc would be a nice idea ;-)

I can't contribute much on the bash side, but for zsh, the shell I use.
I'm attaching here what I've got. It does seem to work for me for a
number of commands. It completes for help, add, delete, commit, log, and
(to some degree) for build. I'm posting it here, since it is neither
finished nor well tested, but zsh users can try it out.

I copied from subversion, which tries to cache stuff per directory, but
that doesn't seem to work because the directory name (which was used as
key in the associative array) was always set to "." -- I fixed that, but
I decided to cache only "osc repos" output. Caching of "modified" status
of files per directory doesn't seem like a good idea to me, because
there is no way to invalidate the cache entry, and that status can
change all the time. But I think it is worth caching the build targets,
for example, for the log and build command, because the don't change
frequently.

Peter
-- 
Allen Gewalten zum Trutz sich erhalten.
 
SUSE LINUX Products GmbH
Research & Development
#compdef osc

# modified from _svn
# reset _cache_osc_status array after use
# add completion for diff
# add completion for log

_osc () {
  local curcontext="$curcontext" state line expl ret=1

  _arguments -C \
    '(-)--help[print help information]' \
    '(- *)--version[print client version information]' \
    '1: :->cmds' \
    '*:: :->args' && ret=0

  if [[ -n $state ]] && (( ! $+_osc_cmds )); then
    typeset -gHA _osc_cmds
    _osc_cmds=(
      ${=${(f)${"$(LC_ALL=C _call_program commands osc help)"#l#*Available subcommands:}}/(#s)[[:space:]]#(#b)([a-z]##)[[:space:]]#(\([a-z, ?]##\))#/$match[1] :$match[1]${match[2]:+:${${match[2]//[(),]}// /:}}:}
    )
  fi

  case $state in
    cmds)
      _wanted commands expl 'osc command' _osc_commands && ret=0
    ;;
    args)
      local cmd args usage
      typeset -gHA _cache_osc_status
      typeset -gHA _cache_osc_modifiedfiles
      typeset -gHA _cache_osc_repos

      cmd="${${(k)_osc_cmds[(R)*:$words[1]:*]}:-${(k)_osc_cmds[(i):$words[1]:]}}"
      if (( $#cmd )); then
        curcontext="${curcontext%:*:*}:osc-${cmd}:"

        usage=${${(M)${(f)"$(LC_ALL=C _call_program options osc help $cmd)"}:#usage:*}#usage:*$cmd] }
        args=(
          ${=${${${(M)${(f)"$(LC_ALL=C _call_program options osc help $cmd)"##*Valid options:}:#* :*}%% #:*}/ arg/:arg:}/(#b)-([[:alpha:]]) \[--([a-z-]##)\](:arg:)#/(--$match[2])-$match[1]$match[3] (-$match[1])--$match[2]$match[3]}
        )

        case $cmd in;
          add)
            args+=(
              '*:file:_files -g "*(^e:_osc_controlled:)"'
            )
          ;;
          commit)
            args+=(
              '*:file:_files -g "*(e:_osc_status:)"'
            )
            _cache_osc_status=()
          ;;
          delete)
            args+=(
              '*:file:_files -g ".osc(/e:_osc_deletedfiles:)"'
            )
          ;;
          diff)
            args+=(
              '*:file:_files -g "*(e:_osc_modifiedfiles:)"'
            )
            _cache_osc_modifiedfiles=()
          ;;
          help)
            args+=(
              '*::sub command:_osc_commands'
            )
          ;;
          log)
            args+=(
              '*::sub repos:_osc_repos'
            )
            #_cache_osc_repos=()
          ;;
          build)
            args+=(
              '*::sub repos:_osc_repos'
            )
            #_cache_osc_repos=()
          ;;
          # revert)
          #   args+=(
          #     '*:file:_files -g "(.osc|*)(/e:_osc_deletedfiles:,e:_osc_status:)"'
          #   )
          # ;;
          *)
            case $usage in
              *(SRC|DST|TARGET|URL*PATH)*)
                args+=(
                  '*: : _alternative "files:file:_files" "urls:URL:_osc_urls"'
                )
              ;;
              *URL*) args+=( ':URL:_osc_urls' ) ;;
              *PATH*) args+=( '*:file:_files' ) ;;
            esac
          ;;
        esac

        _arguments "$args[@]" && ret=0

      else
        _message "unknown osc command: $words[1]"
      fi
    ;;
  esac

  return ret
}



(( $+functions[_osc_controlled] )) ||
_osc_controlled() {
  [[ -f ${(M)REPLY##*/}.osc/${REPLY##*/} ]]
}

(( $+functions[_osc_deletedfiles] )) ||
_osc_deletedfiles() {
  # Typical usage would be _files -g '.osc(/e:_osc_deletedfiles:)'
  local cont controlled
  reply=( )
  [[ $REPLY = (*/|).osc ]] || return
  controlled=( $REPLY/*~$REPLY/_*(N:t) )
  for cont in ${controlled}; do
    [[ -e $REPLY:h/$cont ]] || reply+=( ${REPLY%.osc}$cont )
  done
}

(( $+functions[_osc_modifiedfiles] )) ||
_osc_modifiedfiles() {
  local dir=$REPLY:h
  local pat="${1:-([M]|?M)}"

  if (( ! $+_cache_osc_modifiedfiles[$dir] )); then
    _cache_osc_modifiedfiles[$dir]="$(_call_program files osc status $dir)"
  fi

  (( ${(M)#${(f)_cache_osc_modifiedfiles[$dir]}:#(#s)${~pat}*$REPLY} ))
}

(( $+functions[_osc_status] )) ||
_osc_status() {
  local dir=$REPLY:h
  local pat="${1:-([ADMR~]|?M)}"
  if [ $dir = "." ]; then 
    dir=$PWD
  fi

  if (( ! $+_cache_osc_status[$dir] )); then
    _cache_osc_status[$dir]="$(_call_program files osc status $dir)"
   else
  fi

  (( ${(M)#${(f)_cache_osc_status[$dir]}:#(#s)${~pat}*$REPLY} ))
}

(( $+functions[_osc_urls] )) ||
_osc_urls() {
  local expl

  if [[ -prefix *: ]]; then
    _urls
  else
    compset -S '[^:]*'
    _wanted url-schemas expl 'URL schema' compadd -S '' - \
        file:// http:// https:// osc:// osc+ssh://
  fi
}

(( $+functions[_osc_commands] )) ||
_osc_commands() {
  compadd "$@" -k _osc_cmds || compadd "$@" ${(s.:.)_osc_cmds}
}

(( $+functions[_osc_repos] )) ||
_osc_repos() {
  local dir=$REPLY:h
  local tmp

  if [ $dir = "." ]; then 
    dir=$PWD
  fi

  if (( ! $+_cache_osc_repos[$dir] )); then
    _cache_osc_repos[$dir]="$(_call_program repos osc repos)"
  fi

  tmp=()
  for line in ${(f)_cache_osc_repos[$dir]}; do
    line=($=line)
    tmp+=$line
  done

  compadd $tmp
}

_osc "$@"
< Previous Next >
References