Otomatik tamamlama ile komut dosyası nasıl oluşturulur?

96

svn gibi bir program kullandığımda ve Gnome Terminalinde yazdığımda:

svn upd

tuşuna basın ve Sekmesi 'yi seçin:

svn update

Özel bash komutumda böyle bir şey yapmak mümkün mü?

    
sordu UAdapter 17.10.2011 17:12

5 cevap

33

Programlanabilir Tamamlama 'yı kullanabilirsiniz. Bazı örnekler için /etc/bash_completion ve /etc/bash_completion.d/* değerlerine bakın.

    
verilen cevap Florian Diesch 17.10.2011 17:54
160

Altı ay geciktim ama aynı şeyi arıyordum ve bunu buldum:

Yeni bir dosya oluşturmanız gerekecek:

/etc/bash_completion.d/foo

Statik bir otomatik tamamlama için (örneğin, --help / --verbose ) şunu ekleyin:

_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 , geçerli komut satırındaki tüm kelimeleri içeren bir dizidir.
  • COMP_CWORD , geçerli imleç konumunu içeren kelimenin bir dizinidir.
  • COMPREPLY , Bash'in olası tamamlamaları okuduğu bir dizi değişkeni.

Ve compgen komutu, --help , --verbose ve --version öğesinin geçerli sözcüğü "${cur}" ile eşleşen öğelerin dizisini döndürür:

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

Kaynak: İşte

    
verilen cevap Louis Soulez 13.09.2013 17:41
33

Tüm bash tamamlamaları /etc/bash_completion.d/ dizininde depolanır. Öyleyse, bash_completion ile yazılım oluşturuyorsanız, deb / make yüklemesinin, bu dizindeki yazılımın ismine sahip bir dosyayı indirmesini sağlamak faydalı olacaktır. İşte Rsync için bir örnek bash tamamlama betiği:

# 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
    [email protected](config|password-file|include-from|exclude-from))
        _filedir
        return 0
        ;;
    [email protected](T|-temp-dir|-compare-dest))
        _filedir -d
        return 0
        ;;
    [email protected](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]}" == [email protected](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

Programdaki programla en yakından eşleşen bash tamamlama dosyalarını gözden geçirmeniz yararlı olacaktır. En basit örneklerden biri rrdtool dosyasıdır.

    
verilen cevap Marco Ceppi 13.01.2012 18:28
28

İşte tam bir öğretici.

Otomatik tamamlamayı kullanmak istediğiniz admin.sh adında bir komut örneğine sahip olmanızı sağlar.

#!/bin/bash

while [ $# -gt 0 ]; do
  arg=
  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

Seçenek kısa listesini not edin. Bu seçenekle komut dosyası çağırmak, bu komut dosyası için olası tüm seçenekleri yazdırır.

Ve işte otomatik tamamlama senaryosuna sahipsin:

_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

Tamamlanacak son argümanın, otomatik tamamlama eklemek istediğiniz komut dosyasının adı olduğunu unutmayın. Tek yapmanız gereken, otomatik tamamlama komut dosyanızı bashrc olarak

olarak eklemektir.
source /path/to/your/autocomplete.sh

veya kopyalayın     /etc/bash.completion.d

    
verilen cevap kokosing 14.06.2014 12:33
7

İstediğiniz tek şey basit bir kelimeye dayalı otomatik tamamlama (yani hiçbir alt komut tamamlama veya herhangi bir şey) değilse, complete komutunun, yalnızca doğru şeyi yapan -W seçeneği vardır.

Örneğin, jupyter adlı bir programın otomatik olarak tamamlanması için .bashrc öğesinde aşağıdaki satırlarım var:

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

Artık jupyter <TAB> <TAB> benim için otomatik tamamlar.

gnu.org adresindeki dokümanlar yararlıdır.

Doğru olarak ayarlanan IFS değişkenine güveniyor gibi görünüyor, ancak bu benim için herhangi bir soruna neden olmadı.

Dosya adı tamamlandığını ve varsayılan BASH tamamlanmasını eklemek için -o seçeneğini kullanın:

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

Bunu zsh olarak kullanmak için, complete % s_de ~/.zshrc komutunu çalıştırmadan önce aşağıdaki kodu ekleyin:

# make zsh emulate bash if necessary
if [[ -n "$ZSH_VERSION" ]]; then
    autoload bashcompinit
    bashcompinit
fi
    
verilen cevap Ben 28.11.2016 01:04

Etiketlerdeki diğer soruları oku