Um script de conclusão de tabulação Bash pode ser usado em zsh?


87

Eu tenho um script de conclusão de tabulação Bash para o Hadoop do Apache. Normalmente, eu uso zsh como meu shell do dia-a-dia. Tende a ser bem parecido com o bash quando preciso, mas parece que os sistemas de preenchimento de tabulação são radicalmente diferentes entre eles. Existe uma maneira simples de "converter" as definições de conclusão de tabulação bash existentes para trabalhar em zsh? Não quero investir muito tempo nisso, mas se for fácil, economizaria um pouco de esforço.

Respostas:


39

A partir desta página (datado de 2010/01/05):

Zsh pode lidar com funções de completação de bash. A última versão de desenvolvimento do zsh tem uma função bashcompinit que, quando executada, permite que o zsh leia as especificações e funções de conclusão do bash. Isso está documentado na página do manual zshcompsys. Para usá-lo, tudo o que você precisa fazer é executar bashcompinit a qualquer momento após o compinit. Ele irá definir funções completas e compgen correspondentes aos builtins do bash.


A boa notícia: acho que isso deve funcionar, então muito obrigado. A má notícia: por algum motivo, o sistema no qual estou tentando fazer isso não parece carregar / etc / zshrc quando eu logo via SSH. Não sei o suficiente sobre o processo de login para dizer por que isso acontece. Talvez seja hora de fazer outra pergunta ...
Coderer

1
@Coderer: Em primeiro lugar, você diz "/ etc / zshrc". No meu sistema, é /etc/zsh/zshrc. Além disso, verifique os seguintes arquivos na ordem inversa (listados na ordem em que são originados durante a inicialização zsh): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofilee $ZDOTDIR/.zprofile(provavelmente ~/.zprofile) para ver se a RCSvariável está em branco. Se for, isso evitaria que os arquivos subsequentes após o arquivo no qual ele não foi definido sejam originados. Finalmente, verifique o shell para o usuário /etc/passwde certifique- zshse de que ele não tenha um -fargumento.
Pausado até novo aviso.

Obrigado por todos os comentários - eu recorri ao hack clássico do programador nº 1, "stdout debugging" (declarações de eco em cada script de inicialização) e encontrei o problema. Por alguma razão, nosso / etc / zprofile estava terceirizando os vários scripts /etc/profile.d, que estavam sendo fornecidos novamente em / etc / zshrc. Simplesmente mover as instruções de carregamento automático para o topo de / etc / zprofile corrigiu o problema.
Coderer

154
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file

9
Esta é a melhor resposta, pois diz a você como usar o bashcompinit. Bom trabalho.
pyrospade de

5
Obrigado, ótima resposta, infelizmente isso não funciona se o script usar o comando bash _init_completion.
0fnt de

5
Isso não funcionou para mim. Eu ainda estava recebendo complete:13: command not found: compdeferros.
Jatin Kumar

Se não funcionar, verifique o script (doh :)) - pode haver uma if is-bashmarca de seleção na parte superior.
olejorgenb

Isso não funciona para alguns scripts usando o _get_comp_words_by_refque não é definido por bashcompinit. A maioria das conclusões não usa esta função.
Franklin Yu

38
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Estou executando o zsh zsh 5.0.2 (x86_64-apple-darwin13.0) sem nenhum ~ / .zshrc e a sequência acima funcionou em um shell zsh recém-gerado.

Agradecimentos ao script git-completed.bash pela dica: D


Continue lendo para mais detalhes nas 3 linhas acima:

O Bash possui um suporte de preenchimento automático incrível, mas os scripts de preenchimento automático bash não funcionam diretamente zsh, pois o ambiente zsh não possui as funções auxiliares de preenchimento automático bash essenciais compgen, como complete,. Ele faz isso em um esforço para manter a sessão zsh rápida.

Atualmente, o zsh é fornecido com scripts de preenchimento apropriados, como compinite bashcompinitque têm as funções necessárias para oferecer suporte a scripts de preenchimento automático do bash.

