Comment combiner zsh autocomplete pour les arguments de la fonction wrapper et la commande existante

40

Je travaille principalement dans GVIM et de nombreux terminaux. À l'origine, je préférais ouvrir tous mes fichiers dans une seule instance de vim. À cette fin, j'ai utilisé un alias pour ouvrir les fichiers de mes terminaux dans le «serveur vim» actuel.

alias rv="gvim --remote-silent"

Toutefois, le fait que plusieurs fichiers de plusieurs projets soient ouverts dans une seule instance de vim a une incidence sur ma productivité. Je suis donc en train de mettre à niveau mon alias vers une fonction.

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

Maintenant, cette nouvelle rva ses propres options. Je peux l'utiliser pour:

  • liste les serveurs vim disponibles (-l --list)
  • définir le serveur vim par défaut pour le shell actuel (-s --set)
  • affiche le serveur vim par défaut (-i --info)
  • ouvrir des fichiers sur un serveur vim spécifique (-t --target)
  • ouvrir les fichiers sur le serveur vim par défaut: rv files...

Cependant, étant donné que j'utilise une fonction au rvlieu d'un alias, je perds la finalisation de zsh dont je jouissais auparavant. J'ai lu des informations sur la création d'une fonction d'achèvement _rv, qui affichera rvles options, mais je souhaite combiner mes options d'achèvement avec les options d'achèvement vim existantes. Je sais qu'il peut y avoir des conflits avec rv' -set vim' -s, mais je suppose que je peux gérer cela avec élégance avec le --séparateur.

TLDR; Alors, comment puis-je créer un script d'achèvement qui combine les _argumentsoptions pour _rvet _vim? Je préfère réutiliser _vimsi possible au lieu de copier-coller sa liste d'arguments dans _rv.

Voici mon _rv. Mis à jour le 2014/6/10 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 "$@"

Comportement actuel

Actuellement, le _rvtestament est utilisable, mais pas idéal.

  • Lorsque je tape rv <TAB>, je ne vois pas les options de vim. Seules les options rv et les chemins de fichiers sont affichés. _vimcomplète les chemins de fichiers pour moi, alors allez-y!
  • Lorsque je tape rv -s <TAB>, je vois la liste des serveurs vim, mais les chemins de fichiers sont également affichés. Un fichier n'est pas autorisé à ce stade de la commande et ne doit pas apparaître dans la saisie semi-automatique.

Comportement attendu

  • Lorsque je tape rv <TAB>, je m'attends à voir: 1) les options rv, 2) les options vim, 3) la liste des chemins de fichiers
  • Lorsque je tape rv -s <TAB>, j’attends de voir: 1) les noms de serveurs vim (tels que fournis par _rv_vim_servers.
  • Lorsque je tape rv /valid/file/path/<TAB>, je m'attends à ne voir qu'une liste de chemins de fichiers. Étant donné que _vimcette capacité existe déjà, je préférerais compter sur elle.
Justin C
la source
1
Cette unix.stackexchange.com/questions/128199/… pourrait être utile.
Clobrano
1
compdefa une -noption qui dit "empêche les remplacements déjà définis pour la commande ou le contexte d'être écrasés". Alors, avez-vous essayé compdef _vim rvsuivi de compdev -n _rv rv?
Lqueryvg
3
28 votes positifs et pas de réponse ... et c'est une question à propos de zsh ... Je vais essayer d'invoquer @ StéphaneChazelas pour vous ^^ (j'essaie de ne pas en abuser, mais c'est amusant. S'il vous plaît, Stéphane, dites-moi si je ne devrais pas fais ça ... et je supprimerai ça et je ne le referai jamais) ... Si quelqu'un ici peut connaître la réponse, ce devrait être lui
Olivier Dulac
1
@OlivierDulac Je pense que vous recevez des notifications uniquement si vous avez déjà posté dans le fil de discussion. (Les noms en double sont autorisés, cela a donc un sens.) Vous pouvez néanmoins le trouver sur le chat.
Sparhawk
Pourrait-il être possible de générer le _vim fichier d' origine , mais avant cela, écrasez la _argumentsfonction par une fonction locale personnalisée? Ce faisant, vous obtiendrez les arguments de _vim. Peut-être avec un processus zsh séparé.
Raphael Ahrens

Réponses:

1

J'ai trouvé / usr / share / zsh / functions / Completion / Unix / _git qui contient quelques astuces pour des alias comme celui-ci et a fini par définir ces fonctions pour les alias:

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

Ensuite, faites une compdef droite g = git. Le système autocomplete verra que vous exécutez, par exemple, g ls et utilisera la fonction _git-ls autocomplete.

Comme trouvé ici

Adedoyin Akande
la source
merci, mais pas tout à fait. votre solution suppose que je veux seulement l'auto-complétion _git-ls-files. Cette question a git-ls(pour rester avec votre convention) avec ses propres options, et certaines de ces options se chevauchent git-ls-files. Au lieu d'écrire autocomplete pour toutes les options de git-ls, comment puis-je écrire une autocomplète qui prend l'auto-complétion _git-ls-files(qui couvre par exemple 90%) et les combine avec la complétion automatique des options restantes (disons 10%)?
Justin C