Rewriting last console output line dynamically breaks when resizing window #14264

Open
opened 2026-01-31 04:05:25 +00:00 by claunia · 10 comments
Owner

Originally created by @paulkapa on GitHub (Jun 19, 2021).

Windows Terminal version (or Windows build number)

Windows Terminal Preview Version: 1.9.1523.0

Other Software

  • DISM.exe

  • Example code that outputs to the console:

public class ClearConsoleOutput {
    public static void main(String[] args) throws Exception {
        // text to output to the console
        String text = "Hello World ";
        for(int i=0; i<10000; i++) {
            // prints String = "[text][i]" and places the cursor on the line below  String
            System.out.println(text + i);
            // Pause execution of the code below so that the text is visible for 10ms
            Thread.sleep(10);
            // [count] = [lines_printed_to_console] + [new_lines_created_after_output] - 1
            int count = 1; 
            // Erase only the lines printed to the console
            System.out.print(String.format("\033[%dA",count)); // Move up [count] lines
            System.out.print("\033[2K"); // Erase line content
            // OR Erase all content printed to the console
            //System.out.print(String.format("\033[2J")); // Erase all content
        }
    }
}

Steps to reproduce

Disclaimer: if you run DISM.exe do not close the console until the process finishes.

ELSE compile and run ClearConsoleOutput java class above using:

  • javac --release 8 ClearConsoleOutput.java
  • java ClearConsoleOutput

in Windows Terminal application running an instance of PowerShell or cmd

Run DISM command or ClearConsoleOutput class above in Windows Terminal application (PowerShell or cmd) , and when text is being written to the console, resize Windows Terminal window by dragging from one of the edges. Pressing Ctrl + Scroll_Wheel_Up/Down or Ctrl + '+'/'-' produces a similar result.

The terminal needs to be resized such that while text is printed, the window height is smaller than the content height. The pictures below show the result after the window has been resized to a normal viewing mode.

Expected Behavior

For DISM.exe

The "[==== {x}% ====]" progress bar should appear only once, as last line in the terminal, being updated as needed by the process it is attached to.

For ClearConsoleOutput class

The string "Hello World {x}" should be visible as a single line of text when being updated once every 10 milliseconds.

Actual Behavior

In both cases

The line containing the updating text should appear only once and display exactly the information it needs to provide, even if it I decide in the exact moment the command/program is running to resize the window dimensions or increase/decrease the font size. Below are the results of running DISM.exe and ClearConsoleOutput class after the window was returned to its regular size.

image

image

Conclusion:

Depending on the way the window is being resized, the output can appear: concatenated, incomplete, on separate lines, multiple times on the same line, even in the wrong order.
As seen in the updated version below, which includes a timestamp for each statement printed, the expected output is one continuously updating line counting from 0 to 9999, but the actual output is unreadable.

Desired behavior:

image

