Reflowing ConPTY: Add programmatic reflow & plain-text render #21461

Closed
opened 2026-01-31 07:45:24 +00:00 by claunia · 2 comments
Owner

Originally created by @Unit2795 on GitHub (Apr 1, 2024).

Originally assigned to: @lhecker on GitHub.

Description of the new feature/enhancement

Synopsis:

  1. Expose ConPTY's reflow capability as a separate function to allow programmatic reflow of text containing VT sequences.
  2. A function to output plain text as it would appear in the console from text containing VT sequences could be useful for applications that cannot interpret VT sequences.

Both of these already seem to be part of the library but are not documented or exposed publicly.

Description

Reflow

Applications may maintain their own buffer/scrollback history that is larger than the buffer size of ConPTY. Issuing ResizePseudoConsole alone may not be adequate in this case (or if reflow output is disabled using PSEUDOCONSOLE_RESIZE_QUIRK). A function where you provide text containing VT sequences along with from/to character grid dimensions and receive the reflowed output would be useful. TextBuffer::Reflow may already suffice?

  • Not many premade libraries exist for this. Some candidates I found:
  • If you don’t also resize ConPTY, you’ll need to perform this reflow calculation on each output from ConPTY

Plain-text Render

Much like ReadConsoleOutputCharacter where you can read the characters in a console. A function where you supply text containing VT sequences, have it rendered, and receive the plain-text output as it would appear in the console would be useful for display in situations where plain text is the only option.

Use-cases

  1. ConPTY output is being displayed in multiple terminals of differing size or is being displayed a while after it has been produced (such as for replays or history).
  2. ConPTY output is being utilized/displayed by something that cannot interpret VT sequences; such as in email, pattern/regex matching, dialogs, txt files, etc.

Proposed technical implementation details (optional)

Possible Solutions:

  1. Add a function that exposes the reflow capability of ConPTY. Taking an input string containing VT sequences, an original terminal size, and a desired terminal size; and outputting the reflowed text. Though since the buffer may be larger than the desired size (such as a scrollback history with thousands of lines) some special precautions may need to be taken?

    • Example Pseudocode:

      ReflowConsoleText(inputText, fromSize, toSize)
      ReflowConsoleText("\x1b[48;1HHELLOWORLD", {x=80,y=24}, {x=120,y=30})
      
  2. Add a function that renders text containing VT sequences into plain text:

    • Example Pseudocode:

      PlainConsoleText(inputText, size)
      PlainConsoleText("\x1b[48;1HHELLOWORLD", {x=120,y=30})
      // Output: "HELLOWORLD"
      

Related

