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.