简体   繁体   English

可以在 zsh 中使用 Bash 选项卡完成脚本吗?

[英]Can a Bash tab-completion script be used in zsh?

I have a Bash tab-completion script for Apache's Hadoop.我有一个用于 Apache Hadoop 的 Bash 选项卡完成脚本。 Normally, I use zsh as my day-to-day shell.通常,我使用 zsh 作为我的日常 shell。 It tends to be pretty bash-like when I need it to be, but it looks like the tab-completion systems are radically different between them.当我需要它时,它往往非常像 bash,但看起来它们之间的制表符完成系统完全不同。 Is there a simple way to "convert" the existing bash-tab-completion definitions to work in zsh?有没有一种简单的方法可以“转换”现有的 bash-tab-completion 定义以在 zsh 中工作? I don't want to invest a ton of time in this, but if it's easy I'd save a moderate amount of effort.我不想在这方面投入大量时间,但如果这很容易,我会节省一些精力。

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

I am running zsh zsh 5.0.2 (x86_64-apple-darwin13.0) without any ~/.zshrc and the above sequence worked in a freshly spawned zsh shell.我正在运行 zsh zsh 5.0.2 (x86_64-apple-darwin13.0)没有任何 ~/ zsh 5.0.2 (x86_64-apple-darwin13.0)并且上述序列在新生成的 zsh shell 中工作。

Thanks to git-completion.bash script for the hint :D感谢 git-completion.bash 脚本的提示:D


Read-on for more details on above 3 lines:继续阅读以上 3 行的更多详细信息:

Bash has awesome in built auto completion support but the bash autocomplete scripts don't work directly zsh as zsh environment doesn't have the essential bash autocomplete helper functions like compgen , complete . Bash 在内置自动完成支持方面非常compgen ,但 bash 自动完成脚本不能直接运行 zsh,因为 zsh 环境没有必要的 bash 自动完成辅助功能,如compgencomplete It does so in an effort to keep zsh session fast.这样做是为了让 zsh 会话保持快速。

These days zsh is shipped with appropriate completion scripts like compinit and bashcompinit which have the required functions to support bash autocomplete scripts. compinit ,zsh 附带了适当的完成脚本,如compinitbashcompinit ,它们具有支持 bash 自动完成脚本所需的功能。

autoload <func_name> : Note that autoload is defined in zsh and not bash. autoload <func_name> :请注意,自动加载是在 zsh 而不是 bash 中定义的。 autoload looks for a file named in the directory paths returned by fpath command and marks a function to load the same when it is first invoked. autoload查找在fpath命令返回的目录路径中命名的文件,并标记一个函数以在第一次调用时加载该文件。

  • -U: Ignore any aliases when loading a function like compinit or bashcompinit -U:在加载像 compinit 或 bashcompinit 这样的函数时忽略任何别名
  • +X: Just load the named function fow now and don't execute it +X:现在只加载命名函数 fow 并且不执行它

For example on my system echo $fpath returns /usr/share/zsh/site-functions and /usr/share/zsh/5.0.5/functions and both compinit and bashcompinit are available at /usr/share/zsh/5.0.5/functions .例如在我的系统上echo $fpath返回/usr/share/zsh/site-functions/usr/share/zsh/5.0.5/functions并且compinitbashcompinit都可以在/usr/share/zsh/5.0.5/functions

Also for most people may be only autoload -U +X bashcompinit && bashcompinit is required because some other script like git autocomplete or their own ~/.zshrc may be doing autoload -U +X compinit && compinit , but it's safe to just run both of them.同样对于大多数人来说,可能只需要autoload -U +X bashcompinit && bashcompinit因为其他一些脚本,如 git autocomplete 或他们自己的~/.zshrc可能正在执行autoload -U +X compinit && compinit ,但只运行两者是安全的其中。

From this page (dated 2010/01/05):从此页面(日期为 2010/01/05):

Zsh can handle bash completions functions. Zsh 可以处理 bash 完成功能。 The latest development version of zsh has a function bashcompinit, that when run will allow zsh to read bash completion specifications and functions. zsh 的最新开发版本有一个函数 bashcompinit,运行时将允许 zsh 读取 bash 完成规范和函数。 This is documented in the zshcompsys man page.这记录在 zshcompsys 手册页中。 To use it all you need to do is run bashcompinit at any time after compinit.要使用它,您需要做的就是在 compinit 之后随时运行 bashcompinit。 It will define complete and compgen functions corresponding to the bash builtins.它将定义与 bash 内置函数相对应的 complete 和 compgen 函数。

I am running Antigen as a Oh-My-Zsh plugin manager.我将Antigen作为 Oh-My-Zsh 插件管理器运行。 I had a few bash completion scripts written by coworkers that I wanted to load into Zsh with a simple source /path/to/completion .我有一些由同事编写的 bash 完成脚本,我想使用简单的source /path/to/completion将它们加载到 Zsh 中。

I had some trouble, because it seems like either Antigen or OMZ (hard to tell) concern themselves with only loading completion scripts from their plugins.我遇到了一些麻烦,因为似乎 Antigen 或 OMZ(很难说)只关心从他们的插件加载完成脚本。 I finally got around this by autoloading bashcompinit and compinit after antigen apply .我终于通过在antigen apply之后自动加载bashcompinitcompinit解决了这个问题。 Simply autoloading bashcompinit wasn't enough.仅仅自动加载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 creates its .zcompdump file at $ANTIGEN_COMPDUMP which for me was ~/.antigen/.zcompdump Antigen 在$ANTIGEN_COMPDUMP创建它的.zcompdump文件,对我来说是~/.antigen/.zcompdump

The re-invoke of compinit and bashcompinit create a second .zcompdump at $HOME/.zcompdump重新调用 compinit 和 bashcompinit 在$HOME/.zcompdump创建第二个$HOME/.zcompdump

That seems to all work out, because I am able to use the completions set up by /path/to/bash_completion .似乎都解决了,因为我能够使用/path/to/bash_completion设置的完成。 I've deleted both .zcompdump files a few times to make sure they're regenerated and seems to work.我已经多次删除了 .zcompdump 文件以确保它们重新生成并且似乎可以工作。

I've had to rm the .zcompdump files a few times after a machine reboot because of errors thrown when trying to tab complete, but I'm unsure if that's due to this set up or something else.由于尝试完成选项卡时抛出错误,我不得不在机器重新启动后多次 rm .zcompdump 文件,但我不确定这是由于此设置还是其他原因。 rm ~/.zcompdump && rm $ANTIGEN_COMPDUMP and a new shell fixes that for me. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMP和一个新的 shell 为我修复了这个问题。

Versions used at time of writing:撰写本文时使用的版本:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3

For zsh use:对于zsh使用:

  • compdef
  • compadd

My example:我的例子:

# 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

Source: My code https://github.com/reduardo7/bashx来源:我的代码https://github.com/reduardo7/bashx

@JatinKumar's answer got me on the right track, but I had to use complete instead of source . @JatinKumar 的回答让我走上了正确的道路,但我不得不使用complete而不是source So all together:所以大家一起:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM