Як комбінувати zsh autocomplete для аргументів функції обгортки та існуючої команди


40

Я працюю здебільшого у гвімі та багатьох терміналах. Спочатку я вважав за краще відкрити всі свої файли в одному екземплярі 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« -sі vim» -s, але я думаю, що я можу це елегантно впоратися з --роздільником.

TLDR; Отже, як створити сценарій завершення, який поєднує в собі _argumentsваріанти як _rvі _vim? Я вважаю за краще повторно використовувати, _vimякщо можливо, замість того, щоб вставити копію в список аргументів _rv.

Ось моя _rv. Оновлено 6.10.2014 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/… може бути корисним.
клобрано

1
compdefмає -nпараметр, який говорить, що "запобігає перезапису будь-яких завершень, уже визначених для команди або контексту". Отже, ви намагалися compdef _vim rvслідувати за цим compdev -n _rv rv?
Lqueryvg

3
28 оновлень і жодної відповіді ... і це питання про zsh ... Я спробую попросити @ StéphaneChazelas для вас ^^ (Я намагаюся не зловживати цим, але це весело. Будь ласка, Стефане, скажи мені, чи не варто зробіть це ... і я видалю це, і більше ніколи цього не робити) ... Якщо хтось тут може знати відповідь, це повинен бути він
Олів'є Дулак

1
@OlivierDulac Я думаю, ви отримуватимете сповіщення лише в тому випадку, коли ви вже розмістили в потоці. (Дозволені копії імен, тому це має сенс.) Ви, можливо, могли його знайти в чаті.
Sparhawk

Чи можна отримати джерело оригінального _vim файлу, але перед цим перезаписати _argumentsфункцію за допомогою спеціальної локальної функції? Тим самим ви отримаєте аргументи _vim. Можливо, з окремим процесом zsh.
Рафаель Аренс

Відповіді:


1

Я знайшов / usr / share / zsh / function / 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%) варіантів?
Джастін С
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.