Fix rendering when terminal is erased on first render #586
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #585.
@matteodepalo did a great job documenting the issue, so I'm not going to repeat it here.
Context
Ink has two ways of rendering output, depending how tall it is:
If output is shorter than terminal height, Ink erases the lines from last output and writes lines from the new output. Ink tracks how many lines did the last output have for this to work. This is handled in https://github.com/vadimdemedes/ink/blob/master/src/log-update.ts, which is a fork of
log-update
package.If output is equal or taller than terminal height, Ink erases the entire terminal history (or scrollback as it's commonly referred to) and writes new output. Note that Ink doesn't need to track how many lines to erase here, because it just erases the entire contents of the current terminal.
ink/src/ink.tsx
Lines 176 to 182 in 8a04760
Root cause
The key insight here is this:
In #585, the very first render starts with the second rendering method and erases the terminal completely. On next render, the first method kicks in, but there's no information how many lines to erase, since second method doesn't store that information.
That's why the output from the first render doesn't get erased, since for
logUpdate
this variable is zero.ink/src/log-update.ts
Line 12 in 8a04760
Solution
This PR fixes this bug by separating the write operation that erases the terminal and writes the output. This way, even if the entire terminal is erased,
logUpdate
is still used to render the output and keep track of how many lines were written.I've also added
force
option tologUpdate
render function to force it to always render the string we give to it without bailing out if it equals to the last output. This can happen whenStatic
output changes, but normal output isn't.ink/src/log-update.ts
Lines 23 to 25 in 8a04760
I've also added
erase
option tologUpdate
render function, so that we can tell it to not do erasing of its own, if we erased the entire terminal already.