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


120

svnGnome Terminali gibi bir program kullanıp yazdığımda:

svn upd

ve Tabotomatik olarak tamamlandı çarptı :

svn update

Özel bash betiğimde böyle bir şey yapmak mümkün mü?


"bash betiğini" açıklamak, bir betiği düzenlerken? Bununla ne yapmak istiyorsun?
Bruno Pereira,

3
Konsolda komut dosyası kullanırken
UAdapter 17:11

Tamamlamalarınızı nereye koyacağınızla ilgili olarak, bu soruya ve ayrıca kabul edilen cevabın yorumlarına bakınız .
Jarno

Yanıtlar:


44

Programlanabilir Tamamlama özelliğini kullanabilirsiniz . En göz /etc/bash_completionve /etc/bash_completion.d/*bazı örnekler için.


131
Doğrudan soru ile ilgili basit bir örnek eklemeye ne dersiniz?
MountainX

2
Ubuntu 16 için gerçek scriptler/usr/share/bash-completion/completions/<program>
Peter

17
Ben, örnekler bir linke değil cevaba dahil edilmelidir.
billynoah

2
Bu platformun basit bir google aramayla bulunabilecek belgelerin tümüne daha pratik bir alternatif olacağına inanıyorum. Bir dökümantasyon bağlantısı bırakmak, buna yardımcı olmaz. Bir çapa içeren bağlantı elbette pek farketmez.
timuçin

4
The provided link has that already- bugün olabilir, ama yarın olmayabilir. Veya gelecek yıl. Veya on yıl içinde. Belgelerle ilgili olarak hala ilgili olanları önerebilecekleriniz ne olursa olsun, Yığın Taşması bu nedenlerle yalnızca bağlantı yanıtlarını önermez.
Liam Dawson,

205

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

Yeni bir dosya oluşturmanız gerekecek:

/etc/bash_completion.d/foo

Statik bir otomatik tamamlama için ( --help/ --verboseörneğin) ş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 sözcükleri içeren bir dizidir.
  • COMP_CWORD Geçerli imleç konumunu içeren sözcüğün bir dizinidir.
  • COMPREPLY Bash'in olası tamamlamaları okuduğu bir dizi değişkenidir.

Ve compgenkomut gelen elemanların dizisi döndürür --help, --verboseve --versionmevcut kelime eşleştirme "${cur}":

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

Kaynak: http://www.debian-administration.org/articles/316


27
Bu kabul edilen cevap olmalı! Bu tam bir örnek.
Victor Schröder

5
İpucu: Biri, başlangıçta olmayan kelimeler için öneriler isterse -ve hedef sözcüğü yazmaya başlamak zorunda kalmadan onlara göstermek istiyorsanız , sadece if [...] thenve fisatırlarını kaldırın .
Cedric Reichenbach

1
Saatlerdir aradığım kesin cevap bu, ve sadece dosyanın yerleştirilmesi gerektiğinden hiç bahsetmeyen bazı karmaşık belgelerde boğuldu /etc/bash_completion.d/. Buraya geldim, çünkü bir yere bir cevap göndermek istedim, ama birilerinin başından üç yıl ileride olduğu ortaya çıktı :) Net, özlü ve eksiksiz bir örnek, teşekkür ederim!
Steen Schütt


34

Tüm bash tamamlamaları içinde saklanır /etc/bash_completion.d/. Eğer bash_completion ile bir yazılım oluşturuyorsanız, deb / make install komutunun bu dizindeki yazılımın adını içeren bir dosya bırakması faydalı olacaktır. İşte Rsync için örnek bir 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
    --@(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

Orada, programınızla en çok eşleşen bash tamamlama dosyalarından birini incelemeniz faydalı olacaktır. En basit örneklerden biri rrdtooldosya.


2
Tamamlamaları diğer konumlardan yüklenecek şekilde yapılandırabilir miyiz? IE. ~ / .local
Chris

1
Evet, istediğiniz yere buna benzer bir dosya koymak ve sonra koyabilirsiniz source ~/.local/mycrazycompletionsenin içinde~/.bashrc
Stefano Palazzo

Adresindeki talimatlara bakın @Chris Bash Tamamlama SSS
Jarno

Günümüzde çoğu tamamlama pkg-config --variable = completeionsdir bash-complete` komutuyla verilen dizinde bulunur ve bu dizin yukarıda verilen Bash Completion SSS tarafından verilen öneridir.
jarno

34

İşte tam bir eğitim.

Otomatik tamamlama çalışmasını istediğiniz admin.sh adında bir komut dosyası örneği verelim.

#!/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

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

Ve burada otomatik tamamlama komut dosyası var:

_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. Yapmanız gereken tek şey, otomatik tamamlama komut dosyanızı bashrc'ye eklemek

source /path/to/your/autocomplete.sh

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


1
prevDeğişken ne için? Kullanmıyor gibisin.
dimo414

@ dimo414 Öyle görünüyor ki, bu değişkeni kaldırdım
19'da

-o nospaceSeçenek ne yapar ?
Andrew Lamarra

11

İstediğiniz tüm basit bir kelime tabanlı otomatik tamamlama (yani alt completekomut tamamlama veya herhangi bir şey) ise, komut -Wsadece doğru olanı yapan bir seçeneğe sahiptir.

Örneğin, jupyter.bashrc adlı bir programı otomatik olarak tamamlamak için 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'

Şimdi jupyter <TAB> <TAB>benim için otomatik tamamlar.

Docs gnu.org de faydalıdır.

IFSDoğru ayarlanan değişkene bağlı görünüyor , ancak bu benim için herhangi bir soruna neden olmadı.

Dosya adı tamamlama ve varsayılan BASH tamamlama eklemek için aşağıdaki -oseçeneği kullanın:

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

Bunu zsh'da kullanmak için, completekomutunu çalıştırmadan önce aşağıdaki kodu ekleyin ~/.zshrc:

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

Bu çalışmayı nasıl yapabilirim bash jupyter <TAB><TAB>?
papampi

@papampi, bence sadece bir seviye bitirme ile işe yarıyor - bence yukarıdaki katmanlardan birine daha çok ihtiyaç duyacağınız 2 kat ile yapmayı düşünüyorum. Ayrıca, son zamanlarda bash tamamlanması hakkında oldukça iyi bir öğretici okudum . Tam olarak ihtiyacınız olanı yapmıyor, ama belki size yardım eder. İyi şanslar!
Ben
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.