Resolver todos os aliases em uma linha de comando zsh

12

Aninhei aliases e desejo resolvê-los antes de executar o comando. Como faço isso?

Se existe uma função que não está vinculada a nenhuma tecla, também M-x foobaré bom para mim. Eu poderia até usar comando externo ( type, command, which, qualquer que seja). Eu tentei de tudo, desde o segmento Por que não usar "what"? O que usar então? mas nada funciona.

WeSenseASoulInSearchOfAnswers
fonte
2
C-x aexpande o alias sob o cursor (supondo que você esteja usando o sistema de conclusão).
Stéphane Chazelas
Certo _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Isso é útil, porém ainda é uma pena que no bash se possa expandir toda a linha, mas no zsh não.
WeSenseASoulInSearchOfAnswers
Suponho que seja possível escrever um comando vinculável que seja chamado _expand_aliasaté que o buffer de edição não seja mais alterado.
precisa saber é

Respostas:

10

Observe que Ctrl-Alt-E in bashnão apenas expande aliases. Também expande variáveis, substituição de comando (!), Substituição de processo (!), Expansão aritmética e remove aspas (não gera geração de nome de arquivo (globbing) ou expansão de til).

Nem sempre consegue expandir aliases. Portanto, embora tenha seus usos, é importante perceber que seu resultado potencialmente altera o significado da linha de comando, tem efeitos colaterais e é potencialmente perigoso.

Por exemplo, em:

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

Se eu pressionar M-C-Eaqui, isso me dá:

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

O que me dá uma linha de comando completamente diferente (e imagine o que teria acontecido se eu tivesse tido em rm -rf *vez de pwdacima) e não expande o fooalias.

Com zsh, para aumentar a nota de Gilles sobre aliases expandidos dentro de funções, você pode:

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

Isso expandirá os aliases apenas se a linha de comando atual for sintaticamente válida (portanto, ela também funciona como um verificador de sintaxe).

Ao contrário bashdo MCE, ele também resolve completamente os aliases. Por exemplo, se você tiver:

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

Será expandido para:

$ ls --color -l

Observe que ele também canoniza a sintaxe para coisas como:

$ for i (*) cmd $i; foo

será alterado para:

$ for i in *
        do
                cmd $i
        done
        foo
Stéphane Chazelas
fonte
Isso é buggy. Se eu tiver alias ls='ls --color'e digite C-x amais ls, eu recebo: \ls --color(para que o novo lsnão é mal interpretado como um alias). Mas com o seu expand-aliases, eu recebo ls --color:, tornando o resultado ambíguo.
precisa saber é
@ vinc17, não é ambíguo, pois resolve o alias completamente (nesse sentido, é menos problemático do que o bashequivalente). Mas é verdade que, se você executar o comando depois disso, obterá outra rodada de expansão de alias (como em bash); portanto, idealmente, você deseja desativar temporariamente a expansão de alias, por exemplo, envolva isso em a (){ setopt localoptions noexpandalias; ...; }. Observe que você pode dizer que o _expand_aliasbuggy é bem como expande o alias quando executado \ls.
Stéphane Chazelas
@ vinc17, que a barra invertida feita por _expand_aliastambém é facilmente enganada como alias 'foo=repeat 3 foo'ou alias ls='ls --color'; alias '\ls=echo fooled'. Não há solução perfeita aqui.
Stéphane Chazelas
Em relação _expand_aliasa isso alias 'foo=repeat 3 foo', eu consideraria a barra invertida ausente como um bug. E alias '\ls=echo fooled'não deve ser permitido; aqui eu prefiro bash, que diz: bash: alias: '\ls': invalid alias name.
precisa saber é
@ vinc17, eu não consigo ver como isso pode ser visto como outra coisa senão uma limitação bash. Se você não gosta de aliases com barras invertidas, não os use, mas por que deseja que o shell os rejeite? Embora os aliases sejam uma substituição das funções de um homem pobre no csh (de onde eles vêm), nos shells do tipo Bourne, eles são hacks para fazer truques que não podem ser feitos com funções, alguma forma de expansão de macro que se conecta no início no analisador de shell , Não vejo sentido em restringir o que ele pode fazer.
Stéphane Chazelas
6

Se você inserir uma linha de comando em uma definição de função e depois imprimir a função, os aliases serão expandidos. Você também terá espaço em branco normalizado.

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

Para colocar tudo isso em um comando interativo, você pode criar um widget zle. Você pode definir uma função diretamente inserindo seu código em uma entrada na functionsmatriz; você obterá o efeito de normalização quando voltar a ler.

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

Você obtém o mesmo efeito de normalização no preexecgancho . Os aliases também são expandidos no momento em que uma função é carregada automaticamente ( autoload -Ugeralmente é usada para evitar a expansão do alias).

A _expand_aliasfunção de conclusão expande a palavra sob o cursor se for um alias. Ele usa a aliasesmatriz . Não é recursivo. Você pode implementar um expansor de alias mais geral usando aliases, mas é um pouco difícil, porque descobrir os locais onde os alias são expandidos está intimamente conectado à sintaxe do shell.

Gilles 'SO- parar de ser mau'
fonte
2
Eu sempre usei autoload -Usimplesmente porque a documentação do zsh o recomenda, mas nunca entendi o que -Urealmente fazia até ler isso :). Também para qualquer pessoa interessada, pode-se invocar as _expand_alias funcionar diretamente digitando seu alias na linha de comando, batendo <Esc>, x, para iniciar o minibuffer, em seguida, digitando_expand_alias<Enter>
the_velour_fog
2

Se você tem muitos aliases sofisticados aninhados e não tem certeza do que o zsh está realmente fazendo com eles e em qual ordem as opções são passadas para o comando, sempre é possível iniciar o zsh com a -xopção Isso imprimirá comandos e argumentos conforme eles são executados.

Esteja ciente, no entanto, de que esta opção é destinada para fins de depuração, para que imprima muitas coisas inúteis logo após a zsh -xchamada (basicamente todas as funções / widget / plug-in do seu .zshrc) e, durante a execução do comando, também pode ser detalhada, especialmente se você tiver definido preexece precmdgancho.

Devo também mencionar que ele imprime apenas os comandos que são finalmente executados, e os comandos separados são impressos separadamente.

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

Você verá

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