Originally created by @paulkapa on GitHub (Jun 19, 2021). ### Windows Terminal version (or Windows build number) Windows Terminal Preview Version: 1.9.1523.0 ### Other Software - DISM.exe - Example code that outputs to the console: ``` public class ClearConsoleOutput { public static void main(String[] args) throws Exception { // text to output to the console String text = "Hello World "; for(int i=0; i<10000; i++) { // prints String = "[text][i]" and places the cursor on the line below String System.out.println(text + i); // Pause execution of the code below so that the text is visible for 10ms Thread.sleep(10); // [count] = [lines_printed_to_console] + [new_lines_created_after_output] - 1 int count = 1; // Erase only the lines printed to the console System.out.print(String.format("\033[%dA",count)); // Move up [count] lines System.out.print("\033[2K"); // Erase line content // OR Erase all content printed to the console //System.out.print(String.format("\033[2J")); // Erase all content } } } ``` ### Steps to reproduce > Disclaimer: if you run DISM.exe do not close the console until the process finishes. > > ELSE compile and run ClearConsoleOutput java class above using: > > * `javac --release 8 ClearConsoleOutput.java` > * `java ClearConsoleOutput` > > in Windows Terminal application running an instance of PowerShell or cmd Run DISM command or ClearConsoleOutput class above in Windows Terminal application (PowerShell or cmd) , and when text is being written to the console, resize Windows Terminal window by dragging from one of the edges. Pressing `Ctrl + Scroll_Wheel_Up/Down` or `Ctrl + '+'/'-'` produces a similar result. *The terminal needs to be resized such that while text is printed, the window height is smaller than the content height.* The pictures below show the result after the window has been resized to a normal viewing mode. ### Expected Behavior #### For DISM.exe The "`[==== {x}% ====]`" progress bar should appear only once, as last line in the terminal, being updated as needed by the process it is attached to. #### For ClearConsoleOutput class The string "`Hello World {x}`" should be visible as a single line of text when being updated once every 10 milliseconds. ### Actual Behavior #### In both cases The line containing the updating text should appear only once and display exactly the information it needs to provide, even if it I decide in the exact moment the command/program is running to resize the window dimensions or increase/decrease the font size. Below are the results of running DISM.exe and ClearConsoleOutput class after the window was returned to its regular size. ![image](https://user-images.githubusercontent.com/33447471/122635009-10571800-d0ea-11eb-9e87-6a9a9e4d2a2e.png) ![image](https://user-images.githubusercontent.com/33447471/122635651-e1db3c00-d0ed-11eb-8a9b-73d0914a8268.png) #### Conclusion: Depending on the way the window is being resized, the output can appear: concatenated, incomplete, on separate lines, multiple times on the same line, even in the wrong order. As seen in the updated version below, which includes a timestamp for each statement printed, the expected output is one continuously updating line counting from 0 to 9999, but the actual output is unreadable. #### Desired behavior: ![image](https://user-images.githubusercontent.com/33447471/122683550-96698080-d208-11eb-9336-22790e259e0e.png)
claunia added the Area-OutputIssue-BugProduct-Terminal labels 2026-01-31 04:05:25 +00:00
Author
Owner

@paulkapa commented on GitHub (Jun 22, 2021):

I have found the other day an article saying that this is a known problem for consoles developed by Microsoft and that in some cases it is labeled "won't fix". I find it funny that for those posts, the solution was presented in the form: "Right click title bar to go to properties -> layout and disable Line wrapping". In the case of the Windows Terminal you cannot do that, and the only feature I can imagine might prevent some cases of this kind presented above is: #10466

@paulkapa commented on GitHub (Jun 22, 2021): I have found the other day an article saying that this is a known problem for consoles developed by Microsoft and that in some cases it is labeled "won't fix". I find it funny that for those posts, the solution was presented in the form: "Right click title bar to go to properties -> layout and disable Line wrapping". In the case of the Windows Terminal you cannot do that, and the only feature I can imagine might prevent some cases of this kind presented above is: #10466
Author
Owner

@DHowett commented on GitHub (Jul 8, 2021):

Weird question. If you run your Java application for long enough, does it start to emit broken escape sequences to the Terminal? You may start seeing garbage like ;31 and 2J showing up as though they were missing the Esc.

@DHowett commented on GitHub (Jul 8, 2021): Weird question. If you run your Java application for long enough, does it start to emit broken escape sequences to the Terminal? You may start seeing garbage like `;31` and `2J` showing up as though they were missing the <kbd>Esc</kbd>.
Author
Owner

@paulkapa commented on GitHub (Jul 8, 2021):

Weird question. If you run your Java application for long enough, does it start to emit broken escape sequences to the Terminal? You may start seeing garbage like ;31 and 2J showing up as though they were missing the Esc.

Unfortunately, I have not encountered this type of problem with that code in particular. My Windows Terminal character encoding settings are in their default state, as when the application was installed. Also, as stated in the issue description, the observations were made using PowerShell and cmd. Maybe differences between what character encoding the JVM uses and the character encoding of the console running in your Windows Terminal Application are making the strings (that could be changed to bytes for less processing of the output on the part of the console) be printed in incomplete form when something like this happens:

Screenshot 2021-07-09 002323

... or like this:

Untitled

Note:

For the examples in this comment I used the following modification to the code in the issue description.

From:
for(int i = 0; i < 10000; i++)

To:
for(int i = 0; i < Integer.MAX_VALUE; i++)

In order to investigate further I need to know in what context did you run the java code in order to get the output you mentioned.

My setup:

  • PowerShell or cmd running in Windows Terminal
  • javac --release 8 ClearConsoleOutput.java
  • java ClearConsoleOutput
