랩퍼 함수 인수와 기존 명령에 대해 zsh 자동 완성을 결합하는 방법


40

나는 주로 gvim과 많은 터미널에서 일합니다. 원래 모든 단일 파일을 단일 vim 인스턴스에서 여는 것을 선호했습니다. 이를 위해 현재 'vim 서버'의 터미널에서 파일을 열기 위해 별칭을 사용했습니다.

alias rv="gvim --remote-silent"

그러나 단일 Vim 인스턴스에서 여러 프로젝트의 많은 파일을 열면 생산성에 영향을 미치므로 별칭을 함수로 업그레이드하고 있습니다.

# 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 --list)
  • 현재 쉘의 기본 vim 서버를 설정하십시오 (-s --set)
  • 기본 vim 서버를 표시합니다 (-i --info).
  • 특정 Vim 서버에서 파일 열기 (-t --target)
  • 기본 vim 서버에서 파일을 엽니 다 : rv files...

그러나 rv별칭 대신 함수를 사용하고 있기 때문에 이전에 즐겼던 zsh 완료를 잃습니다. 완료 기능 작성에 대해 읽었으며, 옵션 _rv이 표시 rv되지만 완료 옵션을 기존 vim 완료 옵션과 결합하려고합니다. 나는 몇 가지 충돌이있을 수 있습니다 알고 rv-svim-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>하면 vim 옵션이 표시되지 않습니다. rv 옵션 및 파일 경로 만 표시됩니다. _vim나를 위해 파일 경로를 완성하고 있습니다.
  • 를 입력하면 rv -s <TAB>vim 서버 목록이 표시되지만 파일 경로도 표시됩니다. 이 시점에서 명령의 파일은 허용되지 않으며 자동 완성에 나타나지 않아야합니다.

예상되는 행동

  • 입력하면 rv <TAB>1) rv 옵션, 2) vim 옵션, 3) 파일 경로 목록이 표시됩니다.
  • 를 입력하면 rv -s <TAB>1) vim 서버 이름 (에서 제공 한대로)이 표시됩니다 _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 and no answer ... 그리고 zsh에 대한 질문입니다 ... @ StéphaneChazelas를 호출하려고합니다 ^^ (남용하지는 않지만 재미 있습니다. 이 작업을 수행하면 ...이 작업을 삭제하고 다시는 수행하지 않습니다.) ... 여기 누군가가 답을 알 수 있다면 그 사람이되어야합니다
Olivier Dulac

1
@OlivierDulac 나는 스레드에 이미 게시 한 경우에만 알림을받는다고 생각합니다. (중복 된 이름이 허용되므로 의미가 있습니다.) 채팅에서 그를 찾을 수 있습니다.
Sparhawk

원본 _vim 파일 을 소싱 할 수 있었지만 그렇게하기 전에 _arguments사용자 정의 로컬 함수로 함수를 덮어 쓰겠 습니까? 그렇게하면에서 인수를 얻을 수 있습니다 _vim. 별도의 zsh 프로세스가있을 수 있습니다.
Raphael Ahrens

답변:


1

나는 / usr / share / zsh / functions / Completion / 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.