Serverline : Avoir l'input et l'output en même temps

L'output ne coupe plus l'input

a marqué ce sujet comme résolu.
Auteur du sujet

NPM Version Node Version NPM Downloads Linux Build

serverline
serverline

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 :

Exemple sans serverline

Exemple sans serverline

> 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.

Édité par A-312

+3 -0

Super intéressant ! (il n’y aurait pas moyen de mettre qu’on puisse taper des commandes dans la console Django sur zds-site d’ailleurs ?)

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.

$ ./mon_programme > sortie_std 2> erreur_std ?

+0 -0
Auteur du sujet

Super intéressant ! (il n’y aurait pas moyen de mettre qu’on puisse taper des commandes dans la console Django sur zds-site d’ailleurs ?)

Vanadiae

Merci :D

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.

$ ./mon_programme > sortie_std 2> erreur_std ?

Vanadiae

Il faudra que je regarde et voir que ça donne si j’exécute la commande avec mocha/nodejs.

+0 -0

Pratique, j’en ai cherché un y’a pas si longtemps. As-tu essayé de le coupler à npm-run-all ? :)

Je l’essaye et je reviens vers toi !

Tant de choses, tant de vies, tant de possibilités.

+0 -0

Excellent ! Merci A-32. :)

Pour remplacer npm-run-all, j’ai ajouté à la fin de ton script d’exemple ce bout de code :

process.argv.slice(2).map(script => {
    const { spawn } = require('child_process');

    const ls = spawn('npm', ['run', script]);

    ls.stdout.on('data', data => {
        console.log(`${data}`.slice(0, data.length - 1));
    });

    ls.stderr.on('data', error => {
        console.log(`${error}`.slice(0, data.length - 1));
    });

    ls.on('close', code => {
        console.log(`child process exited with code ${code}`);
    });
});

J’ai plus qu’à configurer mon processus d’exécution dans package.json :

"scripts": {
    "start": "node rlprovider fakelog fakeerror",
    "fakelog": "node displayFakeLog",
    "fakeerror": "node displayFakeError"
}

Avant j’utilisais pm2 en dév sauf que depuis les dernières versions, ça plante complètement sur Windows ; y’a une console par processus qui pop 2s puis disparaît de l’écran. Au début ça va … quand tu commences à coder sur des fichiers, le flash devient plus que chiant ! :/

Je continue à l’utiliser sur le serveur de production, ça m’assure que le daemon redémarre les processus quand il faut et qu’il log tout ça proprement (bien qu’avec Docker, j’ai plus trop de souci xD). En revanche quand je code, j’ai fait un mixte npm-run-all & nodemon qui me permet de lancer les logs serveur & client sur le même terminal ; ça me permet d’arrêter tous les processus avec CTRL+C.

Tout ça c’est dans l’optique d’utiliser le mode watch, ton script va bien me servir !

Tant de choses, tant de vies, tant de possibilités.

+0 -0
Auteur du sujet

Avant j’utilisais pm2 en dév sauf que depuis les dernières versions, ça plante complètement sur Windows ; y’a une console par processus qui pop 2s puis disparaît de l’écran. Au début ça va … quand tu commences à coder sur des fichiers, le flash devient plus que chiant ! :/

Oh ! On connait ça avec @Helmasaur sur le zds-site. :pirate: Je vais aller essayer npm-runn


ls.stdout.on('data', fonctionne bien? Si je comprends il va réutiliser les escapes code que j’ai glissé dans mon module ? (Je cherche un moyen d’enregistrer l’output dans un fichier, comme c’est affiché dans la console, mais sans les escapes-code qui déplacent le curseur).

+1 -0

ls.stdout.on('data', fonctionne bien? Si je comprends il va réutiliser les escapes code que j’ai glissé dans mon module ? (Je cherche un moyen d’enregistrer l’output dans un fichier, comme c’est affiché dans la console, mais sans les escapes-code qui déplacent le curseur).

A-312

Ça marche, on ne peut mieux ! :D

La sortie des sous-processus de Node.js sont nativement silencieux. C’est pour cette raison que j’ai utilisé ls.stdout.on('data', pour capturer la sortie et l’afficher en pensant bien à utiliser ta fonction modifié de console.log. Effectivement, ça n’affiche pas les escapes-code, c’est comme si on exécutait un terminal à côté - il est totalement isolé.

Tant de choses, tant de vies, tant de possibilités.

+0 -0

Avant j’utilisais pm2 en dév sauf que depuis les dernières versions, ça plante complètement sur Windows ; y’a une console par processus qui pop 2s puis disparaît de l’écran. Au début ça va … quand tu commences à coder sur des fichiers, le flash devient plus que chiant ! :/

Yarflam

Oh ! On connait ça avec @Helmasaur sur le zds-site. :pirate: Je vais aller essayer npm-runn

A-312

En vrai, j’ai toujours utilisé pm2 sur Windows et je n’ai jamais rencontrer de soucis… Hormis pour Zeste de Savoir :-° .

Concernant le projet, je ne le comprends pas vraiment.

Édité par Helmasaur

+0 -0

En vrai, j’ai toujours utilisé pm2 sur Windows et je n’ai jamais rencontrer de soucis… Hormis pour Zeste de Savoir :-° .

Helmasaur

La version 2.10.4 de pm2 fonctionne correctement sur Windows.

Tant de choses, tant de vies, tant de possibilités.

+0 -0
Auteur du sujet

Le module est propre à js mais son fonctionemment serait reproductible dans n’importe quel langage non ?

Shikamarus_Shadows

Oui, il suffit d’utiliser la logique des 3 lignes que j’ai cité :) Par contre, le plus compliqué est dans le refresh du prompt selon le langage. ;)

+1 -0

Le module est propre à js mais son fonctionemment serait reproductible dans n’importe quel langage non ?

Shikamarus_Shadows

Comme je disais tu as rlwrap qui fait en partie cela, juste qu’il n’a pas moyen d’identifier le prompt donc il le traite comme n’importe quel texte, mais la zone de saisie reste sur la dernière ligne de l’écran, non mélangée à la sortie.

Et ça gère d’autres fonctionnalités comme l’édition de ligne et l’historique.

Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte