Cuando uso el programa like svn
y escribo en Gnome Terminal:
svn upd
y presiona Tabse autocompleta para:
svn update
¿Es posible hacer algo así en mi script bash personalizado?
Cuando uso el programa like svn
y escribo en Gnome Terminal:
svn upd
y presiona Tabse autocompleta para:
svn update
¿Es posible hacer algo así en mi script bash personalizado?
Respuestas:
Puede usar la finalización programable . Mira /etc/bash_completion
y /etc/bash_completion.d/*
para algunos ejemplos.
/usr/share/bash-completion/completions/<program>
The provided link has that already
- Podría ser hoy, pero podría no ser mañana. O el año que viene. O en una década. Independientemente de lo que sugiera sobre la documentación que sigue siendo relevante, Stack Overflow desalienta las respuestas de solo enlace por estos motivos.
Llego seis meses tarde pero estaba buscando lo mismo y encontré esto:
Tendrás que crear un nuevo archivo:
/etc/bash_completion.d/foo
Para un autocompletado estático ( --help
/ --verbose
por ejemplo) agregue esto:
_foo()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--help --verbose --version"
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _foo foo
COMP_WORDS
es una matriz que contiene todas las palabras individuales en la línea de comando actual.COMP_CWORD
es un índice de la palabra que contiene la posición actual del cursor.COMPREPLY
es una variable de matriz desde la cual Bash lee las posibles terminaciones.Y el compgen
comando devuelve la matriz de elementos de --help
, --verbose
y --version
coinciden con la palabra actual "${cur}"
:
compgen -W "--help --verbose --version" -- "<userinput>"
-
y mostrarlas sin tener que comenzar a escribir la palabra objetivo, simplemente elimine las líneas if [...] then
y fi
.
/etc/bash_completion.d/
. Solo vine aquí porque quería publicar una respuesta en alguna parte, pero resultó que alguien tenía tres años de ventaja todo el tiempo :) Ejemplo claro, conciso y completo, ¡gracias!
Todas las terminaciones de bash se almacenan en /etc/bash_completion.d/
. Entonces, si está creando software con bash_completion, valdría la pena que deb / make install suelte un archivo con el nombre del software en ese directorio. Aquí hay un script de finalización de bash de ejemplo para Rsync:
# bash completion for rsync
have rsync &&
_rsync()
{
# TODO: _split_longopt
local cur prev shell i userhost path
COMPREPLY=()
cur=`_get_cword`
prev=${COMP_WORDS[COMP_CWORD-1]}
_expand || return 0
case "$prev" in
--@(config|password-file|include-from|exclude-from))
_filedir
return 0
;;
-@(T|-temp-dir|-compare-dest))
_filedir -d
return 0
;;
-@(e|-rsh))
COMPREPLY=( $( compgen -W 'rsh ssh' -- "$cur" ) )
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-v -q -c -a -r -R -b -u -l -L -H \
-p -o -g -D -t -S -n -W -x -B -e -C -I -T -P \
-z -h -4 -6 --verbose --quiet --checksum \
--archive --recursive --relative --backup \
--backup-dir --suffix= --update --links \
--copy-links --copy-unsafe-links --safe-links \
--hard-links --perms --owner --group --devices\
--times --sparse --dry-run --whole-file \
--no-whole-file --one-file-system \
--block-size= --rsh= --rsync-path= \
--cvs-exclude --existing --ignore-existing \
--delete --delete-excluded --delete-after \
--ignore-errors --max-delete= --partial \
--force --numeric-ids --timeout= \
--ignore-times --size-only --modify-window= \
--temp-dir= --compare-dest= --compress \
--exclude= --exclude-from= --include= \
--include-from= --version --daemon --no-detach\
--address= --config= --port= --blocking-io \
--no-blocking-io --stats --progress \
--log-format= --password-file= --bwlimit= \
--write-batch= --read-batch= --help' -- "$cur" ))
;;
*:*)
# find which remote shell is used
shell=ssh
for (( i=1; i < COMP_CWORD; i++ )); do
if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then
shell=${COMP_WORDS[i+1]}
break
fi
done
if [[ "$shell" == ssh ]]; then
# remove backslash escape from :
cur=${cur/\\:/:}
userhost=${cur%%?(\\):*}
path=${cur#*:}
# unescape spaces
path=${path//\\\\\\\\ / }
if [ -z "$path" ]; then
# default to home dir of specified
# user on remote host
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi
# escape spaces; remove executables, aliases, pipes
# and sockets; add space at end of file names
COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/ /\\\\\\\ /g' -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' ) )
fi
;;
*)
_known_hosts_real -c -a "$cur"
_filedir
;;
esac
return 0
} &&
complete -F _rsync $nospace $filenames rsync
# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh
Probablemente valdría la pena revisar uno de los archivos de finalización de bash que más se ajuste a su programa. Uno de los ejemplos más simples es el rrdtool
archivo.
source ~/.local/mycrazycompletion
en tu~/.bashrc
pkg-c
onfig --variable = completionsdir bash-completar` y ese directorio es la recomendación dada por las preguntas frecuentes de finalización de Bash vinculadas anteriormente.
Aquí hay un tutorial completo.
Tengamos un ejemplo de script llamado admin.sh en el que le gustaría tener el autocompletado funcionando.
#!/bin/bash
while [ $# -gt 0 ]; do
arg=$1
case $arg in
option_1)
# do_option_1
;;
option_2)
# do_option_1
;;
shortlist)
echo option_1 option_2 shortlist
;;
*)
echo Wrong option
;;
esac
shift
done
Opción de nota lista corta. Al llamar al script con esta opción, se imprimirán todas las opciones posibles para este script.
Y aquí tienes el script de autocompletar:
_script()
{
_script_commands=$(/path/to/your/script.sh shortlist)
local cur
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "${_script_commands}" -- ${cur}) )
return 0
}
complete -o nospace -F _script ./admin.sh
Tenga en cuenta que el último argumento para completar es el nombre del script al que desea agregar autocompletado. Todo lo que necesita hacer es agregar su secuencia de comandos de autocompletar a bashrc como
source /path/to/your/autocomplete.sh
o cópielo a /etc/bash.completion.d
prev
variable? Parece que no lo usas.
-o nospace
opción?
Si todo lo que desea es un autocompletado basado en palabras (para que no se complete el subcomando ni nada), el complete
comando tiene una -W
opción que simplemente hace lo correcto.
Por ejemplo, tengo las siguientes líneas en mi .bashrc
para completar automáticamente un programa llamado jupyter :
# gleaned from `jupyter --help`
_jupyter_options='console qtconsole notebook' # shortened for this answer
complete -W "${_jupyter_options}" 'jupyter'
Ahora se jupyter <TAB> <TAB>
autocompleta para mí.
Los documentos en gnu.org son útiles.
Parece depender de que la IFS
variable se configure correctamente, pero eso no me ha causado ningún problema.
Para agregar la finalización del nombre de archivo y la finalización predeterminada de BASH, use la -o
opción:
complete -W "${_jupyter_options}" -o bashdefault -o default 'jupyter'
Para usar esto en zsh, agregue el siguiente código antes de ejecutar el complete
comando en su ~/.zshrc
:
# make zsh emulate bash if necessary
if [[ -n "$ZSH_VERSION" ]]; then
autoload bashcompinit
bashcompinit
fi
bash jupyter <TAB><TAB>
?