Comment faire pour que bash completion fonctionne avec des alias?

Affaire au point:

je suis un mac avec bash v3.2.17, j'utilise git installé via macports avec la variante bash_completion.

quand je tape git checkout m<tab> . par exemple, je l'obtiens complété à master .

cependant, j'ai un alias pour git checkout , gco . Quand je tape gco m<tab> , je n'obtiens pas le nom de la branche autocompleted.

idéalement je voudrais autocompletion juste par magie travail pour tous mes alias. Est-il possible? À défaut, j'aimerais personnaliser manuellement pour chaque alias. Alors, comment dois-je faire?

160
demandé sur greg-449 2008-12-05 08:17:09

10 réponses

comme indiqué dans les commentaires ci-dessus,

complete -o default -o nospace -F _git_checkout gco

ne fonctionnera plus. Cependant, il y a une fonction __git_complete dans Git-completion.bash qui peut être utilisé pour configurer l'achèvement des alias comme suit:

__git_complete gco _git_checkout
152
répondu chris_sutter 2013-02-21 18:25:48

j'ai rencontré ce problème et j'ai trouvé ce code. Cela vous donnera automatiquement achèvement pour tous les alias. Exécutez-le après avoir déclaré tous (ou n'importe quel) alias.

# wrap_alias takes three arguments:
# : The name of the alias
# : The command used in the alias
# : The arguments in the alias all in one string
# Generate a wrapper completion function (completer) for an alias
# based on the command and the given arguments, if there is a
# completer for the command, and set the wrapper as the completer for
# the alias.
function wrap_alias() {
  [[ "$#" == 3 ]] || return 1

  local alias_name=""
  local aliased_command=""
  local alias_arguments=""
  local num_alias_arguments=$(echo "$alias_arguments" | wc -w)

  # The completion currently being used for the aliased command.
  local completion=$(complete -p $aliased_command 2> /dev/null)

  # Only a completer based on a function can be wrapped so look for -F
  # in the current completion. This check will also catch commands
  # with no completer for which $completion will be empty.
  echo $completion | grep -q -- -F || return 0

  local namespace=alias_completion::

  # Extract the name of the completion function from a string that
  # looks like: something -F function_name something
  # First strip the beginning of the string up to the function name by
  # removing "* -F " from the front.
  local completion_function=${completion##* -F }
  # Then strip " *" from the end, leaving only the function name.
  completion_function=${completion_function%% *}

  # Try to prevent an infinite loop by not wrapping a function
  # generated by this function. This can happen when the user runs
  # this twice for an alias like ls='ls --color=auto' or alias l='ls'
  # and alias ls='l foo'
  [[ "${completion_function#$namespace}" != $completion_function ]] && return 0

  local wrapper_name="${namespace}${alias_name}"

  eval "
function ${wrapper_name}() {
  let COMP_CWORD+=$num_alias_arguments
  args=( \"${alias_arguments}\" )
  COMP_WORDS=( $aliased_command ${args[@]} ${COMP_WORDS[@]:1} )
  $completion_function
  }
"

  # To create the new completion we use the old one with two
  # replacements:
  # 1) Replace the function with the wrapper.
  local new_completion=${completion/-F * /-F $wrapper_name }
  # 2) Replace the command being completed with the alias.
  new_completion="${new_completion% *} $alias_name"

  eval "$new_completion"
}

# For each defined alias, extract the necessary elements and use them
# to call wrap_alias.
eval "$(alias -p | sed -e 's/alias \([^=][^=]*\)='\''\([^ ][^ ]*\) *\(.*\)'\''/wrap_alias   '\'''\'' /')"

unset wrap_alias
51
répondu Hesky Fisher 2009-11-25 03:16:28

dans git-completion.bash il y a une ligne:

complete -o default -o nospace -F _git git

en regardant cette ligne (et la fonction _git) vous pouvez ajouter cette ligne à votre .bash_profile :

complete -o default -o nospace -F _git_checkout gco
18
répondu Chris Lloyd 2012-09-19 15:27:55

j'ai alias g= 'git', et combiné avec mes alias git je tape des choses comme

$ g co <branchname>

la solution la plus simple pour mon cas d'utilisation spécifique était d'ajouter une seule ligne à git-completion.

juste au-dessous de cette ligne:

__git_complete git _git

j'ai ajouté cette ligne pour gérer mon seul " g " alias:

__git_complete g _git
15
répondu wonderfulthunk 2012-05-22 18:07:22

idéalement, j'aimerais que l'autocomplétion fonctionne par magie pour tous mes pseudonymes. Est-il possible?

Oui, c'est possible avec le projet complete-alias (sur Linux). La prise en charge de Mac est expérimentale, mais les utilisateurs ont fait état de succès.

9
répondu Cyker 2018-05-22 23:22:49

cette page de forum montre une solution.

mettez ces lignes dans votre .bashrc ou .bash_profile :

# Author.: Ole J
# Date...: 23.03.2008
# License: Whatever

# Wraps a completion function
# 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 ) that will complete
# the 'agi' alias. (complete -F _apt_get_install agi)
#
function make-completion-wrapper () {
    local function_name=""
    local arg_count=$(($#-3))
    local comp_function_name=""
    shift 2
    local function="
function $function_name {
    ((COMP_CWORD+=$arg_count))
    COMP_WORDS=( "$@" ${COMP_WORDS[@]:1} )
    "$comp_function_name"
    return 0
}"
    eval "$function"
}

# and now the commands that are specific to this SO question

alias gco='git checkout'

# we create a _git_checkout_mine function that will do the completion for "gco"
# using the completion function "_git"
make-completion-wrapper _git _git_checkout_mine git checkout

# we tell bash to actually use _git_checkout_mine to complete "gco"
complete -o bashdefault -o default -o nospace -F _git_checkout_mine gco

Cette solution est similaire à le script de balshetzer , mais seulement celui-ci fonctionne réellement pour moi. (le script de balshetzer avait des problèmes avec certains de mes alias.)

5
répondu hcs42 2017-05-23 11:55:07

vous pouvez également essayer d'utiliser des alias Git. Par exemple, dans mon fichier ~/.gitconfig , j'ai une section qui ressemble à ceci:

[alias]
        co = checkout

pour que vous puissiez taper git co m<TAB> , et qui devrait s'étendre à git co master , qui est la commande git checkout .

4
répondu mipadi 2008-12-05 15:39:26

une autre option est d'utiliser le fichier ~/.bash_completion . Pour créer le gco alias pour git checkout mettez juste ceci là:

_xfunc git __git_complete gco _git_checkout

puis dans ~/.bashrc vous devez mettre juste l'alias lui-même:

alias gco='git checkout'

deux lignes. C'est tout.

explication:

le ~/bash_completion est fourni à la fin du script principal de bash_completion. Dans gentoo J'ai trouvé le script principal dans /usr/share/bash-completion/bash_completion .

le _xfunc git bit s'occupe de l'approvisionnement du git-completion fichier pour vous de sorte que vous n'avez pas besoin de mettre quoi que ce soit d'autre dans ~/.bashrc .

la réponse acceptée exige que vous copiez .git-completion.sh et de la source de votre ~/.bashrc fichier que je trouve boiteux.


PS: j'essaie toujours de trouver comment ne pas source l'ensemble du script git-completion dans mon environnement bash. Veuillez commenter ou modifier si vous trouvez un moyen.

3
répondu kub1x 2016-09-18 08:17:56

vous avez juste à trouver la commande complete et dupliquer la ligne ayant le nom d'alias à la place.

j'ai alias d-m="docker-machine" . Par mots, d-m doit être l'alias de docker-machine .

donc sur Mac (via brew), les fichiers d'achèvement sont dans cd `brew --prefix`/etc/bash_completion.d/ .

Pour mon cas, j'ai édité le fichier appelé docker-machine .

Tout en bas, il y avait:

complete -F _docker_machine docker-machine

donc j'ai juste ajouté une autre ligne, avec mon alias:

complete -F _docker_machine docker-machine
complete -F _docker_machine d-m
2
répondu luckydonald 2016-11-07 11:07:37

regardez d'abord la commande d'achèvement originale. Exemple:

$ complete | grep git

complete -o bashdefault -o default -o nospace -F __git_wrap__git_main git

ajoutez maintenant ces derniers à votre script de démarrage (par exemple~/.bashrc):

# copy the original statement, but replace the last command (git) with your alias (g)
complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g

# load dynamically loaded completion functions (may not be required)
_completion_loader git

la ligne _completion_loader peut ne pas être requise. Mais pour certaines situations, la fonction completion n'est chargée dynamiquement qu'après avoir tapé la commande et appuyé sur TAB la première fois. Donc si vous n'avez pas utilisé la commande originale, et essayez l'alias + TAB , vous pourriez avoir une erreur comme "bash: achèvement: la fonction '_docker"introuvable".

0
répondu wisbucky 2018-07-26 22:50:04