Skip to content
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

WIP: Fix decoration leaking into newline at end of screen buffer #19019

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

SteveL-MSFT
Copy link
Member

@SteveL-MSFT SteveL-MSFT commented Jan 24, 2023

PR Summary

When writing content and the screen buffer scrolls, the decorations also get written to the next line. This is most evident when using a background color and the entire newline contains the background color. Fix is to insert a VT Reset sequence if the terminal supports VT.

This was validated on macOS and Windows. This shows the before and after:

write-color-fix.mp4

PR Context

This fixes part of the issue reported below, but PSCal needs to account for when the screen buffer scrolls and the cursor position has changed. Ideally, it should not be using cursor position to render, but instead pre-calculate all the rows.

Fix #18984

PR Checklist

@daxian-dbw
Copy link
Member

This seems to be a by-design behavior in the .NET and terminal perspective. The problem is that we are writing out the newline along with the text, so the restoring of the original background color doesn't happen until after the newline gets written out. When it's at the last line in terminal, that newline triggers a buffer scroll when the background color is still Blue, and that's why the newly added line also has the Blue background color, hence the leak.

It works fine in Windows PowerShell because it writes out newline in a different Write call, where foreground and background are not changed.

So, I think maybe the right fix is to check if we are at the end of terminal before writing in Host, and if so, write out the newline in a separate call without changing the foreground and background.

@SteveL-MSFT
Copy link
Member Author

@daxian-dbw Windows PowerShell doesn't use VT, so the behavior is different for the Console API. If the VT background sequence exists and you write a newline by itself, the entire line after the newline will have the background color. You can see this in zsh/bash:

echo -e "\e[44m1\n2"

So writing a newline in a separate call w/o reseting will result in a whole line with that decoration.

@daxian-dbw
Copy link
Member

This behavior is not related to VT decorations, and I can reproduce it with the following C# code as a console application:

// See https://aka.ms/new-console-template for more information

ConsoleColor bg = Console.BackgroundColor;
Console.BackgroundColor = ConsoleColor.Blue;

try {
    Console.WriteLine("Hello, World!");
}
finally {
    Console.BackgroundColor = bg;
}

image

If I choose to write the newline in a separate call, after restoring the background color, then it will work as expected.
This is what Windows PowerShell does.

// See https://aka.ms/new-console-template for more information

ConsoleColor bg = Console.BackgroundColor;
Console.BackgroundColor = ConsoleColor.Blue;

try {
    Console.Write("Hello, World!");   // <= write out the text, no newline
}
finally {
    Console.BackgroundColor = bg;
}

Console.WriteLine();   // write out the newline after the restoring of background/foreground color

image

But this doesn't mean this problem doesn't exist in Windows PowerShell, you can reproduce it in Windows PowerShell by running write-Host "hello`n" -BackgroundColor Red at the last line of the terminal window:

image

@SteveL-MSFT
Copy link
Member Author

SteveL-MSFT commented Jan 25, 2023

I see. I misunderstood what you meant previously. I'll make the change. Note that if you use Write-Output with content including VT, I need the other change to reset anyways.

@daxian-dbw
Copy link
Member

daxian-dbw commented Jan 25, 2023

@SteveL-MSFT, I'm just thinking aloud here, still not sure what is the right fix yet.
If we care about non-VT terminals, then we should consider do what Windows PowerShell does -- use a separate write for the newline, without changing foreground/background when writing.

As for VT decoration, when writing out "`e[44m1`n2" in PowerShell, it leaks background color even if it's not at the last line of the terminal:

image

So, the question is -- is that the expected behavior? The user may intentionally omit the Reset sequence, but should be rare.
If that is not the desired behavior, then we should prepend the Reset sequence to the prompt we write out, to avoid the leak (not super sure if that would be the right fix though, let me know what you think).

@SteveL-MSFT
Copy link
Member Author

@daxian-dbw the current fix has the same behavior as in zsh. The first here is the fix, the second zsh, the last current pwsh.

image

Comment on lines +841 to +846