Originally created by @Unit2795 on GitHub (Apr 1, 2024). Originally assigned to: @lhecker on GitHub. # Description of the new feature/enhancement ## Synopsis: 1. Expose ConPTY's reflow capability as a separate function to allow programmatic reflow of text containing VT sequences. 2. A function to output plain text as it would appear in the console from text containing VT sequences could be useful for applications that cannot interpret VT sequences. Both of these already seem to be part of the library but are not documented or exposed publicly. - https://github.com/microsoft/terminal/blob/de7f931228312996a8b586e5348d5dda46610b84/src/buffer/out/textBuffer.cpp#L2527 - https://github.com/microsoft/terminal/blob/de7f931228312996a8b586e5348d5dda46610b84/src/buffer/out/textBuffer.cpp#L2053 ## Description ### Reflow Applications may maintain their own buffer/scrollback history that is larger than the buffer size of ConPTY. Issuing [ResizePseudoConsole](https://learn.microsoft.com/en-us/windows/console/resizepseudoconsole) alone may not be adequate in this case (or if reflow output is disabled using `PSEUDOCONSOLE_RESIZE_QUIRK`). A function where you provide text containing VT sequences along with from/to character grid dimensions and receive the reflowed output would be useful. [`TextBuffer::Reflow`](https://github.com/microsoft/terminal/blob/de7f931228312996a8b586e5348d5dda46610b84/src/buffer/out/textBuffer.cpp#L2527) may already suffice? - Not many premade libraries exist for this. Some candidates I found: - https://github.com/darrenstarr/VtNetCore - If you don’t also resize ConPTY, you’ll need to perform this reflow calculation on each output from ConPTY ### Plain-text Render Much like [ReadConsoleOutputCharacter](https://learn.microsoft.com/en-us/windows/console/readconsoleoutputcharacter) where you can read the characters in a console. A function where you supply text containing VT sequences, have it rendered, and receive the plain-text output as it would appear in the console would be useful for display in situations where plain text is the only option. ## Use-cases 1. ConPTY output is being displayed in multiple terminals of differing size or is being displayed a while after it has been produced (such as for replays or history). 2. ConPTY output is being utilized/displayed by something that cannot interpret VT sequences; such as in email, pattern/regex matching, dialogs, txt files, etc. # Proposed technical implementation details (optional) Possible Solutions: 1. Add a function that exposes the reflow capability of ConPTY. Taking an input string containing VT sequences, an original terminal size, and a desired terminal size; and outputting the reflowed text. Though since the buffer may be larger than the desired size (such as a scrollback history with thousands of lines) some special precautions may need to be taken? - Example Pseudocode: ``` ReflowConsoleText(inputText, fromSize, toSize) ReflowConsoleText("\x1b[48;1HHELLOWORLD", {x=80,y=24}, {x=120,y=30}) ``` 2. Add a function that renders text containing VT sequences into plain text: - Example Pseudocode: ``` PlainConsoleText(inputText, size) PlainConsoleText("\x1b[48;1HHELLOWORLD", {x=120,y=30}) // Output: "HELLOWORLD" ``` # Related - https://github.com/microsoft/terminal/issues/16911
claunia added the Issue-FeatureNeeds-TriageNeeds-Tag-Fix labels 2026-01-31 07:45:25 +00:00
Author
Owner

@lhecker commented on GitHub (Apr 3, 2024):

Thank you so much for your excellent issue! Unfortunately, after discussion, we have decided that we want to pursue a different direction at this time.

Even if we were to expose ConPTY's reflow algorithm in some way, it still wouldn't solve the issue for those terminals that have their own text storage and thus necessarily their own reflow algorithms. Instead we want to solve the issue in these ways:

  • ConPTY currently renders all text into its internal buffer first, as if it had a display to render to. Then it reads that text back and writes it out as VT to the output pipe.
    Instead we want to translate the Win32 console APIs directly to VT output. The internal buffer will then only be used for servicing ReadConsole* API calls. ResizePseudoConsole will thus not cause any text to be emitted in the output pipe anymore, because it's entirely detached from that VT output pipe.
  • MAYBE there could be an in-process ConPTY library in the future which would offer a COM interface that allows its users to supply their own text buffer implementation. This would then solve not just the reflow issue but also the internal ConPTY buffer from getting out of sync during ResizePseudoConsole. Maybe.

Regarding PlainConsoleText, it'd be nice if you could extend what your use-case for such a function is. Generally speaking however, we're not planning to offer functions that parse VT sequences at the moment as (for now) we're focused on the above topics and similar when it comes to ConPTY.

@lhecker commented on GitHub (Apr 3, 2024): Thank you so much for your excellent issue! Unfortunately, after discussion, we have decided that we want to pursue a different direction at this time. Even if we were to expose ConPTY's reflow algorithm in some way, it still wouldn't solve the issue for those terminals that have their own text storage and thus necessarily their own reflow algorithms. Instead we want to solve the issue in these ways: * ConPTY currently renders all text into its internal buffer first, as if it had a display to render to. Then it reads that text back and writes it out as VT to the output pipe. Instead we want to translate the Win32 console APIs directly to VT output. The internal buffer will then only be used for servicing `ReadConsole*` API calls. `ResizePseudoConsole` will thus not cause any text to be emitted in the output pipe anymore, because it's entirely detached from that VT output pipe. * _MAYBE_ there could be an in-process ConPTY library in the future which would offer a COM interface that allows its users to supply their own text buffer implementation. This would then solve not just the reflow issue but also the internal ConPTY buffer from getting out of sync during `ResizePseudoConsole`. _Maybe._ Regarding `PlainConsoleText`, it'd be nice if you could extend what your use-case for such a function is. Generally speaking however, we're not planning to offer functions that parse VT sequences at the moment as (for now) we're focused on the above topics and similar when it comes to ConPTY.
Author
Owner

