एलियास के साथ काम करने के लिए मैं बैश पूरा कैसे करूं?


195

इसका स्पष्ट उदाहरण:

मैं मैक पर bash v3.2.17 के साथ हूँ, मैं bash_completion संस्करण के साथ macports के माध्यम से स्थापित git का उपयोग कर रहा हूँ।

जब मैं टाइप git checkout m<tab>। उदाहरण के लिए, मैं इसे पूरा करता हूं master

हालांकि, मैं करने के लिए एक अन्य नाम मिल गया है git checkout, gco। जब मैं टाइप करता हूं gco m<tab>, तो मुझे शाखा का नाम स्वत: प्राप्त नहीं होता है।

आदर्श रूप में मैं अपने सभी उपनामों के लिए जादुई रूप से काम करने के लिए स्वतः पूर्णता चाहूंगा। क्या यह संभव है? असफल होना, मैं इसे प्रत्येक उपनाम के लिए मैन्युअल रूप से अनुकूलित करना चाहूंगा। तो, मैं कैसे जाऊं?


3
पूरा-डिफॉल्ट -o नोस्पेस-एफ आजकल काम नहीं करता है
अट्ठाइस

5
शीर्ष उत्तर की तुलना में अधिक upvotes के साथ प्रश्न अक्सर महान सुविधा अनुरोधों का
Ciro Santilli 郝海东 otes otes otes 六四

2
सुपरयुजर के एक अन्य उत्तर के रूप में किसी ने मुझे बताया कि मेरा प्रश्न इस एक का एक था। superuser.com/questions/436314/…
dstarh

जवाबों:


183

जैसा कि ऊपर टिप्पणी में कहा गया है,

complete -o default -o nospace -F _git_checkout gco

अब काम नहीं करेगा। हालांकि, __git_completegit-complete.bash में एक फंक्शन है, जिसका उपयोग एलियास जैसे पूरा करने के लिए सेट किया जा सकता है:

__git_complete gco _git_checkout

6
यह एकमात्र सही उत्तर है जो मैंने कई गलत लोगों के बीच देखा है।
अठाइस

45
यदि आप git के लिए वैश्विक उपनाम "g" का उपयोग करते हैं, तो आप __git_complete g __git_mainसभी git कमांड पर काम कर रहे कोड को पूरा करने के लिए भी जोड़ सकते हैं ।
ओन्ड्रेज मचुल्दा

5
^ ^ उन नए के लिए git / shell / bash। उपरोक्त टिप्पणी एक वैश्विक शेल उर्फ ​​को संदर्भित करती है, न कि एक देशी गित उर्फ ​​को।
एलिजा लिन

14
मुझे यह कहां लगाना चाहिए?
बेन्रेगन

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किसी कारणवश मैक ओएस एक्स पर काम नहीं करती थी। इसे बदलकर इसे ((COMP_CWORD+=$num_alias_arguments))ठीक कर दिया गया
मारियो एफ

5
वाह, यह बहुत बढ़िया है - धन्यवाद! wrap_aliasउपनाम की परिभाषा में दोहरे उद्धरण चिह्नों पर चुटकुले, और मुझे लगता है कि यह मल्टी-कमांड उपनाम ( alias 'foo=bar; baz') के लिए बहुत मायने नहीं रखता है , इसलिए मैं इसके | grep -v '[";|&]'बाद एक अतिरिक्त डाल रहा हूं alias -p। साथ ही, यह सैकड़ों उर्फ ​​परिभाषाओं के लिए थोड़ा धीमा हो जाता है, लेकिन मुझे यह पुष्टि करने में खुशी हो रही है कि आउटपुट echoका उपयोग करके evalऔर कैश फ़ाइल में पाइपिंग करके (जो कि तब evalएक ही समय में एड हो सकता है ) ठीक काम करता है और सुपर-फास्ट है ।
जो लिस

2
एक और संकेत: wrap_aliasको पूरा करने की आवश्यकता है, इसलिए मुझे कोड के source /etc/bash_completionसामने चलना पड़ा wrap_alias
जो लिस

2
लाइन let COMP_CWORD+=$num_alias_argumentsको बदलने के बाद इसने OS X 10.7.2 पर मेरे लिए काम किया let \"COMP_CWORD+=$num_alias_arguments\"
आईआरएच

7
पर इस स्क्रिप्ट का अद्यतन संस्करण देखें superuser.com/a/437508/102281 (उदाहरण के लिए, मैं COMP_LINE और COMP_POINT जो कुछ Git पूर्ण करने के लिए आवश्यक हैं के लिए समर्थन जोड़ा)।
जॉन मेलोर

