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.