별칭으로 작업하기 위해 bash 완료를 어떻게 얻습니까?


195

지목 사항:

나는 bash v3.2.17을 사용하는 Mac에서 bash_completion 변형과 함께 macports를 통해 설치된 git을 사용하고 있습니다.

내가 입력하면 git checkout m<tab>. 예를 들어에 완료되었습니다 master.

그러나, 나는 별칭을 가지고있다 git checkout, gco. 을 입력 gco m<tab>하면 지점 이름이 자동 완성되지 않습니다.

이상적으로는 자동 완성 기능을 사용하여 모든 별칭에 마술처럼 작동하고 싶습니다. 가능합니까? 실패하면 각 별칭에 대해 수동으로 사용자 정의하고 싶습니다. 그래서 어떻게해야합니까?


3
완료 -o 기본 -o nospace -F는 현재 작동하지 않습니다
eighteyes

5
인기 답변보다 더 많은 투표율을 가진 질문은 종종 훌륭한 기능 요청을
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
누군가가 나에게 지적한 것처럼 수퍼 유저의 또 다른 대답은 내 질문에 이것의 속임수가 있다는 것입니다. superuser.com/questions/436314/…
dstarh

답변:


183

위의 의견에서 언급했듯이

complete -o default -o nospace -F _git_checkout gco

더 이상 작동하지 않습니다. 그러나 __git_completegit-completion.bash에는 다음과 같이 별칭의 완성을 설정하는 데 사용할 수 있는 기능이 있습니다.

__git_complete gco _git_checkout

6
이것은 많은 잘못된 것들 중에서 내가 본 유일한 대답입니다.
eighteyes

45
git에 전역 별칭 ​​"g"를 사용하는 경우 __git_complete g __git_main모든 git 명령에서 코드 완성을 수행하도록 추가 할 수도 있습니다 .
Ondrej Machulda

5
^^ git / shell / bash를 처음 사용하는 분들. 위의 주석은 기본 자식 별칭이 아닌 전역 쉘 별칭을 나타냅니다.
Elijah Lynn

14
이것을 어디에 두어야합니까?
benregn

15
마침내 이것을 올바르게하는 방법을 알아 냈습니다! 1 단계) 복사 git-completion.bash에서 <your git install folder>/etc/bash-completion.d/~/.git-completion.bash 2 단계)를 추가 source ~/.git-completion.bash하여에 .bash_profile 3 단계)를 추가 __git_complete gco _git_checkout하여 .bash_profile에 위의 줄 끝에서 아무 곳. 4 단계) 셸을 재부팅하고 별칭 자동 완성을 즐기십시오! :)
kpsfoo

54

나는이 문제에 부딪 쳤고이 코드 스 니펫을 생각해 냈습니다. 이렇게하면 모든 별칭의 완성이 자동으로 제공됩니다. 모든 (또는 다른) 별명을 선언 한 후 실행하십시오.

# 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

6
let COMP_CWORD+=$num_alias_arguments어떤 이유로 Mac OS X 에서 회선 이 작동하지 않았습니다. ((COMP_CWORD+=$num_alias_arguments))그래도 그것을 수정으로 교체
Mario F

5
와우, 대단해-고마워! wrap_alias별칭 정의에서 큰 따옴표를 숨기면 다중 명령 별칭 ( alias 'foo=bar; baz')에는 별로 의미가 없으므로 . | grep -v '[";|&]'뒤에 여분을 추가 합니다 alias -p. 또한 수백 가지 별칭 정의에 대해서는 약간 느리지 만 출력 echo대신 eval캐시 파일로 출력을 파이핑하는 대신 eval잘 작동하고 매우 빠르다는 것을 확인하게되어 기쁩니다. .
Jo Liss

2
또 다른 힌트 : wrap_alias완료를 설정해야하므로 코드 source /etc/bash_completion앞에서 이동해야했습니다 wrap_alias.
Jo Liss

2
이 줄 let COMP_CWORD+=$num_alias_arguments을로 변경 한 후 OS X 10.7.2에서 나에게 도움이 되었습니다 let \"COMP_CWORD+=$num_alias_arguments\".
irh

