[sisyphus] [#5235] zsh completion for rpm
Alexey Tourbin
=?iso-8859-1?q?at_=CE=C1_altlinux=2Eru?=
Сб Окт 23 07:05:33 MSD 2004
Здравствуйте.
Я научился программировать на zsh. :)
Предлагаю протестировать новую (значительно переделанную) дополнялку
для rpm. Теперь будут дополняться команды rpmbuild, rpmqurey и др.
Как проще всего подключить дополнялку:
$ mkdir -p ~/fpath
$ cp -a _rpm ~/fpath
$ echo 'typeset -U fpath' >> ~/.zshenv
$ echo 'fpath=(~/fpath $fpath)' >> ~/.zshenv
$ . ~/.zshenv
$ rm -rf ~/.zcomp*
$ compinit
Чтобы включился кэш:
$ zstyle ':completion::complete:*' use-cache 1
$ echo "!!" >> ~/.zshrc
Тогда список установленных пакетов сохранится в ~/.zcomcache/,
кэш автоматически обновляется при изменении базы rpm и/или apt.
Пример дополнения:
$ rpm --eval %co<TAB>
%compress_docs %configure
$ rpm --eval %con<TAB>
$ rpm --eval %configure
Known bugs: --target как следует не дополняется.
Как оно теперь будет работать. В массивах rpmb_opts0, rpmq_opts0 и др.
лежат опции командной строки, которые идентифицируют соответствующий режим.
Т.е. в rpmb_opts0 находятся опции типа (-bc, -bb, -ba), в rpmq_opts0 --
опции типа (-qa, -qi). В массивах rpmb_opts1, rpmq_opts1 лежат
дополнительные опции для соответствующего режима, например
--short-circut для rpmb и --lastchange для rpmq.
Смысл в том, что при использовании специализированных команд (rpmbuild,
rpmquery) соответствующие опции opts0 и opts1 можно будет скармливать в
любом порядке. При использовании rpm сначала нужно будет задать режим с
помощью opts0, а затем уже подключится соответствующий opts1.
Т.е. можно будет дополнять
$ rpmbuild --short-circuit -ba ...
но не
$ rpm --short-circuit -ba ...
а только
$ rpm -ba --short-circuit ...
Это ограничение можно как-то обойти, но я пока не знаю как.
rpmpopt -- хитрая штука. Например
$ rpm -qg Editors
и
$ rpm -gq Editors
работают одинаково хорошо, также как и (уже в другом режиме)
$ rpm -Vg Editors
$ rpm -gV Editors
а в других случаях -g не работает.
Кстати группы тоже дополняются:
$ rpm -qg D<TAB>
$ rpm -qg De<TAB>
$ rpm -qg Development/
$ rpm -qg Development/<TAB>
C Functional KDE\ and\ QT Objective-C Ruby
C++ GNOME\ and\ GTK+ Kernel Other Scheme
Databases Haskell Lisp Perl Tcl
Debuggers Java ML Python
Жду замечаний.
----------- следующая часть -----------
#compdef rpm rpmb rpmd rpme rpmi rpmk rpmq rpmt=rpmb rpmu=rpmi rpmv rpmbuild=rpmb rpmdb=rpmd rpmquery=rpmq rpmsign=rpmk rpmverify=rpmv
# This uses `_arguments' in a state-machine kind of way. These states
# have names and before executing the default action for such a state
# we try to call a function with the name `_rpm_<state>'. If such a
# function exists, we return with its return status immediately. This
# allows users to override the default completions by simply defining
# these functions.
# The states (and possible values for the `<state>' above) are:
#
# query
# complete for `rpm -q' query
# verify
# complete for `rpm --verify'
# install
# complete for `rpm -i' or `rpm --install'
# upgrade
# complete for `rpm -U' or `rpm --upgrade'
# uninstall
# complete for `rpm -e' or `rpm --erase'
# build_b
# complete for `rpm -bx' (the stage `x' is already completed)
# build_t
# complete for `rpm -tx' (the stage `x' is already completed)
# sigcheck
# complete for `rpm --sigcheck'
# rebuild
# complete for `rpm --rebuild'
# package
# complete a RPM package name
# package_file
# complete a RPM package file name
# tags
# complete a tag name
# capability
# complete a capability
# relocate
# complete a `old=new' pair of paths
_rpm () {
local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]"
typeset -A opt_args
local ret=1
local -a tmp expl
local -a common_opts
common_opts=(
-{\?,-help}'[print help information]'
'--version[print the version of rpm being used]'
'(-v --verbose)--quiet[provide less detailed output]'
'(--quiet)*'-{v,-verbose}'[provide more detailed output]'
'--define[define macro <name> with value <body>]:'
'--eval[print macro expansion]:macro:->macros'
-{r,-root}'[use <dir> as the top level directory]:rpm root directory:_files -/'
'--dbpath[use <dir> as the directory for the database]:rpm database path:_files -/'
'--macros[read <file:...> instead of default macro file(s)]:resource file:_files'
'--rcfile[read <file:...> instead of default rpmrc file(s)]:resource file:_files'
'--showrc[display final rpmrc and macro configuration]'
'--ftpproxy:ftp proxy server:_hosts'
'--ftpport:ftp port number'
'--httpproxy:http proxy server:_hosts'
'--httpport:http port number'
'--pipe:pipe command:->command'
)
local -a rpmb_opts0 rpmb_opts1
rpmb_opts0=(
'(-t)-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
'(-b)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
'(-b -t --recompile)--rebuild[build binary package from source package]:*:source rpm file:->build_src'
'(-b -t --rebuild)--recompile[build through %install from source package]:*:source rpm file:->build_src'
)
rpmb_opts1=(
--{with,enable}'[enable configure option for build]:'
--{without,disable}'[disable configure option for build]:'
'--target:specify a build target:->target'
'--buildroot:build root directory:_files -/'
'--buildarch:architecture for which to build:->target'
'--buildos:operating system for which to build:'
'--short-circuit[skip straight to specified stage]'
--{clean,nobuild,rmsource,sign,test}
)
# package selection options of which only one can be used
local -a selectopts sopts
selectopts=(
-{a,-all}'[query all packages]'
-{f,-file}'[query packages that own specified files]'
-{p,-package}'[query uninstalled packages]'
-{g,-group}'[query packages in one of specified groups]'
--fileid --hdrid --pkgid --tid --querybynumber
--triggeredby --whatprovides --whatrequires
)
sopts=${selectopts%\[*}\ --specfile
selectopts=(
"(* $sopts)"${selectopts[1,2]}
"($sopts)"${selectopts[3,-1]}
'(-a --all)*: :->package-select'
)
local -a rpmdb_opts0 rpmdb_opts1
rpmd_opts0=(
'--initdb[initialize database]'
'--rebuilddb[rebuild database]'
)
rpmd_opts1=(
# none so far
)
local -a rpme_opts0 rpme_opts1
rpme_opts0=( '(-e --erase)'-{e+,-erase}'[uninstall mode]:*:uninstall:->uninstall' )
rpme_opts1=( --{allmatches,justdb,repackage,test} --no{deps,scripts,preun,postun,trigger{s,un,postun}} )
local -a rpmi_opts0 rpmi_opts1
rpmi_opts0=(
'(-i --install)'-{i+,-install}'[install mode]:*:install:->install'
'(-U --upgrade)'-{U+,-upgrade}'[upgrade mode]:*:upgrade:->upgrade'
'(-F --freshen)'-{F+,-freshen}'[freshen mode]:*:upgrade:->upgrade'
)
rpmi_opts1=(
'--excludepath:file to exclude:_files -/'
'--relocate:relocate:->relocate'
'--prefix:package prefix directory:_files -/'
'(-h --hash)'-{h,-hash}
'(--replacepkgs --replacefiles --oldpackage)--force'
'(--force)--'{replacefiles,replacepkgs}
--{aid,allfiles,badreloc,excludedocs,ignorearch,ignoreos,ignoresize,includedocs,justdb,percent,repackage,test}
--np{digest,signature,deps,suggest,order,pre,post,preun,postun,trigger{s,in,un,postun}}
'(--nopre --nopost --nopreun --nopostun)--noscripts'
)
local -a rpmk_opts0 rpmk_opts1
rpmk_opts0=(
'(-K --checksig)'-{K+,-checksig}'[signature check mode]:*:sigcheck:->sigcheck'
'(--resign --addsign)'--{resign,addsign}':*:package:->package_file'
)
rpmk_opts1=( --no{gpg,pgp,md5,signature,digest} )
local -a rpmq_opts0 rpmq_opts1
rpmq_opts0=( -{q+,-query}'[query mode]:*:query:->query' --querytags )
rpmq_opts1=(
# --dump requires one of -{l,c,d}
# --triggers requires --script
"${(@)selectopts}"
"($sopts)--specfile[query specified spec file as if it were a package]"
'(-i --info)'{-i,--info}'[display package information]'
'--changelog[display change log]'
'--lastchange[display last changelog entry]'
'(-s --state -l --list --filesbypkg)'{-l,--list}'[display package file list]'
'(-s --state -l --list --filesbypkg)'{-s,--state}'[show file states]'
'(-s --state -l --list)--filesbypkg[list files with package names]'
-{d,-docfiles}'[documentation files only]'
-{c,-configfiles}'[configuration files only]'
'--dump[show all information]'
'--provides[show capabilities provided]'
\*--{qf,queryformat}'[specify format for package information]:rpm query format:->tags'
-{R,-requires}'[list dependencies]'
'--scripts[show (un)install scripts]'
{--triggers,--triggerscripts}'[show trigger scripts]'
)
local -a rpmv_opts0 rpmv_opts1
rpmv_opts0=( '(-V -y --verify)'{-V+,-y+,--verify}'[verify mode]:*:verify:->verify' )
rpmv_opts1=( "${(@)selectopts}" --no{deps,files,scripts,digest,signature,linkto,md5,size,user,group,mtime,mode,rdev} )
case "$service" in
rpmq)
state=query
;&
rpmv)
state=verify
;&
rpm?)
local service_opts0="${service}_opts0" service_opts1="${service}_opts1"
_arguments -C -s "${(@)common_opts}" "${(P@)service_opts0}" "${(P@)service_opts1}" && ret=0
;;
rpm)
_arguments -C -s "${(@)common_opts}" "${(@)rpmb_opts0}" "${(@)rpmd_opts0}" "${(@)rpme_opts0}" \
"${(@)rpmi_opts0}" "${(@)rpmk_opts0}" "${(@)rpmq_opts0}" "${(@)rpmv_opts0}" \
'--setperms[set file permissions]:*:package:->setattrs' \
'--setugids[set file owner/group]:*:package:->setattrs' \
&& ret=0
;;
esac
not_opts() {
local var="$1"
print -l -- "\!${(@)^${(@)${(@)${(@)${(P@)var%%[[:]*}#*)}%[+-]}#\*}}"
}
# As long as we have a state name...
while [[ -n "$state" ]]; do
# First try to call a user-defined function.
_call_function ret _rpm_$state && return ret
# Copy the state and reset `state', to simplify the test above.
lstate="$state"
state=''
tmp=()
# Dispatch...
case "$lstate" in
query)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmq_opts0)}" "${(@)rpmq_opts1}" && ret=0
;;
setattrs)
_arguments -s --set{perm,ugids} "${selectopts[@]}" && ret = 0
;;
verify)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmv_opts0)}" "${(@)rpmv_opts1}" \
;;
install|upgrade)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmi_opts0)}" "${(@)rpmi_opts1}" \
'*:package file:->package_file' && ret=0
;;
uninstall)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpme_opts0)}" "${(@)rpme_opts1}" \
'*:package:->package' && ret=0
;;
build_b)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmb_opts0)}" "${(@)rpmb_opts1}" \
'*:spec file:_files -g "*.spec(-.)"' && ret=0
;;
build_t)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmb_opts0)}" "${(@)rpmb_opts1}" \
'*:tar file:_files -g "*.(#i)(tar|tar.gz|tar.bz2|tgz)(-.)"' && ret=0
;;
build_src)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmb_opts0)}" "${(@)rpmb_opts1}" \
'*:source package file:_files -g "(#i)*.src.rpm(-.)"' && ret=0
;;
sigcheck)
_arguments -s "${(@)common_opts}" "${(f@)$(not_opts rpmk_opts0)}" "${(@)rpmk_opts1}" \
'*:package file:->package_file' && ret=0
;;
package-select)
case "${opt_args[(i)${sopts// /|}]}" in
-f|--file) _files ;;
-p|--package) state=package_file ;;
-g|--group) state=groups ;;
--fileid|--pkgid) _message -e md5 md5 ;;
--hdrid) _message -e sha1 sha1 ;;
--querybynumber) _message -e value number ;;
--what*) state=capabilities ;;
--specfile) state=spec_files ;;
*) state=package ;;
esac
;;
macros)
local -a macros
local mfile
for mfile in {/usr/lib/rpm/{,*/}macros,/etc/rpm/macros{,.d/*},~/.rpmmacros}(-.N); do
macros+=( ${${(M)${(f)"$(<$mfile)"}:#%[^\{]*}%%[[:blank:]]*} )
done
if zstyle -t ":completion:${curcontext}:macros" prefix-hidden; then
macros=( ${macros#%} )
_wanted macros expl macro compadd -p '%' -a - macros
else
_wanted macros expl macro compadd -a - macros
fi
;;
command)
compset -q
_normal
;;
target)
if [[ ${+_rpm_targets} -eq 0 ]]; then
typeset -gaU _rpm_targets
_rpm_targets=( ${${(M)${(f)"$(_call_programs targets rpm --showrc)"}:#compatible archs*}##*: } )
fi
_wanted targets expl 'target platform' compadd -a - _rpm_targets && ret=0
;;
groups)
if [[ ${+_rpm_groups} -eq 0 ]]; then
typeset -gaU _rpm_groups
_rpm_groups=( "${(f)$(</usr/lib/rpm/GROUPS)}" )
fi
_wanted groups expl 'group' _multi_parts / _rpm_groups && ret=0
;;
package)
_wanted packages expl 'package' \
_rpm_packages installed && ret=0
;;
spec_files)
_wanted specfiles expl 'spec file' \
_files -g '*.spec(-.)' && ret=0
;;
package_file)
_wanted files expl 'package file' \
_files -g '*.(#i)rpm(-.)' && ret=0
if [[ -prefix 1 (f|ht)tp:// ]]; then
_wanted urls expl 'URL of rpm package file' \
_urls -f -g '*.(#i)rpm(-.)' "${expl[@]}" && ret=0
else
_wanted urls expl 'URL of rpm package file' \
compadd -S '' "${expl[@]}" ftp:// http:// && ret=0
fi
;;
tags)
local -a suf
if compset -P "*%*${${QIPREFIX:+{}:-\{}"; then
compset -S '(|\\)}*' || suf=( -qS ${${QIPREFIX:+\}}:-\\\}} )
_wanted tags expl 'rpm tag' compadd -M 'm:{a-z}={A-Z}' "$suf[@]" - \
"${(L@)${(@f)$(_call_program tags rpm --querytags 2>/dev/null)}#RPMTAG_}" && ret=0
else
_message -e formats 'rpm query format'
fi
;;
capabilities)
_wanted capabilities expl capability compadd \
${(f)"$(_call_program capabilities rpm -qa --queryformat '%\{requirename}\\n' 2>/dev/null)"}
;;
relocate)
if compset -P '*='; then
_description directories expl 'new path'
else
_description directories expl 'old path'
fi
_files "$expl[@]" -/ && ret=0
;;
esac
[[ ret -eq 0 || $nm -ne $compstate[nmatches] ]] && return 0
done
return ret
}
_rpm "$@"
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип : application/pgp-signature
Размер : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url : <http://lists.altlinux.org/pipermail/sisyphus/attachments/20041023/f2c65615/attachment-0003.bin>
Подробная информация о списке рассылки Sisyphus