मैं अपने उपनामों के लिए टैब-पूरा करने के लिए कैसे बैश हो सकता हूं?


45

मेरे पास बैश पूरा करने वाली स्क्रिप्ट्स का एक समूह है (ज्यादातर बैश-इट और कुछ मैन्युअल सेटअप का उपयोग करके)।

मैं भी तरह सामान्य कार्यों के लिए उपनाम सेटअप का एक समूह है gcoके लिए git checkout। अभी मैं टाइप कर सकता हूं git checkout dTabऔर developमेरे लिए पूरा हो गया है लेकिन जब मैं टाइप gco dTabकरता हूं तो वह पूरा नहीं होता।

मैं यह मान रहा हूं क्योंकि पूरी स्क्रिप्ट पूरी हो रही है gitऔर यह देखने में विफल है gco

क्या मेरे एलियास के साथ काम करने के लिए मेरी पूरी स्क्रिप्ट्स को उदारतापूर्वक / प्रोग्रामेटिक तरीके से प्राप्त करने का कोई तरीका है? उपनाम के उद्देश्य को हराकर अन्य प्रकार का उपयोग करने पर पूरा नहीं हो पा रहा है।


आप किस ओएस और बैश का उपयोग कर रहे हैं? मैं उबंटू 11.10 पर हूं और 4.2.10 (1) -release (x86_64-pc-linux-gnu) और मैं अपने कई उपनामों के लिए अपने शेल में बनाया गया यह फ़ंक्शन है। btw bash --versionइसे पाने के लिए (उपयोग न करें -v, अलग-अलग आउटपुट)।
माइकल डुरंट

क्षमा करें, जानकारी के बारे में बहुत कुछ याद नहीं है - OSX शेर, GNU बैश, संस्करण 3.2.48 (1) -release (x86_64-apple-darwin11)
dstarh

1
@killermist: जब तक मैं पूरी तरह से गलत नहीं हो जाता, तब तक zsh बॉक्स से बाहर अलियासाइड कमांड को पूरा नहीं करता। एक फ़ंक्शन को कार्यान्वित करना जो परिभाषित उपनामों को पूरा करने के लिए जोड़ता है, बैश की तुलना में बहुत आसान प्रतीत होता है, हालांकि, जैसे कि एसवीएस के पूरा होने के सिस्टम को बैश की तुलना में अधिक शक्तिशाली और अधिक सीधा दोनों लगता है।
कोप्सिएक

क्रॉस साइट डुप्लिकेट: stackoverflow.com/questions/342969/…
Ciro Santilli 新疆 over over over

1
@MichaelDurrant क्या आपको यकीन है कि यह वास्तव में उपनामों के लिए बनाया गया है? मैं बैश 4.3.42 (1) -release (x86_64-pc-linux-gnu) के साथ Ubuntu 15.10 पर हूं और ऐसी कोई बात नहीं है। मैंने कुछ पहले रिलीज का भी परीक्षण किया। उदाहरण के लिए यदि आप इसमें टाइप करते हैं तो इसके लिए ll --[TAB]विकल्पों की सूची प्रिंट करेंगे ls? मुझे इस पर बहुत संदेह है, लेकिन अगर आपको यकीन है कि इस तरह की चीज 11.10 में मौजूद है, तो मैं इसके माध्यम से खुदाई करने और इसे हटाने के लिए उत्सुक हूं।
छह

जवाबों:


42

निम्नलिखित कोड, इस ढेर अतिप्रवाह उत्तर से अनुकूलित है और यह उबंटू फ़ोरम चर्चा धागा आपके सभी परिभाषित उपनामों के लिए पूर्णता जोड़ देगा:

# Automatically add completion for all aliases to commands having completion functions
function alias_completion {
    local namespace="alias_completion"

    # parse function based completion definitions, where capture group 2 => function and 3 => trigger
    local compl_regex='complete( +[^ ]+)* -F ([^ ]+) ("[^"]+"|[^ ]+)'
    # parse alias definitions, where capture group 1 => trigger, 2 => command, 3 => command arguments
    local alias_regex="alias ([^=]+)='(\"[^\"]+\"|[^ ]+)(( +[^ ]+)*)'"

    # create array of function completion triggers, keeping multi-word triggers together
    eval "local completions=($(complete -p | sed -Ene "/$compl_regex/s//'\3'/p"))"
    (( ${#completions[@]} == 0 )) && return 0

    # create temporary file for wrapper functions and completions
    rm -f "/tmp/${namespace}-*.tmp" # preliminary cleanup
    local tmp_file; tmp_file="$(mktemp "/tmp/${namespace}-${RANDOM}XXX.tmp")" || return 1

    local completion_loader; completion_loader="$(complete -p -D 2>/dev/null | sed -Ene 's/.* -F ([^ ]*).*/\1/p')"

    # read in "<alias> '<aliased command>' '<command args>'" lines from defined aliases
    local line; while read line; do
        eval "local alias_tokens; alias_tokens=($line)" 2>/dev/null || continue # some alias arg patterns cause an eval parse error
        local alias_name="${alias_tokens[0]}" alias_cmd="${alias_tokens[1]}" alias_args="${alias_tokens[2]# }"

        # skip aliases to pipes, boolean control structures and other command lists
        # (leveraging that eval errs out if $alias_args contains unquoted shell metacharacters)
        eval "local alias_arg_words; alias_arg_words=($alias_args)" 2>/dev/null || continue
        # avoid expanding wildcards
        read -a alias_arg_words <<< "$alias_args"

        # skip alias if there is no completion function triggered by the aliased command
        if [[ ! " ${completions[*]} " =~ " $alias_cmd " ]]; then
            if [[ -n "$completion_loader" ]]; then
                # force loading of completions for the aliased command
                eval "$completion_loader $alias_cmd"
                # 124 means completion loader was successful
                [[ $? -eq 124 ]] || continue
                completions+=($alias_cmd)
            else
                continue
            fi
        fi
        local new_completion="$(complete -p "$alias_cmd")"

        # create a wrapper inserting the alias arguments if any
        if [[ -n $alias_args ]]; then
            local compl_func="${new_completion/#* -F /}"; compl_func="${compl_func%% *}"
            # avoid recursive call loops by ignoring our own functions
            if [[ "${compl_func#_$namespace::}" == $compl_func ]]; then
                local compl_wrapper="_${namespace}::${alias_name}"
                    echo "function $compl_wrapper {
                        (( COMP_CWORD += ${#alias_arg_words[@]} ))
                        COMP_WORDS=($alias_cmd $alias_args \${COMP_WORDS[@]:1})
                        (( COMP_POINT -= \${#COMP_LINE} ))
                        COMP_LINE=\${COMP_LINE/$alias_name/$alias_cmd $alias_args}
                        (( COMP_POINT += \${#COMP_LINE} ))
                        $compl_func
                    }" >> "$tmp_file"
                    new_completion="${new_completion/ -F $compl_func / -F $compl_wrapper }"
            fi
        fi

        # replace completion trigger by alias
        new_completion="${new_completion% *} $alias_name"
        echo "$new_completion" >> "$tmp_file"
    done < <(alias -p | sed -Ene "s/$alias_regex/\1 '\2' '\3'/p")
    source "$tmp_file" && rm -f "$tmp_file"
}; alias_completion

साधारण (केवल आदेश, कोई तर्क नहीं) उपनाम के लिए यह मूल पूर्ण फ़ंक्शन को उपनाम के लिए असाइन करेगा; तर्कों के साथ उपनामों के लिए, यह एक रैपर फ़ंक्शन बनाता है जो अतिरिक्त तर्कों को मूल पूर्ण फ़ंक्शन में सम्मिलित करता है।

लिपियों के विपरीत, यह विकसित हो गया है, यह फ़ंक्शन उपनाम अन्य कमांड और उसके तर्कों के लिए उद्धरण का सम्मान करता है (लेकिन पूर्व को पूर्ण कमांड द्वारा मिलान किया जाना है, और इसे नेस्टेड नहीं किया जा सकता है), और इसे विश्वसनीय रूप से सूचियों और आदेशों के लिए उपनामों को फ़िल्टर करना चाहिए। पाइप (जो छोड़ दिया जाता है, क्योंकि यह पता लगाना असंभव है कि पूर्ण शेल कमांड लाइन पार्स लॉजिक को फिर से बनाने के बिना उनमें क्या पूरा करना है)।

प्रयोग

या तो एक शेल स्क्रिप्ट फ़ाइल और स्रोत के रूप में कोड को सेव करें या फंक्शन होल को कॉपी करें, या .bashrc(या आपकी सही डॉट फ़ाइल )। महत्वपूर्ण बात यह है कि दोनों को पूरा करने के बाद फ़ंक्शन को कॉल करें और उपनाम की अन्य परिभाषाएँ सेट की गई हैं (उपरोक्त कोड अपनी परिभाषा के ठीक बाद फ़ंक्शन को "स्रोत और भूल जाओ" आत्मा में कॉल करता है, लेकिन आप कॉल को कहीं भी डाउनस्ट्रीम में स्थानांतरित कर सकते हैं यदि आपको बेहतर लगता है)। यदि आप इसे छोड़ने के बाद अपने वातावरण में फ़ंक्शन नहीं चाहते हैं, तो आप unset -f alias_completionइसे कॉल करने के बाद जोड़ सकते हैं ।

टिप्पणियाँ

यदि आप bash4.1 या इसके बाद के संस्करण का उपयोग कर रहे हैं और गतिशील रूप से भरी हुई पूर्णताओं का उपयोग करते हैं, तो स्क्रिप्ट आपके सभी अलियास किए गए आदेशों के लिए पूर्णताओं को लोड करने का प्रयास करेगी ताकि यह आपके उपनामों के लिए आवरण कार्यों का निर्माण कर सके।


1
मैं उस स्क्रिप्ट को कैसे स्थापित करूंगा ?
डेर होकस्टाप्लर

1
@ ऑलिवर साल्ज़बर्ग: आपको इसे अपने शेल प्रोफ़ाइल फ़ाइलों में से एक में प्रोसेस करना होगा, जो कि बैश पूरा होने के बाद महत्वपूर्ण है - जो शायद इसे बनाएगा ~/.bashrc। या तो इसे शेल स्क्रिप्ट फ़ाइल के रूप में संग्रहीत करें और इसे स्रोत ( . /path/to/alias_completion.sh), या कोड को कॉपी और पेस्ट करें।
kopischke

1
@OliverSalzburg: उपयोग के निर्देश जोड़े (अभी आप ओपी नहीं हैं) ध्यान नहीं दिया।
कोप्सिएके

1
@kopischke इस प्रश्न को देखें - जाहिरा तौर पर फाइलों के तहत /usr/share/bash-completion/completions/वे केवल पहली बार लोड होते हैं जब उपयोगकर्ता वास्तव में हिट करता है [TAB]। इसलिए भले ही फ़ंक्शन इससे लोड किया ~/.bashrcगया हो, इसमें एलियन के लिए पूर्ण आदेश उत्पन्न नहीं होंगे। यह सुनिश्चित करने के बाद complete -pके लिए काम कर रहा है apt-getऔर apt-cacheमैं टर्मिनल के लिए अपने कार्य प्रतिलिपि चिपकाया और इसे सही ढंग से काम कर रहा है।
जमादग्नि

1
@kopischke तो मुझे यकीन नहीं है कि सभी गतिशील रूप से भरी हुई फ़ाइलों की सोर्सिंग को कैसे मजबूर किया जाए, या यदि यह उचित हो तो भी। अभी के लिए मैंने जनरेट की हुई पूर्ण फ़ाइल की प्रतिलिपि बनाई /tmpहै ~/.bash_completionऔर मैन्युअल रूप से इसकी प्रासंगिक source /usr/share/bash-completion/completions/प्रविष्टियों ( शुरुआत में apt-getऔर apt-cache- apt-{cache,get}काम नहीं करता है) में जोड़ा है ।
जमदग्नि

4

क्या मेरे एलियास के साथ काम करने के लिए मेरी पूरी स्क्रिप्ट्स को उदारतापूर्वक / प्रोग्रामेटिक तरीके से प्राप्त करने का कोई तरीका है?

हां, यहां पूर्ण-उर्फ परियोजना है जो आपकी समस्या को हल करती है। यह उपयोग किए बिना सामान्य और प्रोग्रामेटिक उपनाम पूरा करता है eval


2

यह उन लोगों के लिए मैनुअल तरीका है, जो इसकी तलाश कर रहे हैं।

सबसे पहले, मूल पूर्ण कमांड को देखें। उदाहरण:

$ complete | grep git

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

अब इन्हें अपनी स्टार्टअप स्क्रिप्ट में जोड़ें (उदाहरण ~ / .bashrc):

# load dynamically loaded completion functions (may not be required)
_completion_loader git

# 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

स्रोत: https://superuser.com/a/1004334

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