¿Se puede utilizar un script de finalización de tabulación de Bash en zsh?

87

Tengo un script de finalización de pestañas Bash para Hadoop de Apache. Normalmente, uso zsh como mi caparazón diario. Tiende a ser bastante parecido a un bash cuando lo necesito, pero parece que los sistemas de finalización de pestañas son radicalmente diferentes entre ellos. ¿Existe una forma sencilla de "convertir" las definiciones existentes de bash-tab-complete para que funcionen en zsh? No quiero invertir mucho tiempo en esto, pero si es fácil, ahorraría una cantidad moderada de esfuerzo.

Coderer
fuente

Respuestas:

39

De esta página (con fecha 05/01/2010):

Zsh puede manejar funciones de finalización de bash. La última versión de desarrollo de zsh tiene una función bashcompinit, que cuando se ejecuta permitirá a zsh leer las especificaciones y funciones de finalización de bash. Esto está documentado en la página de manual de zshcompsys. Para usarlo, todo lo que necesita hacer es ejecutar bashcompinit en cualquier momento después de compinit. Definirá funciones completas y compgen correspondientes a las incorporaciones de bash.

Pausado hasta nuevo aviso.
fuente
La buena noticia: creo que esto debería funcionar, así que muchas gracias. La mala noticia: por alguna razón, el sistema en el que estoy tratando de lograr esto no parece cargar / etc / zshrc cuando inicio sesión a través de SSH. No sé lo suficiente sobre el proceso de inicio de sesión como para decir por qué es así. Quizás sea hora de hacer otra pregunta ...
Coderer
1
@Coderer: Primero que nada, dices "/ etc / zshrc". En mi sistema, lo es /etc/zsh/zshrc. Además, verifique los siguientes archivos en orden inverso (enumerados en el orden en que se han obtenido durante el inicio zsh): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofiley $ZDOTDIR/.zprofile(probablemente ~/.zprofile) para ver si la RCSvariable está desactivada. Si es así, evitaría que los archivos subsiguientes después del archivo en el que está desarmado se obtengan. Finalmente, verifique el shell para el usuario /etc/passwdy asegúrese de que sea zshy asegúrese de que no tenga un -fargumento.
Pausado hasta nuevo aviso.
Gracias por todos los comentarios: recurrí al truco de programador clásico n. ° 1, "depuración estándar" (declaraciones de eco en cada script de inicio) y encontré el problema. Por alguna razón, nuestro / etc / zprofile estaba obteniendo los diversos scripts /etc/profile.d, que luego se obtenían nuevamente en / etc / zshrc. Simplemente moviendo las declaraciones de carga automática a la parte superior de / etc / zprofile solucionó el problema.
Coderer
157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
freestyler
fuente
10
Esta es la mejor respuesta, ya que le dice cómo usar bashcompinit. Buen trabajo.
Pyrospade
5
Gracias, gran respuesta, desafortunadamente esto no funciona si el script usa el comando _init_completion bash.
0fnt
6
Esto no funcionó para mí. Todavía recibía un complete:13: command not found: compdeferror.
Jatin Kumar
Si no funciona, verifique el script (doh :)); puede que tenga una if is-bashmarca en la parte superior.
olejorgenb
Esto no funciona para algunos scripts _get_comp_words_by_refque no están definidos por bashcompinit. Sin embargo, la mayoría de las terminaciones no usan esta función.
Franklin Yu
39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Estoy ejecutando zsh zsh 5.0.2 (x86_64-apple-darwin13.0) sin ~ / .zshrc y la secuencia anterior funcionó en un shell zsh recién generado.

Gracias al script git-completation.bash por la pista: D


Siga leyendo para obtener más detalles sobre las 3 líneas anteriores:

Bash tiene impresionantes en apoyo finalización automática incorporada, pero los scripts Bash autocompletar no trabajan directamente zsh zsh como el medio ambiente no tiene la función de autocompletar de bash esenciales funciones auxiliares como compgen, complete. Lo hace en un esfuerzo por mantener rápida la sesión de zsh.

En estos días, zsh se envía con scripts de finalización apropiados como compinity bashcompinitque tienen las funciones necesarias para admitir scripts de autocompletar bash.