@Unit2795 commented on GitHub (Apr 4, 2024):

No problem @lhecker, I figured there were more important things to focus on at the moment anyways and my proposed solutions may have not been the best route. But I wanted to get the request out there.

You're right that part of my issue is ResizePseudoConsole causing my text buffer to get out of sync. I display the output of ConPTY in another terminal (usually Windows Terminal or conhost directly) and my application stores a large scrollback buffer. Ensuring the scrollback is formatted properly after resizing has been the challenge I faced but I recognize this is probably from a lack of familiarity on my part. The terminal that displays ConPTY's output is not always visible and when it is started, its dimensions tend to differ from ConPTY's. So when I write the scrollback buffer to this terminal, it tends to be mangled without me reflowing it first. In my application, at times the output of ConPTY may also be displayed simultaneously in terminals of differing size. Programmatic reflow seemed like my best option at the time. I know this is an even more exceptionally niche use-case though.

Being able to supply your own buffer sounds like another good possible solution. I'm not familiar enough with low level terminal emulation and the Win32 APIs to say what might be best, so I'm sure you guys will pick what's best.

My use case for extracting plain text from VT sequences, as they would appear in the console, is mentioned briefly above:

ConPTY output is being utilized/displayed by something that cannot interpret VT sequences; such as in email, pattern/regex matching, dialogs, txt files, etc

My particular use-case is producing log files and regex-matching console output in my terminal automation library. Very similar to the "Export Text" option currently available in Windows Terminal, but programmatically (mentioned in this discussion https://github.com/microsoft/terminal/discussions/16504). I could probably just use ReadConsoleOutputCharacter but my only issue is sometimes I need to produce this plain-text after the console has already closed.

Similar to producing plain text; RTF and HTML would be great too, possibly similar to:

Thanks for the reply and consideration, looking forward to seeing what comes next.

@Unit2795 commented on GitHub (Apr 4, 2024): No problem @lhecker, I figured there were more important things to focus on at the moment anyways and my proposed solutions may have not been the best route. But I wanted to get the request out there. You're right that part of my issue is `ResizePseudoConsole` causing my text buffer to get out of sync. I display the output of ConPTY in another terminal (usually Windows Terminal or conhost directly) and my application stores a large scrollback buffer. Ensuring the scrollback is formatted properly after resizing has been the challenge I faced but I recognize this is probably from a lack of familiarity on my part. The terminal that displays ConPTY's output is not always visible and when it is started, its dimensions tend to differ from ConPTY's. So when I write the scrollback buffer to this terminal, it tends to be mangled without me reflowing it first. In my application, at times the output of ConPTY may also be displayed simultaneously in terminals of differing size. Programmatic reflow seemed like my best option at the time. I know this is an even more exceptionally niche use-case though. Being able to supply your own buffer sounds like another good possible solution. I'm not familiar enough with low level terminal emulation and the Win32 APIs to say what might be best, so I'm sure you guys will pick what's best. My use case for extracting plain text from VT sequences, as they would appear in the console, is mentioned briefly above: > ConPTY output is being utilized/displayed by something that cannot interpret VT sequences; such as in email, pattern/regex matching, dialogs, txt files, etc My particular use-case is producing log files and regex-matching console output in my terminal automation library. Very similar to the "Export Text" option currently available in Windows Terminal, but programmatically (mentioned in this discussion https://github.com/microsoft/terminal/discussions/16504). I could probably just use [ReadConsoleOutputCharacter](https://learn.microsoft.com/en-us/windows/console/readconsoleoutputcharacter) but my only issue is sometimes I need to produce this plain-text after the console has already closed. Similar to producing plain text; RTF and HTML would be great too, possibly similar to: - https://github.com/microsoft/terminal/blob/de7f931228312996a8b586e5348d5dda46610b84/src/buffer/out/textBuffer.cpp#L2090 - https://github.com/microsoft/terminal/blob/de7f931228312996a8b586e5348d5dda46610b84/src/buffer/out/textBuffer.cpp#L2301 Thanks for the reply and consideration, looking forward to seeing what comes next.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21461