Salut à tous,
Avec la maturation de xterm.js
, je pense qu'une fonctionnalité intéressante pour élargir la gamme d'applications xterm.js
pourrait être utile pour la formalisation d'un mode sans tête. Qu'est ce que je veux dire? Eh bien, fondamentalement, pour la capacité de:
À l'heure actuelle, le seul moyen de "définir" de manière fiable l'état d'un client est de rejouer l'ensemble de toutes les commandes qui ont produit l'état de cet éditeur (au moins via l'API publique). Cependant, vous pouvez facilement imaginer vouloir faire des choses comme:
Une grande partie de cela est pratiquement déjà possible si vous sérialisez simplement term.rows
et des indicateurs d'état assortis, mais l'adoption d'une API formelle aiderait beaucoup. Cela peut également aider à améliorer la testabilité et la robustesse de la bibliothèque principale!
Pensées?
Vincent
@vincentwoo Je vois que cela est assez utile, avez-vous une idée de ce à quoi ressemblerait une telle API?
Je pense que vous voudrez probablement un autre constructeur comme term.Headless
, et une nouvelle méthode sur les terminaux sans tête et réguliers comme getState()
qui peut ensuite être introduite dans reset
.
@vincentwoo serait-il également possible de sérialiser l'état sur le serveur et de l'envoyer par câble au client? Récemment, je l'ai fait pour que vous n'ayez pas besoin d'ouvrir xterm sur un élément pour qu'il conserve le tampon, alors cela pourrait suffire?
Ouais, la sérialisation est essentiellement ce que j'entends par "getState", tant que ce qui est produit peut être consommé par le client.
En ce qui concerne simplement l'utilisation du xterm normal sans élément, cela pourrait fonctionner. Je peux lui donner une chance sur node, plus tard.
Je pense que https://github.com/sourcelair/xterm.js/issues/266 signifie qu'il fonctionne essentiellement comme sans tête avant que Terminal.open
soit appelé.
Cool. Des réflexions sur la façon dont l'État exportateur pourrait fonctionner?
Cela dépend de ce qui doit être conservé, juste le tampon et le curseur?
Je ne suis pas sûr moi-même, c'est pourquoi c'était une demande. Je ne sais pas à quoi ressemble la machine à états xterm en interne, ni exactement ce que vous entendez par «tampon» et «curseur».
C'est une excellente proposition @vincentwoo , merci! Je pense que la meilleure partie est la sérialisation de l'état (qui est également la partie principale de cette discussion).
IMO, un bon début dans ce domaine est l'introduction d'une propriété privée (par exemple nommée state
), où nous stockerons les "données" du terminal comme:
Cette propriété doit être utilisée en interne pour "définir" l'état du terminal à chaque fois (et être consultée par les internes du terminal pour voir ce qui se passe lorsque cela est nécessaire), mais elle doit être en lecture seule par le monde extérieur (par exemple term.getState()
).
Comment ça sonne?
Ça me semble bien! Je ne suis pas un expert pour connaître exactement chaque variable d'état qui identifie de manière unique l'état de xterm.js
, mais je suis heureux de donner un coup de pied aux pneus. Je pense qu'essayer de trouver la liste et la tester est aussi un excellent moyen de trouver un comportement bizarre dans la bibliothèque.
Quelques autres choses que nous voulons probablement sérialiser:
@parisk Je pensais qu'une fonction getState
ou serialize
effectuerait la sérialisation à ce stade, nous pourrions tout mettre dans un objet json et renvoyer le json assez facilement. Tout l'état que vous mentionnez peut ne pas appartenir à l'objet Terminal, par exemple le tampon vit dans CircularList
. Il serait plus logique de dire à CircularList
de se sérialiser lors d'un appel à la fonction. Quelque chose comme ça:
Terminal.prototype.getState() {
const state = {};
// this.serializableComponents is an ISerializable[] which ensures they
// have componentKey/getState()
this.serializableComponents.forEach(c => {
state[c.componentKey] = c.getState();
});
// TODO: Add anything owned by Terminal to state
// ...
return state;
}
// Restore using something like this which would do the reverse
Terminal.prototype.restoreState(state: Object): void;
// A static method that returns a Terminal might be better:
Terminal.restoreTerminal(state: Object): Terminal;
C'est une approche intéressante 👍. J'ouvre une succursale pour tenter le coup.
Des mises à jour sur celui-ci? J'ai également un cas d'utilisation similaire.
Copier et coller la proposition pour résoudre ce problème à partir de https://github.com/xtermjs/xterm.js/pull/2213#issuecomment -500233758 ci-dessous
J'ai eu une conversation avec @jerch à ce sujet et nous voyons ces problèmes avec l'approche actuelle consistant à l'inclure dans le noyau:
Compte tenu de cela, nous pensons que la meilleure façon d'aborder cette fonctionnalité est d'utiliser un addon (exemple xterm-addon-serialize
) qui sérialise l'état à l'aide de la nouvelle API de tampon ( Terminal.buffer.*
). La méthode de sérialisation pourrait ressembler à ceci:
/**
* Serializes terminal rows into a string that can be written back to the terminal
* to restore the state. The cursor will also be positioned to the correct cell.
* When restoring a terminal it is best to do before `Terminal.open` is called
* to avoid wasting CPU cycles rendering incomplete frames.
* <strong i="16">@param</strong> rows The number of rows to serialize, starting from the bottom of the
* terminal. This defaults to the number of rows in the viewport.
*/
serialize(rows?: number): string;
Si vous n'êtes pas familier avec les bornes de la chaîne résultante ressemblerait à quelque chose comme ça "\x1b[Hfoo\n\rbar\x1b[2;4H"
pour un simple ligne (déplacer le curseur à la ligne 1, colonne 1, imprimez "foo"
, aller à la ligne suivante et imprimer "bar"
puis positionnez le curseur sur la ligne 2 et la colonne 4).
Cela présente de nombreux avantages:
Notez que cela ne pourrait pas prendre en charge la couleur ou d'autres styles tant que nous n'avons pas exposé les attributs dans l'API, mais c'est quelque chose que nous voulons faire et que nous pourrions améliorer ultérieurement.
Suppression du mode sans tête du titre car xterm.js le prend déjà en charge en fonctionnant correctement sans appeler open
.
Commentaire le plus utile
Des mises à jour sur celui-ci? J'ai également un cas d'utilisation similaire.