函数摘要与函数文件目录不同!

函数摘要与函数文件目录不同!

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

所以,我的问题是

  1. zcompile在核心 Zsh 功能上使用是一个坏主意吗?
  2. 为什么在使用摘要时需要手动执行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 种方法可以自动加载某些内容。

  1. 如果有一个名为的文件,element.zwc它将被加载并搜索函数。 (消化)。我个人需要进一步研究这一点,但是您可以使用 .zwc 文件来查看 zwc 文件中的内容zcompile -t。 (我知道您在上面使用过这个,只是将其发布在这里)

  2. 如果三个是名为的字码文件(编译文件) element/function.zwc

  3. 常见的是如果它是 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,它有点无关,但我建议您检查一下。它本质上是根据需要重新编译您的文件:

https://github.com/zsh-users/zsh/blob/284b5aaeb08f90520ac7dc385e8921471678e7dd/Functions/Misc/zrecompile

相关内容