-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Line wrap #404
Line wrap #404
Conversation
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.
@imsnif thanks for taking a crack at this, there have been a tonne of issues filed in vscode to get this fixed.
src/utils/LineWrap.js
Outdated
@@ -0,0 +1,47 @@ | |||
export function padLine (line, x, defAttr) { |
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.
Missing a copyright statement (copy from some other file)
src/utils/LineWrap.js
Outdated
@@ -0,0 +1,47 @@ | |||
export function padLine (line, x, defAttr) { | |||
var ch = [defAttr, ' ', 1, 'pad']; // does xterm use the default attr? |
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.
All new files are being being built in TypeScript, this will basically involve renaming the file to use extension .ts
and fixing up the errors on npm start
(if any).
src/xterm.js
Outdated
this.lines[i].push(ch); | ||
var origLineCount = this.lines.length | ||
this.lines = this.lines | ||
.map(l => unpadLine(l)) |
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.
I'm a little concerned about how many arrays are being constructed here on every resize as this.lines
is capable of becoming very large (configuring scrollback
). Have you considered an approach similar to this?
- On resize, calculate how many rows each line will take up so that we can fetch a 'virtual line' for any row
y
, Encapsulate this inside a TypeScript class (a row index would know which index inthis.lines
and also which index of the line to start/end at). - Inside
refresh
, fetch each line using the lookup generated in on resize. - Potentially remove the padding from the lines all together if it's reasonably fast to determine the width of each character in the line.
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.
Sounds good - that's a pretty neat solution that would do away with most of this. Thanks!
Just to make sure I understand correctly - the Typescript class would be inserted into this.lines instead of the respective line (if resize deems it should be wrapped or unwrapped), and be dealt with in the refresh method so it displays accordingly?
That would also mean moving the resize method's update of this.y, this.ybase and this.ydisp into the refresh method as well, I think?
In any case, I'll try to whip something up sometime this week.
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.
So initially I'm thinking just keeping a small class or array alongside this.lines
that mapped to the various indexes. Something like this:
export class IRowPosition {
lineIndex: number; // the index of this.lines
startIndex: number; // The start index in this.lines[lineIndex]
endIndex: number; // The end index in this.lines[lineIndex]
}
// I'm sure there's a better name for this
export class WrappedLineLookup {
// this.lines[y]
// ->
// var row = this.lineLookup.getRow(y);
// var line = this.lines[row.lineIndex]
// for (var x = row.startIndex; x < row.endIndex; x++) { ... }
public getRow(index: number): any { ... }
// this.line.length -> this.lineLookup.rowCount
public get rowCount(): number { ... }
}
We should try getting the naming on this right though as it could quickly get confusing (line, row, wrappedLine, IRowPosition
's members, etc.)
Eventually we should completely wrap this.lines
in a TerminalBuffer
class (utilizing CircularList from my WIP branch) and moving ybase
, ydisp
, y
into Viewport
. That's quite a lot of refactoring though, we should slowly move to a better design so we don't break everything in the meantime 😉
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.
Wouldn't keeping an additional object to this.lines be problematic for the same reason my solution from the previous PR (with this.lineCache) was problematic? That if this.lines is changed outside the resize method everything would get messed up?
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.
Good point 😦
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.
@imsnif let's wait for @Tyriar to push his branch including the CircularList, which implements the functionality I showcased in my own branch. Then you will be able to re-use the code included there as a foundation for the line wrapping.
Discussion thread: #410 (comment)
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.
Thanks again for your effort and for your co-operation so far!
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.
Sure thing. Let me know when I can start working on it.
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.
I see #422 was merged. Is that it then, shall I start working on line wrapping over the weekend?
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.
That would be great 😃 I suggest starting out by extending CIrcularList
in a Lines
class similar to what https://github.com/sourcelair/xterm.js/pull/410/files was trying to accomplish before CircularList
existed. That way we can keep CircularList
nice and generic and keep that complexity in that class.
src/utils/LineWrap.js
Outdated
return line | ||
} | ||
|
||
export function unpadLine (line) { |
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 method needs documentation, especially since it is in single-line syntax, which can be hard to read and understand.
src/utils/LineWrap.js
Outdated
} | ||
|
||
export function wrapLines (unwrappedLine, x, defAttr) { | ||
return unwrappedLine.reduce((memo, e, index) => { |
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.
Please use traditional function syntax, when the function has "actual body", which is closer to the current coding style.
src/utils/LineWrap.js
Outdated
} | ||
return memo | ||
}, []) | ||
.map((wrappedLine, index) => { |
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.
Please use traditional function syntax, when the function has "actual body", which is closer to the current coding style.
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.
My apologies for the rough implementation. I plan on cleaning everything up once we decide on a proper solution to the problem discussed above.
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.
No problem. Thought about it, but I also thought to mention this nevertheless!
Please take a look at my comment below which might be helpful: #404 (comment)
The work you have done is really great. Thank you so much for this.
First of all thanks a lot for your contribution @imsnif! I 'd really like to see this moving forward and help as much as possible with this, since it's a great addition and we have a working PoC. Let me share a few thoughts and concerns with the current implementation, which are definitely "tackle-able". 1 - Code formattingBefore merging this we should ensure that the code formatting and styling is as close as possible to the code base's formatting and styling. This requires the following:
2 - Code structureConsidering code structure, I am quite skeptical for introducing a fourth flag. Amending the same object in many different places can be a mess and the core parts of xterm.js that did not change after we forked term.js are still a little bit messy. Let's not add any more complexity to this. It will only make things worse. What I propose instead is handle this in a "self-contained environment" (e.g. a resize handler at A proposed quick-draft format of such an object I thought might work is: // Object in the following format:
//
// {
// lineNumber: lineWrapData,
// anotherLineNumber: anotherLineWrapData,
// andSoOnLineNumber: andSoOnLineWrapData
// }
var wrapState = {
1: {
'state': 'wrap',
'wrapStart': 75
}
}; Does this make sense at all? (Ideally these structs should be TypeScript classes or interfaces. /cc @Tyriar to take a look as well |
@parisk I think a large resize handler is a bit too heavy, I think it looks great right now that I don't have to debounce the Also as mentioned in this thread, there's an issue keeping this data away from the |
Add prepublish script and change main
Always build TypeScript in `lib/`
Fix linux firefox paste
@Tyriar the resize logic is complex and actually is an important part of the rendering process. Moving it into it's own module eventually with < 300 lines of code in total will make things more manageable. (this does not have to happen right now) |
Adding a getting started instruction for adding xterm to a parent div and listening for data output from xterm
Signed-off-by: Paris Kasidiaris <paris@sourcelair.com>
…n-npm Include appropriate files in npm.
Signed-off-by: Paris Kasidiaris <paris@sourcelair.com>
Clean up npm publish
Added Getting started content from the xtermjs.org website
Tsify lib used for browserify typescript sources. But folder /lib consist of js files has already compiled from TypeScript sources (by gulp task tsc). So Tsify library does nothing in this case. Signed-off-by: Aleksandr Andrienko <aandrienko@codenvy.com>
Signed-off-by: Paris Kasidiaris <paris@sourcelair.com>
Fix missing Number.isNaN in IE
Signed-off-by: Paris Kasidiaris <paris@sourcelair.com>
hey @imsnif any ETA? |
@amir-arad hoping to be done by the end of this month. |
Remove excess library.
That's great @imsnif, thank you. Everyone let's hold on asking ETAs though. We should put no pressure on contributors. |
@imsnif you might want to rebase against origin/master and recreate the PR to fix the non-you commits, the diff and get rid of the older conversations. |
Oh dear, pushed to the wrong branch. :) |
@imsnif Gentlest of pings 🙏 |
Hey @LucianBuzzo, This looks great! A quick glance through the code shows me that this is implemented slightly differently than what we talked about above here, correct me if I'm wrong? Not with an external index but rather with caching the overflow? If you'd like to help out with my current wip branch (https://github.com/imsnif/xterm.js/tree/line-wrap-wip) - I'd also love the help. It really is almost finished... This mostly suffered from an unexpected lack of free time on my part. |
@imsnif If you're close to completion on your branch then I'll dive in and help on that. I suggest opening up issues on your fork for outstanding tasks and I'll submit PR's directly to your WIP branch. |
@LucianBuzzo - sounds great. I'll start opening issues and tag you. If anyone else wants in, just let me know. |
So, I've opened some issues in my fork. Anyone who feels like helping out: please, by all means. If anything is unclear, please let me know and I'll do my best to get back to you ASAP. |
After a review of the external index approach and some discussion between @imsnif and myself here imsnif#1 (comment), we feel that the solution in this branch https://github.com/LucianBuzzo/xterm.js/tree/lb-line-wrap may be the best course of action. |
Thanks for putting the joint effort on this @LucianBuzzo and @imsnif. If the end experience is the same for the end user and the code quality is satisfying, then there is no objection to move on by me. So let's move on 😄 . Is there any additional input needed on our behalf at this moment? |
Closing this in favor of #609. |
Continuing the conversation in this PR: #386
And addressing this issue: #325
This is a rough implementation, and is not yet 100% ready - but it is mostly working.
The reason I'm making this PR now is that I've made quite a few assumptions regarding the way you'd like to solve this issue.
Namely, I've added a fourth "cell" to the array representing each character. The cell can either be undefined, 'wrapped', or 'pad':
'wrapped' would mean that this character has been wrapped when the terminal window was shrunk - we have to mark this because we need to know to 'unwrap' it when the terminal window is expanded again.
'pad' would mean that this character is just a padding character (when we wrapped a line and had to fill the space up until the column width of the terminal) - we have to mark this so that we know these characters can be discarded when we unwrap the line (we can't just do this with normal whitespace, because otherwise we'd end up potentially removing actual 'wanted' whitespace).
If this solution is generally acceptable, I would be happy to expand the test coverage, tidy up the code and fix some small issues (namely the cursor x position when expanding, and integrating it with the current wrapping mechanism in the write method).
Would very much love to hear your thoughts.