Je vais essayer de fournir un aperçu de la façon dont le système de complétion zsh fonctionne et un aller incomplet à ce problème.
Le fichier qui s'exécute lorsque vous utilisez la complétion TAB pour man
dans zsh se trouve dans le répertoire /usr/share/zsh/${ZSH_VERSION}/functions
. L'arborescence varie d'une distribution à l'autre, mais le fichier porte le numéro _man
et indique l'achèvement pour man
, apropos
et whatis
.
Après _man est invoqué, il fonctionne comme suit (description sommaire):
- si vous remplissez pour
man
et --local-file
a été spécifié comme premier drapeau, appelez fichiers standard d'achèvement (_files
)
- construire
manpath
variable à partir un ensemble de valeurs par défaut/$MANPATH
. C'est là que les pages de manuel seront recherchées
- déterminer si nous invoquions
man
avec un paramètre de numéro de section, si oui - que ces sections seront recherchées
- si le
zstyle ':completion:*:manuals' separate-sections true
a été utilisé, des sections distinctes de la production (ne se mélangent pas entre les)
- invoquez
_man_pages
pour fournir une liste des pages de manuel pour le match
_man_pages
fait maintenant un peu de magie avec compfiles -p pages '' '' "$matcher" '' dummy '*'
. pages
est la variable avec tous les répertoires contenant des pages de manuel pour les sections demandées. Le modèle de globulation réel est construit à partir du paramètre implicite $PREFIX
et le dernier paramètre à compfiles
- *
dans ce cas. Il en résulte /usr/share/man/man1
être transformé en /usr/share/man/man1/foo*
- La nouvelle liste des modèles glob est globbed, obtenir tous les fichiers qui correspondent au modèle
_man_pages
les bandes puis tous les suffixes des fichiers et les ajoute à la liste des widgets d'achèvement des choix par maintenant, en utilisant compadd
, comme vous pouvez le voir, la liste des pages de manuel est déterminée directement par $PREFIX
variable. Afin de faire zsh:foo
pour ne répertorier que les pages man de zsh*
qui contiennent le mot foo
, il doit être divisé en :
caractère (le cas échéant).
L'ajout suivant à _man_pages
résoudre partiellement le problème (zsh 4.3.4):
Original:
_man_pages() {
local matcher pages dummy sopt
zparseopts -E M+:=matcher
if (($#matcher)); then
matcher=(${matcher:#-M})
matcher="$matcher"
else
matcher=
fi
pages=(${(M)dirs:#*$sect/})
compfiles -p pages '' '' "$matcher" '' dummy '*'
pages=(${^~pages}(N:t))
(($#mrd)) && pages[$#pages+1]=($(awk $awk $mrd))
# Remove any compression suffix, then remove the minimum possible string
# beginning with .<->: that handles problem cases like files called
# `POSIX.1.5'.
[[ $OSTYPE = solaris* ]] && sopt='-s '
if ((CURRENT > 2)) ||
! zstyle -t ":completion:${curcontext}:manuals.$sect" insert-sections
then
compadd "[email protected]" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
else
compadd "[email protected]" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
fi
}
Modifiés (rechercher ## commentaires mod):
_man_pages() {
local matcher pages dummy sopt
zparseopts -E M+:=matcher
if (($#matcher)); then
matcher=(${matcher:#-M})
matcher="$matcher"
else
matcher=
fi
pages=(${(M)dirs:#*$sect/})
##mod
# split components by the ":" character
local pref_words manpage_grep orig_prefix
# save original prefix (just in case)
orig_prefix=${PREFIX}
# split $PREFIX by ':' and make it an array
pref_words=${PREFIX//:/ }
set -A pref_words ${=pref_words}
# if there are both manpage name and grep string, use both
if (($#pref_words == 2)); then
manpage_grep=$pref_words[2]
# PREFIX is used internally by compfiles
PREFIX=$pref_words[1]
elif (($#pref_words == 1)) && [[ ${PREFIX[1,1]} == ":" ]]; then
# otherwise, prefix is empty and only grep string exists
PREFIX=
manpage_grep=$pref_words[1]
fi
compfiles -p pages '' '' "$matcher" '' dummy '*'
##mod: complete, but don't strip path names
pages=(${^~pages})
(($#mrd)) && pages[$#pages+1]=($(awk $awk $mrd))
##mod: grep pages
# Build a list of matching pages that pass the grep
local matching_pages
typeset -a matching_pages
# manpage_grep exists and not empty
if ((${#manpage_grep} > 0)); then
for p in ${pages}; do
zgrep "${manpage_grep}" $p > /dev/null
if (($? == 0)); then
#echo "$p matched $manpage_grep"
matching_pages+=($p)
fi
done
else
# there's no manpage_grep, so all pages match
matching_pages=(${pages})
fi
#echo "\nmatching manpages: "${matching_pages}
pages=(${matching_pages}(N:t))
# keep the stripped prefix for now
#PREFIX=${orig_prefix}
# Remove any compression suffix, then remove the minimum possible string
# beginning with .<->: that handles problem cases like files called
# `POSIX.1.5'.
[[ $OSTYPE = solaris* ]] && sopt='-s '
if ((CURRENT > 2)) ||
! zstyle -t ":completion:${curcontext}:manuals.$sect" insert-sections
then
compadd "[email protected]" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
else
compadd "[email protected]" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
fi
}
Cependant, il ne fonctionne pas encore complètement (si vous décommentez la ligne #echo "$p matched $manpage_grep"
, vous pouvez voir qu'il construit la liste) - Je suppose que quelque part en interne, la co Le système mpletion voit que, par exemple, "zshcompctl" ne correspond pas au préfixe "zsh: foo", et n'affiche pas les résultats obtenus. J'ai essayé de garder $PREFIX
comme il est après avoir dépouillé la chaîne grep, mais il ne veut toujours pas travailler.
Quoi qu'il en soit, cela devrait au moins vous aider à démarrer.
Merci pour votre réponse! –