Palimpseste
Quatre versions d’un outil d’écriture pour découvrir qu’annuler un texte ne le rend pas identique à lui-même.
Un texte qu’on annule ne redevient pas tout à fait le texte d’avant. Il m’a fallu quatre versions du même outil pour le formuler comme ça.
L’outil s’appelle Palimpseste, et le nom fait le travail : un parchemin gratté, réécrit, où l’ancien texte transparaît sous le nouveau. Chaque couche de mon texte y est un éditeur à part entière, posé à droite du précédent. La couleur d’un caractère est sa couche — il n’y a pas de champ « couche » rangé quelque part, la couleur est la donnée. Et chaque caractère porte un identifiant, huit signes en base 36, qui le suit d’une couche à la suivante. C’est ce qui permet de repeindre le même caractère dans tous les panneaux d’un coup : on ne repeint pas une position, on repeint une identité.
Puis on annule.
CodeMirror tient un historique honnête, en ceci qu’il gère ce qu’il dit gérer : le document. Il restitue les caractères, pas ce que je savais d’eux. Frapper, annuler, refaire — le texte à l’écran est identique au signe près, et tous les caractères sont des inconnus. Les identifiants ont été refrappés à neuf, le suivi entre panneaux est mort, et rien n’a planté. C’est la pire espèce de défaut : celui où l’écran est d’accord avec vous.
La réparation tient en dix lignes, et elle porte un nom que je ne connaissais pas — invertedEffects :
const charsInverter = invertedEffects.of(tr => {
const charsTouched = tr.docChanged
|| tr.effects.some(eff => eff.is(setCharsEffect));
if (!charsTouched) return [];
return [setCharsEffect.of(tr.startState.field(charsField))];
});
À chaque transaction qui touche aux caractères, on tend à l’historique l’effet inverse : un effet qui transporte les caractères d’avant, identifiants compris. L’annulation le rejoue. L’identité revient verbatim.
Ce qui m’intéresse là-dedans n’est pas la ligne de code, c’est la question qu’elle a fini par poser. Qu’est-ce qui fait qu’un texte reste le même texte ? L’identité signe à signe ne suffit pas : c’est exactement ce que produisait le défaut, un texte identique, composé d’autres caractères. Il faut porter l’identité à part, et la restaurer explicitement, sinon elle s’évapore à la première annulation. Un palimpseste dit la même chose dans l’autre sens — le texte effacé n’est pas de l’absence de texte.
Le compte, lui, n’est pas glorieux. Une v3 arborescente, une v4 abandonnée en route parce que la couture entre le moteur et l’éditeur refusait de se simplifier, une v5 archivée, et un successeur qui s’appelle git-nacre : git sait déjà dire « c’est la même ligne, elle a bougé », et je n’avais aucune raison de le réécrire. Quatre outils pour une idée qui tient en dix lignes. C’est le vrai ratio, et je préfère l’écrire que l’arrondir.
P.S. Ce texte est la seule chose qui sort du dépôt. Le reste est archivé, ce qui est exactement ce qu’il fallait en faire.