if (newLine)
{
// write the newline after resetting the colors so there isn't a buffer wide colored line when buffer scrolls
this.WriteImpl(string.Empty, newLine: true);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why we reset only for newline.
I believe we should think about every output as atomic operation - set all attributes at start and reset all attributes at end because in the general case we do not know who and what will be output to the console in the next moment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if you Write-Host -nonewline, the formatandoutput will eventually emit a newline before the prompt.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean some sequential write operations in script (before prompt) .

@SteveL-MSFT SteveL-MSFT changed the title Fix decoration leaking into newline at end of screen buffer WIP: Fix decoration leaking into newline at end of screen buffer Jan 25, 2023
@pull-request-quantifier-deprecated

This PR has 18 quantified lines of changes. In general, a change size of upto 200 lines is ideal for the best PR experience!


Quantification details

Label      : Extra Small
Size       : +12 -6
Percentile : 7.2%

Total files changed: 2

Change summary by file extension:
.cs : +8 -2
.ps1 : +4 -4

Change counts above are quantified counts, based on the PullRequestQuantifier customizations.

Why proper sizing of changes matters

Optimal pull request sizes drive a better predictable PR flow as they strike a
balance between between PR complexity and PR review overhead. PRs within the
optimal size (typical small, or medium sized PRs) mean:

  • Fast and predictable releases to production:
    • Optimal size changes are more likely to be reviewed faster with fewer
      iterations.
    • Similarity in low PR complexity drives similar review times.
  • Review quality is likely higher as complexity is lower:
    • Bugs are more likely to be detected.
    • Code inconsistencies are more likely to be detected.
  • Knowledge sharing is improved within the participants:
    • Small portions can be assimilated better.
  • Better engineering practices are exercised:
    • Solving big problems by dividing them in well contained, smaller problems.
    • Exercising separation of concerns within the code changes.

What can I do to optimize my changes

  • Use the PullRequestQuantifier to quantify your PR accurately
    • Create a context profile for your repo using the context generator
    • Exclude files that are not necessary to be reviewed or do not increase the review complexity. Example: Autogenerated code, docs, project IDE setting files, binaries, etc. Check out the Excluded section from your prquantifier.yaml context profile.
    • Understand your typical change complexity, drive towards the desired complexity by adjusting the label mapping in your prquantifier.yaml context profile.
    • Only use the labels that matter to you, see context specification to customize your prquantifier.yaml context profile.
  • Change your engineering behaviors
    • For PRs that fall outside of the desired spectrum, review the details and check if:
      • Your PR could be split in smaller, self-contained PRs instead
      • Your PR only solves one particular issue. (For example, don't refactor and code new features in the same PR).

How to interpret the change counts in git diff output

  • One line was added: +1 -0
  • One line was deleted: +0 -1
  • One line was modified: +1 -1 (git diff doesn't know about modified, it will
    interpret that line like one addition plus one deletion)
  • Change percentiles: Change characteristics (addition, deletion, modification)
    of this PR in relation to all other PRs within the repository.


Was this comment helpful? 👍  :ok_hand:  :thumbsdown: (Email)
Customize PullRequestQuantifier for this repository.

@SteveL-MSFT
Copy link
Member Author

I'll hold off on fixing the test issues until we agree on how this should be fixed

@ghost ghost added the Review - Needed The PR is being reviewed label Feb 1, 2023
@ghost
Copy link

ghost commented Feb 1, 2023

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

@daxian-dbw daxian-dbw added WG-Interactive-Console the console experience Needs-Triage The issue is new and needs to be triaged by a work group. labels May 1, 2023
@tillig
Copy link

tillig commented Aug 6, 2023

Has there been any continued discussion on how this should be fixed? This is painful for enhanced prompt tools like oh-my-posh, too, when working in Powershell.

@dkaszews
Copy link
Contributor

I really dislike manipulating ConsoleColor directly, as it has given me trouble when trying to fix #18003 . Can we not switch to OSC sequences from $PSStyle instead?

@SteveL-MSFT SteveL-MSFT added the WG-NeedsReview Needs a review by the labeled Working Group label Sep 25, 2023
@SteveL-MSFT
Copy link
Member Author

This is waiting on WG-Interactive to discuss and make a decision

@microsoft-github-policy-service microsoft-github-policy-service bot removed the Review - Needed The PR is being reviewed label Sep 25, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the Review - Needed The PR is being reviewed label Oct 2, 2023
@microsoft-github-policy-service
Copy link
Contributor

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Extra Small Needs-Triage The issue is new and needs to be triaged by a work group. Review - Needed The PR is being reviewed WG-Interactive-Console the console experience WG-NeedsReview Needs a review by the labeled Working Group
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PowerShell draws background wrong to the end
6 participants