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.

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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.