Bonjour,
Je vous présente mon module serverline, il permet d’éviter que l’input et l’output se mélangent. L’affichage serait mélangé sans mon module comme ceci :
> h 64.51.38.166 user connected.
el 216.206.207.44 user connected.
p 35.54.96.71 user connected.
Au lieu d’avoir > help
sur une seule ligne.
Genèse du module
Je voulais pouvoir lancer une commande lors du développement sans avoir à éteindre mon serveur. Mon premier réflexe a été d’essayer avec readline mais j’avais le bug ci-dessus. J’ai donc essayé dans un premier temps de rewrite console.log
ainsi que ses alias (error, warn, info), ça marché très bien, c’était une solution bricolée que j’ai voulu améliorer.
Pour améliorer mon code, je suis allé voir les sources du module Console dans le git de node. Et j’ai vu que depuis la v10, je pouvais redéclarer la classe Console
avec mes propres objects Streams.Writable
:
const collection = {
stdout: new stream.Writable(),
stderr: new stream.Writable()
}
console = new Console(collection.stdout, collection.stderr)
Ensuite, j’ai relié l’input et l’output de la console avec mes streams. Le cœur du module, c’est-à-dire la partie qui gère l’affichage fait 3 lignes (il m’a fallu du temps pour trouver la bonne combinaison sans bug), elle utilise des escapes séquences pour positionner l’affichage correctement.
Explication du fonctionnement du module
text += '\n\r\x1B[' + nbline + 'A\x1B[0J'
text += chunk.toString()
text += Array(nbline).join('\n')
La première ligne est chargé d’effacer la zone de saisie > zone de saisie
. Tout d’abord on saute une ligne \n
et on veille à être en début de ligne \r
. La variable nbline
représente la taille du prompt (zone de saisie) et Esc[ValueA va déplacer le curseur vers le haut (donc au niveau de >
), il nous reste plus qu’à effacer tout ce qui se trouve entre le curseur et le bas de la console ce qui efface : > zone de saisie
.
Si vous ne comprenez pas la différence entre \n
et \r
essayez : console.log("Mon plat favori est les\ngauffres aux chocolats\r- crêpes\n:P")
.
La deuxième ligne, va écrire le contenu du message qu’on voulait afficher par exemple 'message'
dans console.log('message')
.
Dernière phase, réécrire la prompt > zone de saisie
, on pourrait très bien s’embêter à essayer d’afficher nous-même mais on va laisser le module readline s’en occuper pour nous avec readline._refreshLine()
. Vu qu’il n’a rien suivi de ce qu’on a fait, il croit toujours que les X dernières lignes sont la prompt donc on va sauter de ligne X fois.
Vas-tu améliorer ton module ?
Je voudrais créer des tests qui vérifient que l’output se fait correctement dans la console, cependant il me semble que je dois passer par un autre langage, car je n’ai pas réussi à sauvegarder et comparer l’output de façon viable pour avoir un test correct et fonctionnel. Travis actuellement s’occupe uniquement d’eslint.
Bon vol,
A.