- Introducción a cómo implementar una función de autocompletación con tabulador en Bash y Zsh que muestra descripciones incluso para palabras ya completadas
- Bash y Zsh usan APIs de autocompletación distintas, y solo Zsh ofrece por defecto la función de mostrar descripciones en la autocompletación
- Se implementa una estructura que genera candidatos con
_generate_foo_completionsy los devuelve conCOMPREPLYen Bash ycompadden Zsh - Para implementar en Bash la función de descripciones de Zsh, se incluyen las descripciones en las cadenas candidatas y solo se eliminan cuando hay un único candidato
- Incluso cuando hay un solo candidato, se mejora el comportamiento agregando ambigüedad intencionalmente para que al presionar
<TAB>se muestre la descripción - El script final ofrece la misma experiencia de usuario en ambos shells y soporta completado parcial, completado total y visualización de descripciones de candidatos
Contexto del problema
- La autocompletación con tabulador (tab-completion) es útil para explorar comandos o flags, y ayuda especialmente cuando se usa por primera vez una API o una herramienta CLI
- Zsh por defecto solo muestra descripciones cuando hay varios candidatos, y Bash solo puede hacerlo mediante configuración adicional
- Sin embargo, para una palabra ya completada, ninguno de los dos shells muestra descripciones
- Por eso, para ver una descripción, el usuario debe pasar por un proceso incómodo como este
- borrar algunos caracteres para que coincidan varios candidatos
- presionar la tecla
<TAB>para revisar la lista de candidatos - buscar visualmente la descripción deseada
- volver a escribir los caracteres eliminados para ejecutar el comando
Resumen de la solución
- Incluso cuando hay un solo candidato, se agrega un candidato ficticio (dummy completion) para volver ambigua la lista
- De este modo, tanto Bash como Zsh muestran la lista de candidatos junto con sus descripciones
- Eso sí, hay que evitar que el texto de la descripción se inserte en el comando real
Conceptos básicos
- La autocompletación con tabulador funciona recibiendo la palabra actual y la posición del cursor al presionar
<TAB>, y devolviendo una lista de candidatos posibles - Bash: asigna los candidatos al arreglo
COMPREPLY - Zsh: registra los candidatos con el comando
compadd - La función
_generate_foo_completionsimprime cadenas candidatas, y en un caso real puede generarlas dinámicamente según el estado del CLI
Soporte simultáneo para Bash y Zsh
- Se implementa para cada shell con las funciones
_complete_foo_bashy_complete_foo_zsh - Se distingue con
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi - El usuario aplica el script registrándolo en
.bashrco.zshrc
Mostrar descripciones en Zsh
- Se usa el formato
nombre: descripciónen las cadenas candidatas - Zsh:
compadd -d raw -- $trimmedpara pasar nombre y descripción como arreglos paralelos - Bash: solo se pasan a
COMPREPLYlos candidatos sin la parte de la descripción (por defecto no soporta descripciones)
Implementar descripciones en Bash
- Cuando hay varios candidatos, se muestran tal cual las cadenas que incluyen la descripción
- Cuando hay un solo candidato, solo entonces se elimina la descripción
- Se aprovecha el comportamiento de autocompletación de Bash, que inserta solo el prefijo común, para evitar que la descripción forme parte de la entrada real
Mostrar descripciones incluso con un solo candidato
- Para mostrar la descripción incluso al presionar
<TAB>sobre una palabra ya completada, se agrega un candidato ficticio que introduce ambigüedad - Zsh: se agrega el candidato ficticio tanto a los dos arreglos paralelos (
raw,trimmed) - Bash: cuando hay un solo candidato, se agrega solo el nombre a
trimmed
Resultado final
- Con varios candidatos, se muestran tanto el nombre como la descripción
- Incluso con un solo candidato, la descripción puede verse con
<TAB> - Bash y Zsh ofrecen la misma experiencia
- Ejemplo de uso:
$ foo <TAB> apple: a common fruit banana: starchy and high in potassium apricot: sour fruit... cherry: small and sweet...
1 comentarios
Opiniones en Hacker News
fish_update_completions~/.cache/fish/generated_completions/curlcon-L→ 'Follow redirects',-O→ 'Write output to file named as remote file'car TABse expande ablkdiscard, porque eso falla incluso si cargo no está en el PATH--help, me pregunto si fish tiene algo como_gnu_genericde zsh ocomplete -F _longoptde bashzypper search fish-completion, salen más de 200 paquetes, así que sentí que algo andaba rarocomplete-filename, enlazada a M-/, que completan solo nombres de archivo ignorando el contextolsy luego cambiando el comandocomplete -rse comporta como quiero, parece que el problema está en los scripts de bash-completion$fpathquedan en caché y mejora la velocidad de inicioargparsey páginas manargparsede scripts fish, pero es muchísimo mejor que optparse_gnu_genericpermite un completado simple basado en--help--generatede ripgrep y la generación de completado en tiempo de ejecución de PHP Symfony--completionque las bibliotecas parser comunes implementen automáticamentecomplete_kill_1, obtienes completado para el primer argumento del comandokillset-java-home, usar_describepara completar por versión la lista de~/apps/java/*