Takma adlarla çalışmak için bash tamamlamasını nasıl edinebilirim?


195

Konuşma konusu olan mesele:

Ben bash v3.2.17 ile bir mac üzerinde, bash_completion varyantı ile macports üzerinden yüklü git kullanıyorum.

Ben yazarken git checkout m<tab>. örneğin, tamamlanmasını sağladım master.

Ancak, ben için bir takma ad var git checkout, gco. Ben yazarken gco m<tab>, ben otomatik olarak tamamlanıp tamamlanmayacağını şube adını alamadım.

İdeal olarak, otomatik tamamlamanın sihirli bir şekilde tüm takma adlarım için çalışmasını istiyorum. Mümkün mü? Başarısız olursa, her takma ad için manuel olarak özelleştirmek istiyorum. Peki, ben de nasıl gideceğim?


3
complete -o default -o nospace -F günümüzde çalışmıyor
eighteyes

5
Üst cevap daha upvotes ile Sorular genellikle büyük ima özellik istekleri
Ciro Santilli郝海东冠状病六四事件法轮功

2
Biri bana süper sorudan gelen bir başka cevap, sorumun bunun bir çiftliği olduğunu belirtti. superuser.com/questions/436314/…
dstarh

Yanıtlar:


183

Yukarıdaki yorumlarda belirtildiği gibi,

complete -o default -o nospace -F _git_checkout gco

artık çalışmaz. Bununla birlikte, __git_completegit-completion.bash içinde aşağıdaki gibi takma adlar için tamamlamayı ayarlamak üzere kullanılabilecek bir işlev vardır :

__git_complete gco _git_checkout

6
Birçok yanlış cevap arasında gördüğüm tek doğru cevap bu.
sekizey

45
Git için genel "g" takma adı kullanırsanız __git_complete g __git_main, tüm git komutlarında kod tamamlama işlevinin çalışmasını da ekleyebilirsiniz .
Ondrej Machulda

5
^^ Git / shell / bash için yeni olanlar için. Yukarıdaki yorum, yerel bir git diğer adını değil, genel bir kabuk diğer adını belirtir.
Elijah Lynn

14
Bunu nereye koymalıyım?
benregn

15
Sonunda bunu düzgün bir şekilde nasıl yapacağını anladım! Adım 1) git-completion.bash' <your git install folder>/etc/bash-completion.d/den ~/.git-completion.bash Adım 2'ye kopyalayın ) Adım 3'e ekleyin source ~/.git-completion.bash. .bash_profile) __git_complete gco _git_checkout.Bash_profile dosyanızdaki yukarıdaki satırdan sonra herhangi bir yere ekleyin . Adım 4) kabuğu yeniden başlatın ve takma ad otomatik tamamlama tadını çıkarın! :)
kpsfoo

54

Ben de bu sorunla karşılaştı ve bu kod snippet ile geldi. Bu, tüm takma adlar için otomatik olarak tamamlanmanızı sağlar. Tüm (veya herhangi bir) diğer adı bildirdikten sonra çalıştırın.

# 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
hat let COMP_CWORD+=$num_alias_argumentsMac OS X'te herhangi bir nedenle çalışmadı. ((COMP_CWORD+=$num_alias_arguments))Sabit olsa ile değiştirilmesi
Mario F

5
Vay canına, bu harika - teşekkürler! wrap_aliastakma ad tanımında çift tırnak boğuluyor ve sanırım çok komutlu takma adlar ( alias 'foo=bar; baz') için pek mantıklı değil , bu yüzden | grep -v '[";|&]'sonra bir ekstra koyuyorum alias -p. Ayrıca, yüzlerce takma ad tanımlaması için biraz yavaşlaşıyor, ancak çıktıyı bir önbellek dosyası echoyerine kullanmanın evalve daha sonra evalbir seferde düzenlenebileceğinin doğru çalıştığını ve süper hızlı olduğunu onaylamaktan mutluluk duyuyorum. .
Jo Liss

2
Başka bir ipucu: wrap_aliastamamlamaların ayarlanmasını gerektirir, bu yüzden kodun source /etc/bash_completionönünde hareket etmek zorunda kaldım wrap_alias.
Jo Liss

