如何在 zsh 中正确调用 compinit(和 bashcompinit)
How to properly call compinit (and bashcompinit) in zsh
讨论了整个问题 here and here。由于参与这些讨论的人都不能 100% 确定这个问题,所以我在这里寻求帮助。 (为了完整起见,我将从头开始。)
假设我们有两个脚本(来源 ~/.zshrc
)为 ZSH 设置了一些完成逻辑。现在根据我所学,在脚本中的某个时刻你需要像这样调用 compinit
和 bashcompinit
(从 NVM 完成脚本复制)
if [[ -n ${ZSH_VERSION-} ]]; then
autoload -U +X compinit && if [[ ${ZSH_DISABLE_COMPFIX-} = true ]]; then
compinit -u
else
compinit
fi
autoload -U +X bashcompinit && bashcompinit
fi
显然,根据 ZSH 手册,bashcompinit
必须在 compinit
之后调用(不确定是否相关)。现在的问题是,当第二个脚本调用 compinit
时,第一个脚本的逻辑就消失了(即第一个脚本的完成不可用)。重现此内容的一个简单片段是(从 here 复制):
complete -W "hello world" one
one <tab> # to see autocomplete working
compinit
one <tab> # to see autocomplete NOT working
有人提出 (here) 类似下面的方法来解决问题(通过在调用之前检查 compinit
是否已经被调用):
if [[ -n ${ZSH_VERSION-} ]]; then
if ! command -v compinit > /dev/null; then
autoload -U +X compinit && if [[ ${ZSH_DISABLE_COMPFIX-} = true ]]; then
compinit -u
else
compinit
fi
fi
autoload -U +X bashcompinit && bashcompinit
fi
另一个想法是不在自定义完成脚本中调用 compinit
和 bashcompinit
,而是在 ~/.zshrc
中调用(这会损害 NVM 等工具的自动安装过程)。
我想知道一般设置完成的正确方法是什么(或者特别是关于调用 compinit
)。
谢谢。
Let's say we have two scripts (sourced in ~/.zshrc
) that set up some completion logic for ZSH. Now based on what I learned, at some point in the script you need to call compinit
and bashcompinit
不,那不是您的脚本应该做的。不是你的脚本,而是 user 应该在他们的 .zshrc
文件中调用 compinit
来启用 Zsh 的完成系统。此外,对于每个 shell 个实例,它应该被调用 一次 。
相反,3rd 方脚本有两种正确的方法来为 Zsh 添加补全功能:
- 如果用户应该为他们的每个 shell 实例分别 运行 您的脚本(这似乎是您的情况),那么:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和 compinit
。
- 告诉他们在这些行之前获取您的脚本。
- 当你的脚本 运行s 时,让它将包含你的完成函数的目录添加到用户的
$fpath
。
- 但是,如果您还提供了安装程序,那么您可以:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和 compinit
。
- 让安装程序将您的完成函数复制到
/usr/local/share/zsh/site-functions
(默认情况下在 Zsh 的 $fpath
中)。
(后者也是安装软件时包管理器应该做的。)
Apparently, according to ZSH manual, bashcompinit
must be called after compinit
, (not sure if it's relevant).
是的,它是相关的,但不,不是您认为的那样。除此之外,bashcompinit
定义了函数 complete
,然后(就像 Bash 中的 complete
内置)可以用来向 Zsh 添加 Bash 完成函数.像 compinit
一样,bashcompinit
意味着每个 shell.
只调用一次
如果您的包不提供原生 Zsh 完成功能,那么您应该执行以下操作:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和 compinit
。
- 告诉用户确保在以上行之后,
autoload -Uz bashcompinit
和bashcompinit
被调用。
- 然后,在这些行之后,他们应该按照您在 Bash.
中给出的安装完成的相同说明进行操作
讨论了整个问题 here and here。由于参与这些讨论的人都不能 100% 确定这个问题,所以我在这里寻求帮助。 (为了完整起见,我将从头开始。)
假设我们有两个脚本(来源 ~/.zshrc
)为 ZSH 设置了一些完成逻辑。现在根据我所学,在脚本中的某个时刻你需要像这样调用 compinit
和 bashcompinit
(从 NVM 完成脚本复制)
if [[ -n ${ZSH_VERSION-} ]]; then
autoload -U +X compinit && if [[ ${ZSH_DISABLE_COMPFIX-} = true ]]; then
compinit -u
else
compinit
fi
autoload -U +X bashcompinit && bashcompinit
fi
显然,根据 ZSH 手册,bashcompinit
必须在 compinit
之后调用(不确定是否相关)。现在的问题是,当第二个脚本调用 compinit
时,第一个脚本的逻辑就消失了(即第一个脚本的完成不可用)。重现此内容的一个简单片段是(从 here 复制):
complete -W "hello world" one
one <tab> # to see autocomplete working
compinit
one <tab> # to see autocomplete NOT working
有人提出 (here) 类似下面的方法来解决问题(通过在调用之前检查 compinit
是否已经被调用):
if [[ -n ${ZSH_VERSION-} ]]; then
if ! command -v compinit > /dev/null; then
autoload -U +X compinit && if [[ ${ZSH_DISABLE_COMPFIX-} = true ]]; then
compinit -u
else
compinit
fi
fi
autoload -U +X bashcompinit && bashcompinit
fi
另一个想法是不在自定义完成脚本中调用 compinit
和 bashcompinit
,而是在 ~/.zshrc
中调用(这会损害 NVM 等工具的自动安装过程)。
我想知道一般设置完成的正确方法是什么(或者特别是关于调用 compinit
)。
谢谢。
Let's say we have two scripts (sourced in
~/.zshrc
) that set up some completion logic for ZSH. Now based on what I learned, at some point in the script you need to callcompinit
andbashcompinit
不,那不是您的脚本应该做的。不是你的脚本,而是 user 应该在他们的 .zshrc
文件中调用 compinit
来启用 Zsh 的完成系统。此外,对于每个 shell 个实例,它应该被调用 一次 。
相反,3rd 方脚本有两种正确的方法来为 Zsh 添加补全功能:
- 如果用户应该为他们的每个 shell 实例分别 运行 您的脚本(这似乎是您的情况),那么:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和compinit
。 - 告诉他们在这些行之前获取您的脚本。
- 当你的脚本 运行s 时,让它将包含你的完成函数的目录添加到用户的
$fpath
。
- 告诉用户确保从他们的点文件中调用
- 但是,如果您还提供了安装程序,那么您可以:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和compinit
。 - 让安装程序将您的完成函数复制到
/usr/local/share/zsh/site-functions
(默认情况下在 Zsh 的$fpath
中)。
- 告诉用户确保从他们的点文件中调用
(后者也是安装软件时包管理器应该做的。)
Apparently, according to ZSH manual,
bashcompinit
must be called aftercompinit
, (not sure if it's relevant).
是的,它是相关的,但不,不是您认为的那样。除此之外,bashcompinit
定义了函数 complete
,然后(就像 Bash 中的 complete
内置)可以用来向 Zsh 添加 Bash 完成函数.像 compinit
一样,bashcompinit
意味着每个 shell.
如果您的包不提供原生 Zsh 完成功能,那么您应该执行以下操作:
- 告诉用户确保从他们的点文件中调用
autoload -Uz compinit
和compinit
。 - 告诉用户确保在以上行之后,
autoload -Uz bashcompinit
和bashcompinit
被调用。 - 然后,在这些行之后,他们应该按照您在 Bash. 中给出的安装完成的相同说明进行操作