zsh完了システムがどのように機能するかについての洞察を提供しようとしますが、この問題は不完全です。
manzshでTAB補完を使用するときに実行されるファイルは、/usr/share/zsh/${ZSH_VERSION}/functionsディレクトリの下にあります。ツリーはディストリビューションによって異なりますが、ファイルの名前は、、および_manの補完を提供します。manaproposwhatis
_manが呼び出されると、次のように機能します(大まかな説明)。
- 完了し
man、--local-file最初のフラグとして指定された場合は、標準ファイルの完了を呼び出します(_files)
manpathデフォルトのセット/から変数を作成します$MANPATH。これは、マンページが検索される場所です
- セクション番号パラメーターを使用して呼び出したかどうかを判別
manします。はいの場合、それらのセクションのみが検索されます
- が使用された場合は
zstyle ':completion:*:manuals' separate-sections true、出力のセクションを分離します(それらを混在させないでください)
- 呼び出し
_man_pagesて、一致するマニュアルページのリストを提供します
_man_pagesで少し魔法をかけcompfiles -p pages '' '' "$matcher" '' dummy '*'ます。pagesは、要求されたセクションのマンページを含むすべてのディレクトリを持つ変数です。実際のグロブパターンは、暗黙のパラメータ$PREFIXと最後のパラメータからcompfiles-*この場合は-に構築されます。これにより、次の/usr/share/man/man1ように変換されます/usr/share/man/man1/foo*
- グロブパターンの新しいリストがグロブされ、パターンに一致するすべてのファイルが取得されます
_man_pages次に、ファイルからサフィックスを取り除き、次を使用してそれらを選択の完了ウィジェットリストに追加します。compadd
ご覧のとおり、マンページのリストは$PREFIX変数によって直接決定されます。単語を含むzsh:foomanページのみをリストするためには、文字(存在する場合)に分割する必要があります。zsh*foo:
次の追加により_man_pages、問題が部分的に解決されます(zsh 4.3.4)。
オリジナル:
_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 "$@" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
else
compadd "$@" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
fi
}
変更(## 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 "$@" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
else
compadd "$@" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
fi
}
ただし、まだ完全には機能していません(#echo "$p matched $manpage_grep"行のコメントを外すと、リストが作成されていることがわかります)-内部のどこかで、完了システムは、たとえば、「zshcompctl」がプレフィックス「zsh」と一致していないことを認識していると思われます。 :foo "であり、結果の一致は表示されません。grep文字列を削除した後、そのままにしておこうとしまし$PREFIXたが、それでも機能しません。
とにかく、これは少なくともあなたが始めるはずです。