autoload <func_name>: Tenga en cuenta que la carga automática se define en zsh y no en bash. autoloadbusca un archivo nombrado en las rutas de directorio devueltas por el fpathcomando y marca una función para cargar el mismo cuando se invoca por primera vez.

  • -U: ignore cualquier alias al cargar una función como compinit o bashcompinit
  • + X: Simplemente cargue la función nombrada ahora y no la ejecute

Por ejemplo, en mi sistema echo $fpathdevuelve /usr/share/zsh/site-functionsy /usr/share/zsh/5.0.5/functionsy ambos compinity bashcompinitestán disponibles en /usr/share/zsh/5.0.5/functions.

Además, para la mayoría de las personas, es posible que solo autoload -U +X bashcompinit && bashcompinitsea ​​necesario porque algún otro script como git autocomplete o el suyo propio ~/.zshrcpueden estar funcionando autoload -U +X compinit && compinit, pero es seguro ejecutar ambos.

Jatin Kumar
fuente
¿Qué son -Uy +Xpara qué?
jmk
Respuesta actualizada con más detalles.
Jatin Kumar
6
Esto todavía tiene poco sentido; la página de manual describe el objetivo de +X foohacer la misma carga automática, simplemente invocando foo, pero sin ejecutarla inmediatamente ... así que autoload +X foo && fooparece completamente redundante. ¿Puede explicar por qué eligió este patrón?
ELLIOTTCABLE
2
@ELLIOTTCABLE El objetivo autoload -U +X bashcompinit && bashcompinites que (debido a &&) ejecutará bashcompinitIFF, el módulo se encuentra realmente. Normal autoload foosiempre devuelve verdadero. Más tarde, cuando se intenta ejecutar foo, a continuación, zsh finalmente le dice "archivo de definición de función no encontrado". Con autoload +Xobtienes el error de inmediato.
Ferd
1
La página de manual todavía no está clara en ese punto, me parece: autoload +Xcarga la función sin ejecutarla, que es más de autoloadlo que hace, sin +X. Sin +X, la carga automática ni siquiera carga la función; Simplemente marca el nombre como una referencia a una función que se cargará más tarde. La carga real no se intenta hasta que se invoca la función por primera vez. Si desea determinar si la función nombrada se carga correctamente , debe utilizar +Xpara realizar el paso de carga inmediatamente.
2019
4

Para zshuso:

  • compdef
  • compadd

Mi ejemplo:

# 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

Fuente: Mi código https://github.com/reduardo7/bashx

Eduardo Cuomo
fuente
1
Debe revelar que es el autor del marco bashx vinculado.
Ben
4

Estoy ejecutando Antigen como administrador de complementos Oh-My-Zsh. Tenía algunos scripts de finalización de bash escritos por compañeros de trabajo que quería cargar en Zsh con un simple source /path/to/completion.

Tuve algunos problemas, porque parece que Antigen u OMZ (difícil de decir) se preocupan solo por cargar scripts de finalización desde sus complementos. Finalmente logré solucionar esto mediante la carga automática bashcompinit y compinit después antigen apply. La simple carga automática bashcompinitno fue 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 crea su .zcompdumparchivo en el $ANTIGEN_COMPDUMPque para mí estaba~/.antigen/.zcompdump

La re-invocación de compinit y bashcompinit crea un segundo .zcompdump en $HOME/.zcompdump

Eso parece a cabo todo el trabajo, porque soy capaz de utilizar las terminaciones creados por /path/to/bash_completion. He eliminado ambos archivos .zcompdump varias veces para asegurarme de que se regeneren y parezcan funcionar.

Tuve que rm los archivos .zcompdump varias veces después de reiniciar la máquina debido a errores lanzados al intentar completar la pestaña, pero no estoy seguro de si eso se debe a esta configuración o algo más. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPy un nuevo caparazón me lo arregla.

Versiones utilizadas al momento de escribir:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Walter Wilfinger
fuente
0

La respuesta de @JatinKumar me puso en el camino correcto, pero tuve que usar en completelugar de source. Así que todos juntos:

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
jschmitter
fuente