Resolver todos los alias en una línea de comando zsh

12

He anidado alias y quiero resolverlos todos antes de ejecutar el comando. ¿Cómo puedo hacer eso?

Si hay una función que no está vinculada a ninguna tecla, también M-x foobarestá bien para mí. Incluso podría utilizar comando externo ( type, command, which, lo que sea). Intenté todo desde el hilo ¿Por qué no usar "which"? ¿Qué usar entonces? Pero nada funciona.

WeSenseASoulInSearchOfAnswers
fuente
2
C-x aexpande el alias debajo del cursor (suponiendo que esté utilizando el sistema de finalización).
Stéphane Chazelas
Derecho, _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Eso es útil, sin embargo, es una pena que en bash se pueda expandir toda la línea, pero en zsh no.
WeSenseASoulInSearchOfAnswers
Supongo que es posible escribir un comando enlazable que invoca _expand_aliashasta que el búfer de edición ya no cambie.
vinc17

Respuestas:

10

Tenga en cuenta que Ctrl-Alt-E bashno solo expande los alias. También expande variables, sustitución de comandos (!), Sustitución de procesos (!), Expansión aritmética y elimina comillas (no genera generación de nombre de archivo (globbing) o expansión de tilde).

No siempre logra expandir los alias. Entonces, aunque tiene sus usos, es importante darse cuenta de que su resultado potencialmente cambia el significado de la línea de comando, tiene efectos secundarios y es potencialmente peligroso.

Por ejemplo en:

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done

Si presiono M-C-Eaquí, eso me da:

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done

Lo que me da una línea de comando completamente diferente (e imagina lo que hubiera pasado si hubiera tenido en rm -rf *lugar de pwdarriba) y no expande el fooalias.

Con zsh, para construir sobre la nota de Gilles sobre alias expandidos dentro de las funciones, puede hacer:

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases

Eso expandirá los alias solo si la línea de comando actual es sintácticamente válida (por lo que funciona como un verificador de sintaxis).

Contrariamente a bashla MCE, también resuelve completamente los alias. Por ejemplo si tienes:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll

Se ampliará a:

$ ls --color -l

Tenga en cuenta que también canoniza la sintaxis para que cosas como:

$ for i (*) cmd $i; foo

se cambiará a:

$ for i in *
        do
                cmd $i
        done
        foo
Stéphane Chazelas
fuente
Esto tiene errores. Si tengo alias ls='ls --color'y escribo de C-x anuevo ls, obtengo: \ls --color(para que lo nuevo lsno se malinterprete como un alias). Pero con tu expand-aliases, obtengo: ls --colorhaciendo que el resultado sea ambiguo.
vinc17
@ vinc17, no es ambiguo porque resuelve completamente el alias (en ese sentido, es menos defectuoso que el bashequivalente). Pero es cierto si ejecuta el comando después de eso, obtendrá otra ronda de expansión de alias (como en bash), por lo que idealmente desearía deshabilitar temporalmente la expansión de alias, por ejemplo, envuelva eso en a (){ setopt localoptions noexpandalias; ...; }. Tenga en cuenta que podría decir que _expand_aliases defectuoso y expande el alias cuando se ejecuta \ls.
Stéphane Chazelas
@ vinc17, ese escape de barra invertida hecho por _expand_aliastambién se engaña fácilmente como alias 'foo=repeat 3 foo'o alias ls='ls --color'; alias '\ls=echo fooled'. No hay una solución perfecta aquí.
Stéphane Chazelas
En cuanto _expand_aliasa alias 'foo=repeat 3 foo', consideraría la barra invertida faltante como un error. Y alias '\ls=echo fooled'no debería permitirse; aquí prefiero fiesta, que dice: bash: alias: '\ls': invalid alias name.
vinc17
@ vinc17, no puedo ver cómo eso puede verse como algo más que una limitación en bash. Si no le gustan los alias con barras invertidas, no los use, pero ¿por qué querría que el shell los rechace? Si bien los alias son el reemplazo de las funciones de un hombre pobre en csh (de dónde provienen), en los shells tipo Bourne, son trucos para hacer trucos que no se pueden hacer con funciones, alguna forma de expansión macro que se engancha temprano en el analizador de shell , No veo el punto de restringir lo que puede hacer.
Stéphane Chazelas
6

Si inserta una línea de comando en una definición de función y luego imprime la función, los alias se expandirán. También obtendrá espacios en blanco normalizados.

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}

Para poner todo esto en un comando interactivo, puede hacer un widget zle. Puede definir una función directamente insertando su código en una entrada en la functionsmatriz; obtendrá el efecto de normalización cuando lea de nuevo.

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey  normalize-command-line

Obtiene el mismo efecto de normalización en el preexecgancho . Los alias también se expanden en el momento en que una función se carga automáticamente ( autoload -Use usa comúnmente para evitar la expansión de alias).

La _expand_aliasfunción de finalización expande la palabra debajo del cursor si es un alias. Utiliza la aliasesmatriz . No es recursivo. Puede implementar un expansor de alias más general usando aliases, pero es algo difícil, porque descubrir las ubicaciones donde se expanden los alias está íntimamente conectado con la sintaxis de shell.

Gilles 'SO- deja de ser malvado'
fuente
2
Siempre lo usé autoload -Usimplemente porque la documentación de zsh lo recomienda, pero nunca entendí lo que -Urealmente hice hasta que leí esto :). También para cualquier persona interesada, se puede invocar las _expand_alias funcionan directamente escribiendo sus alias en la línea de comandos, golpear <Esc>, x, para poner en marcha el minibúfer, a continuación, escribiendo_expand_alias<Enter>
the_velour_fog
2

Si tiene muchos alias elegantes anidados y no está seguro de qué está haciendo realmente zsh con ellos y en qué orden se pasan las opciones al comando, siempre puede iniciar zsh con la -xopción. Esto imprimirá comandos y argumentos a medida que se ejecutan.

Sin embargo, tenga en cuenta que esta opción está destinada más bien a fines de depuración, por lo que imprime muchas cosas inútiles justo después de la zsh -xinvocación (básicamente todas y cada función / widget / complemento de su .zshrc), y durante la ejecución del comando también podría ser detallado, especialmente si has definido preexecy precmdgancho.

También debo mencionar que imprime solo los comandos que finalmente se ejecutan, y los comandos separados se imprimen por separado, así que después

alias a='echo a'
alias b='echo b'
alias c='echo c'
alias d='echo d'
a && b || c; d

Ya verás

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
jimmij
fuente