วิธีรวมการเติมข้อความอัตโนมัติ zsh สำหรับอาร์กิวเมนต์ของฟังก์ชันตัวตัดคำและคำสั่งที่มีอยู่


40

ฉันทำงานเป็นส่วนใหญ่ใน gvim และเทอร์มินัลจำนวนมาก เดิมทีฉันต้องการเปิดไฟล์ทั้งหมดในอินสแตนซ์กลุ่มเดียว ด้วยเหตุนี้ฉันจึงใช้นามแฝงเพื่อเปิดไฟล์จากเทอร์มินัลของฉันใน 'เซิร์ฟเวอร์ vim' ปัจจุบัน

alias rv="gvim --remote-silent"

แต่การเปิดไฟล์จำนวนมากจากหลายโครงการเปิดในอินสแตนซ์ vim เดียวส่งผลกระทบต่อผลผลิตของฉันดังนั้นฉันจึงอัพเกรด alias เป็นฟังก์ชัน

# main function
rv() {
    local args options server

    options=$(getopt -o hils:t: -l "help,info,list,set:,target:" -- "$@")

    if [[ $? -ne 0 ]]; then
        echo "Failed to parse options."
        return 1
    fi

    # a little magic, necessary when using getopt
    eval set -- "$options"

    # go through the options with a case and use shift to analyze one option at a time.
    while true; do
        case "$1" in
            -h|--help)
                echo "Usage: $0 [-hil] [--help] [--info] [--list]";
                echo "       $0 {-s | --set} <name> [<file1 file2...>]";
                echo "       $0 {-t | --target} <name>] <file1 file2...>";
                return 0;;
            -i|--info)
                gvim_show_info;
                return 0;;
            -l|--list)
                gvim_list_servers;
                return 0;;
            -s|--set)
                gvim_set_server_name ${2:u};
                shift 2;;
            -t|--target)
                server="$2";
                shift 2;;
            --)
                shift;
                break;;
        esac
    done

    if [[ "$#" -eq 0 ]]; then
        # if no files specified...
        if [[ -n "$server" ]]; then
            # throw error if --target option was specified.
            echo "Error!  --target requires one or more filenames."
            return 1;
        fi
    else
        # if files were specified...
        if [[ -n "$server" ]]; then
            # if --target was specified
            gvim_run_remote $server "$@"
        else
            gvim_run_remote $(gvim_get_default_server) "$@"
        fi
    fi

    return 0;
}

ตอนนี้ใหม่นี้rvมีตัวเลือกของตัวเอง ฉันสามารถใช้มันเพื่อ:

  • รายการเซิร์ฟเวอร์ vim ที่มีอยู่ (-l - รายการ)
  • ตั้งค่าเซิร์ฟเวอร์ vim เริ่มต้นสำหรับเชลล์ปัจจุบัน (-s --set)
  • แสดงเซิร์ฟเวอร์ vim เริ่มต้น (-i --info)
  • เปิดไฟล์ในเซิร์ฟเวอร์ vim เฉพาะ (-t --target)
  • เปิดไฟล์ในเซิร์ฟเวอร์ vim ที่เป็นค่าเริ่มต้น: rv files...

อย่างไรก็ตามเนื่องจากฉันใช้ฟังก์ชั่นrvแทนนามแฝงฉันจึงสูญเสียความสมบูรณ์ของ zsh ที่ฉันเคยเพลิดเพลิน ฉันได้อ่านเกี่ยวกับการสร้างฟังก์ชั่นเสร็จสมบูรณ์_rvที่จะแสดงrvตัวเลือกของ แต่ฉันต้องการที่จะรวมตัวเลือกความสมบูรณ์ของฉันกับตัวเลือกเสร็จสิ้นเป็นกลุ่มที่มีอยู่ ฉันรู้ว่าอาจมีความขัดแย้งกับrv's -sและvim' s -sแต่ฉันคิดว่าฉันสามารถจัดการที่สง่างามด้วย--ตัวคั่น

TLDR; ดังนั้นฉันจะสร้างสคริปต์เสร็จสมบูรณ์ที่รวม_argumentsตัวเลือกสำหรับทั้งสอง_rvและ_vimอย่างไร ฉันชอบที่จะนำมาใช้ถ้าเป็นไปได้แทนการคัดลอกวางของรายการอาร์กิวเมนต์เข้า_vim_rv

_rvต่อไปนี้เป็นของฉัน อัปเดต 2014/6/10 16:10

#compdef rv

_rv() {
    typeset -A opt_args
    local alternatives

    alternatives=(
        'args:rv options:_rv_options'
        'files:file:_vim_files'
    )

    _alternative $alternatives && return 0

    return 1
}

_rv_options() {
    local arguments

    arguments=(
        '(-i -l -s -t --info --list --set --target)'{-h,--help}'[Print usage info.]'
        '(-h -l -s -t --help --list --set --target)'{-i,--info}'[Print default vim server. As stored in $GVIM_SERVER.]'
        '(-i -h -s -t --info --help --set --target)'{-l,--list}'[Print list of existing vim servers.]'
        '(-i -h -l -t --info --help --list --target)'{-s,--set}'[Set default vim server for the current shell.]:vim servers:_rv_vim_servers'
        '(-i -h -l -s --info --help --list --set)'{-t,--target}'[Open files in a particular vim server.]:vim servers:_rv_vim_servers'
        )

    _arguments -s -C $arguments && return 0

    return 1
}

