エイリアスを使用してbash補完を取得するにはどうすればよいですか?


195

適例:

私はbash v3.2.17を搭載したMacで、bash_completionバリアントを使用してmacports経由でインストールされたgitを使用しています。

私がタイプするときgit checkout m<tab>。たとえば、私はそれを完成させるmasterます。

ただし、のエイリアスがgit checkoutありgcoます。入力するとgco m<tab>しても、ブランチ名がオートコンプリートされません。

理想的には、オートコンプリートがすべてのエイリアスに対して魔法のように機能することを望みます。出来ますか?それができない場合は、エイリアスごとに手動でカスタマイズしたいと思います。それで、私はどちらかについてどうしますか?


3
complete -o default -o nospace -Fは現在機能していません
eighteyes 2013年

5
上位の回答よりも賛成票が多い質問は、多くの場合、優れた機能のリクエストを
Ciro Santilli郝海东冠状病六四事件法轮功

2
スーパーユーザーからのもう1つの回答は、誰かが私の質問にはこれの誤りがあったということを私に指摘したからです。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 2013年

45
gitにグローバルエイリアス「g」を使用する場合は、追加__git_complete g __git_mainして、すべてのgitコマンドでコード補完を機能させることもできます。
Ondrej Machulda 2013

5
^^ git / shell / bashが初めての方。上記のコメントは、ネイティブgitエイリアスではなく、グローバルシェルエイリアスを参照しています。
Elijah Lynn

14
これはどこに置けばいいですか?
benregn 2013年

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 2014

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))修正済みのものに置き換える
マリオF

5
うわー、それは素晴らしいです-ありがとう! wrap_aliasエイリアス定義で二重引用符が詰まっているため、マルチコマンドエイリアス(alias 'foo=bar; baz')にはあまり意味がないので、の| grep -v '[";|&]'後に余分を付けていalias -pます。また、それは別名定義の何百ものために少し遅くなるが、私は使用していることを確認するために幸せechoの代わりに、eval(その後、することができたし、キャッシュファイルに出力をパイプeval一度の」EDする)の罰金を動作し、超高速です。
Jo Liss

2
別のヒント:wrap_alias補完を設定する必要があるためsource /etc/bash_completionwrap_aliasコードの前に移動する必要がありました。
Jo Liss、2013年

2
これは、行let COMP_CWORD+=$num_alias_argumentsをに変更した後、OS X 10.7.2で動作しましたlet \"COMP_CWORD+=$num_alias_arguments\"
11

7
superuser.com/a/437508/102281でこのスクリプトの更新されたバージョンを参照してください(たとえば、一部のgit補完に必要なCOMP_LINEおよびCOMP_POINTのサポートを追加しました)。
John Mellor 2014年

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
一部のgit * bash関数は、このメソッドを使用して機能しなくなりました
cmcginty

はい、これはgit_completion.bashで何かが変更されるまでは以前はうまく機能していました...完全なコマンドでは機能しますが、エイリアスでは機能しません。
Michael Smith

最新のgitで機能する回答については、このページの最後をご覧ください。
eighteyes 2013年

これに対する承認済みの回答を「正しいもの」に変更したり、変更を反映するために承認済みの回答を少なくとも更新したりしないでください。
Tony K.

これがうまく機能-私の.bash_profileにこれを追加し、これまでの別名でとせずに罰金を動作します:github.com/larrybotha/dotfiles/blob/master/...
ラリー・

15

g = 'git'にエイリアスを設定し、gitエイリアスと組み合わせて、次のように入力します

$ g co <branchname>

私の特定の使用例に対するより簡単な修正は、git-completionに1行を追加することでした。

この行のすぐ下:

__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 2016

14

理想的には、オートコンプリートがすべてのエイリアスに対して魔法のように機能することを望みます。出来ますか?

はい、それはcomplete-aliasプロジェクト(Linux)で可能です。Macのサポートは実験的なものですが、ユーザーは成功を報告しています。


4
おかげさまで、これは世界中のすべてのユーティリティがbash補完を実装する方法を理解するよりもはるかに優れています。
artm '19 / 06/19

2
実際、エイリアスの補完を構成する時間を節約できました。
Samir Alajmovic

2
Linuxのチャームのように動作します(Macではテストされていません)。書いてくれてありがとう!
ビットマスク2018年

1
これはとても素晴らしいです!機能するだけで、大騒ぎする必要はありません。ありがとう!
emi

5

Gitエイリアスを使用することもできます。たとえば、私の~/.gitconfigファイルには、次のようなセクションがあります。

[alias]
        co = checkout

したがってgit co m<TAB>、と入力git co masterすると、git checkoutコマンドであるに展開されます。


5

このフォーラムページは解決策を示しています。

これらの行を.bashrcorまたは.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引用符はとして引用されるべき\"です。これはおそらくあなたの'引用の1つを線に沿ってどこかで食べてしまいます。
トム・ヘイル

5

もう1つのオプションは、~/.bash_completionファイルを使用することです。のgcoエイリアスを作成するには、次のgit checkoutように入力します。

_xfunc git __git_complete gco _git_checkout

次に~/.bashrc、エイリアス自体を配置する必要があります:

alias gco='git checkout'

2行。それでおしまい。

説明:

~/bash_completionメインbash_completionスクリプトの最後で供給されます。gentooで私はメインスクリプトをで見つけました/usr/share/bash-completion/bash_completion

この_xfunc gitビットはgit-completionファイルのソースを処理するので、他に何も入れる必要はありません~/.bashrc

受け入れられた答えはあなたが私が不完全だと思う.git-completion.shあなたの~/.bashrcファイルからそれをコピーして調達することを要求します。


PS:私はまだ、git-completionスクリプト全体をbash環境に読み込まないようにする方法を見つけようとしています。方法が見つかったら、コメントするか編集してください。


なぜ_xfunc git必要なのですか?
トム・ヘイル

@TomHale答えを改善しようとしました。やるのでsource ~/.git-completion.shはなく、私に任せ_xfuncます。だけでそれを実行するほうがいいと感じ~/.bash_completionます。_xfunc(またはソーシング)がなければ、__git_complete関数は存在しません。
kub1x 2016

1
~/.bash_completionファイルは必要ありません。この_xfunc行はで機能します.bashrc
トム・ヘイル

2

あなただけを見つける必要があります 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がより複雑です。
wisbucky

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て最初にを押した後にのみ、完了関数が動的にロードされます。したがって、元のコマンドを使用しておらず、エイリアス+を試してみると、TAB「bash:completion:function '_docker' not found」のようなエラーが表示される場合があります。


1

この質問にはたくさんの答えがあり、私と同じように、読者は混乱していると思います。私の場合、ドットファイルをGitの異なるバージョンの複数のプラットフォームで動作させる必要がありました。私もしませんalias g=gitが代わりに持っていますg関数として定義しました。

これを達成するために、ここではさまざまな答えを1つのソリューションにまとめる必要がありました。これはすでに答えを繰り返しますが、私は私のボートの誰かがこの質問に最初に来たときに私が持っているようにこの編集が有用であると思うかもしれないと思いました。

これは、新旧の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.