¿Cómo obtengo la finalización de bash para los alias de comando?

57

Estoy buscando obtener la finalización de tabulación en mis alias de línea de comandos, por ejemplo, digamos que definí el siguiente alias:

alias apt-inst='sudo aptitude install'

¿Hay alguna forma de obtener las finalizaciones proporcionadas por aptitude cuando presiono la tecla tab? es decir, cuando escribo 'sudo aptitude install gnumer' y presiono tab, aptitude completa esto en gnumeric, o si hubo incertidumbre, enumera todos los paquetes disponibles que comienzan con gnumer. Si lo hago usando mi alias, nada, sin completar.

levesco
fuente

Respuestas:

30

Hay un gran hilo sobre esto en los foros de Ubuntu . Ole J propone la siguiente función de definición de finalización de alias:

function make-completion-wrapper () {
  local function_name="$2"
  local arg_count=$(($#-3))
  local comp_function_name="$1"
  shift 2
  local function="
    function $function_name {
      ((COMP_CWORD+=$arg_count))
      COMP_WORDS=( "$@" \${COMP_WORDS[@]:1} )
      "$comp_function_name"
      return 0
    }"
  eval "$function"
  echo $function_name
  echo "$function"
}

Úselo para definir una función de finalización para su alias, luego especifique esa función como completadora para el alias:

make-completion-wrapper _apt_get _apt_get_install apt-get install
complete -F _apt_get_install apt-inst

Prefiero usar alias para agregar argumentos siempre usados ​​a los programas existentes. Por ejemplo, con grep, siempre quiero omitir dispositivos y archivos binarios, así que hago un alias para grep. Para agregar nuevos comandos como grepbin, utilizo un script de shell en mi ~/bincarpeta. Si esa carpeta está en su camino, se completará automáticamente.

Shawn J. Goff
fuente
2
Impresionante, tenía miedo de que no fuera posible.
levesque
Tenga en cuenta que este código tiene algunos problemas. Vea mi respuesta para su explicación y resolución.
Tom Hale
Nota: Estaba usando esta técnica para otro comando, y tuve que usar en complete -o default -F ...lugar de complete -F ...hacer que cosas como la finalización automática del nombre de archivo funcionaran correctamente al pasar args (Bash 4.3.46).
joelittlejohn
28

Pruebe complete-alias , que resuelve este problema exactamente.

Después de instalarlo, puede usar una función genérica para completar muchos alias como este:

complete -F _complete_alias <myalias1>
complete -F _complete_alias <myalias2>
complete -F _complete_alias <myalias3>

Es posible que desee obtener el archivo complete_alias en cada instancia de bash a través de .bash_profileo similar.

instalación

mkdir ~/.bash_completion.d
curl https://raw.githubusercontent.com/cykerway/complete-alias/master/bash_completion.sh \
     > ~/.bash_completion.d/complete_alias

solicitud

source ~/.bash_completion.d/complete_alias

alias container=docker\ container
complete -F _complete_alias container

containerahora puede ser completado automáticamente por el _docker()controlador de finalización original ;

$ container l<Tab>
logs  ls    

$ container s<Tab>
start  stats  stop   
Cyker
fuente
2
Dado que este software parece ser tuyo, podrías hacerlo mejor que esto. Agregue instrucciones para instalarlo. Describa lo que hace y cómo usarlo. De lo contrario, esto es solo spam.
muru
@muru Estaba pensando en pegar algún código aquí, pero probablemente sea más largo de lo aceptado aquí. Supongo que las personas no tienen problemas para leer la sección Instalar en un archivo README, y en este caso son solo varias líneas.
Cyker
2
el punto es poder juzgar si vale la pena visitar dicho README, solo por la respuesta.
muru
Esta es una respuesta adecuada y resuelve el problema exactamente.
Ярослав Рахматуллин
1
Esta es una respuesta excelente y muy completa que funciona perfectamente, ¡gracias! Probablemente se haya actualizado ya que @muru tuvo problemas con él.
Brian Topping
3

Respuesta 2018

Debe agregar su alias al programa 'completo'. Dependiendo del tipo de autocompletado que desee lograr, debe usar -c o -F.

Para autocompletar paquetes:

complete -c name_of_your_alias

Para el autocompletado de comandos:

complete -F name_of_your_alias

Para verificar si su alias se agregó correctamente:

complete | grep name_of_your_alias

Finalmente, para eliminar un alias de 'complete':

complete -r name_of_your_alias

En tu caso:

complete -c apt-inst
Adrián López
fuente
1
Por favor no continúe su respuesta en los comentarios. Si tiene cosas que decir, edítelas en la respuesta.
G-Man dice 'Restablecer a Monica'
2
complete -F xxxno funciona en OSX (solo muestra el uso complete: usage: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]). ¿Tienes algún puntero? Gracias.
Anthony Kong
Use esto en su lugar: unix.stackexchange.com/questions/224227/…
Rich
2

Aquí está el código de la respuesta de Shawn J. Goff con algunas mejoras:

  • Se corrigieron los errores de sintaxis resaltados por shell-check, por ejemplo, el primero "de "$@"hecho terminó la cadena de definición de función.
  • Se eliminó return 0para que el valor de retorno de la función subyacente se pueda devolver al llamador.

.

# Wraps a completion function, eg for use with an alias.
# Usage:
# make-completion-wrapper <actual completion function> <name of new func.>
#                         <command name> <list supplied arguments>
# eg.
#   alias agi='apt-get install'
#   make-completion-wrapper _apt_get _apt_get_install apt-get install
#     # defines a function called _apt_get_install (that's $2) that will
#     # complete the 'agi' alias. 
#   complete -F _apt_get_install agi
function make-completion-wrapper {
  local function_name="$2"
  local arg_count=$(( $#-3 ))
  local comp_function_name="$1"
  shift 2
  local function="function $function_name {
      (( COMP_CWORD += $arg_count ))
      COMP_WORDS=( \"\$@\" \${COMP_WORDS[@]:1} )
      \"$comp_function_name\"
    }"
  eval "$function"
  # echo "$function"
}
export -f make-completion-wrapper
Tom Hale
fuente
No me funciona en Bash 4.3.46, me temo. La respuesta de Shaun J. Goff hace el trabajo.
joelittlejohn
1
"Finalizar" la cadena de definición de función es a propósito; el punto es incluir argumentos de la función externa en la COMP_WORDSmatriz. Si usamos make-completion-wrapper _apt_get _apt_get_install apt-get installcomo ejemplo, después shift 2, $@contiene apt-get install. La definición de la función incluye apt-get install(las dos palabras literales) al asignar COMP_WORDS.
Jeffery al
0

Como una extensión de la respuesta @Giles, la siguiente función de conveniencia nombra automáticamente el contenedor generado por make-completion-wrapperpara permitir definir la finalización en una línea:

function complete-alias  {
    # uses make-completion-wrapper: https://unix.stackexchange.com/a/4220/50978
    # example usage
    # complete-alias _pass pshow pass show
    # complete-alias _pass pgen pass generate

    EXISTING_COMPLETION_FN=${1} && shift
    ALIAS=${1} && shift
    AUTOGEN_COMPLETION_FN="__autogen_completion_${ALIAS}"
    make-completion-wrapper ${EXISTING_COMPLETION_FN} ${AUTOGEN_COMPLETION_FN} ${*}
    complete -F ${AUTOGEN_COMPLETION_FN} ${ALIAS}
}
user84207
fuente