web-dev-qa-db-fra.com

Comment puis-je obtenir la complétion de bash pour travailler avec des alias?

Exemple: 

Je suis sur 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 le complète à master.

Cependant, j'ai un alias pour git checkout, gco. Lorsque je tape gco m<tab>, le nom de la branche n’est pas complété automatiquement.

Idéalement, j'aimerais que l'auto-complétion fonctionne comme par magie pour tous mes alias. C'est possible? A défaut, j'aimerais le personnaliser manuellement pour chaque alias. Alors, comment vais-je?

176
kch

Comme indiqué dans les commentaires ci-dessus,

complete -o default -o nospace -F _git_checkout gco

ne fonctionnera plus. Cependant, il existe une fonction __git_complete dans git-completion.bash qui peut être utilisée pour configurer la complétion d'alias comme ceci:

__git_complete gco _git_checkout
162
chris_sutter

J'ai rencontré ce problème aussi et est venu avec cet extrait de code. Cela vous donnera automatiquement la complétion pour tous les alias. Exécutez-le après avoir déclaré tout (ou tout) alias.

# wrap_alias takes three arguments:
# $1: The name of the alias
# $2: The command used in the alias
# $3: 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="$1"
  local aliased_command="$2"
  local alias_arguments="$3"
  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 \1 \2 '\''\3'\'' /')"

unset wrap_alias
52
Hesky Fisher

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
Chris Lloyd

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 consistait à ajouter une seule ligne à git-completion.

Juste en dessous de cette ligne:

__git_complete git _git

J'ai ajouté cette ligne pour gérer mon simple alias 'g':

__git_complete g _git
15
wonderfulthunk

Idéalement, j'aimerais que l'auto-complétion fonctionne comme par magie pour tous mes alias. C'est possible?

Oui, c'est possible avec le complete-alias project (sous Linux). La prise en charge de Mac est expérimentale, mais les utilisateurs ont signalé leur succès.

12
Cyker

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 $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"
    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 au script balshetzer , mais seul celui-ci fonctionne pour moi. (Le script de balshetzer avait des problèmes avec certains de mes alias.)

5
hcs42

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

Donc, vous pouvez taper git co m<TAB>, et cela devrait être étendu à git co master, qui est la commande git checkout.

4
mipadi

Une autre option consiste à utiliser le fichier ~/.bash_completion. Pour créer l'alias gco pour git checkout, il suffit de l'indiquer 

_xfunc git __git_complete gco _git_checkout

Ensuite, dans ~/.bashrc, vous devez simplement mettre le pseudonyme: 

alias gco='git checkout'

Deux lignes. C'est tout. 

Explication:

Le ~/bash_completion est généré à la fin du script principal bash_completion. Dans gentoo, j'ai trouvé le script principal dans /usr/share/bash-completion/bash_completion

Le bit _xfunc git se charge de rechercher le fichier git-completion pour vous, de sorte que vous n'avez rien d'autre à ajouter dans ~/.bashrc

La réponse acceptée nécessite que vous copiez .git-completion.sh et le sourcez à partir de votre fichier ~/.bashrc que je trouve nul. 


PS: J'essaie toujours de comprendre comment ne pas utiliser le script git-completion complet dans mon environnement bash. Veuillez commenter ou modifier si vous trouvez un moyen. 

4
kub1x

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

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

Donc, sur Mac (via brassage), 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, je viens d'ajouter une autre ligne, avec mon alias:

complete -F _docker_machine docker-machine
complete -F _docker_machine d-m
2
luckydonald

Il y a beaucoup de réponses à cette question et, comme moi, je parie beaucoup de lecteurs confus. Pour mon cas, j'avais également eu l'obligation de faire fonctionner mes fichiers de points sur plusieurs plates-formes avec différentes versions de Git. Je n’ai pas non plus alias g=git, mais plutôt g défini en tant que fonction.

Pour ce faire, j'ai dû regrouper différentes réponses ici en une solution. Bien que cela répète les réponses déjà, je pensais que quelqu'un dans mon bateau pourrait trouver cette compilation utile comme je le ferais lorsque je suis arrivé pour la première fois à cette question.

Cela suppose l’achèvement des versions plus anciennes et plus récentes de Git, les valeurs par défaut d’Ubuntu et brew install git sous MacOS. Dans le dernier cas, les compléments installés de la brasserie n'étaient pas traités par bash (quelque chose que je diagnostiquerai plus tard).

# Alias g to git

g() {
  if [[ $# > 0 ]]; then
    git "$@"
  else
    git status -sb
  fi
}

# Preload git completion in Ubuntu which is normally lazy loaded but we need
# the __git_wrap__git_main function available for our completion.
if [[ -e /usr/share/bash-completion/completions/git ]]; then
  source /usr/share/bash-completion/completions/git
Elif [[ -e /usr/local/etc/bash_completion.d/git-completion.bash ]]; then
  source /usr/local/etc/bash_completion.d/git-completion.bash
fi

if command_exists __git_complete; then
  __git_complete g _git
Elif command_exists __git_wrap__git_main; then
  complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g
fi
0
Sukima

Tout d'abord, recherchez la commande d'achèvement d'origine. Exemple:

$ complete | grep git

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

Ajoutez-les maintenant à 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. Toutefois, dans certaines situations, la fonction d'achèvement n'est chargée de manière dynamique qu'après avoir tapé la commande et appuyé sur TAB la première fois. Ainsi, si vous n'avez pas utilisé la commande d'origine et essayez l'alias + TAB, vous risquez d'obtenir une erreur du type "bash: complétion: fonction '_docker' introuvable".

0
wisbucky

Si vous utilisez alias g='git', j'ajoute cette ligne de code dans .bash_aliases

complete -o default -o nospace -F _git g
0
Druta Ruslan