2
Bu çizgi değiştirdikten sonra OS X 10.7.2 üzerinde benim için çalıştı let COMP_CWORD+=$num_alias_argumentsiçin let \"COMP_CWORD+=$num_alias_arguments\".
irh

7
Bu komut dosyasının güncellenmiş sürümüne superuser.com/a/437508/102281 adresinden bakın (örneğin, bazı git tamamlamaları için gerekli olan COMP_LINE ve COMP_POINT için destek ekledim).
John Mellor

18

Gelen git-completion.bashbir çizgi vardır:

complete -o default -o nospace -F _git git

Bu satıra (ve _git işlevine) bakarak bu satırı şu öğelere ekleyebilirsiniz .bash_profile:

complete -o default -o nospace -F _git_checkout gco

4
git * bash işlevlerinden bazıları artık bu yöntemi kullanarak çalışmaz
cmcginty

Evet bu git_completion.bash içinde bir şey değişene kadar harika çalışırdı ... Şimdi tam komutla çalışıyor, ancak takma adla çalışmıyor.
Michael Smith

Modern git'te çalışan cevaplar için bu sayfanın sonuna bakın.
sekizey

Kabul edilen cevabı "doğru cevap" olarak değiştirmemeli mi yoksa en azından kabul edilen cevabı değişikliği yansıtacak şekilde güncellememeli miyiz?
Tony K.

bu iyi çalışıyor - bunu .bash_profile'ıma ekledi ve şu ana kadar takma adlarla ve takma adlar olmadan iyi çalışıyor: github.com/larrybotha/dotfiles/blob/master/…
Larry

15

G = 'git' takma adını aldım ve git takma adlarımla birleştirdim

$ g co <branchname>

Özel kullanım durumum için daha basit düzeltme, git-completion'a tek bir satır eklemekti.

Bu satırın hemen altında:

__git_complete git _git

Bu satırı tek 'g' takma adımı işlemek için ekledim:

__git_complete g _git

2
(Cygwin kullanıyorum.) Dosyayı git-completionveya o satırı bulamadım /etc/bash_completion.d/git, ancak complete -o default -o nospace -F _git gtakma adımdan sonra ekledim .bash_aliasesve işe yaradı!
idbrii

Bir dosyayı /etc/bash-completion.d/içeri veya daha yeni bir dosyada düzenlerseniz /usr/share/bash-completion/, bu dosya paket yöneticinizi kullanarak her güncellendiğinde değişikliklerinizi kaybedeceğinizi unutmayın.
kub1x

14

İdeal olarak, otomatik tamamlamanın sihirli bir şekilde tüm takma adlarım için çalışmasını istiyorum. Mümkün mü?

Evet, tam takma ad projesiyle (Linux'ta) mümkündür. Mac desteği deneyseldir ancak kullanıcılar başarılı olduklarını bildirmiştir.


4
Çok teşekkürler, bu dünyadaki her yardımcı programın bash tamamlamasını nasıl uyguladığını bulmaktan çok daha iyi.
artm

2
Gerçekten, takma adlar için tamamlamaları yapılandırırken biraz zaman kazandım.
Samir Alajmovic

2
Linux'ta cazibe gibi çalışır (Mac'te test edilmemiştir). Yazdığınız için teşekkürler!
bitmask

1
Bu sade harika! Sadece çalışıyor, etrafında karışıklık yok, çok daha iyi! Teşekkürler!
emi

5

Git takma adlarını kullanmayı da deneyebilirsiniz. Örneğin, ~/.gitconfigdosyamda, şuna benzer bir bölüm var:

[alias]
        co = checkout

Yani yazabilirsiniz git co m<TAB>ve bu genişletmek gerektiğini git co masterolan git checkoutkomut.


5

Bu forum sayfası bir çözüm gösterir.

SİZİN içine şu satırları koyun .bashrcveya .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

Bu çözüm balshetzer'in senaryosuna benziyor , ancak sadece bu aslında benim için çalışıyor. (balshetzer'in senaryosunda bazı takma adlarla ilgili sorunlar vardı.)


