我有一个 Apache Hadoop 的 Bash 补全脚本。通常,我在日常工作中使用 zsh 作为我的 shell。当需要时,它往往像 Bash 一样。但是,在它们之间的 tab 补全系统看起来存在根本性差异。是否有一种简单的方法可以将现有的 bash-tab-completion 定义转换为适用于 zsh 的定义?我不想花费大量时间在此上,但如果很容易的话,我可以节省相当多的精力。
我有一个 Apache Hadoop 的 Bash 补全脚本。通常,我在日常工作中使用 zsh 作为我的 shell。当需要时,它往往像 Bash 一样。但是,在它们之间的 tab 补全系统看起来存在根本性差异。是否有一种简单的方法可以将现有的 bash-tab-completion 定义转换为适用于 zsh 的定义?我不想花费大量时间在此上,但如果很容易的话,我可以节省相当多的精力。
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script
我正在运行 zsh zsh 5.0.2 (x86_64-apple-darwin13.0)
,没有任何 ~/.zshrc,并且上述命令在一个全新的 zsh shell 中可以正常工作。感谢 git-completion.bash 脚本的提示:D。
Bash 具有出色的内置自动补全支持,但 bash 自动补全脚本不能直接在 zsh 中工作,因为 zsh 环境没有必要的 bash 自动补全帮助函数,例如 compgen
、complete
,这是为了保持 zsh 会话快速。
现在,zsh 随附了适当的完成脚本,如 compinit
和 bashcompinit
,它们具有支持 bash 自动补全脚本所需的函数。
autoload <func_name>
:请注意,autoload 是在 zsh 中定义的,而不是 bash。 autoload
在由 fpath
命令返回的目录路径中查找名为 <func_name> 的文件,并在第一次调用该函数时标记为加载相同的文件。
例如,在我的系统上,echo $fpath
返回 /usr/share/zsh/site-functions
和 /usr/share/zsh/5.0.5/functions
,并且两者都可在 /usr/share/zsh/5.0.5/functions
找到 compinit
和 bashcompinit
。
此外,对于大多数人来说,可能只需要运行 autoload -U +X bashcompinit && bashcompinit
,因为某些其他脚本(如 git 自动补全或他们自己的 ~/.zshrc
)可能正在执行 autoload -U +X compinit && compinit
,但同时运行这两个命令是安全的。
+X foo
的作用是做与调用 foo
相同的自动加载,但不立即执行它...所以 autoload +X foo && foo
看起来完全是多余的。你能解释一下为什么选择这种模式吗? - ELLIOTTCABLEautoload -U +X bashcompinit && bashcompinit
的目的是(由于 &&
)只有在实际找到模块时才会执行 bashcompinit
。普通的 autoload foo
总是返回 true。稍后,当您尝试运行 foo
时,zsh 最终会告诉您“找不到函数定义文件”。使用 autoload +X
,您可以立即获得错误信息。 - FeRDautoload +X
加载函数但不执行它-这比没有+X
的autoload
更多。没有+X
,autoload
甚至不会加载函数;它只是标记名称,表示稍后将要加载一个函数。实际的加载直到首次调用该函数才会尝试。如果您想确定命名的函数是否成功加载,您需要使用+X
立即执行加载步骤。 - FeRD来自这个页面(日期为2010/01/05):
Zsh可以处理bash自动完成函数。 Zsh的最新开发版本具有一个名为bashcompinit的函数,当运行该函数时,它将允许zsh读取bash完成规范和函数。这在zshcompsys手册中有记录。要使用它,您只需在compinit之后的任何时间运行bashcompinit即可。它会定义与bash内置complete和compgen函数对应的complete和compgen函数。
我正在使用Antigen作为Oh-My-Zsh插件管理器。 我有几个同事编写的bash完成脚本,我想用简单的source /path/to/completion
将它们加载到Zsh中。
我遇到了一些困难,因为似乎Antigen或OMZ(很难确定)只关心从它们的插件加载完成脚本。 最终,我通过在antigen apply
之后autoload bashcompinit
和compinit
来解决了这个问题。 仅仅autoload bashcompinit
是不够的。
source ~/.antigen/antigen.zsh
antigen use oh-my-zsh
antigen apply
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/bash_completion
$ANTIGEN_COMPDUMP
处创建它的.zcompdump
文件,对我来说是~/.antigen/.zcompdump
。$HOME/.zcompdump
处创建第二个.zcompdump文件。/path/to/bash_completion
设置的补全。我已经删除了几次.zcompdump文件以确保它们被重新生成,并且似乎可以正常工作。rm ~/.zcompdump && rm $ANTIGEN_COMPDUMP
并打开一个新的shell就可以解决问题。Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
对于 zsh
使用:
compdef
compadd
我的示例:
# bash completion for bxrun (/home/ecuomo/projects/bashx/bxrun)
_bxrun_methods() {
grep "^\s*\(function\s\+\)\?__.\+()\s*{.*$" "${1}" | while read line ; do
echo "$line" | sed "s/()\s*{.*//g" | sed "s/\s*\(function\s\+\)\?__//g"
done
}
_bxrun_lst() {
if [ -d "/home/ecuomo/projects/bashx/src/actions" ]; then
for f in /home/ecuomo/projects/bashx/src/actions/* ; do
if [ -f "${f}" ]; then
basename "${f}" | sed 's/\..*$//g'
fi
done
fi
_bxrun_methods "/home/ecuomo/projects/bashx/bxrun"
_bxrun_methods "/home/ecuomo/projects/bashx/src/bashx.sh"
}
_bxrun() {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $( compgen -W '$( _bxrun_lst )' -- $cur ) )
}
_bxrun_zsh() {
compadd `_bxrun_lst`
}
if type complete >/dev/null 2>/dev/null; then
# bash
complete -F _bxrun bxrun
else if type compdef >/dev/null 2>/dev/null; then
# zsh
compdef _bxrun_zsh bxrun
fi; fi
@JatinKumar的回答让我找到了正确的方向,但我必须使用complete
而不是source
。所以全部内容如下:
autoload -Uz compinit && compinit
autoload -U +X bashcompinit && bashcompinit
complete -C /usr/local/bin/terraform terraform
complete -C /usr/local/aws/bin/aws_completer aws
complete -C /usr/local/bin/az az
if is-bash
检查。 - olejorgenb