最近のbashの完成で既存の完成を再利用する方法は?

最近のbashの完成で既存の完成を再利用する方法は?

私は使うニックネーム一部のプログラムにいくつかのパラメータを追加します。

たとえば、

alias git.home='git --git-dir=$HOME/.git.home/'

complete -o bashdefault -o default -o nospace -F _git git.home \
  2>/dev/null || complete -o default -o nospace -F _git git.home

bash-completion v.1:2.0-1(「debian 7 wheezy」)で動作します:完全な
tabパラメータとオプションニックネーム git.homeそして「原本」git

しかし、(「debian 8 jessie」)を入力して押すと、bash-completion v.1:2.1-4次のエラーが表示されます。git.hometab

bash:完了: '_git'関数が見つかりません。

git最新バージョンのパッケージで既存の完成(for)を再利用するにはどうすればよいですかbash-completion


修正する

部分的な解決策を探す:source /usr/share/bash-completion/completions/git以前に実行complete ...

しかし、別のエラーが発生します。 - git.home log+ space+tab結果:

致命的:gitリポジトリ(または親ディレクトリ)ではありません:.git HEAD

答え1

最新バージョンのbash-completionパッケージ(gitなど)で既存の完成を再利用する方法

次の行を次の行に追加します~/.bashrc

_completion_loader git
eval $(complete -p git | perl -pe 's/(\s)git$/$1git.home/')

説明する:

bash-completionこれは動的ローディングを使用して行われます。1.90。したがって、 をgit入力するまで compspec は使用できませんgitSpaceTab

努力する:

bash
complete -p git # bash: complete: git: no completion specification
git<space><tab>
complete -p git # complete -o bashdefault -o default -o nospace -F __git_wrap__git_main git

_completion_loader git模倣git, Space, Tab(つまり、ロードされた compspec git)

complete -p git | perl -pe 's/(\s)git$/$1git.home/'次のためのcompspecビルド(aのcompspecをgit.home置き換える)gitgit.homegit

eval生成された compspec を実行します。

タイプgit.home、、、。SpacepTabあなたは見なければなりません:

popt   pull   push

しかし、 git.home log、、Space生産するTab

致命的:gitリポジトリ(または親ディレクトリ)ではありません:.git HEAD

このメッセージはgit完了エラーの結果です。アップストリームに修正があります。完了:「致命的:gitリポジトリではありません」エラーを停止します。

もう一つの質問のようです:)

_githome(){ 
   GIT_DIR=$HOME/.git.home
   complete -o default -o nospace -F _git git.home
 }

期待どおりに動作しません。GIT_DIR現在のセッションに設定しました。回避策を試してください。

bash
git clone git://git.debian.org/git/bash-completion/bash-completion.git ~/bash-completion
cd ~/bash-completion
git log<space><tab> # completion for current repo
git.home log<space><tab> # completion for GIT_DIR
git log<space><tab> # completion for GIT_DIR

答え2

修正する

解決策ニックネーム git.home、repoで実行されます~/.git.home

部分的に基づくこの回答

次に追加~/.bashrc:

alias git.home='git --git-dir=$HOME/.git.home/'

_completion_loader git
eval "$(complete -p git | sed -r 's/(\s)git$/\1git.home/')"

eval "$(type __gitdir | 
  sed '1d;1,/if/s|if|if [[ "$COMP_LINE" == "git.home "* ]]; then\necho "$HOME/.git.home"\nelif|')"

最終説明eval(他のルートについては、以下を参照してください。回答):

__gitdir()git repoディレクトリへのパスを返す関数にパッチを当てています。から:

$ type __gitdir | head -n 4
__gitdir is a function
__gitdir () 
{ 
    if [ -z "${1-}" ]; then

到着する:

$ type __gitdir | head -n 7
__gitdir is a function
__gitdir () 
{ 
    if [[ "$COMP_LINE" == "git.home "* ]]; then
        echo "$HOME/.git.home";
    else
        if [ -z "${1-}" ]; then

つまり、コマンドがaで始まると、"git.home "関数はを返します$HOME/.git.home

答え3

これはすべての完成機能に適用される一般的な答えです。 1行の出力がsedORとして解析され、perl外部呼び出しなしで実装できると仮定すると、他の回答の安全性が心配されます。

# Usage: complete_as TARGET COMMAND [COMMAND...]
# Tab-complete one or more COMMANDs like TARGET
complete_as() {
  _completion_loader "$1"
  local completion="$(complete -p "$1")"
  completion="${completion%[[:space:]]$1}"
  shift
  eval "$completion $@"
}
complete_as git git.home

以前の回答のコードと同様に、sedこれはターゲットコマンド()の最後のインスタンスを新しいコマンド()に置き換えますが、perl$1$2パラメータの置換、出力の各行で作業するのではなく、内容全体を見てください。完成関数の出力には時々(の場合のように)末尾に改行文字があるため、これは重要ですcomplete -W "$(_parse_help foo)" foo。外部通話を削除すると速度も速くなりますが、頻繁に行うとわかります。

__gitdir同様の機能を修正するために、同様のセキュリティを構築し、bash 置換を使用することができます。アレクサンダー・バラキンの答えする。

また、見ることができますこのzshソリューション同じ問題について。

関連情報