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.