ऑटो-पूर्ण के साथ स्क्रिप्ट कैसे बनाएं?


119

जब मैं प्रोग्राम का उपयोग करता हूं जैसे svnऔर मैं सूक्ति टर्मिनल में टाइप करता हूं:

svn upd

और Tabयह स्वतः पूर्ण हो गया:

svn update

क्या मेरे कस्टम बैश स्क्रिप्ट में ऐसा कुछ करना संभव है?


"बैश स्क्रिप्ट" की व्याख्या करें, आपका मतलब किसी स्क्रिप्ट को संपादित करते समय है? आपकी इसके साथ क्या करने की इच्छा है?
ब्रूनो परेरा

3
कंसोल में स्क्रिप्ट का उपयोग करते समय
UAdapter

जहां तक ​​आपकी पूर्णता को रखने की जगह है, इस प्रश्न को देखें और वहां स्वीकृत उत्तर के लिए टिप्पणियां भी।
जरनो

जवाबों:


44

आप प्रोग्रामेबल कम्पलीशन का उपयोग कर सकते हैं । पर नज़र डालें /etc/bash_completionऔर /etc/bash_completion.d/*कुछ उदाहरण के लिए।


130
सीधे सवाल से संबंधित एक साधारण उदाहरण सहित कैसे?
माउंटेनएक्स

2
उबंटू 16 के लिए वास्तविक लिपियों में स्थित हैं/usr/share/bash-completion/completions/<program>
पीटर

16
इमो, उदाहरणों को उत्तर में शामिल किया जाना चाहिए, लिंक में नहीं।
बिलीनाह

2
मेरा मानना ​​है कि इस प्लेटफ़ॉर्म को पूर्ण दस्तावेज़ों के लिए एक अधिक व्यावहारिक विकल्प माना जाता है जो कि एक साधारण Google खोज के साथ मिल सकता है। डॉक्यूमेंटेशन लिंक को डंप करने से मदद नहीं मिलती है। एक लंगर युक्त लिंक निश्चित रूप से बहुत अंतर नहीं करता है।
टिमुइन

4
The provided link has that already- यह आज हो सकता है, लेकिन यह कल नहीं हो सकता। या अगले साल। या एक दशक में। जो कुछ भी आप अभी भी प्रासंगिक होने के बारे में सुझाव दे सकते हैं, स्टैक ओवरफ्लो इन कारणों के लिए लिंक-केवल उत्तरों को हतोत्साहित करता है।
लियाम डॉसन

205

मुझे छह महीने देर हो गई है लेकिन मैं एक ही चीज की तलाश में था और यह पाया:

आपको एक नई फ़ाइल बनानी होगी:

/etc/bash_completion.d/foo

एक स्थैतिक स्वत: पूर्णता के लिए ( --help/ --verboseउदाहरण के लिए) इसे जोड़ें:

_foo() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help --verbose --version"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _foo foo
  • COMP_WORDS वर्तमान कमांड लाइन में सभी व्यक्तिगत शब्दों से युक्त एक सरणी है।
  • COMP_CWORD वर्तमान कर्सर स्थिति वाले शब्द का एक सूचकांक है।
  • COMPREPLY एक सरणी वैरिएबल है जिसमें से बैश संभावित पूर्णता को पढ़ता है।

और compgenकमांड चालू शब्द से तत्वों की सरणी लौटाता है --help, --verboseऔर :--version"${cur}"

compgen -W "--help --verbose --version" -- "<userinput>"

स्रोत: http://www.debian-administration.org/articles/316


27
यह स्वीकृत उत्तर होना चाहिए! इसका पूरा उदाहरण है।
विक्टर श्रोडर

5
युक्ति: यदि कोई ऐसे शब्दों के लिए सुझाव चाहता है जो उसके साथ शुरू नहीं हो रहे हैं -और उन्हें लक्ष्य शब्द लिखना शुरू करने के बिना दिखाना है, तो बस if [...] thenऔर fiलाइनों को हटा दें ।
सेड्रिक रीचेनबाक

1
यह सटीक उत्तर है जो मैं घंटों से देख रहा हूं, और यह पता चला है कि यह कुछ जटिल प्रलेखन में डूब गया है जिसमें कभी उल्लेख नहीं किया गया है कि फ़ाइल को अंदर रखा जाना चाहिए /etc/bash_completion.d/। मैं केवल यहाँ आया था क्योंकि मैं एक उत्तर कहीं पोस्ट करना चाहता था, लेकिन यह किसी को तीन साल आगे सब के साथ :) स्पष्ट, संक्षिप्त और पूर्ण उदाहरण देता है, धन्यवाद!
स्टीन स्कुट


34

सभी बैश पूर्ति में संग्रहीत हैं /etc/bash_completion.d/। तो अगर आप bash_completion के साथ सॉफ़्टवेयर का निर्माण कर रहे हैं, तो उस डिरेक्टरी में सॉफ़्टवेयर के नाम के साथ डिब / इंस्टाल ड्रॉप करना सार्थक होगा। यहाँ रुपये के लिए एक उदाहरण बैश पूरा स्क्रिप्ट है:

# bash completion for rsync

have rsync &&
_rsync()
{
    # TODO: _split_longopt

    local cur prev shell i userhost path   

    COMPREPLY=()
    cur=`_get_cword`
    prev=${COMP_WORDS[COMP_CWORD-1]}

    _expand || return 0

    case "$prev" in
    --@(config|password-file|include-from|exclude-from))
        _filedir
        return 0
        ;;
    -@(T|-temp-dir|-compare-dest))
        _filedir -d
        return 0
        ;;
    -@(e|-rsh))
        COMPREPLY=( $( compgen -W 'rsh ssh' -- "$cur" ) )
        return 0
        ;;
    esac

    case "$cur" in
    -*)
        COMPREPLY=( $( compgen -W '-v -q  -c -a -r -R -b -u -l -L -H \
            -p -o -g -D -t -S -n -W -x -B -e -C -I -T -P \
            -z -h -4 -6 --verbose --quiet --checksum \
            --archive --recursive --relative --backup \
            --backup-dir --suffix= --update --links \
            --copy-links --copy-unsafe-links --safe-links \
            --hard-links --perms --owner --group --devices\
            --times --sparse --dry-run --whole-file \
            --no-whole-file --one-file-system \
            --block-size= --rsh= --rsync-path= \
            --cvs-exclude --existing --ignore-existing \
            --delete --delete-excluded --delete-after \
            --ignore-errors --max-delete= --partial \
            --force --numeric-ids --timeout= \
            --ignore-times --size-only --modify-window= \
            --temp-dir= --compare-dest= --compress \
            --exclude= --exclude-from= --include= \
            --include-from= --version --daemon --no-detach\
            --address= --config= --port= --blocking-io \
            --no-blocking-io --stats --progress \
            --log-format= --password-file= --bwlimit= \
            --write-batch= --read-batch= --help' -- "$cur" ))
        ;;
    *:*)
        # find which remote shell is used
        shell=ssh
        for (( i=1; i < COMP_CWORD; i++ )); do
            if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then
                shell=${COMP_WORDS[i+1]}
                break
            fi
        done
        if [[ "$shell" == ssh ]]; then
            # remove backslash escape from :
            cur=${cur/\\:/:}
            userhost=${cur%%?(\\):*}
            path=${cur#*:}
            # unescape spaces
            path=${path//\\\\\\\\ / }
            if [ -z "$path" ]; then
                # default to home dir of specified
                # user on remote host
                path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
            fi
            # escape spaces; remove executables, aliases, pipes
            # and sockets; add space at end of file names
            COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
                command ls -aF1d "$path*" 2>/dev/null | \
                sed -e 's/ /\\\\\\\ /g' -e 's/[*@|=]$//g' \
                -e 's/[^\/]$/& /g' ) )
        fi
        ;;
    *)  
        _known_hosts_real -c -a "$cur"
        _filedir
        ;;
    esac

    return 0
} &&
complete -F _rsync $nospace $filenames rsync

# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh

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


2
क्या हम अन्य स्थानों से लोड करने के लिए पूर्णताओं को कॉन्फ़िगर कर सकते हैं? अर्थात। ~ / .लोकल
क्रिस

1
हाँ, आप इस तरह की एक फ़ाइल जहां भी आप चाहते रखा और फिर रख सकते हैं source ~/.local/mycrazycompletionअपने में~/.bashrc
Stefano Palazzo


आजकल अधिकांश पूर्णताएँ pkg-config --variable = completeionsdir bash-complete` द्वारा दी गई निर्देशिका में स्थित हैं और यह निर्देशिका ऊपर दिए गए Bash Completion FAQ द्वारा दी गई अनुशंसा है।
जरनो

33

यहाँ एक पूर्ण ट्यूटोरियल है।

आओ हमारे पास स्क्रिप्ट का एक उदाहरण है, जिसे admin.sh कहा जाता है, जिसमें आप स्वतः पूर्ण कार्य करना चाहते हैं।

#!/bin/bash

while [ $# -gt 0 ]; do
  arg=$1
  case $arg in
    option_1)
     # do_option_1
    ;;
    option_2)
     # do_option_1
    ;;
    shortlist)
      echo option_1 option_2 shortlist
    ;;
    *)
     echo Wrong option
    ;;
  esac
  shift
done

नोट विकल्प शॉर्टलिस्ट। इस विकल्प के साथ स्क्रिप्ट को कॉल करना इस स्क्रिप्ट के सभी संभावित विकल्पों को प्रिंट करेगा।

और यहाँ आपके पास स्वतः पूर्ण स्क्रिप्ट है:

_script()
{
  _script_commands=$(/path/to/your/script.sh shortlist)

  local cur
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  COMPREPLY=( $(compgen -W "${_script_commands}" -- ${cur}) )

  return 0
}
complete -o nospace -F _script ./admin.sh

ध्यान दें कि पूरा करने के लिए अंतिम तर्क उस स्क्रिप्ट का नाम है जिसे आप स्वतः पूर्ण करना चाहते हैं। आपको बस इतना करने की ज़रूरत है कि आप अपनी स्वतः पूर्ण स्क्रिप्ट को bashrc में जोड़ दें

source /path/to/your/autocomplete.sh

या इसे /etc/bash.completion.d पर कॉपी करें


1
prevचर किसके लिए है? आप इसका उपयोग नहीं करते हैं।
dimo414

@ dimo414 यह बहुत लगता है, मुझे लगता है कि चर हटाया
kokosing

-o nospaceविकल्प क्या करता है?
एंड्रयू लामरा 3

11

यदि आप चाहते हैं कि एक सरल शब्द आधारित ऑटो-पूर्ति हो (तो कोई सब-कॉम्प्लेक्स पूरा होने या कुछ भी नहीं), completeकमांड में एक -Wविकल्प है कि बस सही काम करता है।

उदाहरण के लिए, मेरे पास ज्यूप्टर.bashrc नामक प्रोग्राम को स्वतः पूर्ण करने के लिए निम्नलिखित पंक्तियाँ हैं :

# gleaned from `jupyter --help`
_jupyter_options='console qtconsole notebook' # shortened for this answer
complete -W "${_jupyter_options}" 'jupyter'

अब jupyter <TAB> <TAB>मेरे लिए ऑटोकंप्लीट्स।

डॉक्स gnu.org में सहायक होते हैं।

ऐसा लगता है कि IFSवेरिएबल पर सही तरीके से भरोसा किया जा रहा है, लेकिन इससे मेरे लिए कोई समस्या नहीं हुई है।

फ़ाइल नाम पूर्णता और डिफ़ॉल्ट BASH पूर्णता जोड़ने के लिए, -oविकल्प का उपयोग करें :

complete -W "${_jupyter_options}" -o bashdefault -o default 'jupyter'

Zsh में इसका उपयोग करने के लिए, completeअपने में कमांड चलाने से पहले निम्न कोड जोड़ें ~/.zshrc:

# make zsh emulate bash if necessary
if [[ -n "$ZSH_VERSION" ]]; then
    autoload bashcompinit
    bashcompinit
fi

मैं यह काम कैसे करूँ bash jupyter <TAB><TAB>?
पापंपी

@papampi, मुझे लगता है कि यह केवल एक स्तर के पूरा होने के साथ काम करता है - मुझे लगता है कि इसे 2 परतों के साथ करने के लिए आपको ऊपर दिए गए अधिक जटिल उत्तरों में से एक की आवश्यकता होगी। इसके अलावा, मैंने हाल ही में बैश पूरा होने के बारे में एक बहुत अच्छा ट्यूटोरियल पढ़ा । यह ठीक वैसा नहीं है जैसा आपको चाहिए, लेकिन हो सकता है कि यह आपकी मदद करे। सौभाग्य!
बेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.