Come combinare il completamento automatico zsh per gli argomenti della funzione wrapper e il comando esistente


40

Lavoro principalmente in gvim e in molti terminali. Inizialmente, ho preferito aprire tutti i miei file in un'unica istanza di vim. A tal fine ho usato un alias per aprire i file dai miei terminali nell'attuale "server vim".

alias rv="gvim --remote-silent"

Ma avere molti file di più progetti aperti in una singola istanza di vim influisce sulla mia produttività, quindi sto aggiornando il mio alias a una funzione.

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

Ora questo nuovo rvha le sue opzioni. Posso usarlo per:

  • elenca i server vim disponibili (-l --list)
  • imposta il server vim predefinito per la shell corrente (-s --set)
  • mostra il server vim predefinito (-i --info)
  • aprire i file in un server vim specifico (-t --target)
  • aprire i file nel server vim predefinito: rv files...

Tuttavia, poiché sto usando una funzione per rvanziché un alias, perdo il completamento zsh che mi è piaciuto in precedenza. Ho letto sulla creazione di una funzione di completamento _rv, che mostrerà rvle opzioni di completamento, ma voglio combinare le mie opzioni di completamento con le opzioni di completamento vim esistenti. So che potrebbero esserci dei conflitti con rv' -se vim' -s, ma immagino di poterlo gestire elegantemente con il --separatore.

TLDR; Quindi, come posso creare uno script di completamento che combina le _argumentsopzioni per entrambi _rve _vim? Preferisco riutilizzare, _vimse possibile, piuttosto che incollare la copia nella sua lista di argomenti _rv.

Ecco la mia _rv. Aggiornato il 16/06/2014 alle 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 "$@"

Comportamento attuale

Attualmente il _rvcompletamento sarà utilizzabile, ma non ideale.

  • Quando scrivo rv <TAB>, non vedo le opzioni vim. Vengono visualizzate solo le opzioni rv e i percorsi dei file. _vimsta completando i percorsi dei file per me, quindi evviva!
  • Quando scrivo rv -s <TAB>, vedo l'elenco dei server vim, ma vengono visualizzati anche i percorsi dei file. Un file non è consentito a questo punto nel comando e non dovrebbe apparire nel completamento automatico.

Comportamento atteso

  • Quando scrivo rv <TAB>, mi aspetto di vedere: 1) opzioni rv, 2) opzioni vim, 3) elenco percorsi file
  • Quando scrivo rv -s <TAB>, mi aspetto di vedere: 1) i nomi dei server vim (come fornito da _rv_vim_servers.
  • Quando scrivo rv /valid/file/path/<TAB>, mi aspetto di vedere solo un elenco di percorsi di file. Dal momento che _vimha già questa capacità, preferirei fare affidamento su di essa.

1
Questo unix.stackexchange.com/questions/128199/… potrebbe essere utile.
clobrano,

1
compdefha -nun'opzione che dice che "impedisce che qualsiasi completamento già definito per il comando o il contesto venga sovrascritto". Quindi, hai provato compdef _vim rvseguito da compdev -n _rv rv?
Lqueryvg,

3
28 voti positivi e nessuna risposta ... ed è una domanda su zsh ... Proverò a invocare @ StéphaneChazelas per te ^^ (Cerco di non abusare di questo, ma è divertente. Per favore Stephane, dimmi se non dovrei fai questo ... e lo cancellerò e non lo farò mai più) ... Se qualcuno qui può conoscere la risposta, dovrebbe essere lui
Olivier Dulac

1
@OlivierDulac Penso che ricevi notifiche solo se hai già pubblicato nella discussione. (Sono consentiti nomi duplicati, quindi questo ha senso.) Tuttavia potresti trovarlo in chat.
Sparhawk,

Potrebbe essere possibile originare il _vim file originale , ma prima di farlo sovrascrivere la _argumentsfunzione con una funzione locale personalizzata? In questo modo otterresti gli argomenti da _vim. Forse con un processo zsh separato.
Raphael Ahrens,

Risposte:


1

Ho trovato / usr / share / zsh / funzioni / Completion / Unix / _git che aveva alcuni suggerimenti per alias come questo e ho finito per definire queste funzioni per gli alias:

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

Quindi, esegui una composizione diretta g = git. Il sistema di completamento automatico vedrà che stai eseguendo, ad esempio, gs e usa la funzione di completamento automatico _git-ls.

Come trovato qui


grazie, ma non del tutto. la tua soluzione presuppone che desidero solo il completamento automatico da _git-ls-files. Questa domanda ha git-ls(attenersi alla tua convenzione) con le sue opzioni e alcune di quelle si sovrappongono git-ls-files. Invece di scrivere il completamento automatico per tutte le opzioni di git-ls, come faccio a scrivere un completamento automatico che prende il completamento automatico _git-ls-files(che copre il 90%) e li combina con il completamento automatico delle restanti opzioni (il 10%)?
Justin C,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.