Merge pull request #1016 from VorpalBlade/feature/3rd-party-completion

Support extending zsh completion for third party commands
pull/1018/head
Alad Wenter 2 months ago committed by GitHub
commit 15389b30a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      completions/Makefile
  2. 160
      completions/zsh/_aur
  3. 15
      completions/zsh/_aur_local_packages
  4. 28
      completions/zsh/_aur_packages
  5. 20
      completions/zsh/_aur_repositories

@ -1,9 +1,14 @@
PREFIX ?= /usr
SHRDIR ?= $(PREFIX)/share
.PHONY = bash install-bash zsh install-zsh
.PHONY = bash install-bash install-zsh
ZSH_SITE_FUNCTIONS = \
zsh/_aur \
zsh/_aur_local_packages \
zsh/_aur_packages \
zsh/_aur_repositories
bash: bash/aur
zsh: zsh/_aur.zsh
bash/aur: bash/aurutils.in ../lib/*
bash $< >$@
@ -11,6 +16,8 @@ bash/aur: bash/aurutils.in ../lib/*
install-bash: bash/aur
@install -Dm644 bash/aur -t '$(DESTDIR)$(SHRDIR)/bash-completion/completions'
install-zsh: zsh/_aur.zsh
@install -Dm644 zsh/_aur.zsh '$(DESTDIR)$(SHRDIR)/zsh/site-functions/_aur'
@install -Dm755 zsh/run-help-aur -t '$(DESTDIR)$(SHRDIR)/zsh/functions/Misc'
install-zsh: zsh/run-help-aur $(ZSH_SITE_FUNCTIONS)
@install -Dm644 zsh/run-help-aur -t '$(DESTDIR)$(SHRDIR)/zsh/functions/Misc'
@install -d '$(DESTDIR)$(SHRDIR)/zsh/site-functions/'
@install -m644 -t '$(DESTDIR)$(SHRDIR)/zsh/site-functions/' $(ZSH_SITE_FUNCTIONS)

@ -1,45 +1,18 @@
#compdef aur
# Helper to complete aur package names
# $@ Optional extra arguments to aur pkglist
__aur_list_pkgs() {
# Because of the large number of items causing slowdowns, only do this completion if there is
# at least one letter. In addition we also skip processing if the current completion starts
# with a -, which would be an option. This speeds up generating the list of options in case
# __aur_list_pkgs is used for * (remaining positional arguments). Then we don't need to evaluate
# any of this when we already know we are completing a flag.
#
# Note that additional care needs to be taken to not give the wrong behaviour for a situation
# like "aur sync --ignore=a<tab>". That is what the IPREFIX stuff is about, it lets us skip
# the "--ignore=" part.
local working_data="${words[$CURRENT]#${IPREFIX}}"
if [[ ${working_data} == "" || ${working_data[1]} == '-' ]]; then
return
fi
declare -a pkgs
pkgs=( $(aur pkglist --ttl 86400 --systime $@ 2>/dev/null) )
# Since we are dealing with very long lists of possible completions (~80k as of writing this),
# speed is of the utmost importance for a good user experience. A low level compadd call gave
# the best performance in testing.
local expl
_description packages expl 'package'
compadd "$expl[@]" - $pkgs
}
# Helper to list local packages.
__aur_list_local_packages() {
declare -a pkgs
local repo
for repo in ${(f)"$(aur repo --list-repo)"}; do
pkgs+=( $(aur repo -lq -d $repo 2>/dev/null) )
done
if [[ ${#pkgs} -eq 0 ]]; then
_message "package (no local packages found)"
else
_values package $pkgs
fi
}
#
# AUR supports third party extension of subcommands. This completion does too:
#
# In order to define completion for an aur subcommand "aur-mycmd" you need to
# create a file _aur-mycmd:
# * The first line should be: #compdef aur-mycmd
# * The second line should be: #description Description of Mycmd goes here
#
# Then the normal completion function follows, using _arguments or whatever you
# prefer.
#
# This completion mechanism was taken from the _git completion bundled with zsh.
#
# Helper to list valid repo-add attributes
__aur_list_attributes() {
@ -52,30 +25,12 @@ __aur_list_attributes() {
fi
}
# Helper to complete repository names
# If --all is given, also complete sync repositories, not just local ones.
__aur_list_repos()
{
if [[ $1 == '--all' ]]; then
_values repository $(pacconf --repo-list 2>/dev/null)
else
declare -a repos
repos=( $(aur repo --repo-list 2>/dev/null) )
if [[ ${#repos} -eq 0 ]]; then
_message "repository (none found)"
else
_values repository $repos
fi
fi
}
# Helper to call out to makepkg/makechrootpkg completion
__aur_complete_for()
{
service=$1 $_comps[$1]
}
declare -ga _aur_build_sync_args
# Flags that are used by both aur-build and aur-sync
# Prevents having to duplicate them in both places
@ -107,10 +62,10 @@ _aur_build_sync_args=(
# Repo args
'--pacman-conf=[the pacman.conf used for syncing and retriving local repositories, for chroot also used inside the container]:configuration file: _files'
'--root=[the root directory for the repository]:directory: _files -/'
'(-d --database)'{-d,--database=}'[the name of the pacman database]:repository: __aur_list_repos'
'(-d --database)'{-d,--database=}'[the name of the pacman database]:repository: _aur_repositories'
)
_aur_build() {
_aur-build() {
local -a args
args=(
@ -135,7 +90,7 @@ _aur_build() {
_arguments -s $args $_aur_build_sync_args
}
_aur_chroot() {
_aur-chroot() {
local -a args
args=(
@ -160,12 +115,12 @@ _aur_chroot() {
{-x,--suffix=}'[the path component SUFFIX in the pacman configuration, default to extra]:suffix: '
+ positional
'*:pkgname: __aur_list_pkgs'
'*:pkgname: _aur_packages'
)
_arguments -s -S $args
}
_aur_depends() {
_aur-depends() {
local -a args
args=(
@ -183,12 +138,12 @@ _aur_depends() {
{-t,--table}'[output dependency information as a tab separated table]'
+ positional
'*:pkgname: __aur_list_pkgs'
'*:pkgname: _aur_packages'
)
_arguments -s $args
}
_aur_fetch() {
_aur-fetch() {
local -a args
local -A sync_types
@ -215,15 +170,15 @@ _aur_fetch() {
)
# This is to handle the fact that -r/--recurse changes the meaning of positional arguments
if [[ $words[(ie)-r] -le ${#words} || $words[(ie)--recurse] -le ${#words} ]]; then
_arguments -s $args '*:pkgname: __aur_list_pkgs'
_arguments -s $args '*:pkgname: _aur_packages'
else
_arguments -s $args '*:pkgbase: __aur_list_pkgs -b'
_arguments -s $args '*:pkgbase: _aur_packages -b'
fi
}
_aur_graph() {
_aur-graph() {
local -a args
args=(
@ -232,7 +187,7 @@ _aur_graph() {
_arguments -s $args
}
_aur_pkglist() {
_aur-pkglist() {
local -a args
args=(
@ -256,7 +211,7 @@ _aur_pkglist() {
_arguments -s $args
}
_aur_query() {
_aur-query() {
local -a args
args=(
@ -265,12 +220,12 @@ _aur_query() {
'(-e --exit-if-empty)'{-e,--exit-if-empty}'[if no results are found, exit with status 1 instead of 0]'
'(-r --raw)'{-r,--raw}'[do not process results (implied by --type=info)]'
'(-t --type)'{-t,--type=}'[type of request]:type:(search info)'
'*:pkgname: __aur_list_pkgs'
'*:pkgname: _aur_packages'
)
_arguments -s $args
}
_aur_repo() {
_aur-repo() {
local -a args
args=(
@ -290,7 +245,7 @@ _aur_repo() {
+ options
'--status-file=[print status information to a specified file]:file: _files'
'(-c --config)'{-c,--config=}'[set an alternate pacman.conf file path]:config file: _files'
'(-d --database --repo)'{-d,--database=,--repo=}'[the name of a pacman repository]:repository: __aur_list_repos --all'
'(-d --database --repo)'{-d,--database=,--repo=}'[the name of a pacman repository]:repository: _aur_repositories --all'
'(-q --quiet)'{-q,--quiet}'[only print package names]'
'(-r --root)'{-r,--root=}'[the path to the root of a local repository]:path: _files -/'
'(-S --sync)'{-S,--sync}'[query repositories in DBPATH/sync]'
@ -298,19 +253,19 @@ _aur_repo() {
_arguments -s $args
}
_aur_repo-filter() {
_aur-repo-filter() {
local -a args
args=(
'(-a --all --sync)'{-a,--all,--sync}'[query all available pacman repositories (pacsift --sync)]'
'--config=[set an alternate pacman.conf file path]:config file: _files'
'(-d --database)'{-d,--database=}'[restrict output to pacman repository]:repository: __aur_list_repos --all'
'(-d --database)'{-d,--database=}'[restrict output to pacman repository]:repository: _aur_repositories --all'
'--sysroot[set an alternative system root]:path: _files -/'
)
_arguments -s $args
}
_aur_search() {
_aur-search() {
local -a args
# Groups (+ name) are used to simplify handling of options being exclusive
@ -344,25 +299,25 @@ _aur_search() {
# Determine if this is an info search by checking if the index of -i or --info in the words
# array is less than the length of the array.
if [[ $words[(ie)-i] -le ${#words} || $words[(ie)--info] -le ${#words} ]]; then
_arguments -s $args '*:search term: __aur_list_pkgs'
_arguments -s $args '*:search term: _aur_packages'
else
_arguments -s $args '*:search term: '
fi
}
_aur_srcver() {
_aur-srcver() {
local -a args
args=(
'--buildscript[read the package script instead of the PKGBUILD]:: _files'
{-j,--jobs=}'[set the amount of makepkg processes run in parallel]:number of jobs: '
'--no-prepare[do not run the prepare() function in the PKGBUILD]'
'*:pkgbase: __aur_list_pkgs -b'
'*:pkgbase: _aur_packages --pkgbase'
)
_arguments -s $args
}
_aur_sync() {
_aur-sync() {
local -a args
# Groups (+ name) are used to simplify handling of options being exclusive
@ -380,7 +335,7 @@ _aur_sync() {
'(--provides-from)--no-provides[do not take virtual dependencies (provides) in pacman sync repositories into account to resolve package dependencies]'
'(-o --no-build)'{-o,--no-build}'[print target packages and their paths instead of building them]'
'(-u --upgrades)'{-u,--upgrades}'[update all obsolete AUR packages in a local repository]'
'*--ignore=:package: __aur_list_local_packages'
'*--ignore=:package: _aur_local_packages'
# These overwrite each other and are thus mutually exlusive
+ '(no_ver)'
@ -391,12 +346,12 @@ _aur_sync() {
'--rebuild-tree[as --rebuild-tree, but append all packages in the repository (see -d) as targets]'
+ positional
'*:packages: __aur_list_pkgs'
'*:packages: _aur_packages'
)
_arguments -s $args $_aur_build_sync_args
}
_aur_vercmp() {
_aur-vercmp() {
local -a args
args=(
@ -409,7 +364,7 @@ _aur_vercmp() {
_arguments -s $args
}
_aur_view() {
_aur-view() {
local -a args
args=(
@ -443,6 +398,10 @@ _aur() {
cmds[vercmp]="check packages for AUR updates"
cmds[view]="inspect git repositories"
for k in ${(k)_aur_third_party_commands}; do
cmds[$k]=_aur_third_party_commands[$k]
done
local -a descs=()
local k
for k in ${(k)cmds}; do
@ -456,8 +415,39 @@ _aur() {
case $state in
options)
if [[ ${cmds[${words[1]}]} != "" ]]; then
_aur_${words[1]}
_aur-${words[1]}
fi
;;
esac
}
# Based on code in _git, this allows third party commands extending aur and allows
# completions for them.
# Load any _aur-* definitions so that they may be completed as commands.
declare -gA _aur_third_party_commands
_aur_third_party_commands=()
local file input
for file in ${^fpath}/_aur-*~(*~|*.zwc)(-.N); do
local name=${${file:t}#_aur-}
if (( $+_aur_third_party_commands[$name] )); then
continue
fi
local desc=
integer i=1
while read input; do
if (( i == 2 )); then
if [[ $input == '#description '* ]]; then
desc=:${input#\#description }
fi
break
fi
(( i++ ))
done < $file
_aur_third_party_commands+=([$name]=$desc)
done
_aur

@ -0,0 +1,15 @@
#autoload
# Helper to complete package names in local repositories
_aur_local_packages() {
declare -a pkgs
local repo
for repo in ${(f)"$(aur repo --list-repo)"}; do
pkgs+=( $(aur repo -lq -d $repo 2>/dev/null) )
done
if [[ ${#pkgs} -eq 0 ]]; then
_message "package (no local packages found)"
else
_values package $pkgs
fi
}

@ -0,0 +1,28 @@
#autoload
# Helper to complete AUR package names
# $@ Optional extra arguments to aur pkglist, such as --pkgbase to complete base package names
_aur_packages() {
# Because of the large number of items causing slowdowns, only do this completion if there is
# at least one letter. In addition we also skip processing if the current completion starts
# with a -, which would be an option. This speeds up generating the list of options in case
# _aur_packages is used for * (remaining positional arguments). Then we don't need to evaluate
# any of this when we already know we are completing a flag.
#
# Note that additional care needs to be taken to not give the wrong behaviour for a situation
# like "aur sync --ignore=a<tab>". That is what the IPREFIX stuff is about, it lets us skip
# the "--ignore=" part.
local working_data="${words[$CURRENT]#${IPREFIX}}"
if [[ ${working_data} == "" || ${working_data[1]} == '-' ]]; then
return
fi
declare -a pkgs
pkgs=( $(aur pkglist --ttl 86400 --systime $@ 2>/dev/null) )
# Since we are dealing with very long lists of possible completions (~80k as of writing this),
# speed is of the utmost importance for a good user experience. A low level compadd call gave
# the best performance in testing.
local expl
_description packages expl 'package'
compadd "$expl[@]" - $pkgs
}

@ -0,0 +1,20 @@
#autoload
# Helper to complete names of local "file://"-based repositories
#
# If --all is given, also complete sync repositories, not just local file based
# ones.
_aur_repositories()
{
if [[ $1 == '--all' ]]; then
_values repository $(pacconf --repo-list 2>/dev/null)
else
declare -a repos
repos=( $(aur repo --repo-list 2>/dev/null) )
if [[ ${#repos} -eq 0 ]]; then
_message "repository (none found)"
else
_values repository $repos
fi
fi
}
Loading…
Cancel
Save