-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement getState method #613
Conversation
src/xterm.js
Outdated
@@ -251,6 +251,52 @@ function Terminal(options) { | |||
inherits(Terminal, EventEmitter); | |||
|
|||
/** | |||
* Returns the current mode of the terminal. Can be one of the following: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If only 1 of these modes can be active at once we should turn that into an enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I was thinking about that, but I am not exactly sure how this works right now.
I took a look at the following links and I was not able to find any reference to the origin
mode, so I ditched it. Also I cannot understand if insert mode can co-exist with application mode:
continue; | ||
} | ||
|
||
if (typeof value.getState == 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 when Terminal
is in TS I think we can do if value instanceof ISerializable
which is even nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move forward with this and implement an interface ISerializable
. For serialization tests this can be done at the level of the component as well (tests for the Buffer go in Buffer.test.ts).
5d38551
to
ff5baee
Compare
@Tyriar I am thinking about whether I should include the buffers as "plain text to be rendered" or as an array of lines (each line can either be a string, or an array of characters). I have not decided yet, but my gut tells me that having an array of lines (each line should be a string) should do the work pretty well. Any opinions on this? |
@parisk My use cases for this would be to:
lines: [
// one line, saying "hello world",
// "hello" has green foreground and white background (ascii color)
[
{ text: 'hello', fg: 'green', bg: 'white', bold: false, underline: false },
{ text: ' world': fg: 'fg', bg: 'bg', bold: false, underline: false }
]
] In general, having some sort of parser that can be used to transform raw tty data into something that can be easily rendered by a browser would be very useful. |
|
ff5baee
to
7f8f8ff
Compare
I'm excited to see this PR progress along! |
c74a49c
to
42d287c
Compare
OK, I just pushed an update here, that makes My only thought here is that the buffers can get really really big, really quickly. This implies that:
Any ideas on how we could work around better with this issue? If nothing comes, I will move on with implementing tests utilizing static files for the buffer data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we hold off on merging this until a Terminal.setState
or a new constructor that takes a state is created? Otherwise we would be shipping code that isn't used potentially for a few versions?
Also some basic tests would be good 😃
|
||
let state = { | ||
buffers: { | ||
normal: normalBuffer, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should create a CircularList.getState
function which returns data from indexes 0 to CircularList.length
. That's all the data that's meaningful:
With the 24 lines from the CircularList it should be easy to create a new CircularList constructor or setState
method which sets the length to 24 and puts those 24 lines into the list.
}); | ||
|
||
// Iterate through all terminal properties to embed their state as well. | ||
for (let i in properties) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this retrieve any data yet? Maybe we should comment it out if it's not used yet?
42d287c
to
31a7e51
Compare
@parisk I imagine there's pretty straightforward compression you can do if many entries in the buffer share the same mode? |
@vincentwoo if size matters I was thinking consumers could always gzip it or something. Seems like the better way to go to avoid additional complexity in the codebase imo. |
Maybe this should just go in Buffer.getState/setState post #717 If the serialize functions are nicely separated it should be pretty simple. |
Should we do it before then or before a release? Changes to the buffer
format are breaking between releases at that point.
|
@vincentwoo I'd wait until at least this and #717 are merged. The buffer format may indeed change in the future as it's still using the original character format from term.js which is a little strange ( |
@vincentwoo let's hold off until we merge the new buffer classes into After that, I think it will be pretty much easier to iterate over performance improving, benchmarking etc. |
I would find this useful in my Atom package |
@ioquatix this will hopefully land in 3.0 🙂. |
I think I mentioned it before but I think we should only move forward with this if we allow breakages across versions. Otherwise this will severely impact our ability to improve the buffer and other components in the future. We could do this in a way that minimizes breakages for users though, the state could have a |
I am perfectly fine with that, I don't want to constrain xterm.js development speed at all. I think anyone who uses this feature is liable to be a savvier user and probably can deal with the consequences. |
In the case of script-runner, it's really not that important, it's more like, nice to have it working correctly - if the version is updated and some old panels fail to reload correctly, it's not a big deal. |
I can't tell you how much I'm looking forward to this PR :) |
* See xtermjs/xterm.js#613 for more details.
@Tyriar I think it's OK to introduce breaking changes when we have a new major version out (e.g. 4.0). Considering versioning the serialized state, I think it's a great idea, so I'll put it in a todo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opps forgot to submit the review
@@ -68,7 +68,7 @@ function createTerminal() { | |||
protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; | |||
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; | |||
|
|||
term.open(terminalContainer); | |||
term.open(terminalContainer, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the , true
as this arg was removed
* Returns the current position and style of the terminal cursor. | ||
* It returns an object in the following form: {position: [x, y], style: "cursorStyle"} | ||
*/ | ||
Terminal.prototype._getCursor = function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be deleted since we're on v3 now.
continue; | ||
} | ||
|
||
if (typeof value.getState == 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move forward with this and implement an interface ISerializable
. For serialization tests this can be done at the level of the component as well (tests for the Buffer go in Buffer.test.ts).
@parisk I think we should allow "breaking changes" to the getState data even between minor versions, not doing so could be overly restricting. Basically defer the breakage to a separate schema version contained in the |
@Tyriar do you have any components in might that might need to break their serialized form more than once in (let's say) a year? |
Closing this, as I will open a fresh one for |
Looking forward to this, can you add a link here to the new issue? |
Was this ever implemented? |
@ioquatix, nope. This was not implemented at all. PRs are welcome though. I would love to review. |
Okay. I don't really know enough about it nor do I have the time :( |
This is a PoC for a
getState
terminal method that will return the serialized current state of the terminal.Things to include in state
To do
getState
State size
It seems that the serialized state of the terminal can get kinda big, relatively easily. This happens because of the (verbose) way we are storing the buffers.
Maybe we should entertain the idea of keeping less information in memory and computing some things on the fly instead, considering buffers.
Example
less typings.json
in the terminalterm.getState()
in the browser's dev tools to retrieve the stateScreenshot
This PR should eventually close #595.