_rv_vim_servers() {
    local -a servers
    servers=( ${(f)"$(_call_program servers vim --serverlist 2>/dev/null)"} )
    _wanted servers expl server compadd -M 'm:{a-z}={A-Z}' -a servers && return
}

# invoke the completion command during autoload
_rv "$@"

พฤติกรรมปัจจุบัน

ปัจจุบันการ_rvสำเร็จจะใช้งานได้ แต่ไม่เหมาะ

  • เมื่อฉันพิมพ์rv <TAB>ฉันไม่เห็นตัวเลือกที่เป็นกลุ่ม แสดงเฉพาะตัวเลือก rv และพา ธ ไฟล์ _vimกำลังทำเส้นทางไฟล์ให้ฉันดังนั้นไชโยถึงเรื่องนั้น!
  • เมื่อฉันพิมพ์rv -s <TAB>ฉันจะเห็นรายการเซิร์ฟเวอร์ที่เป็นกลุ่ม แต่ยังแสดงเส้นทางของไฟล์ ไฟล์ไม่ได้รับอนุญาต ณ จุดนี้ในคำสั่งและไม่ควรปรากฏในการเติมข้อความอัตโนมัติ

พฤติกรรมที่คาดหวัง

  • เมื่อฉันพิมพ์rv <TAB>ฉันคาดว่าจะเห็น: 1) ตัวเลือก rv, 2) ตัวเลือกที่เป็นกลุ่ม, 3) รายการเส้นทางไฟล์
  • เมื่อฉันพิมพ์rv -s <TAB>ฉันคาดว่าจะเห็น: 1) ชื่อเซิร์ฟเวอร์ที่เป็นกลุ่ม _rv_vim_servers(ให้เป็นไปตาม
  • เมื่อฉันพิมพ์rv /valid/file/path/<TAB>ฉันคาดว่าจะเห็นรายการเส้นทางไฟล์เท่านั้น เนื่องจาก_vimมีความสามารถนี้อยู่แล้วฉันจึงต้องการใช้มัน

1
unix.stackexchange.com/questions/128199/นี้อาจเป็นประโยชน์
clobrano

1
compdefมี-nตัวเลือกที่บอกว่า "ป้องกันความสำเร็จใด ๆ ที่กำหนดไว้แล้วสำหรับคำสั่งหรือบริบทจากการเขียนทับ" คุณเคยลองcompdef _vim rvแล้วตามด้วยcompdev -n _rv rv?
Lqueryvg

3
28 upvotes และไม่มีคำตอบ ... และเป็นคำถามเกี่ยวกับ zsh ... ฉันจะพยายามเรียก @ StéphaneChazelasให้คุณ ^^ (ฉันพยายามที่จะไม่ใช้สิ่งนี้ แต่มันสนุกโปรดสเตฟานบอกฉันว่าฉันไม่ควร ทำสิ่งนี้ ... และฉันจะลบสิ่งนี้และไม่ทำอีกเลย) ... หากใครบางคนที่นี่อาจรู้คำตอบมันควรจะเป็นเขา
Olivier Dulac

1
@OlivierDulac ฉันคิดว่าคุณจะได้รับการแจ้งเตือนเฉพาะเมื่อคุณได้โพสต์ในกระทู้แล้ว (อนุญาตให้ใช้ชื่อซ้ำได้ดังนั้นจึงสมเหตุสมผล) คุณอาจพบเขาในการแชท
Sparhawk

เป็นไปได้หรือไม่ที่จะส่ง_vim ไฟล์ต้นฉบับแต่ก่อนที่จะเขียนทับ_argumentsฟังก์ชันด้วยฟังก์ชันโลคัลแบบกำหนดเอง? _vimโดยการทำเช่นคุณจะได้รับจากการขัดแย้ง อาจจะมีกระบวนการ zsh แยก
Raphael Ahrens

คำตอบ:


1

ฉันพบ / usr / share / zsh / ฟังก์ชั่น / เสร็จสิ้น / Unix / _git ซึ่งมีเคล็ดลับสำหรับนามแฝงเช่นนี้และสิ้นสุดการกำหนดฟังก์ชั่นเหล่านี้สำหรับนามแฝง:

_git-ls () {
  # Just return the _git-ls-files autocomplete function
  _git-ls-files
}

จากนั้นทำ compdef แบบตรง g = git ระบบเติมข้อความอัตโนมัติจะเห็นว่าคุณกำลังใช้งานอยู่ตัวอย่างเช่น g ls และใช้ฟังก์ชั่น _git-ls เติมข้อความอัตโนมัติ

เท่าที่พบที่นี่


ขอบคุณ แต่ไม่มาก _git-ls-filesวิธีการแก้ปัญหาของคุณถือว่าฉันต้องการเพียงอัตโนมัติสมบูรณ์จาก คำถามนี้มีgit-ls(ที่จะติดกับการประชุมของคุณ) git-ls-filesกับตัวเลือกของตัวเองและบางส่วนของตัวเลือกเหล่านั้นทับซ้อนกับ แทนที่จะเขียนการเติมข้อความอัตโนมัติสำหรับตัวเลือกทั้งหมดgit-lsฉันจะเขียนการเติมข้อความอัตโนมัติที่ใช้การเติมข้อความอัตโนมัติจาก_git-ls-files(ซึ่งครอบคลุมถึง 90%) และรวมเข้ากับตัวเลือกการเติมข้อความอัตโนมัติที่เหลือ (พูด 10%) ได้อย่างไร
Justin C
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.