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
Fix progress rendering when using double-wide unicode #21303
Conversation
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
|
||
int emptyPadLength = barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength; | ||
int emptyPadLength = barWidth - rawUI.LengthInBufferCells(sb.ToString()) - secRemainLength; |
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.
It looks that sb
contains VT sequences, does LengthInBufferCells
strip off VT sequences when counting cells?
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.
LengthInBufferCells
seems to only handle double-wide chars and nothing with VT. It seems that we shouldn't allow VT in the status description since it would screw up rendering anyways, so I'll add a change that will error if VT is in the status description.
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.
It's good to prevent a user from using VT decorated Status
and Activity
.
However, here we already appended PSStyle.Instance.Reverse
to the sb
, so the returned result from rawUI.LengthInBufferCells(sb.ToString())
will be incorrect. You will need the original + PSStyle.Instance.Reverse.Length
.
Or, maybe consider to not add the Reverse
prefix until we are wrapping up constructing sb
at the line 440 and 445, where ReverseOff
VT sequence is added. That will make the code clearer and more readable.
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.
PSStyle.Instance.Reverse
should have a buffer cell length of zero since it shouldn't have any printable characters. So the length of it shouldn't be used at all. Removed it in the calculation of the length of the bar.
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.
Exactly, it should have a buffer cell length of zero, but the returned value from rawUI.LengthInBufferCells(sb.ToString())
will include the length of PSStyle.Instance.Reverse
, isn't it
I think that's why + PSStyle.Instance.Reverse.Length
was there to offset it.
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
|
||
int emptyPadLength = barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength; | ||
int emptyPadLength = barWidth - rawUI.LengthInBufferCells(sb.ToString()) - secRemainLength; |
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.
It's good to prevent a user from using VT decorated Status
and Activity
.
However, here we already appended PSStyle.Instance.Reverse
to the sb
, so the returned result from rawUI.LengthInBufferCells(sb.ToString())
will be incorrect. You will need the original + PSStyle.Instance.Reverse.Length
.
Or, maybe consider to not add the Reverse
prefix until we are wrapping up constructing sb
at the line 440 and 445, where ReverseOff
VT sequence is added. That will make the code clearer and more readable.
@@ -432,7 +435,7 @@ internal static bool IsMinimalProgressRenderingEnabled() | |||
barLength = barWidth - 1; | |||
} | |||
|
|||
if (barLength < sb.Length) | |||
if (barLength < rawUI.LengthInBufferCells(sb.ToString())) |
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.
Same here, rawUI.LengthInBufferCells(sb.ToString())
will return the incorrect value as it counts the Reverse
VT sequences in. It would be the best if you can insert the Reverse
prefix when adding the ReverseOff
sequences.
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 one doesn't seem to be resolved.
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
Co-authored-by: Dongbo Wang <dongbow@microsoft.com>
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
if (PercentComplete >= 0 && PercentComplete < 100 && barWidth > 0) | ||
if (PercentComplete >= 0 && barWidth > 0) |
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 don't think PercentComplete < 100
should be removed. This check excluded the case where PercentComplete == 100
, and maybe that was on purpose.
if (barLength >= barWidth) | ||
{ | ||
barLength = barWidth - 1; | ||
} |
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 comment https://github.com/PowerShell/PowerShell/pull/21303/files#r1526931375 actually meant this if-block.
I found this if-block check seems to never be true. PercentComplete >= 0 && PercentComplete < 100, so PercentComplete * barWidth / 100 will always be less than barWidth. Maybe consider remove this if-block?
|
||
int emptyPadLength = barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength; | ||
int emptyPadLength = barWidth - rawUI.LengthInBufferCells(sb.ToString()) - secRemainLength; |
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.
Exactly, it should have a buffer cell length of zero, but the returned value from rawUI.LengthInBufferCells(sb.ToString())
will include the length of PSStyle.Instance.Reverse
, isn't it
I think that's why + PSStyle.Instance.Reverse.Length
was there to offset it.
@@ -432,7 +435,7 @@ internal static bool IsMinimalProgressRenderingEnabled() | |||
barLength = barWidth - 1; | |||
} | |||
|
|||
if (barLength < sb.Length) | |||
if (barLength < rawUI.LengthInBufferCells(sb.ToString())) |
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 one doesn't seem to be resolved.
PR Summary
The previous minimal progress rendering code was using the string length which counts characters and not the buffer cells required. This means that double-wide east asian characters counted as 1 when it should be counted as 2 so that it renders correctly in the console. The fix is to change all usage of getting the length to using a helper function that returns the number of buffer cells for a string.
Here's what it looked like before and after the change:
Recording.2024-03-04.152825.mp4
PR Context
Fix #21293
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.(which runs in a different PS Host).