¿Se puede usar un script de finalización de pestaña Bash en zsh?
tab-completion (5)
Tengo una secuencia de comandos de finalización de la pestaña Bash para Hadoop de Apache. Normalmente, uso zsh como mi shell del día a día. Tiende a ser bastante bash cuando necesito que lo sea, pero parece que los sistemas de finalización de pestañas son radicalmente diferentes entre ellos. ¿Existe una forma sencilla de "convertir" las definiciones de finalización de bash-tab existentes para que funcionen en zsh? No quiero invertir mucho tiempo en esto, pero si fuera fácil, ahorraría un esfuerzo moderado.
A partir de esta página (fechada el 2010/01/05):
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 del 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 los componentes bash.
Estoy ejecutando Antigen como administrador de complementos Oh-My-Zsh. Tuve algunos scripts de finalización de bash escritos por compañeros de trabajo que quería cargar en Zsh con una source /path/to/completion
simples.
Tuve algunos problemas, porque parece que tanto Antigen como OMZ (difícil de decir) se preocupan de solo cargar los scripts de finalización de sus complementos. Finalmente bashcompinit
esto al bashcompinit
automáticamente bashcompinit
y compinit
después de antigen apply
. Simplemente bashcompinit
no 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 crea su archivo .zcompdump
en $ANTIGEN_COMPDUMP
que para mí era ~/.antigen/.zcompdump
La reinvención de compinit y bashcompinit crea un segundo .zcompdump en $HOME/.zcompdump
Parece que todo funciona, porque soy capaz de usar las terminaciones configuradas por /path/to/bash_completion
. He eliminado ambos archivos .zcompdump un par de veces para asegurarme de que estén regenerados y que parece que funcionan.
Tuve que reiniciar los archivos .zcompdump varias veces después de reiniciar la máquina debido a los errores que se produjeron al intentar completar la pestaña, pero no estoy seguro de que se deba a esta configuración o algo más. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMP
y un nuevo shell lo corrige para mí.
Versiones usadas al momento de escribir:
Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Para uso zsh
:
-
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
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 ningún ~ / .zshrc y la secuencia anterior funcionó en una shell zsh recién creada.
Gracias a la secuencia de comandos git-completed.bash por la sugerencia: D
Lectura para más detalles sobre las 3 líneas anteriores:
Bash tiene un impresionante soporte de autocompletado incorporado, pero los scripts de autocompletado de bash no funcionan directamente zsh, ya que el entorno zsh no tiene las funciones de ayuda de autocompletado de bash esenciales como compgen
, complete
. Lo hace en un esfuerzo por mantener la sesión zsh rápida.
En estos días, zsh se entrega con los scripts de finalización adecuados, como compinit
y bashcompinit
que tienen las funciones necesarias para admitir los scripts de autocompletado de bash.
autoload <func_name>
: autoload <func_name>
cuenta que autoload está definido en zsh y no en bash. autoload
busca un archivo nombrado en las rutas de directorio devueltas por el comando fpath
y marca una función para cargarlo cuando se invoca por primera vez.
- -U: ignora cualquier alias al cargar una función como compinit o bashcompinit
- + X: Simplemente carga la función nombrada ahora y no la ejecutes
Por ejemplo, en mi sistema echo $fpath
devuelve /usr/share/zsh/site-functions
y /usr/share/zsh/5.0.5/functions
y compinit
y bashcompinit
están disponibles en /usr/share/zsh/5.0.5/functions
.
También para la mayoría de las personas puede ser que solo se requiera autoload -U +X bashcompinit && bashcompinit
se requiere porque algún otro script como git autocompletar o su propio ~/.zshrc
puede estar haciendo la autoload -U +X compinit && compinit
, pero es seguro ejecutar ambos de ellos.
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file