Calcule “1/(40 varetas/​barril) → L/100km” no prompt do Zsh

Muitas vezes preciso de um cálculo rápido ou de uma conversão de unidades. Em vez de recorrer a uma ferramenta separada, algumas linhas de Zsh mudança de configuração = em uma calculadora. Digitando = 660km / (2/3)c * 2 -> ms me dá 6.60457 ms1 sem sair do meu terminal, graças ao editor de linha Zsh.

A ideia principal parece simples: definir = como um alias para um comando da calculadora. eu prefiro Numbateuma calculadora científica que suporta conversões de unidades.
Qalcular é um segundo próximo.2 Se nenhum deles estiver disponível, voltaremos ao recurso integrado do Zsh zcalc módulo.

Como o alias usos integrados = como separador para nome e valor, precisamos alterar o aliases matriz associativa:

if (( $+commands(numbat) )); then
  aliases(=)='numbat -e'
elif (( $+commands(qalc) )); then
  aliases(=)='qalc'
else
  autoload -Uz zcalc
  aliases(=)='zcalc -f -e'
fi

Com isso em vigor, = 847/11 torna-se numbat -e 847/11.

O primeiro problema surge rapidamente. Digitando = 5 * 3 falha: Zsh expande o *
caractere como um padrão glob antes de passá-lo para a calculadora. O mesmo problema se aplica a outros personagens que Zsh trata especialmente, como > ou |. Você deve citar a expressão:

Corrigimos isso conectando-nos ao editor de linha Zsh para cite a expressão
antes de executá-lo.

Cotação automática com ERRADO

Zsh chama o accept-line widget quando você envia um comando. Nós o substituímos por uma função que detecta o = prefixo e cita a expressão:

_vbe_calc_accept() {
  case $BUFFER in
    "="*)
      typeset -g _vbe_calc_expr=$BUFFER # not used yet
      BUFFER="= ${(q-)${${BUFFER#=}# }}"
      ;;
  esac
  zle .accept-line
}
zle -N accept-line _vbe_calc_accept

Quando você digita = 5 * 3 e pressione , _vbe_calc_accept tira o
= prefixo, cita o restante com o (q-) sinalizador de expansão de parâmetroe reescreve o buffer para = '5 * 3' antes de invocar o original .accept-line widget. Como bônus, você pode economizar algumas teclas com
=5*3! 🚀

Agora você pode calcular expressões matemáticas e converter unidades diretamente do seu shell. Zsh cita automaticamente suas expressões:

$ = '1 + 2'
3
$ = 'pi/3 + pi |> cos'
-0.5
$ = '17 USD -> EUR'
14.7122 €
$ = '180*500mg -> g'
90 g
$ = '5 gigabytes / (2 minutes + 17 seconds) -> megabits/s'
291.971 Mbit/s
$ = 'now() -> tz("Asia/Tokyo")'
2026-03-22 22:00:03 JST (UTC +09), Asia/Tokyo
$ = '1 / (40 rods / hogshead) -> L / 100km'
118548 × 0.01 l/km
O sistema métrico é a ferramenta do diabo! Meu carro leva quarenta varas até o barril, e é assim que eu gosto! – Vovô SimpsonUma estrela está queimando

Armazenando histórico não citado

Como está, Zsh registra o citado expressão na história. Você deve retirá-lo antes de enviá-lo novamente. Caso contrário, o ERRADO widget cita-o uma segunda vez.
Bart Schaefer forneceu uma solução para armazenar a versão original:

_vbe_calc_history() {
  return ${+_vbe_calc_expr}
}
add-zsh-hook zshaddhistory _vbe_calc_history

_vbe_calc_preexec() {
  (( ${+_vbe_calc_expr} )) && print -s $_vbe_calc_expr
  unset _vbe_calc_expr
  return 0
}
add-zsh-hook preexec _vbe_calc_preexec

O zshaddhistory hook retorna 1 se estivermos avaliando uma expressão, informando
Zsh para não gravar o comando. O preexec hook então adiciona o comando original sem aspas com print -s.


O código completo está disponível em meu encolher. Uma alternativa comum é a
noglob modificador de pré-comando. Se você ficar com to em vez de ->
para conversão de unidades, cobre 90% dos casos de uso. Para obter um truque relacionado ao editor de linha Zsh, veja como uso aliases de expansão automática para corrigir erros de digitação comuns.


  1. Este é o mais rápido que um pacote pode viajar entre Paris e Marselha através de fibra óptica. ↩︎

  2. Qalculate é menos compreensivo com unidades. Por exemplo, ele analisa “Mbps” como megabarn por picossegundo: ☢️

    $ numbat -e '5 MB/s -> Mbps'
    40 Mbps
    $ qalc 5 MB/s to Mbps
    5 megabytes/second = 0.000005 B/ps
    

    ↩︎

Deseja saber mais sobre Software Livre Clique Aqui!

Deixe um comentário

Translate »