7
superuser.com/a/437508/102281 에서이 스크립트의 업데이트 된 버전을 참조하십시오 (예 : 일부 git 완료에 필요한 COMP_LINE 및 COMP_POINT에 대한 지원을 추가했습니다).
John Mellor

18

에서 git-completion.bash선이있다 :

complete -o default -o nospace -F _git git

해당 줄과 _git 함수를 보면이 줄을 다음에 추가 할 수 있습니다 .bash_profile.

complete -o default -o nospace -F _git_checkout gco

4
의 일부 자식 *이 방법을 사용하여 bash는 기능이 더 이상 작동하지 않습니다
cmcginty

예, 이것은 git_completion.bash에서 무언가가 바뀔 때까지 훌륭하게 작동했습니다 ... 이제는 전체 명령으로 작동하지만 별칭은 작동하지 않습니다.
Michael Smith

현대 git에서 작동하는 답변에 대해서는이 페이지의 끝을 참조하십시오.
eighteyes

수락 된 답변을 "올바른 답변"으로 변경하거나 변경 사항을 반영하기 위해 최소한 수락 된 답변을 업데이트해야합니까?
Tony K.

이것은 잘 작동합니다-이것을 내 .bash_profile에 추가하고 지금까지 별명을 사용하거나 사용하지 않고 잘 작동합니다. github.com/larrybotha/dotfiles/blob/master/…
Larry

15

나는 g = 'git'이라는 별칭을 가지고 있으며, git 별칭과 결합하여 다음과 같은 것을 입력합니다.

$ g co <branchname>

내 특정 사용 사례에 대한 간단한 수정은 git-completion에 한 줄을 추가하는 것이 었습니다.

이 줄 바로 아래 :

__git_complete git _git

단일 'g'별칭을 처리하기 위해이 줄을 추가했습니다.

__git_complete g _git

2
(Cygwin을 사용하고 있습니다.)에서 파일 git-completion이나 해당 줄을 찾을 수 없지만 별칭 뒤에 /etc/bash_completion.d/git추가 하면 효과가 있습니다! complete -o default -o nospace -F _git g.bash_aliases
idbrii

에서 /etc/bash-completion.d/또는에서 새로 파일을 편집하면 /usr/share/bash-completion/패키지 관리자를 사용하여 파일이 업데이트 될 때마다 변경 사항이 손실됩니다.
kub1x

14

이상적으로는 자동 완성 기능을 사용하여 모든 별칭에 마술처럼 작동하고 싶습니다. 가능합니까?

예, 전체 별칭 프로젝트 (Linux의 경우)로 가능합니다. Mac 지원은 실험적이지만 사용자는 성공을보고했습니다.


4
고마워, 이것은 세계의 모든 유틸리티가 bash 완성을 구현하는 방법을 알아내는 것보다 훨씬 낫습니다.
artm

2
실제로, 별칭의 완성을 구성하는 데 시간이 절약되었습니다.
Samir Alajmovic

2
Linux에서는 매력처럼 작동합니다 (Mac에서는 테스트되지 않음). 작성해 주셔서 감사합니다!
bitmask

1
이것은 대단하다! 그냥 작동하고, 번거롭지 않고, 훨씬 좋습니다! 감사!
emi

5

Git 별칭을 사용해 볼 수도 있습니다. 예를 들어, 내 ~/.gitconfig파일에는 다음과 같은 섹션이 있습니다.

[alias]
        co = checkout

따라서을 입력 하면 명령으로 git co m<TAB>확장됩니다 .git co mastergit checkout


5

이 포럼 페이지 는 솔루션을 보여줍니다.

이 줄을 당신의 .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'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

이 솔루션은 balshetzer의 스크립트 와 유사 하지만 실제로이 솔루션 만 작동합니다. (balshetzer의 스크립트에 내 별칭 중 일부에 문제가있었습니다.)