; Bu neredeyse işe yarıyor - birkaç hata alıyorum, ancak tamamlanma geçiyor. Yapabileceğim başka bir şey var mı? -bash: eval: line 28: unexpected EOF while looking for matching ''' -bash: eval: line 29: syntax error: unexpected end of file
pforhan

@pforhan Yukarıdaki alıntıları görebiliyorum ... dizenin "içindeki tırnaklar functionolarak alıntılanmalıdır \". Bu muhtemelen 'alıntılarınızdan birini satır boyunca bir yerde yiyor .
Tom Hale

5

Bir seçenek daha ~/.bash_completiondosya kullanmaktır . Bunu takmak için gcotakma ad oluşturmak için git checkout:

_xfunc git __git_complete gco _git_checkout

Sonra ~/.bashrcsadece takma adın kendisini koymak zorundasınız:

alias gco='git checkout'

İki çizgi. Bu kadar.

Açıklama:

~/bash_completionAna bash_completion komut sonunda kaynaklı alır. Gentoo'da ana senaryoyu/usr/share/bash-completion/bash_completion .

_xfunc gitBit kaynak ilgilenir git-completionsen başka bir şey koymak gerekmez, böylece sizin için dosyayı ~/.bashrc.

Kabul edilen cevap, topal bulduğum dosyanızdan kopyalamanızı .git-completion.shve kaynaklamanızı gerektirir ~/.bashrc.


PS: Hala tüm git-completionbetiği bash ortamıma nasıl kaynaklayamayacağımı anlamaya çalışıyorum . Bir yol bulursanız lütfen yorum yapın veya düzenleyin.


Neden _xfunc gitgerekli?
Tom Hale

@TomHale Cevabı geliştirmeye çalıştım. Bunu yapmak yerine benim için yapmama source ~/.git-completion.shizin verdim _xfunc. Sadece yapmak daha güzel ve daha temiz hissettiriyor ~/.bash_completion. _xfunc(Veya kaynak sağlama) olmadan __git_completeişlev mevcut değildir.
kub1x

1
~/.bash_completionDosyaya gerek yok - _xfunchat benim için çalışıyor .bashrc.
Tom Hale

2

Sadece completekomutu bulmalı ve bunun yerine takma ada sahip satırı çoğaltmalısınız.

Var alias d-m="docker-machine". Yani, d-miçin takma ad olacaktır docker-machine.

Mac'te (demlemek yoluyla), tamamlama dosyaları içeride cd `brew --prefix`/etc/bash_completion.d/.
Benim durumum için adlı dosyayı düzenledim docker-machine.
En alttaki yol vardı:

complete -F _docker_machine docker-machine

Takma adımla yeni bir satır daha ekledim:

complete -F _docker_machine docker-machine
complete -F _docker_machine d-m

Gibi bu, basit için en iyi çözümü (bire bir) takma adları olan dockerdiğer adı d. Her ne kadar sorudaki örnek için, git checkouttakma adı gcodaha karmaşıktır.
wisbucky

1

İlk olarak, orijinal tamamlama komutuna bakın. Misal:

$ complete | grep git

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

Şimdi bunları başlangıç ​​komut dosyasına ekleyin (örn. ~ / .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Çizgi gerekmeyebilir. Ancak bazı durumlarda, tamamlama işlevi yalnızca komutu yazıp TABilk kez basıldıktan sonra dinamik olarak yüklenir . Dolayısıyla, orijinal komutu kullanmadıysanız ve + diğer adını deneyin, TAB"bash: completion: function '_docker' bulunamadı" gibi bir hata alabilirsiniz.


1

Bu sorunun birçok yanıtı var ve kendim gibi birçok şaşkın okuyucuya bahse girerim. Benim durumum için, nokta dosyalarının Git'in farklı sürümlerine sahip birden fazla platformda çalışması için gereksinimim vardı. Bende değil alias g=gitama onun yerineg bir işlev olarak tanımladım.

Bunu başarmak için burada farklı cevapları tek bir çözümde tokatlamak zorunda kaldım. Her ne kadar bu cevapları tekrarlasa da teknemdeki birisinin bu derlemeyi bu soruya ilk geldiğimde olduğu gibi yararlı bulabileceğini düşündüm.

Bu, eski ve daha yeni Git tamamlama, Ubuntu varsayılanları ve MacOS'ta olduğunu varsayar brew install git. Daha sonraki durumda, demlemek kurulum tamamlamaları bash tarafından işlenmiyordu (daha sonra teşhis edeceğim bir şey).

# 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

0

Kullanırsanız alias g='git', bu kod satırını.bash_aliases

complete -o default -o nospace -F _git g
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.