วิธีสร้างสคริปต์ด้วยการเติมข้อความอัตโนมัติ?


120

เมื่อฉันใช้โปรแกรมเช่นsvnและฉันพิมพ์ใน Gnome Terminal:

svn upd

และกดปุ่มTabเติมข้อความอัตโนมัติเพื่อ:

svn update

เป็นไปได้ไหมที่จะทำเช่นนั้นในสคริปต์ทุบตีที่กำหนดเองของฉัน


อธิบาย "สคริปต์ทุบตี" คุณหมายถึงเมื่อแก้ไขสคริปต์หรือไม่ คุณต้องการทำอะไรกับมัน
Bruno Pereira

3
เมื่อใช้สคริปต์ในคอนโซล
UAdapter

สำหรับสถานที่ที่จะใส่ความสำเร็จของคุณดูคำถามนี้และความคิดเห็นสำหรับคำตอบที่ยอมรับได้ที่นั่น
jarno

คำตอบ:


44

คุณสามารถใช้โปรแกรมได้แล้วเสร็จ มีลักษณะที่/etc/bash_completionและ/etc/bash_completion.d/*สำหรับตัวอย่างบางส่วน


131
วิธีการเกี่ยวกับการรวมตัวอย่างง่ายๆที่เกี่ยวข้องโดยตรงกับคำถาม?
MountainX

2
สคริปต์จริงสำหรับ Ubuntu 16 อยู่ใน/usr/share/bash-completion/completions/<program>
peter

17
อิโมตัวอย่างควรรวมอยู่ในคำตอบไม่ใช่ลิงค์
billynoah

2
ฉันเชื่อว่าแพลตฟอร์มนี้ควรจะเป็นทางเลือกที่เป็นประโยชน์มากกว่าสำหรับเอกสารฉบับเต็มที่สามารถพบได้ด้วยการค้นหา google อย่างง่าย ทิ้งการเชื่อมโยงเอกสารไม่ได้ช่วย ลิงค์ที่มีสมอไม่ได้สร้างความแตกต่างมากนัก
timuçin

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 เป็นตัวแปรอาร์เรย์ที่ Bash อ่านความสำเร็จที่เป็นไปได้

และcompgenคำสั่งส่งคืนอาร์เรย์ขององค์ประกอบจาก--help, --verboseและ--versionการจับคู่คำปัจจุบัน"${cur}":

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

ที่มา: http://www.debian-administr.org/articles/316


27
นี่ควรเป็นคำตอบที่ยอมรับได้! มันเป็นตัวอย่างที่สมบูรณ์
Victor Schröder

5
เคล็ดลับ: หากมีคนต้องการคำแนะนำสำหรับคำที่ไม่ได้เริ่มต้น-และแสดงโดยไม่ต้องเริ่มพิมพ์คำเป้าหมายเพียงแค่ลบif [...] thenและfiบรรทัด
Cedric Reichenbach

1
/etc/bash_completion.d/นี่คือคำตอบที่แน่นอนฉันได้รับการมองหาสำหรับชั่วโมงและก็จะเปิดออกมันก็จมน้ำตายในบางเอกสารที่ซับซ้อนที่ก็ไม่เคยกล่าวว่าไฟล์ควรอยู่ใน ฉันมาที่นี่เพียงเพราะฉันต้องการโพสต์คำตอบที่ไหนสักแห่ง แต่ปรากฎว่ามีใครบางคนอยู่ข้างหน้ามาตลอดสามปี :) ตัวอย่างที่ชัดเจนกระชับและสมบูรณ์ขอขอบคุณ!
Steen Schütt


34

/etc/bash_completion.d/ทุกความสำเร็จของทุบตีถูกเก็บไว้ใน ดังนั้นหากคุณกำลังสร้างซอฟต์แวร์ด้วย bash_completion มันจะคุ้มค่าหากคุณมี deb / ทำการติดตั้งวางไฟล์ด้วยชื่อของซอฟต์แวร์ในไดเรกทอรีนั้น นี่คือตัวอย่างสคริปต์การทุบตี bash สำหรับ 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

เป็นไปได้อย่างคุ้มค่าที่จะตรวจสอบไฟล์ bash เสร็จหนึ่งไฟล์ที่ตรงกับโปรแกรมของคุณมากที่สุด หนึ่งในตัวอย่างที่ง่ายที่สุดคือrrdtoolไฟล์


2
เราสามารถกำหนดค่าความสำเร็จที่จะโหลดจากที่อื่น ๆ IE ~ / .local
Chris

1
ใช่คุณสามารถใส่ไฟล์แบบนี้ทุกที่ที่คุณต้องการแล้วใส่source ~/.local/mycrazycompletionในของคุณ~/.bashrc
Stefano Palazzo


ทุกวันนี้ความสำเร็จส่วนใหญ่จะอยู่ในไดเรกทอรีที่กำหนดโดยคำสั่งpkg-config --variable = completionsdir bash-completion` และไดเรกทอรีนั้นเป็นคำแนะนำที่ได้รับจาก Bash Completion FAQ ที่ลิงก์ด้านบน
jarno

34

นี่คือการสอนที่สมบูรณ์

ให้ตัวอย่างของสคริปต์ชื่อ 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ตัวเลือกทำอย่างไร
Andrew Lamarra

11

หากสิ่งที่คุณต้องการคือการเติมคำอัตโนมัติอย่างง่าย (ดังนั้นจึงไม่มีคำสั่งย่อยหรืออะไรก็ตาม) completeคำสั่งมี-Wตัวเลือกที่ทำสิ่งที่ถูกต้อง

ตัวอย่างเช่นฉันมีบรรทัดต่อไปนี้ใน.bashrcการเติมข้อความอัตโนมัติโปรแกรมที่เรียกว่าjupyter :

# 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

@papampi ฉันคิดว่ามันใช้ได้กับระดับความสำเร็จเพียงระดับเดียว - ฉันคิดว่าจะทำได้ด้วย 2 เลเยอร์คุณต้องได้คำตอบที่ซับซ้อนกว่าข้างต้น นอกจากนี้ฉันเพิ่งอ่านบทช่วยสอนที่ดีเกี่ยวกับการทุบตีเสร็จ มันไม่ได้ทำในสิ่งที่คุณต้องการอย่างแน่นอน แต่บางทีมันอาจช่วยคุณได้ โชคดี!
เบ็น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.