zcompile
我有一个用于创建摘要的函数,如下所示:
function fpath-setup {
local FLATFPATH="${TMPPREFIX}-${ZSH_VERSION}-fpath.zwc"
function {
typeset -a zarr
blacklist=('ztodo' 'zed')
blacklist="^(${(j:|:)blacklist})"
setopt LOCAL_OPTIONS EXTENDED_GLOB
for fp in "$fpath[@]"; do
local ztail=(${zarr:t})
for it in "${fp}/"$~blacklist; do
if [[ -z "${ztail[(r)${it:t}]}" ]]; then
if zcompile "${TMPPREFIX}-try-zcompile" "${it}" &>/dev/null; then
zarr+="${it}"
else
echo "CANNOT COMPILE: ${it}"
fi
else
echo "DUPLICATE: ${it}"
fi
done
done
zcompile "${FLATFPATH}" "$zarr[@]"
zcompile -t "${FLATFPATH}" 'compinit' '_complete' || {
print "Important functions missing from ${FLATFPATH}" >&2
return 1
}
}
if (( $? )); then
print "The fpath is left unchanged." >&2
return 1
else
fpath=("${FLATFPATH}")
fi
}
运行时,$fpath
看起来像这样:
/usr/local/share/zsh/site-functions
/usr/local/Cellar/zsh/5.2/share/zsh/functions
运行后,$fpath
看起来像这样:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
正如您在这里所看到的,Zsh 的核心功能在摘要中:
https://ghostbin.com/paste/wgauy
这似乎工作正常,直到我尝试使用这个提示主题:
https://github.com/sindresorhus/pure/blob/master/pure.zsh#L328
每次提示时我都会收到以下错误:
vcs_info: configured unknown backend: 'git'
vcs_info: use 'vcs_info_printsys' to find supported systems.
可以通过首先不创建摘要或在调用提示符之前运行以下命令来解决此问题:
autoload -Uz VCS_INFO_get_data_git VCS_INFO_detect_git
所以,我的问题是:
zcompile
在核心 Zsh 功能上使用是一个坏主意吗?- 为什么在使用摘要时需要手动执行
autoload
一些操作zcompile
,但在目录中使用常规文件时却不是这样?
编辑:
我做了更多调查,发现了类似的情况fpath
:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-circuit.zwc
命令:
prompt pure # ...vcs_info errors
print -f '%s\n' "${(k)functions[@]}" | grep VCS_INFO_get_data_git
什么也不返回。但是,使用如下 fpath:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
/usr/local/Cellar/zsh/5.2/share/zsh/functions
命令:
prompt pure # NO vcs_info errors!
type $(print -f '%s\n' "${(k)functions[@]}" | grep VCS_INFO_get_data_git)
返回:
VCS_INFO_get_data_git is a shell function from /var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc/VCS_INFO_get_data_git
因此,不知何故,仅仅核心目录的存在/usr/local/Cellar/zsh/5.2/share/zsh/functions
就会导致VCS_INFO_get_data_git
从/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
.
这是否意味着 Zsh 对 core 目录给予特殊对待?为了测试该理论,我将核心函数文件复制到临时位置:
cp -r /usr/local/Cellar/zsh/5.2/share/zsh/functions /tmp
然后在一个新的会话中,使用如下 fpath:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
/tmp/functions
命令:
prompt pure # NO vcs_info errors!!
type $(print -f '%s\n' "${(k)functions[@]}" | grep VCS_INFO_get_data_git)
返回:
VCS_INFO_get_data_git is a shell function from /var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc/VCS_INFO_get_data_git
因此,我必须得出结论,Zsh 并没有特殊对待它的核心目录,而是VCS_INFO_get_data_git
如果该名称的文件存在于任何目录中,它就会自动加载fpath
......但是,如果它先出现,Zsh 仍然会从 DIGEST 加载在里面fpath
。
这很奇怪。
我还没有在任何地方看到这种行为的记录,而且我不清楚 Zsh 是如何实现这一点的(也许了解 Zsh 内部结构的人可以解释)。
为了尝试弄清楚自动加载何时发生,我fpath
通过更改以下内容在新会话中摆弄fpath
:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
/tmp/functions
要删除/tmp/functions
目录:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
然后我尝试更改提示:
prompt pure
与之前一样,这给出了原始vcs_info
错误:
vcs_info: configured unknown backend: 'git'
vcs_info: use 'vcs_info_printsys' to find supported systems.
可以肯定的是,测试:
print -f '%s\n' "${(k)functions[@]}" | grep VCS_INFO_get_data_git
什么都不返回!现在,如果此时我将/tmp/functions
目录添加回 Back fpath
,那么它看起来像:
/var/folders/kb/ydt74z19765cv9vb86rwvcrr0000gn/T/zsh-5.2-fpath.zwc
/tmp/functions
错误vcs_info
继续存在!
谁能解释一下 Zsh 5.2 版本到底发生了什么?
答案1
我正在研究类似的东西,所以我可能有一些有用的东西。
如果您这样做man zshmisc
并转到“自动加载功能”部分,会对此进行一些解释。
http://zsh.sourceforge.net/Doc/Release/Functions.html
这里说了两件事我要指出
首先,我认为你的问题之一是你错过了-U
上面的标志:
如果自动加载内置函数或其等效函数指定了选项 -U,则读取期间通常的别名扩展将被抑制。建议使用 zsh 发行版提供的功能。请注意,对于使用 zcompile 内置命令预编译的函数,在创建 .zwc 文件时必须提供标志 -U,因为相应的信息会编译到后者中。
其次是它如何从 fpath 变量自动加载(我建议阅读该页面,但这里总结了):
element
是 fpath 项,并且function
是尝试自动加载的函数。
有 3 种方法可以自动加载某些内容。
如果有一个名为的文件,
element.zwc
它将被加载并搜索函数。 (消化)。我个人需要进一步研究这一点,但是您可以使用 .zwc 文件来查看 zwc 文件中的内容zcompile -t
。 (我知道您在上面使用过这个,只是将其发布在这里)如果三个是名为的字码文件(编译文件)
element/function.zwc
常见的是如果它是 fpath 中的文件(所以就这样
element/function
)
另请查看man zshbuiltins
并查找 的手册页zcompile
。您可以使用 和-c
来-a
编译所有函数或所有自动加载的函数:
http://zsh.sourceforge.net/Doc/Release/Shell-Builtin-Commands.html
.
如果您在页面上查找内置函数,您还可以找到另一个提到 zsh 字代码的地方。您可以具体看到,如果您使用它,它会查找*.zwc
文件的版本并加载它:
如果找到名为“file.zwc”的文件,该文件比 file 新,并且是 file 的编译形式(使用 zcompile 内置命令创建),则从该文件而不是 file 读取命令。
还有一个可以自动加载的函数,称为 zrecompile,它有点无关,但我建议您检查一下。它本质上是根据需要重新编译您的文件: