Le code suivant, adapté de cette réponse de Stack Overflow et ceci Fil de discussion sur les forums Ubuntu ajoutera des compléments pour tous les alias définis :
# Automatically add completion for all aliases to commands having completion functions
function alias_completion {
local namespace="alias_completion"
# parse function based completion definitions, where capture group 2 => function and 3 => trigger
local compl_regex='complete( +[^ ]+)* -F ([^ ]+) ("[^"]+"|[^ ]+)'
# parse alias definitions, where capture group 1 => trigger, 2 => command, 3 => command arguments
local alias_regex="alias ([^=]+)='(\"[^\"]+\"|[^ ]+)(( +[^ ]+)*)'"
# create array of function completion triggers, keeping multi-word triggers together
eval "local completions=($(complete -p | sed -Ene "/$compl_regex/s//'\3'/p"))"
(( ${#completions[@]} == 0 )) && return 0
# create temporary file for wrapper functions and completions
rm -f "/tmp/${namespace}-*.tmp" # preliminary cleanup
local tmp_file; tmp_file="$(mktemp "/tmp/${namespace}-${RANDOM}XXX.tmp")" || return 1
local completion_loader; completion_loader="$(complete -p -D 2>/dev/null | sed -Ene 's/.* -F ([^ ]*).*/\1/p')"
# read in "<alias> '<aliased command>' '<command args>'" lines from defined aliases
local line; while read line; do
eval "local alias_tokens; alias_tokens=($line)" 2>/dev/null || continue # some alias arg patterns cause an eval parse error
local alias_name="${alias_tokens[0]}" alias_cmd="${alias_tokens[1]}" alias_args="${alias_tokens[2]# }"
# skip aliases to pipes, boolean control structures and other command lists
# (leveraging that eval errs out if $alias_args contains unquoted shell metacharacters)
eval "local alias_arg_words; alias_arg_words=($alias_args)" 2>/dev/null || continue
# avoid expanding wildcards
read -a alias_arg_words <<< "$alias_args"
# skip alias if there is no completion function triggered by the aliased command
if [[ ! " ${completions[*]} " =~ " $alias_cmd " ]]; then
if [[ -n "$completion_loader" ]]; then
# force loading of completions for the aliased command
eval "$completion_loader $alias_cmd"
# 124 means completion loader was successful
[[ $? -eq 124 ]] || continue
completions+=($alias_cmd)
else
continue
fi
fi
local new_completion="$(complete -p "$alias_cmd")"
# create a wrapper inserting the alias arguments if any
if [[ -n $alias_args ]]; then
local compl_func="${new_completion/#* -F /}"; compl_func="${compl_func%% *}"
# avoid recursive call loops by ignoring our own functions
if [[ "${compl_func#_$namespace::}" == $compl_func ]]; then
local compl_wrapper="_${namespace}::${alias_name}"
echo "function $compl_wrapper {
(( COMP_CWORD += ${#alias_arg_words[@]} ))
COMP_WORDS=($alias_cmd $alias_args \${COMP_WORDS[@]:1})
(( COMP_POINT -= \${#COMP_LINE} ))
COMP_LINE=\${COMP_LINE/$alias_name/$alias_cmd $alias_args}
(( COMP_POINT += \${#COMP_LINE} ))
$compl_func
}" >> "$tmp_file"
new_completion="${new_completion/ -F $compl_func / -F $compl_wrapper }"
fi
fi
# replace completion trigger by alias
new_completion="${new_completion% *} $alias_name"
echo "$new_completion" >> "$tmp_file"
done < <(alias -p | sed -Ene "s/$alias_regex/\1 '\2' '\3'/p")
source "$tmp_file" && rm -f "$tmp_file"
}; alias_completion
Pour les alias simples (commande uniquement, pas d'arguments), il affecte la fonction de complétion originale à l'alias ; pour les alias avec arguments, il crée une fonction enveloppante qui insère les arguments supplémentaires dans la fonction de complétion originale.
Contrairement aux scripts dont elle est issue, la fonction respecte les guillemets à la fois pour la commande d'alias et pour ses arguments (mais les premiers doivent être pris en compte par la commande de complétion, et ne peuvent pas être imbriqués), et elle devrait filtrer de manière fiable les alias à listes de commandes y tuyaux (qui sont ignorées, car il est impossible de savoir ce qu'il faut y compléter sans recréer toute la logique d'analyse de la ligne de commande Shell).
Utilisation
Soit vous enregistrez le code dans un fichier Shell Shell et source ou copier la fonction en gros dans, .bashrc
(ou votre fichier de points pertinent ). L'important est d'appeler la fonction après que la complétion bash et les définitions d'alias ont été mises en place (le code ci-dessus appelle la fonction juste après sa définition, dans un esprit "source et oubli", mais vous pouvez déplacer l'appel n'importe où en aval si cela vous convient mieux). Si vous ne voulez pas que la fonction reste dans votre environnement après sa sortie, vous pouvez ajouter unset -f alias_completion
après l'avoir appelé.
Notes
Si vous utilisez bash
4.1 ou supérieur et que vous utilisez des complétions chargées dynamiquement, le script tentera de charger les complétions pour toutes vos commandes aliasées afin de pouvoir construire les fonctions enveloppantes pour vos alias.