autoload <func_name>: Observe que o autoload é definido em zsh e não em bash. autoloadprocura um arquivo nomeado nos caminhos de diretório retornados pelo fpathcomando e marca uma função para carregar a mesma quando for chamada pela primeira vez.

  • -U: ignora quaisquer aliases ao carregar uma função como compinit ou bashcompinit
  • + X: Basta carregar a função nomeada fow agora e não executá-la

Por exemplo, em meu sistema, os echo $fpathretornos /usr/share/zsh/site-functionse /usr/share/zsh/5.0.5/functionse ambos compinite bashcompinitestão disponíveis em /usr/share/zsh/5.0.5/functions.

Além disso, para a maioria das pessoas, ele só autoload -U +X bashcompinit && bashcompinité necessário porque algum outro script, como git autocomplete ou o seu próprio, ~/.zshrcpode estar fazendo autoload -U +X compinit && compinit, mas é seguro executar os dois.


O que são -Ue +Xpara quê?
jmk

Resposta atualizada com mais detalhes.
Jatin Kumar

6
Isso ainda faz pouco sentido; a página de manual descreve o ponto de +X foofazer o mesmo carregamento automático apenas invocando foo, mas sem executá-lo imediatamente ... então autoload +X foo && fooparece completamente redundante. Você pode explicar por que escolheu esse padrão?
ELLIOTTCABLE

1
@ELLIOTTCABLE O objetivo autoload -U +X bashcompinit && bashcompinité que (devido ao &&) ele executará o bashcompinitIFF se o módulo for realmente encontrado. Normal autoload foosempre retorna verdadeiro. Mais tarde, quando você tenta executar foo, em seguida, zsh, finalmente, lhe diz "arquivo de definição de função não encontrado". Com autoload +Xvocê obtém o erro imediatamente.
FeRD

1
A página do manual ainda não está clara nesse ponto, me parece: autoload +Xcarrega a função sem executá-la - o que é mais do que autoloadfaz, sem +X. Sem +X, o autoload nem mesmo carrega a função; Ele apenas marca o nome como uma referência a uma função a ser carregada posteriormente. O carregamento real não é tentado até que a função seja chamada pela primeira vez. Se você deseja determinar se a função nomeada carrega com sucesso , você precisa usar +Xpara executar a etapa de carregamento imediatamente.
FeRD de

4

Para zshuso:

  • compdef
  • compadd

Meu exemplo:

# 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

Fonte: Meu código https://github.com/reduardo7/bashx


1
Você deve divulgar que é o autor da estrutura bashx vinculada.
Ben

4

Estou executando o Antigen como gerenciador de plug-ins Oh-My-Zsh. Eu tinha alguns scripts de conclusão do bash escritos por colegas de trabalho que queria carregar no Zsh com um simples source /path/to/completion.

Tive alguns problemas, porque parece que o Antigen ou o OMZ (difícil de dizer) se preocupam apenas em carregar scripts de conclusão de seus plug-ins. Eu finalmente resolvi isso com o carregamento automático bashcompinit e compinit depois antigen apply. Simplesmente o carregamento automático bashcompinitnão era suficiente.

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 cria seu .zcompdumparquivo no $ANTIGEN_COMPDUMPqual para mim foi~/.antigen/.zcompdump

A nova chamada de compinit e bashcompinit cria um segundo .zcompdump em $HOME/.zcompdump

Isso parece a todo o trabalho fora, porque eu sou capaz de usar as conclusões estabelecidas por /path/to/bash_completion. Excluí os dois arquivos .zcompdump algumas vezes para ter certeza de que eles foram regenerados e parecem funcionar.

Tive que rm os arquivos .zcompdump algumas vezes após a reinicialização da máquina por causa de erros gerados ao tentar concluir a tabulação, mas não tenho certeza se isso é devido a esta configuração ou outra coisa. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPe um novo shell corrige isso para mim.

Versões usadas no momento da escrita:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.