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?
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
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
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
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
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.
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.)
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
.
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.
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
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".