Calculer « 1/(40rods/hogshead) to L/100km » depuis l’invite Zsh
Vincent Bernat
J’ai souvent besoin d’un calcul rapide ou de convertir une unité en une autre.
Plutôt que de recourir à un outil séparé, quelques lignes de configuration Zsh
transforment = en calculatrice. En tapant = 660km / (2/3)c * 2 -> ms,
j’obtiens 6.60457 ms1 sans quitter mon terminal, grâce à l’éditeur
de ligne de Zsh.
L’alias =#
L’idée de base est simple : définir = comme alias vers une calculatrice en
ligne de commande. Je préfère Numbat[1], une calculatrice scientifique gérant
les conversions d’unités. Qalculate[2] est une autre option2. Si aucun
des deux n’est disponible, nous nous rabattons sur le module zcalc intégré à
Zsh.
Comme la commande alias utilise = comme séparateur entre nom et valeur, nous
modifions directement le tableau associatif aliases :
if (( $+commands[numbat] )); then
aliases[=]='numbat -e'
elif (( $+commands[qalc] )); then
aliases[=]='qalc'
else
autoload -Uz zcalc
aliases[=]='zcalc -f -e'
fi
Ainsi, = 847/11 devient numbat -e 847/11.
Le problème des caractères spéciaux#
Le premier problème apparaît vite. Taper = 5 * 3 échoue : Zsh interprète *
comme un motif pour fichiers avant de le transmettre à la calculatrice. Le même
souci se pose avec d’autres caractères spéciaux pour Zsh, comme > ou |. Il
faut protéger l’expression :
$ = '5 * 3'
15
Nous corrigeons cela en nous appuyant sur l’éditeur de ligne de Zsh pour placer l’expression entre guillemets avant son exécution.
Protéger l’expression automatiquement avec ZLE#
Zsh appelle le widget line-finish avant de valider une commande. Nous y
attachons une fonction qui détecte le préfixe = et protège l’expression :
_vbe_calc_quote() {
case $BUFFER in
"="*)
typeset -g _vbe_calc_expr=$BUFFER # not used yet
BUFFER="= ${(q-)${${BUFFER#=}# }}"
;;
esac
}
add-zle-hook-widget line-finish _vbe_calc_quote
Quand on tape = 5 * 3 puis ↲, _vbe_calc_quote protège
l’expression avec le drapeau (q-)[3] et réécrit la
ligne en = '5 * 3' avant que Zsh ne valide la commande. En bonus, vous
pouvez économiser quelques caractères avec =5*3 ! 🚀
Nous pouvons désormais effectuer des calculs et des conversions d’unités directement depuis le shell. Zsh protège automatiquement les expressions :
$ = '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

Conserver l’expression originale dans l’historique#
En l’état, Zsh enregistre l’expression protégée dans l’historique. Il faut la déprotéger avant de la soumettre à nouveau, sinon ZLE la protège une seconde fois. Bart Schaefer[4] m’a fourni une solution pour stocker la version originale :
_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
Le hook zshaddhistory renvoie 1 quand une expression est en cours
d’évaluation, indiquant à Zsh de ne pas enregistrer la commande. Le hook
preexec ajoute ensuite la commande originale, non protégée, avec print -s.
Le code complet est disponible dans mon zshrc[5]. Une alternative courante est
le modificateur noglob[6]. En utilisant to au lieu de -> pour les
conversions d’unités, il couvre 90 % des cas. Pour une astuce similaire avec
l’éditeur de ligne de Zsh, voyez comment j’utilise les expansions automatiques
des alias[7] pour corriger les fautes de frappe courantes.
- https://numbat.dev/
- https://qalculate.github.io/
- https://manpages.debian.org/zshexpn.1.html#q~2
- https://www.zsh.org/mla/users/2026/msg00021.html
- https://github.com/vincentbernat/zshrc/blob/9af588820bed37b3b64b2f06777a77d32f4654c4/rc/alias.zsh#L451-L480
- https://manpages.debian.org/zshmisc.1.html#noglob
- https://vincent.bernat.ch/fr/blog/2025-zsh-expansion-automatique-alias