18

में git-completion.bashएक पंक्ति है:

complete -o default -o nospace -F _git git

उस लाइन (और _itit फ़ंक्शन) को देखते हुए आप इस लाइन को अपने साथ जोड़ सकते हैं .bash_profile:

complete -o default -o nospace -F _git_checkout gco

4
के कुछ Git * बैश कार्यों अब काम इस पद्धति का उपयोग
cmcginty

हाँ यह तब तक बहुत अच्छा काम करता था जब तक git_completion.bash में कुछ बदल नहीं जाता ... अब यह पूर्ण कमांड के साथ काम करता है लेकिन उपनाम के साथ नहीं।
माइकल स्मिथ

इस पृष्ठ का अंत उन उत्तरों के लिए देखें जो आधुनिक git में काम करते हैं।
अठारह

क्या हमें "सही एक" होने के लिए स्वीकार किए गए उत्तर को नहीं बदलना चाहिए, या कम से कम परिवर्तन को प्रतिबिंबित करने के लिए स्वीकृत उत्तर को अपडेट करना चाहिए?
टोनी के।

: - यह अच्छी तरह से काम करता है मेरी .bash_profile को यह जोड़ा, और साथ और अन्य नाम के बिना अब तक ठीक काम करता है github.com/larrybotha/dotfiles/blob/master/...
लैरी

15

मेरे पास गियास = 'git' है, और मेरे git उपनाम के साथ मिलकर मुझे चीजें पसंद हैं

$ g co <branchname>

मेरे विशिष्ट उपयोग के मामले के लिए सरल निर्धारण एक लाइन को गिट-पूरा करने के लिए जोड़ना था।

इस पंक्ति के ठीक नीचे:

__git_complete git _git

मैंने इस लाइन को अपने एकल 'जी' उपनाम से जोड़ा:

__git_complete g _git

2
(मैं Cygwin का उपयोग कर रहा हूँ।) मैं फ़ाइल git-completionया उस लाइन को नहीं ढूँढ सका /etc/bash_completion.d/git, लेकिन मैंने complete -o default -o nospace -F _git gअपने उपनाम के बाद जोड़ा .bash_aliasesऔर यह काम कर गया!
इडबरी 19

खबरदार, कि यदि आप किसी फ़ाइल को /etc/bash-completion.d/नए या नए रूप में संपादित करते हैं /usr/share/bash-completion/, तो आप अपने बदलावों को तब खो देंगे जब तक कि फ़ाइल आपके पैकेज मैनेजर का उपयोग करके अपडेट नहीं हो जाती।
kub1x

14

आदर्श रूप में मैं अपने सभी उपनामों के लिए जादुई रूप से काम करने के लिए स्वतः पूर्णता चाहूंगा। क्या यह संभव है?

हां, यह पूर्ण-उर्फ प्रोजेक्ट (लिनक्स पर) के साथ संभव है । मैक के लिए समर्थन प्रयोगात्मक है लेकिन उपयोगकर्ताओं ने सफलता की सूचना दी है।


4
बहुत बहुत धन्यवाद, यह पता लगाने से बेहतर है कि दुनिया की हर उपयोगिता कैसे पूरी होती है।
आर्टम

2
दरअसल, मुझे कुछ समय के लिए उपनामों को पूरा करने से बचाया।
समीर अलजमोविक

2
लिनक्स पर एक आकर्षण की तरह काम करता है (मैक पर परीक्षण नहीं किया गया)। इसे लिखने के लिए धन्यवाद!
बिटमैस्क

1
यह सादा भयानक है! यह सिर्फ काम करता है, चारों ओर कोई उपद्रव नहीं, बहुत बेहतर! धन्यवाद!
ईएम

5

आप Git उपनामों का उपयोग करके भी देख सकते हैं। उदाहरण के लिए, मेरी ~/.gitconfigफ़ाइल में, मेरा एक खंड है जो इस तरह दिखता है:

[alias]
        co = checkout

तो आप टाइप कर सकते हैं git co m<TAB>, और इसका विस्तार करना चाहिए git co master, जो कि git 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

यह समाधान बेल्शेज़र की स्क्रिप्ट के समान है , लेकिन यह केवल मेरे लिए वास्तव में काम करता है। (बालशेज़र की स्क्रिप्ट में मेरे कुछ उपनामों की समस्या थी।)