@paulkapa commented on GitHub (Jul 8, 2021): > Weird question. If you run your Java application for long enough, does it start to emit broken escape sequences to the Terminal? You may start seeing garbage like `;31` and `2J` showing up as though they were missing the Esc. Unfortunately, I have not encountered this type of problem with that code in particular. My Windows Terminal character encoding settings are in their default state, as when the application was installed. Also, as stated in the issue description, the observations were made using PowerShell and cmd. Maybe differences between what character encoding the JVM uses and the character encoding of the console running in your Windows Terminal Application are making the strings (that could be changed to bytes for less processing of the output on the part of the console) be printed in incomplete form when something like this happens: ![Screenshot 2021-07-09 002323](https://user-images.githubusercontent.com/33447471/124993482-16874700-e04d-11eb-8065-39c457cb49c2.png) ... or like this: ![Untitled](https://user-images.githubusercontent.com/33447471/124994036-e2605600-e04d-11eb-98c5-815123818a7b.png) ### Note: For the examples in this comment I used the following modification to the code in the issue description. From: `for(int i = 0; i < 10000; i++)` To: `for(int i = 0; i < Integer.MAX_VALUE; i++)` In order to investigate further I need to know in what context did you run the java code in order to get the output you mentioned. My setup: * PowerShell or cmd running in Windows Terminal * `javac --release 8 ClearConsoleOutput.java` * `java ClearConsoleOutput`
Author
Owner

@paulkapa commented on GitHub (Jul 9, 2021):

Follow-up to the above comment

No instances of anyhthing like ;31 and 2J were found after the code ran overnight. I don't know how to make a script that makes the console window smaller and larger in a loop continuously, so that the output gets jumbled around, so the only thing the program did was to count towards Integer.MAX_VALUE. It currently reached 2,984,792+ iterations.

Screenshot 2021-07-09 131236

^ In reply to: @DHowett ^

Funny video:

https://user-images.githubusercontent.com/33447471/125070413-969ac480-e0c0-11eb-8afd-e980eeed0119.mp4

@paulkapa commented on GitHub (Jul 9, 2021): ## Follow-up to the above comment No instances of anyhthing like `;31` and `2J` were found after the code ran overnight. I don't know how to make a script that makes the console window smaller and larger in a loop continuously, so that the output gets jumbled around, so the only thing the program did was to count towards `Integer.MAX_VALUE`. It currently reached 2,984,792+ iterations. ![Screenshot 2021-07-09 131236](https://user-images.githubusercontent.com/33447471/125063619-5fc0b080-e0b8-11eb-9850-24a7964465ff.png) ^ In reply to: @DHowett ^ ## Funny video: https://user-images.githubusercontent.com/33447471/125070413-969ac480-e0c0-11eb-8afd-e980eeed0119.mp4
Author
Owner

@paulkapa commented on GitHub (Jul 9, 2021):

I observed the progress over 4,723,054 lines printed to the console (some re-written as the program wants them to be, others just dancing around the window when resizing the console size) and have seen multiple funny ways of making the text being printed all over the place. But no un-escaped control characters of any kind, nor other characters than the ones found in the literal string "Hello World " or in the number range [0, 2147483647].

I have just stated my issue I had one time with the Terminal, and again, to be honest, now I seem to have this exact same issue everywhere XD.

Note: I have managed to acquire more information about how text is processed in the output of the console, some contents of this message were removed.

@paulkapa commented on GitHub (Jul 9, 2021): I observed the progress over 4,723,054 lines printed to the console (some re-written as the program wants them to be, others just dancing around the window when resizing the console size) and have seen multiple funny ways of making the text being printed all over the place. But no un-escaped control characters of any kind, nor other characters than the ones found in the literal string "Hello World " or in the number range [0, 2147483647]. I have just stated my issue I had one time with the Terminal, and again, to be honest, now I seem to have this exact same issue everywhere XD. ##### Hope this sets me in the clear from further code related questions, since I have minimum basic knowledge about how a console works internally, and since the issue was reported as observable by running a version of DISM.exe command that displays a progress bar that updates over time: [removed-content] > Note: I have managed to acquire more information about how text is processed in the output of the console, some contents of this message were removed.
Author
Owner

@DHowett commented on GitHub (Jul 9, 2021):

Hope this sets me in the clear from further code related questions ... anybody else that wants to question ...

I never meant to offend you. We found a bug in the JVM -- one that still exists today! -- that occasionally results in incoming VT being "double-processed" in a way that looks a lot like this, but with the addition of broken VT sequences. It would cause us to do line wrapping on the characters assuming that the entire control sequence was printable text, but then they would be stripped out after the line wrapper mangled them.

@DHowett commented on GitHub (Jul 9, 2021): > Hope this sets me in the clear from further code related questions ... anybody else that wants to question ... I never meant to offend you. We found a bug in the JVM -- one that still exists today! -- that occasionally results in incoming VT being "double-processed" in a way that looks a lot like this, but with the addition of broken VT sequences. It would cause us to do line wrapping on the characters assuming that the entire control sequence was printable text, but then they would be stripped out after the line wrapper mangled them.
Author
Owner

@paulkapa commented on GitHub (Jul 9, 2021):

I never meant to offend you. We found a bug in the JVM -- one that still exists today! -- that occasionally results in incoming

Thanks for the kind words! I just questioned the direction of the question you posed, about what you have just explained now.

No offense taken, glad that a problem was actually in whatever parts of the environment, either console or JVM. The question sounded like targeted to a 5yo, so maybe I got a bit frustrated but I still ran the 250days long program to test what you asked me to XD.

As for your update, I cannot add any more to it. But it sounds like a fun discovery, so good luck and congrats!

@paulkapa commented on GitHub (Jul 9, 2021): > I never meant to offend you. We found a bug in the JVM -- one that still exists today! -- that occasionally results in incoming Thanks for the kind words! I just questioned the direction of the question you posed, about what you have just explained now. No offense taken, glad that a problem was actually in whatever parts of the environment, either console or JVM. The question sounded like targeted to a 5yo, so maybe I got a bit frustrated but I still ran the 250days long program to test what you asked me to XD. As for your update, I cannot add any more to it. But it sounds like a fun discovery, so good luck and congrats!
Author
Owner

@paulkapa commented on GitHub (Aug 26, 2021):

Hi!

A follow-up on this thread... I have noticed that in the case of text formatting using escape sequences, if there are no printable characters after a modifier such as (as used in Java) \u001B[34m Some_Text \u001B[0m, then the formatting will apply until the end of the current line, if not initially, then definitely after the window is resized and text wrapping is re-processed. That means that the last escape sequence is being wrapped at the end of the line

I am using a workaround, where I print a Zero Width No Break Space character, but as I preffered, a null character or something that does not add length to the line does not work.

So, if I want to format the last token in a line, how should I proceed in doing it so that the formatting does not extend to the end of the line?

I will come back with some examples later today.

@paulkapa commented on GitHub (Aug 26, 2021): Hi! A follow-up on this thread... I have noticed that in the case of text formatting using escape sequences, if there are no printable characters after a modifier such as (as used in Java) `\u001B[34m Some_Text \u001B[0m`, then the formatting will apply until the end of the current line, if not initially, then definitely after the window is resized and text wrapping is re-processed. That means that the last escape sequence is being wrapped at the end of the line I am using a workaround, where I print a Zero Width No Break Space character, but as I preffered, a null character or something that does not add length to the line does not work. So, if I want to format the last token in a line, how should I proceed in doing it so that the formatting does not extend to the end of the line? I will come back with some examples later today.
Author
Owner

@zadjii-msft commented on GitHub (Aug 26, 2021):

then the formatting will apply until the end of the current line, if not initially, then definitely after the window is resized

That's actually #32, something that's plagued us since the days immemorial of the console

@zadjii-msft commented on GitHub (Aug 26, 2021): > then the formatting will apply until the end of the current line, if not initially, then definitely after the window is resized That's actually #32, something that's plagued us since the days immemorial of the console
Author
Owner

@paulkapa commented on GitHub (Aug 26, 2021):

That's actually #32, something that's plagued us since...

Ahh.. 😭 😁 Good to hear! Then no need to proceed with examples. I hope the plague gets eradicated!

@paulkapa commented on GitHub (Aug 26, 2021): > That's actually #32, something that's plagued us since... Ahh.. 😭 😁 Good to hear! Then no need to proceed with examples. I hope the plague gets eradicated!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#14264