Comment puis-je obtenir l'achèvement de bash pour les alias de commande?

57

Je cherche à obtenir la complétion par tabulation sur mes alias de ligne de commande, par exemple, disons que j'ai défini l'alias suivant:

alias apt-inst='sudo aptitude install'

Existe-t-il un moyen d'obtenir les finitions fournies par aptitude lorsque je frappe la touche de tabulation? C'est-à-dire que lorsque j'écris 'sudo aptitude install gnumer' et que je clique sur onglet, aptitude complète ceci en gnumeric, ou s'il y avait une incertitude, liste tous les paquetages disponibles commençant par gnumer. Si je le fais en utilisant mon alias, rien - pas de complétion.

levesque
la source

Réponses:

30

Il existe un excellent fil à ce sujet sur les forums Ubuntu . Ole J propose la fonction de définition d'achèvement d'alias suivante:

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"
}

Utilisez-le pour définir une fonction de complétion pour votre alias, puis spécifiez cette fonction en tant que compléteur pour l'alias:

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

Je préfère utiliser des alias pour ajouter des arguments toujours utilisés aux programmes existants. Par exemple, avec grep, je veux toujours ignorer les périphériques et les fichiers binaires, alors je crée un alias pour grep. Pour ajouter de nouvelles commandes telles que grepbin, j'utilise un script shell dans mon ~/bindossier. Si ce dossier est dans votre chemin, il se complétera automatiquement.

Shawn J. Goff
la source
2
Génial, j'avais peur que ce ne soit pas possible.
Levesque
Notez que ce code a quelques problèmes. Voir ma réponse pour leur explication et leur résolution.
Tom Hale
Remarque: J'utilisais cette technique pour une autre commande et je devais l'utiliser complete -o default -F ...au lieu de complete -F ...faire en sorte que des tâches telles que la saisie automatique du nom de fichier fonctionnent correctement lors de la transmission des arguments (Bash 4.3.46).
Joelittlejohn
28

Essayez complete-alias , qui résout ce problème avec précision.

Après l’avoir installé, vous pouvez utiliser une fonction générique pour compléter de nombreux alias comme ceci:

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

Vous souhaiterez peut-être utiliser le fichier complete_alias dans toutes les instances bash .bash_profileou similaires.

installation

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

application

source ~/.bash_completion.d/complete_alias

alias container=docker\ container
complete -F _complete_alias container

containerpeut maintenant être _docker()complété automatiquement par le gestionnaire d'achèvement d' origine ;

$ container l<Tab>
logs  ls    

$ container s<Tab>
start  stats  stop   
Cyker
la source
2
Étant donné que ce logiciel semble être le vôtre, vous pourriez faire mieux que cela. Ajoutez des instructions pour l’installer. Décrivez ce qu'il fait et comment l'utiliser. Sinon, il ne s'agit que de spam.
muru
@muru je pensais coller du code ici mais il est probablement plus long que accepté ici. Je suppose que les utilisateurs n'ont aucun problème à lire la section Installation d'un fichier README et, dans ce cas, il ne s'agit que de plusieurs lignes.
Cyker
2
le but est de pouvoir juger si la visite du dit README en vaut la peine, juste à partir de la réponse.
muru
C'est une réponse adéquate et cela résout le problème avec précision.
рослав Рахматуллин 10/10
1
C'est une excellente et très complète réponse qui fonctionne parfaitement, merci !. Il a probablement été mis à jour depuis que @muru a eu des problèmes avec cela.
Brian Topping
3

2018 réponse

Vous devez ajouter votre alias au programme 'complete'. Selon le type de complétion automatique que vous souhaitez réaliser, vous devez utiliser -c ou -F.

Pour l'auto-complétion du paquet:

complete -c name_of_your_alias

Pour l'auto-complétion de la commande:

complete -F name_of_your_alias

Pour vérifier si votre alias a été ajouté correctement:

complete | grep name_of_your_alias

Enfin, pour supprimer un alias de 'complete':

complete -r name_of_your_alias

Dans ton cas:

complete -c apt-inst
Adrian Lopez
la source
1
S'il vous plaît ne continuez pas votre réponse dans les commentaires. Si vous avez des choses à dire, modifiez- les dans la réponse.
G-Man dit 'Réintégrez Monica'
2
complete -F xxxne fonctionne pas sur OSX (il montre simplement l'utilisation complete: usage: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]). Avez-vous un pointeur? Merci.
Anthony Kong
Utilisez plutôt ceci: unix.stackexchange.com/questions/224227/…
Rich le
2

Voici le code de la réponse de Shawn J. Goff avec quelques améliorations:

  • Correction des erreurs de syntaxe mises en évidence par shell-check, par exemple, le premier "de la chaîne de définition de fonction "$@"réellement terminée .
  • Suppression du return 0afin que la valeur de retour de la fonction sous-jacente puisse être renvoyée à l'appelant.

.

# 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
la source
Cela ne fonctionne pas pour moi dans Bash 4.3.46, j'ai bien peur. La réponse de J. Shaun Goff fait le travail.
Joelittlejohn
1
"Fin" la chaîne de définition de la fonction est faite exprès; le but est d'inclure des arguments de la fonction externe dans le COMP_WORDStableau. Si nous utilisons make-completion-wrapper _apt_get _apt_get_install apt-get installcomme exemple, after shift 2, $@contient apt-get install. La définition de la fonction inclut apt-get install(les deux mots littéraux) lors de l'attribution COMP_WORDS.
Jeffery Jusqu'au
0

En tant qu'extension de la réponse @Giles, la fonction de confort suivante nomme automatiquement l'enveloppe générée par make-completion-wrapperafin de permettre de définir l'achèvement sur une ligne:

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}
}
utilisateur84207
la source