Resolve todos os aliases em uma linha de comando zsh

12

Aninhei aliases e quero resolver todos eles antes de executar o comando. Como faço isso?

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

    
por WeSenseASoulInSearchOfAnswers 17.08.2014 / 16:03

3 respostas

8

Observe que Ctrl-Alt-E em bash não apenas expande os aliases. Também expande variáveis, substituição de comandos (!), Substituição de processos (!), Expansão aritmética e remoção de cotações (não faz geração de nome de arquivo (globbing) ou expansão de til).

Nem sempre consegue expandir os aliases. Assim, 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-E aqui, isso me dará:

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

O que me dá uma linha de comando totalmente diferente (e imagine o que teria acontecido se eu tivesse rm -rf * em vez de pwd acima) e não expandisse o foo alias.

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

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 somente se a linha de comando atual for sintaticamente válida (por isso, funciona como um verificador de sintaxe).

Ao contrário do M-C-E de bash , ele também resolve completamente os aliases. Por exemplo, se você tem:

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

será expandido para:

$ ls --color -l

Note que também canoniza a sintaxe para coisas como:

$ for i (*) cmd $i; foo

será alterado para:

$ for i in *
        do
                cmd $i
        done
        foo
    
por 18.08.2014 / 08:55
5

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

% 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 colocando seu código em uma entrada no functions array; 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 preexec hook . Os aliases também são expandidos no momento em que uma função é carregada automaticamente ( autoload -U é comumente usado para evitar expansão de alias).

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

    
por 18.08.2014 / 02:25
2

Se você tem muitos aliases sofisticados aninhados e não tem certeza do que o zsh está realmente fazendo com eles e em quais opções de ordem são passadas para o comando, então você sempre pode iniciar o zsh com a opção -x . Isto irá imprimir comandos e argumentos conforme eles são executados.

Esteja ciente, entretanto, que essa opção é destinada ao propósito de depuração, portanto ela imprime muitas coisas inúteis logo após zsh -x invocação (basicamente toda e qualquer função / widget / plugin do seu .zshrc) e durante a execução do comando também pode ser detalhado, especialmente se você tiver definido preexec e precmd hook.

Devo mencionar também que ele imprime somente os comandos que são finalmente executados, e os comandos separados são impressos separadamente, assim após

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
    
por 18.08.2014 / 23:17

Tags