; यह लगभग काम करता है - मुझे कुछ त्रुटियां मिलती हैं, लेकिन पूरा होने से गुजरता है। क्या मैं कुछ और कर सकता हूँ? -bash: eval: line 28: unexpected EOF while looking for matching ''' -bash: eval: line 29: syntax error: unexpected end of file
13

@ ओफ़रन मैं उपरोक्त मुद्दों को उद्धृत करते हुए देख सकता हूं ... स्ट्रिंग के "अंदर के उद्धरण को functionउद्धृत किया जाना चाहिए \"। यह शायद आपके 'किसी उद्धरण को रेखा के साथ खाता है ।
टॉम हेल

5

एक और विकल्प ~/.bash_completionफ़ाइल का उपयोग करना है। इसे वहां लगाने के gcoलिए उपनाम बनाने के लिए git checkout:

_xfunc git __git_complete gco _git_checkout

फिर ~/.bashrcआपको केवल खुद को उर्फ ​​रखना होगा:

alias gco='git checkout'

दो लाइनें। बस।

स्पष्टीकरण:

~/bash_completionमुख्य bash_completion स्क्रिप्ट के अंत में sourced हो जाता है। जेंटू में मुझे मुख्य स्क्रिप्ट मिली /usr/share/bash-completion/bash_completion

_xfunc gitबिट सोर्सिंग का ख्याल रखता है git-completionआप के लिए फ़ाइल ताकि आप में कुछ और डाल करने के लिए की जरूरत नहीं है ~/.bashrc

स्वीकृत उत्तर के लिए आपको .git-completion.shअपनी ~/.bashrcफ़ाइल से प्रतिलिपि बनाने और स्रोत करने की आवश्यकता होती है जो मुझे लंगड़ा लगता है।


पुनश्च: मैं अभी भी यह पता लगाने की कोशिश कर रहा हूं कि पूरी git-completionस्क्रिप्ट को मेरे बैश वातावरण में कैसे न करें । अगर आपको कोई रास्ता मिल जाए तो कृपया टिप्पणी करें या संपादित करें।


क्यों _xfunc gitआवश्यक है?
टॉम हेल

@TomHale मैंने उत्तर को बेहतर बनाने का प्रयास किया। करने के बजाय source ~/.git-completion.shमैंने उसे _xfuncअपने लिए करने दिया। यह केवल अच्छे और साफ महसूस करता है कि इसे पूरी तरह से करना है ~/.bash_completion। बिना _xfunc(या सोर्सिंग) __git_completeफ़ंक्शन मौजूद नहीं है।
kub1x

1
~/.bash_completionफ़ाइल के लिए कोई ज़रूरत नहीं है - _xfuncलाइन मेरे लिए काम करती है .bashrc
टॉम हेल

2

आपको बस completeकमांड ढूंढनी है और लाइन को उपनाम नाम की जगह डुप्लिकेट करना है।

मेरे पास है alias d-m="docker-machine"। शब्दों में, के d-mलिए उपनाम होगा docker-machine

तो मैक पर (काढ़ा के माध्यम से), पूर्ण होने वाली फाइलें अंदर हैं 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अधिक जटिल है।
वारबैंक

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: पूर्ण: फ़ंक्शन '_docker' नहीं मिला" जैसी त्रुटि मिल सकती है।


1

इस सवाल के बहुत सारे उत्तर हैं और खुद की तरह मैं बहुत सारे भ्रमित पाठकों की शर्त लगाता हूं। मेरे मामले के लिए मुझे कई प्लेटफ़ॉर्म पर Git के विभिन्न संस्करणों के साथ अपने डॉटफ़ाइल्स का काम करने की आवश्यकता थी। मैं भी नहीं alias g=gitबल्कि gएक समारोह के रूप में परिभाषित किया है।

इसे पूरा करने के लिए मुझे अलग-अलग उत्तरों को एक साथ एक हल में थप्पड़ मारना था। यद्यपि यह उन उत्तरों को पहले से ही दोहराता है जो मैंने पहले ही सोचा था कि मेरी नाव में कोई व्यक्ति इस संकलन को उपयोगी पा सकता है जैसा कि मेरे पास पहली बार होगा जब मैं इस प्रश्न पर आया था।

यह पुराने और नए Git के पूरा होने, उबंटू की चूक और brew install gitMacOS को मानता है । बाद के मामले में शराब की भठ्ठी स्थापित की पूरी प्रक्रिया को दंश द्वारा संसाधित नहीं किया जा रहा था (कुछ मैं बाद में निदान करूंगा)।

# 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

यदि आप उपयोग करते हैं alias g='git', तो मैं इस कोड को कोड में जोड़ता हूं.bash_aliases

complete -o default -o nospace -F _git g
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.