Пример:
Я нахожусь на mac с bash v3.2.17, я использую git, установленный через macports с вариантом bash_completion.
Когда я набираю git checkout m<tab>
. например, я завершаю его до master
.
Однако у меня есть псевдоним git checkout
, gco
. Когда я набираю gco m<tab>
, я не получаю автозаполнение имени ветки.
В идеале я хотел бы, чтобы автозаполнение просто волшебным образом работало для всех моих псевдонимов. Является ли это возможным? В противном случае я хотел бы настроить его вручную для каждого псевдонима. Итак, как мне обойтись?
Как указано в комментариях выше,
complete -o default -o nospace -F _git_checkout gco
больше не будет работать. Однако существует функция __git_complete
в git -completion.bash, которая может быть использована для настройки завершения для псевдонимов вроде:
__git_complete gco _git_checkout
__git_complete g __git_main
чтобы завершить выполнение кода для всех команд git.
Я столкнулся с этой проблемой и придумал этот фрагмент кода. Это автоматически даст вам завершение для всех псевдонимов. Запустите его после объявления всех (или любых) псевдонимов.
# 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
let COMP_CWORD+=$num_alias_arguments
по какой-то причине не работала в Mac OS X. Замена его на ((COMP_CWORD+=$num_alias_arguments))
исправила это
wrap_alias
душит двойные кавычки в определении псевдонима, и я думаю, что это не имеет особого смысла для псевдонимов с несколькими командами ( alias 'foo=bar; baz'
), поэтому я помещаю дополнительную | grep -v '[";|&]'
после alias -p
. Кроме того, он становится немного медленным для сотен определений псевдонимов, но я рад подтвердить, что использую echo
вместо eval
и отправляем вывод в кеш Файл (который затем может быть eval
за один раз) работает отлично и работает очень быстро.
В git-completion.bash
есть строка:
complete -o default -o nospace -F _git git
Глядя на эту строку (и функцию _git), вы можете добавить эту строку в свой .bash_profile
:
complete -o default -o nospace -F _git_checkout gco
У меня есть aliased g = 'git', и в сочетании с моими алиасами git я печатаю такие вещи, как
$ g co <branchname>
Более простым решением для моего конкретного случая использования было добавление отдельной строки в git -completion.
Прямо под этой строкой:
__git_complete git _git
Я добавил эту строку для обработки моего одиночного псевдонима "g":
__git_complete g _git
git-completion
/etc/bash_completion.d/git
или эту строку в /etc/bash_completion.d/git
, но я добавил complete -o default -o nospace -F _git g
после своего псевдонима в .bash_aliases
и это сработало!
/etc/bash-completion.d/
или заново в /usr/share/bash-completion/
, вы потеряете свои изменения всякий раз, когда этот файл обновляется с помощью менеджера пакетов.
В идеале я хотел бы, чтобы автозаполнение просто волшебным образом работало для всех моих псевдонимов. Возможно ли это?
Да, это возможно с проектом complete-alias.
Эта страница форума показывает решение.
Поместите эти строки в .bashrc
или .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 $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
Это решение похоже на balshetzer script, но только этот на самом деле работает для меня. (balshetzer script имел проблемы с некоторыми из моих псевдонимов.)
-bash: eval: line 28: unexpected EOF while looking for matching '''
-bash: eval: line 29: syntax error: unexpected end of file
"
кавычки внутри строки function
должны быть заключены в кавычки \"
. Это , вероятно , ест один из ваших '
кавычек где - то вдоль линии.
Вы также можете попробовать использовать псевдонимы Git. Например, в моем файле ~/.gitconfig
у меня есть раздел, который выглядит так:
[alias]
co = checkout
Итак, вы можете ввести git co m<TAB>
, и это должно быть расширено до git co master
, что является командой git checkout
.
Еще один вариант - использовать файл ~/.bash_completion
. Чтобы создать псевдоним gco
для git checkout
, просто поставьте его здесь:
_xfunc git __git_complete gco _git_checkout
Затем в ~/.bashrc
вам нужно просто поставить псевдоним:
alias gco='git checkout'
Две строки. Это.
Объяснение:
~/bash_completion
получает источник в конце основного файла bash_completion script. В gentoo я нашел главный script в /usr/share/bash-completion/bash_completion
.
Бит _xfunc git
заботится о поиске файла git-completion
для вас, поэтому вам не нужно вставлять что-либо еще в ~/.bashrc
.
Принятый ответ требует, чтобы вы скопировали .git-completion.sh
и отправили его из своего файла ~/.bashrc
, который я нахожу хромым.
PS: Я все еще пытаюсь понять, как не вывести весь git-completion
script в мою среду bash. Просьба прокомментировать или отредактировать, если вы найдете способ.
_xfunc git
?
source ~/.git-completion.sh
_xfunc
я позволил _xfunc
сделать это для меня. Просто приятнее и чище делать это исключительно в ~/.bash_completion
. Без _xfunc
(или источника) функция __git_complete
не существует.
Вам просто нужно найти команду complete
и дублировать строку с именем псевдонима.
У меня есть alias d-m="docker-machine"
. В словах d-m
должен быть псевдоним для docker-machine
.
Итак, на Mac (через brew) файлы завершения находятся в cd `brew --prefix`/etc/bash_completion.d/
.
В моем случае я редактировал файл под названием docker-machine
.
Весь путь внизу:
complete -F _docker_machine docker-machine
Итак, я добавил еще одну строку с моим псевдонимом:
complete -F _docker_machine docker-machine
complete -F _docker_machine d-m
docker
псевдонимом d
. Хотя для примера в вопросе git checkout
псевдонимом gco
более сложен.