Risolvi tutti gli alias in una riga di comando zsh


12

Ho alias nidificati e voglio risolverli tutti prima di eseguire il comando. Come lo faccio?

Se esiste una funzione che non è associata a nessun tasto, M-x foobarva bene anche per me. Potrei anche utilizzare il comando esterno ( type, command, which, a prescindere). Ho provato di tutto dal thread Perché non usare "quale"? Cosa usare allora? ma niente funziona.


2
C-x aespande l'alias sotto il cursore (supponendo che tu stia utilizzando il sistema di completamento).
Stéphane Chazelas,

A destra, _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Questo è utile, comunque è un peccato che in bash si possa espandere l'intera linea ma in zsh no.
WeSenseASoulInSearchOfAnswers

Suppongo che sia possibile scrivere un comando associabile che invochi _expand_aliasfino a quando il buffer di modifica non cambia più.
vinc17,

Risposte:


10

Si noti che Ctrl-Alt-E in bashnon espande solo gli alias. Espande anche le variabili, la sostituzione dei comandi (!), La sostituzione dei processi (!), L'espansione aritmetica e rimuove le virgolette (non genera la generazione del nome del file (globbing) o l'espansione della tilde).

Non sempre riesce a espandere gli alias. Quindi, sebbene abbia i suoi usi, è importante rendersi conto che i suoi risultati cambiano potenzialmente il significato della riga di comando, hanno effetti collaterali ed è potenzialmente pericoloso.

Ad esempio in:

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

Se premo M-C-Equi, mi dà:

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

Il che mi dà una linea di comando completamente diversa (e immagina cosa sarebbe successo se avessi avuto rm -rf *invece di pwdsopra) e non espande l' fooalias.

Con zsh, per costruire sulla nota di Gilles sugli alias espansi all'interno delle funzioni, potresti fare:

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

Ciò espanderà gli alias solo se la riga di comando corrente è sintatticamente valida (quindi funge anche da correttore di sintassi).

Contrariamente al bashMCE, risolve anche completamente gli alias. Ad esempio se hai:

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

Sarà esteso a:

$ ls --color -l

Nota che canonicalizza anche la sintassi, quindi cose come:

$ for i (*) cmd $i; foo

sarà cambiato in:

$ for i in *
        do
                cmd $i
        done
        foo

Questo è un bug. Se ho alias ls='ls --color'e inserite C-x asopra ls, ottengo: \ls --color(in modo che il nuovo lsnon sia interpretato come un alias). Ma con il tuo expand-aliases, ottengo:, ls --colorrendendo ambiguo il risultato.
vinc17,

@ vinc17, non è ambiguo in quanto risolve completamente l'alias (a tal proposito, è meno buggy bashdell'equivalente). Ma è vero se esegui il comando dopo quello, otterrai un altro giro di espansione alias (come in bash), quindi idealmente vorresti disabilitare temporaneamente l'espansione alias, quindi ad esempio avvolgilo in a (){ setopt localoptions noexpandalias; ...; }. Si noti che si può dire che _expand_aliasè buggy e si espande l'alias quando eseguito \ls.
Stéphane Chazelas,

@ vinc17, anche il backslash che fuoriesce _expand_aliasviene facilmente ingannato come alias 'foo=repeat 3 foo'o alias ls='ls --color'; alias '\ls=echo fooled'. Non esiste una soluzione perfetta qui.
Stéphane Chazelas,

Per quanto _expand_aliasriguarda alias 'foo=repeat 3 foo', considererei la barra rovesciata mancante come un bug. E alias '\ls=echo fooled'non dovrebbe essere permesso; qui Preferisco bash, che dice: bash: alias: '\ls': invalid alias name.
vinc17,

@ vinc17, non riesco a vedere come questo possa essere visto come nient'altro che una limitazione in bash. Se non ti piacciono gli alias con barre rovesciate, non usarli, ma perché vorresti che la shell li respingesse? Mentre gli alias sono un sostituto delle funzioni di un uomo povero in csh (da dove provengono), nelle shell tipo Bourne, sono degli hack per fare trucchi che non possono essere fatti con le funzioni, una qualche forma di espansione macro che si aggancia all'inizio del parser di shell , Non vedo il punto nel limitare ciò che può fare.
Stéphane Chazelas,

6

Se si inserisce una riga di comando in una definizione di funzione e quindi si stampa la funzione, gli alias verranno espansi. Otterrai anche spazi bianchi normalizzati.

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

Per mettere tutto questo in un comando interattivo, puoi creare un widget zle. È possibile definire una funzione direttamente inserendo il suo codice in una voce functionsdell'array; otterrai l'effetto di normalizzazione quando rileggi.

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

Si ottiene lo stesso effetto di normalizzazione nel preexecgancio . Gli alias vengono inoltre espansi nel momento in cui una funzione viene caricata automaticamente ( autoload -Uviene comunemente utilizzata per evitare l'espansione dell'alias).

La _expand_aliasfunzione di completamento espande la parola sotto il cursore se è un alias. Usa l' aliasesarray . Non è ricorsivo. È possibile implementare un expander alias più generale usando aliases, ma è un po 'difficile, perché capire dove si espandono gli alias è intimamente connesso con la sintassi della shell.


2
Ho sempre usato autoload -Usemplicemente perché la documentazione di zsh lo consiglia, ma non ho mai capito cosa -Ufacesse fino a quando non ho letto questo :). Anche per chiunque sia interessato, si possono invocare le _expand_alias funzione direttamente digitando i vostri alias nella riga di comando, colpendo <Esc>, xper lanciare il minibuffer, quindi digitando_expand_alias<Enter>
the_velour_fog

2

Se hai molti alias fantasiosi nidificati e non sei sicuro di cosa zsh stia effettivamente facendo con loro e in quale ordine le opzioni vengano passate al comando, puoi sempre avviare zsh con l' -xopzione. Questo stamperà i comandi e gli argomenti man mano che vengono eseguiti.

Tenere presente tuttavia che questa opzione è intesa piuttosto per scopi di debug, quindi stampa molte cose inutili subito dopo l' zsh -xinvocazione (praticamente ogni funzione / widget / plugin del tuo .zshrc), e durante l'esecuzione del comando potrebbe essere anche prolisso, specialmente se hai definito preexece precmdagganciato.

Vorrei anche menzionare che stampa solo quei comandi che vengono infine eseguiti e che i comandi separati vengono stampati separatamente così dopo

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

Vedrai

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
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.