; 이것은 거의 효과가 있습니다-몇 가지 오류가 발생하지만 완료됩니다. 내가 할 수있는 다른 일이 있습니까? -bash: eval: line 28: unexpected EOF while looking for matching ''' -bash: eval: line 29: syntax error: unexpected end of file
pforhan

@pforhan 위의 인용 문제를 볼 수 있습니다 ... 문자열 "안의 따옴표 function는로 인용해야합니다 \". 이것은 아마도 '어딘가에 당신의 따옴표 중 하나를 먹을 것입니다 .
Tom Hale

5

또 다른 옵션은 ~/.bash_completion파일 을 사용하는 것 입니다. gco별칭 을 만들려면 git checkout여기에 넣으십시오.

_xfunc git __git_complete gco _git_checkout

그런 다음 ~/.bashrc별칭 자체를 넣어야합니다.

alias gco='git checkout'

두 줄. 그게 다야.

설명:

~/bash_completion주요 bash_completion 스크립트의 끝에서 공급됩니다. 젠투에서 나는에서 메인 스크립트를 발견했다 /usr/share/bash-completion/bash_completion.

_xfunc git비트는 소싱을 담당 git-completion당신이 무엇을 넣을 필요가 없습니다 당신을 위해 파일을 ~/.bashrc.

수락 된 대답은 내가 절름발이 발견 한 파일 .git-completion.sh에서 복사 하고 소싱해야합니다 ~/.bashrc.


추신 : 여전히 전체 git-completion스크립트를 내 bash 환경 에 소스하지 않는 방법을 찾으려고 노력하고 있습니다. 방법을 찾으면 의견을 말하거나 편집하십시오.


_xfunc git필요한가요?
Tom Hale

@ TomHale 나는 대답을 향상시키기 위해 노력했다. source ~/.git-completion.sh내가 하는 대신 _xfunc에 나를 위해 해보자 . 단지 단독으로하는 것이 더 좋고 깨끗하다고 ​​느낍니다 ~/.bash_completion. 포함하지 않는 _xfunc(또는 소싱)이 __git_complete기능은 존재하지 않습니다.
kub1x

1
~/.bash_completion파일이 필요 없습니다. 이 _xfunc줄은 저에게 효과적입니다 .bashrc.
Tom Hale

2

complete명령 을 찾아서 별칭 이름을 가진 줄을 대신 복제하면됩니다.

나는있다 alias d-m="docker-machine". 즉, d-m의 별칭이됩니다 docker-machine.

따라서 (양조를 통해) Mac에서 완성 파일은에 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

같은 이것은 간단한에 대한 최상의 솔루션 (1-1)의 별칭이다 docker별칭 d. 문제의 예에서는 git checkout별칭 gco이 더 복잡합니다.
wisbucky 2016 년

1

먼저 원래 완료 명령을 찾으십시오. 예:

$ complete | grep git

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

이제 이들을 시작 스크립트에 추가하십시오 (예 : ~ / .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

_completion_loader라인은 필요하지 않을 수 있습니다. 그러나 경우에 따라 완료 기능은 명령을 입력 TAB하고 처음으로 누른 후에 만 ​​동적으로로드 됩니다. 따라서 원래 명령을 사용하지 않고 alias +를 시도하면 TAB"bash : completion : function '_docker'not found"와 같은 오류가 발생할 수 있습니다.


1

이 질문에 대한 많은 답변이 있으며 나처럼 혼란스러워하는 많은 독자들에게 내기를 걸었습니다. 필자의 경우 도트 파일이 다른 버전의 Git을 사용하는 여러 플랫폼에서 작동하도록 요구했습니다. 나는 또한 alias g=git대신 g함수로 정의했다.

이것을 달성하기 위해 여기에 다른 답변을 하나의 솔루션으로 묶어야했습니다. 이것은 이미 답변을 반복하지만 내 보트에있는 누군가 가이 질문에 처음 왔을 때와 같이이 편집이 유용하다고 생각했습니다.

이것은 이전 및 최신 Git 완료, Ubuntu 기본값 및 brew install gitMacOS에서 가정합니다. 후자의 경우 brew 설치 완료는 bash에 의해 처리되지 않았습니다 (나중에 진단 할 것).

# 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.