Jak połączyć autouzupełnianie zsh dla argumentów funkcji opakowania i istniejącej komendy


40

Pracuję głównie w gvim i wielu terminalach. Początkowo wolałem otwierać wszystkie moje pliki w jednym wystąpieniu vima. W tym celu użyłem aliasu do otwierania plików z moich terminali na bieżącym „serwerze vim”.

alias rv="gvim --remote-silent"

Ale posiadanie wielu plików z wielu projektów otwartych w jednym wystąpieniu vima wpływa na moją wydajność, dlatego aktualizuję swój alias do funkcji.

# 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;
}

Teraz ten nowy rvma swoje własne opcje. Mogę go użyć do:

  • wyświetla listę dostępnych serwerów vim (-l --list)
  • ustaw domyślny serwer vim dla bieżącej powłoki (-s --set)
  • pokaż domyślny serwer vim (-i --info)
  • otwieraj pliki na określonym serwerze vim (-t --target)
  • otwórz pliki w domyślnym serwerze vim: rv files...

Ponieważ jednak używam funkcji rvzamiast aliasu, tracę ukończenie zsh, z którego wcześniej korzystałem. Przeczytałem o tworzeniu funkcji uzupełniania _rv, która pokaże rvopcje, ale chcę połączyć moje opcje uzupełniania z istniejącymi opcjami uzupełniania vima. Wiem, że mogą istnieć pewne konflikty z rv„ -si vim” -s, ale myślę, że mogę sobie z tym poradzić elegancko za pomocą --separatora.

TLDR; Jak więc utworzyć skrypt ukończenia, który łączy _argumentsopcje dla obu _rvi _vim? Wolę użyć ponownie, _vimjeśli to możliwe, zamiast kopiować i wklejać listę argumentów _rv.

Oto mój _rv. Zaktualizowano 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 "$@"

Obecne zachowanie

Obecnie _rvukończenie będzie użyteczne, ale nie idealne.

  • Kiedy piszę rv <TAB>, nie widzę opcji vima. Wyświetlane są tylko opcje rv i ścieżki plików. _vimkończy dla mnie ścieżki plików, więc brawo!
  • Kiedy piszę rv -s <TAB>, widzę listę serwerów vim, ale wyświetlane są również ścieżki plików. Plik nie jest w tym momencie dozwolony i nie powinien pojawiać się w autouzupełnianiu.

Spodziewane zachowanie

  • Podczas pisania rv <TAB>oczekuję: 1) opcji rv, 2) opcji vim, 3) listy ścieżek plików
  • Podczas pisania rv -s <TAB>oczekuję: 1) nazw serwerów vim (podanych przez _rv_vim_servers.
  • Kiedy piszę rv /valid/file/path/<TAB>, spodziewam się zobaczyć tylko listę ścieżek plików. Ponieważ _vimma już tę możliwość, wolałbym na niej polegać.


1
compdefma -nopcję, która mówi, że „zapobiega nadpisaniu uzupełnień zdefiniowanych dla polecenia lub kontekstu”. Więc próbowałeś, compdef _vim rva następnie compdev -n _rv rv?
— Lqueryvg,

3
28 głosów pozytywnych i brak odpowiedzi ... i to jest pytanie o zsh ... Spróbuję przywołać dla ciebie @ StéphaneChazelas ^^ (Staram się tego nie nadużywać, ale to fajne. Stephane, powiedz mi, czy nie powinienem zrób to ... a ja to usunę i nigdy więcej tego nie zrobię) ... Jeśli ktoś tutaj zna odpowiedź, powinien to być on
— Olivier Dulac

1
@OlivierDulac Myślę, że otrzymujesz powiadomienia tylko, jeśli już opublikowałeś wątek. (Zduplikowane nazwy są dozwolone, więc ma to sens.) Być może jednak możesz go znaleźć na czacie.
— Sparhawk

Czy możliwe jest źródło oryginalnego _vim pliku, ale zanim to zrobisz, zastąp _argumentsfunkcję niestandardową funkcją lokalną? W ten sposób uzyskasz argumenty od _vim. Może z oddzielnym procesem zsh.
— Raphael Ahrens

Odpowiedzi:


1

Znalazłem / usr / share / zsh / functions / Completion / Unix / _git, który miał kilka wskazówek dla takich aliasów i ostatecznie zdefiniowałem te funkcje dla aliasów:

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

Następnie wykonaj prosty compdef g = git. System autouzupełniania zobaczy, że korzystasz na przykład z g ls i użyjesz funkcji autouzupełniania _git-ls.

Jak znaleziono tutaj


dzięki, ale nie do końca. twoje rozwiązanie zakłada, że ​​chcę tylko od autouzupełniania _git-ls-files. To pytanie ma git-ls(zgodnie z konwencją) własne opcje, a niektóre z nich pokrywają się git-ls-files. Zamiast pisać autouzupełnianie dla wszystkich opcji git-ls, jak napisać autouzupełnianie, które pobiera autouzupełnianie _git-ls-files(które obejmuje powiedzmy 90%) i łączy je z autouzupełnianiem pozostałych (powiedzmy 10%) opcji?
— Justin C
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.