Vraag Hoe script te maken met automatisch aanvullen?


Wanneer ik programma-achtig gebruik svn en ik typ in Gnome Terminal:

svn upd

en druk op tab het is automatisch aangevuld om:

svn update

Is het mogelijk om zoiets te doen in mijn aangepaste bash-script?


96
2017-10-17 15:12


oorsprong


"bash-script" uitleggen, bedoelt u bij het bewerken van een script? wat wil je ermee doen? - Bruno Pereira
bij gebruik van script in console - UAdapter


antwoorden:


U kunt de Programmeerbare voltooiing. Kijk naar /etc/bash_completion en /etc/bash_completion.d/* voor enkele voorbeelden.


34
2017-10-17 15:54



Hoe zit het met het opnemen van een eenvoudig voorbeeld dat direct verband houdt met de vraag? - MountainX
De geboden link heeft dat al. : D - peter
De daadwerkelijke scripts voor Ubuntu 16 bevinden zich in /usr/share/bash-completion/completions/<program> - peter
Imo, voorbeelden moeten worden opgenomen in het antwoord, niet in een link. - billynoah
Ik geloof dat dit platform een ​​praktischer alternatief zou moeten zijn voor volledige documentatie die kon worden gevonden met een eenvoudige google-zoekopdracht. Het dumpen van een documentatielink helpt daar niet bij. De link met een anker maakt zeker niet veel uit. - timuçin


Ik ben zes maanden te laat, maar ik was op zoek naar hetzelfde en vond dit:

U moet een nieuw bestand maken:

/etc/bash_completion.d/foo

Voor een statische automatische aanvulling (--help / --verbose hand40 details hand details 3 details 3 details details 3 hand 3 details 340 hand 3 details 3 hand40 hand 34040 3 3

_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 is een array met alle afzonderlijke woorden in de huidige opdrachtregel.
  • COMP_CWORD is een index van het woord dat de huidige cursorpositie bevat.
  • COMPREPLY  is een array-variabele waaruit Bash de mogelijke voltooiingen leest.

En de compgen opdracht geeft de array met elementen als resultaat --help, --verbose en --version passend bij het huidige woord "${cur}":

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

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


160
2017-09-13 15:41



Dit zou het geaccepteerde antwoord moeten zijn! Het is een compleet voorbeeld. - Victor Schröder
Tip: als iemand suggesties wil voor woorden die niet beginnen met - en laat ze zien zonder het doelwoord te hoeven typen, verwijder gewoon de if [...] then en fi lijnen. - Cedric Reichenbach
Dit is het exacte antwoord waar ik al uren naar op zoek ben, en het blijkt dat het gewoon is verdronken in een aantal gecompliceerde documentatie die gewoon nooit vermeldt dat het bestand moet worden geplaatst /etc/bash_completion.d/. Ik kwam hier alleen omdat ik ergens een antwoord wilde plaatsen, maar het bleek dat iemand al drie jaar vooruit was :) Duidelijk, beknopt en volledig voorbeeld, dank je! - Time Sheep
Tutorial - Een bash-voltooiingsscript maken - Lazarus Lazaridis


Alle bash-voltooiingen worden opgeslagen /etc/bash_completion.d/. Dus als je software met bash_completion bouwt, is het de moeite waard om de deb / make-installatie een bestand te laten droppen met de naam van de software in die map. Hier is een voorbeeld bash-voltooiingsscript voor Rsync:

# 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

Het is waarschijnlijk de moeite waard om een ​​van de bash-voltooiingsbestanden daar te bekijken die het beste overeenkomen met uw programma. Een van de eenvoudigste voorbeelden is de rrdtool het dossier.


33
2018-01-13 17:28



Kunnen we voltooingen configureren om vanaf andere locaties te laden? D.W.Z. ~ / .local - Chris
Ja, je kunt een bestand zoals dit plaatsen waar je maar wilt en dan plaatsen source ~/.local/mycrazycompletion in uw ~/.bashrc - Stefano Palazzo♦


Hier is een complete tutorial.

Laten we een voorbeeld van een script hebben genaamd admin.sh waarnaar u automatisch aanvullen wilt laten werken.

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

Let op de optie shortlist. Met een script met deze optie worden alle mogelijke opties voor dit script afgedrukt.

En hier heb je het autocomplete-script:

_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

Merk op dat het laatste te voltooien argument de naam is van het script waaraan u automatisch aanvullingen wilt toevoegen. Het enige wat u hoeft te doen is om uw autocomplete script toe te voegen aan bashrc als

source /path/to/your/autocomplete.sh

of kopieer het naar     /etc/bash.completion.d


28
2018-06-14 10:33



Wat is de prev variabele voor? Je lijkt het niet te gebruiken. - dimo414
@ dimo414 Het lijkt zo, ik heb die variabele verwijderd - kokosing
Wat doet de -o nospace optie doen? - Andrew Lamarra


Als alles wat u wilt een eenvoudige op woord gebaseerde automatische aanvulling is (dus geen afronding van subopdrachten of iets anders), de complete commando heeft een -W optie die precies goed doet.

Ik heb bijvoorbeeld de volgende regels in mijn .bashrc om een ​​programma genaamd automatisch aan te vullen jupyter:

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

Nu jupyter <TAB> <TAB> autocompletes voor mij.

De docs op gnu.org zijn nuttig.

Het lijkt te vertrouwen op de IFS variabele correct is ingesteld, maar dat heeft geen problemen voor mij veroorzaakt.

Om de completering van de bestandsnaam en standaard BASH-voltooiing toe te voegen, gebruikt u de -o keuze:

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

Om dit in zsh te gebruiken, voeg je de volgende code toe voordat je de complete commando in jouw ~/.zshrc:

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

7
2017-11-28 00:04