Cómo combinar autocompletar zsh para argumentos de la función de envoltura y comando existente

40

Trabajo principalmente en gvim y en muchas terminales. Originalmente, prefería abrir todos mis archivos en una sola instancia de vim. Con ese fin, utilicé un alias para abrir archivos desde mis terminales en el 'servidor vim' actual.

alias rv="gvim --remote-silent"

Pero tener muchos archivos de múltiples proyectos abiertos en una sola instancia de vim afecta mi productividad, por lo que estoy actualizando mi alias a una función.

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

Ahora este nuevo rvtiene sus propias opciones. Puedo usarlo para:

  • enumerar los servidores vim disponibles (-l --list)
  • establece el servidor vim predeterminado para el shell actual (-s --set)
  • muestra el servidor vim predeterminado (-i --info)
  • abrir archivos en un servidor vim específico (-t --target)
  • abrir archivos en el servidor vim predeterminado: rv files...

Sin embargo, como estoy usando una función para en rvlugar de un alias, pierdo la finalización de zsh que disfruté anteriormente. He leído sobre la creación de una función de finalización _rvque mostrará rvlas opciones, pero quiero combinar mis opciones de finalización con las opciones de finalización de vim existentes. Sé que puede haber algunos conflictos con rv's -sy vim' s -s, pero calculo que puedo manejar eso forma elegante con el --separador.

TLDR; Entonces, ¿cómo creo un script de finalización que combine las _argumentsopciones para ambos _rvy _vim? Prefiero reutilizar _vimsi es posible en lugar de copiar y pegar su lista de argumentos _rv.

Aquí está mi _rv. Actualizado 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 "$@"

Comportamiento actual

Actualmente la _rvterminación de la voluntad es utilizable, pero no ideal.

  • Cuando escribo rv <TAB>, no veo las opciones de vim. Solo se muestran las opciones de rv y las rutas de archivos. _vimestá completando rutas de archivos para mí, ¡así que hurra!
  • Cuando escribo rv -s <TAB>, veo la lista de servidores vim, pero también se muestran las rutas de los archivos. Un archivo no está permitido en este punto en el comando, y no debe aparecer en el autocompletado.

Comportamiento esperado

  • Cuando escribo rv <TAB>, espero ver: 1) opciones de rv, 2) opciones de vim, 3) lista de rutas de archivo
  • Cuando escribo rv -s <TAB>, espero ver: 1) los nombres de servidor de vim (según lo dispuesto por _rv_vim_servers.
  • Cuando escribo rv /valid/file/path/<TAB>, espero ver solo una lista de rutas de archivo. Como _vimya tiene esta capacidad, preferiría confiar en ella.
Justin C
fuente
1
Este unix.stackexchange.com/questions/128199/… podría ser útil.
Clobrano
1
compdeftiene una -nopción que dice "evita que se sobrescriban las finalizaciones ya definidas para el comando o contexto". Entonces, ¿lo has intentado compdef _vim rvseguido compdev -n _rv rv?
Lqueryvg
3
28 votos a favor y sin respuesta ... y es una pregunta sobre zsh ... Trataré de invocar a @ StéphaneChazelas por ti ^^ (Intento no abusar de esto, pero es divertido. Por favor, Stephane, dime si no debería haga esto ... y lo borraré y nunca lo volveré a hacer) ... Si alguien aquí puede saber la respuesta, debería ser él
Olivier Dulac
1
@OlivierDulac Creo que solo recibirás notificaciones si ya has publicado en el hilo. (Se permiten nombres duplicados, por lo que esto tiene sentido). Sin embargo, podría encontrarlo en el chat.
Sparhawk
¿Podría ser posible obtener el _vim archivo original , pero antes de hacerlo sobrescribir la _argumentsfunción con una función local personalizada? Al hacerlo, obtendría los argumentos de _vim. Tal vez con un proceso zsh separado.
Raphael Ahrens

Respuestas:

1

Encontré / usr / share / zsh / functions / Completion / Unix / _git que tenía algunos consejos para alias como este y terminé definiendo estas funciones para los alias:

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

Luego, haz un compdef g = git. El sistema de autocompletar verá que está ejecutando, por ejemplo, g ls y usará la función de autocompletar _git-ls.

Como se encuentra aquí

Adedoyin Akande
fuente
gracias, pero no del todo. su solución asume que solo quiero el autocompletado de _git-ls-files. Esta pregunta tiene un git-ls(para seguir con su convención) con sus propias opciones, y algunas de esas opciones se superponen git-ls-files. En lugar de escribir el autocompletado para todas las opciones de git-ls, ¿cómo escribo un autocompletado que toma el autocompletado _git-ls-files(que cubre, por ejemplo, el 90%), y lo combina con el autocompletado de las opciones restantes (por ejemplo, el 10%)?
Justin C