evitar que la finalización de bash altere la variable de guión bajo $_

evitar que la finalización de bash altere la variable de guión bajo $_

Cuando se utiliza la función de finalización de tabulación en bash, la $_variable se modifica:

$ mkdir test
$ cd <TAB><TAB> $_
bash: cd: -d: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]

( <TAB><TAB>Enumerará todos los archivos en el directorio actual, pero no termino usando la salida y escribo $_en su lugar. El comando ejecutado en esta línea será simplemente cd $_.)

El comportamiento esperado sería cambiar a ./test.

¿Cómo puedo evitar que se altere la finalización de bash $_?

Respuesta1

Estás usando elbash-completionpaquete (o un derivado). Para cada finalización de argumento del cdcomando (como se muestra en el complete -presultado):

complete -o nospace -F _cd cd

la _cdfunción se invoca para determinar las terminaciones (ligeramente editada por brevedad):

_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d
        return 0
    fi
    ....

Entonces, por ejemplo, cuando completa en un directorio sin ningún CDPATHconjunto, el último argumento visto para un comando visto es -dy se coloca automáticamente en _. Hay varias otras rutas de código en esa función con efectos secundarios similares.

Dado que _bash es interno, se puede realizar un guardado/restauración convencional (como en el caso deIFS) no funcionará como se esperaba. TúpodríaHazlo con un pequeño truco:

_cd()
{
    local save_="$_"
    ...
    : $save_
    return 0

Debe guardar _inmediatamente al ingresar a una función, :es el comando nulo, que no hace nada en sí mismo pero tiene los efectos secundarios habituales de un comando, como configurar _. Esta operación de restauración será necesaria para cada punto de retorno de cada función potencialmente disruptiva. Aquí también hay una sutileza: normalmente _se establece inmediatamente después del retorno de una función (hasta el último argumento de la llamada a la función, como se esperaba), lo que haría que este método fuera ineficaz. Pero esto no sucede cuando se invoca una función de finalización, ya que no se invoca explícitamente. No considero que esto sea muy robusto...

(Yo prefieroexpansión de la historia, y quédese con !$el que no sufre este problema).

información relacionada