So kombinieren Sie zsh autocomplete für Wrapperfunktionsargumente und vorhandenen Befehl

40

Ich arbeite hauptsächlich in gvim und vielen Terminals. Ursprünglich habe ich es vorgezogen, alle meine Dateien in einer einzigen vim-Instanz zu öffnen. Zu diesem Zweck habe ich einen Alias ​​verwendet, um Dateien von meinen Terminals auf dem aktuellen 'vim-Server' zu öffnen.

alias rv="gvim --remote-silent"

Das Öffnen vieler Dateien aus mehreren Projekten in einer einzigen vim-Instanz wirkt sich jedoch auf meine Produktivität aus. Daher aktualisiere ich meinen Alias ​​auf eine Funktion.

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

Jetzt hat dieser neue rvseine eigenen Optionen. Ich kann es verwenden, um:

  • Liste der verfügbaren VIM-Server (-l --list)
  • Legt den vim-Standardserver für die aktuelle Shell fest (-s --set)
  • zeige den vim Standardserver (-i --info)
  • Dateien auf einem bestimmten VIM-Server öffnen (-t --target)
  • Dateien auf dem vim-Standardserver öffnen: rv files...

Da ich jedoch eine Funktion für rvanstelle eines Alias ​​verwende, verliere ich die zsh-Vervollständigung, die ich zuvor genossen habe. Ich habe auf die Schaffung einer Vervollständigungsfunktion, nachlesen _rv, dass zeigt rv‚s Optionen, aber ich möchte meinen Abschluss Optionen mit den bestehenden vim Abschluss Optionen kombinieren. Ich weiß , dass es einige Konflikte mit sein rv‚s -sund vim‘ s -s, aber ich glaube ich , dass elegant mit dem Griff kann --Separator.

TLDR; Wie erstelle ich ein Abschlussskript, das die _argumentsOptionen für _rvund kombiniert _vim? Ich bevorzuge die Wiederverwendung, _vimwenn möglich, anstatt die Argumente in die Liste einzufügen _rv.

Hier ist meine _rv. Aktualisiert 10.06.2014 16:10 Uhr

#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 "$@"

Aktuelles Verhalten

Derzeit ist der _rvAbschlusswille verwendbar, aber nicht ideal.

  • Bei rv <TAB>der Eingabe werden die vim-Optionen nicht angezeigt. Es werden nur die rv-Optionen und Dateipfade angezeigt. _vimvervollständigt Dateipfade für mich, also auf Wiedersehen!
  • Bei rv -s <TAB>der Eingabe wird die Liste der VIM-Server angezeigt, aber auch die Dateipfade. Eine Datei ist zu diesem Zeitpunkt im Befehl nicht zulässig und sollte nicht in der Autovervollständigung angezeigt werden.

Erwartetes Verhalten

  • Bei der rv <TAB>Eingabe erwarte ich Folgendes: 1) rv-Optionen, 2) vim-Optionen, 3) Dateipfadliste
  • Wenn ich tippe rv -s <TAB>, erwarte ich Folgendes: 1) VIM-Servernamen (wie von bereitgestellt) _rv_vim_servers.
  • Bei der Eingabe rv /valid/file/path/<TAB>erwarte ich nur eine Dateipfadliste. Da _vimdiese Fähigkeit bereits vorhanden ist, würde ich mich lieber darauf verlassen.
Justin C
quelle
1
Diese unix.stackexchange.com/questions/128199/… könnte nützlich sein.
Clobrano
1
compdefhat eine -nOption, die besagt, dass verhindert wird, dass bereits für den Befehl oder den Kontext definierte Vervollständigungen überschrieben werden. Also, hast du es versucht, compdef _vim rvgefolgt von compdev -n _rv rv?
Lqueryvg
3
28 Upvotes und keine Antwort ... und es ist eine Frage zu zsh ... Ich werde versuchen, @ StéphaneChazelas für Sie aufzurufen Wenn jemand hier die Antwort weiß, sollte er es sein
Olivier Dulac
1
@OlivierDulac Ich denke du bekommst nur Benachrichtigungen, wenn du bereits im Thread gepostet hast. (Doppelte Namen sind zulässig, daher ist dies sinnvoll.) Sie können ihn jedoch möglicherweise im Chat finden.
Sparhawk
Könnte es möglich sein, die Originaldatei zu _vim erzeugen, aber vorher die _argumentsFunktion mit einer benutzerdefinierten lokalen Funktion zu überschreiben ? Auf diese Weise würden Sie die Argumente von erhalten _vim. Vielleicht mit einem separaten zsh-Prozess.
Raphael Ahrens

Antworten:

1

Ich fand / usr / share / zsh / functions / Completion / Unix / _git, das einige Tipps für Aliase wie dieses hatte, und definierte schließlich diese Funktionen für die Aliase:

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

Führen Sie dann eine gerade compdef g = git aus. Das Autocomplete-System erkennt, dass Sie beispielsweise g ls ausführen und die Autocomplete-Funktion _git-ls verwenden.

Wie gefunden Hier

Adedoyin Akande
quelle
danke, aber nicht ganz. Ihre Lösung geht davon aus, dass ich nur die automatische Vervollständigung von möchte _git-ls-files. Diese Frage hat eine git-ls(um sich an Ihre Konvention zu halten) mit eigenen Optionen, und einige dieser Optionen überschneiden sich mit git-ls-files. Anstatt Autovervollständigen für alle Optionen von zu git-lsschreiben, wie schreibe ich ein Autovervollständigen, das das Autovervollständigen von _git-ls-files(das etwa 90% abdeckt) nimmt und es mit dem Autovervollständigen der verbleibenden (etwa 10%) Optionen kombiniert?
Justin C