Any way to achieve something like [Console]::SetWindowPosition? #13196

Closed
opened 2026-01-31 03:36:23 +00:00 by claunia · 9 comments
Owner

Originally created by @jazzdelightsme on GitHub (Mar 25, 2021).

(and if current answer is "no", how might we design some way to do it?)

The situation is that I sometimes use PSReadLine's CaptureScreen function to select and copy portions of my console buffer. When you invoke the CaptureScreen function, PSReadLine enters a sort of mode where you can use arrow keys to move the selection around and use shift together with arrow keys (or j/k for us vi people) to extend the selection. The mode stops when you hit enter, resulting in copying a nice HTML (or is it RTF?) reproduction of the selected area into your clipboard. Very handy.

Crucially (for this Issue), when the selection gets near the top (or bottom) of the console window, CaptureScreen will scroll the buffer, so you can keep selecting (or reach the part of your buffer that you wanted to select in the first place). Like this:

CaptureScreenScrollback

But this scroll-when-you-get-near-the-top functionality does not work in Terminal. (In Terminal, the selection line just reaches the top of the window, and you can go no further.)

The root cause is that CaptureScreen is using [Console]::SetWindowPosition to scroll the buffer… and that does not work in Terminal.

Poking around, I see that it seems like this is By Design, right? (for example: #9018)

So… that brings me to the question: okay, if SetWindowPosition will not work, is there any way this could be made to work?

And if not, what might be done to eventually provide a way for this scenario to work?

Thanks!

Originally created by @jazzdelightsme on GitHub (Mar 25, 2021). (and if current answer is "no", how might we design some way to do it?) The situation is that I sometimes use PSReadLine's `CaptureScreen` function to select and copy portions of my console buffer. When you invoke the `CaptureScreen` function, PSReadLine enters a sort of mode where you can use arrow keys to move the selection around and use <kbd>shift</kbd> together with arrow keys (or <kbd>j</kbd>/<kbd>k</kbd> for us vi people) to extend the selection. The mode stops when you hit <kbd>enter</kbd>, resulting in copying a nice HTML (or is it RTF?) reproduction of the selected area into your clipboard. Very handy. Crucially (for this Issue), when the selection gets near the top (or bottom) of the console window, `CaptureScreen` will scroll the buffer, so you can keep selecting (or reach the part of your buffer that you wanted to select in the first place). Like this: ![CaptureScreenScrollback](https://user-images.githubusercontent.com/771085/112552238-b4495580-8d7f-11eb-8552-8171e6e29c27.gif) But this scroll-when-you-get-near-the-top functionality does not work in Terminal. (In Terminal, the selection line just reaches the top of the window, and you can go no further.) The root cause is that `CaptureScreen` is using `[Console]::SetWindowPosition` to scroll the buffer… and that does not work in Terminal. Poking around, I see that it seems like this is By Design, right? (for example: #9018) So… that brings me to the question: okay, if `SetWindowPosition` will not work, is there any way this could be made to work? And if not, what might be done to eventually provide a way for this scenario to work? Thanks!
Author
Owner

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

I mean, what it sounds like you really want is "mark mode" (#715). [Console]::SetWindowPosition is probably not something that we'd work on implementing, because it's just not something that's compatible with other terminal emulators. But if we had real keyboard text selection, then you wouldn't really need Powershell's built-in CaptureScreen, now, would you?

@zadjii-msft commented on GitHub (Mar 26, 2021): I mean, what it sounds like you really want is "mark mode" (#715). `[Console]::SetWindowPosition` is probably _not_ something that we'd work on implementing, because it's just not something that's compatible with other terminal emulators. But if we had _real_ keyboard text selection, then you wouldn't _really_ need Powershell's built-in `CaptureScreen`, now, would you?
Author
Owner

@jazzdelightsme commented on GitHub (Mar 26, 2021):

Not really. On the one hand, yes, #715 would be helpful. But the snag is that I doubt it will work how I want. Whereas if selection/copy is handled by an application, then I can make an application that works exactly how I like.

For example, in addition to copying as HTML, PSReadLine's CaptureScreen does line-wise selection (like shift+v in vim), and you can use j/k to move the selection (like in vim). (I believe I personally added the j/k.) Will Terminal's "mark mode" support j/k movement? What if Terminal's doesn't support HTML copy? Or what if I don't quite like the generated HTML, and I want to tweak it? Or what if Terminal doesn't support line-wise selection? Etc.

Now it's possible that you'll let me add the vim-like selection mode to Terminal (supposing I have time, ha). But even then it won't work quite how I like--whatever Terminal implements will have to be completely agnostic of an application, so if I have PSReadLine configured to only enter CaptureScreen when I press shift+v when in "command mode" (which I do: Set-PSReadlineKeyHandler -ViMode Command -Chord Shift+V -Function CaptureScreen), then Terminal can't replicate that, because it cannot know that I am using PSReadLine, let alone whether or not it is in command mode.

In short, allowing an application to implement it gives a LOT more flexibility. (And #715 is still goodness, since it can provide basic/general functionality for everyone/everyapp for "free".)

So I still would like to be able to implement CaptureScreen in an app. What is the cause of the incompatibility? Is it the fact that the app only has access to the conpty buffer, which is only the size of the window? Or is it something else?

@jazzdelightsme commented on GitHub (Mar 26, 2021): Not really. On the one hand, yes, #715 would be helpful. But the snag is that I doubt it will work how I want. Whereas if selection/copy is handled by an application, then I can make an application that works exactly how I like. For example, in addition to copying as HTML, PSReadLine's `CaptureScreen` does line-wise selection (like <kbd>shift</kbd>+<kbd>v</kbd> in vim), and you can use <kbd>j</kbd>/<kbd>k</kbd> to move the selection (like in vim). (I believe I personally added the <kbd>j</kbd>/<kbd>k</kbd>.) Will Terminal's "mark mode" support <kbd>j</kbd>/<kbd>k</kbd> movement? What if Terminal's doesn't support HTML copy? Or what if I don't quite like the generated HTML, and I want to tweak it? Or what if Terminal doesn't support line-wise selection? Etc. Now it's possible that you'll let me add the vim-like selection mode to Terminal (supposing I have time, ha). But even then it won't work quite how I like--whatever Terminal implements will have to be completely agnostic of an application, so if I have PSReadLine configured to only enter `CaptureScreen` when I press <kbd>shift</kbd>+<kbd>v</kbd> when in "command mode" (which I do: `Set-PSReadlineKeyHandler -ViMode Command -Chord Shift+V -Function CaptureScreen`), then Terminal can't replicate that, because it cannot know that I am using PSReadLine, let alone whether or not it is in command mode. In short, allowing an application to implement it gives a LOT more flexibility. (And #715 is still goodness, since it can provide basic/general functionality for everyone/everyapp for "free".) So I still would like to be able to implement `CaptureScreen` in an app. What is the cause of the incompatibility? Is it the fact that the app only has access to the conpty buffer, which is only the size of the window? Or is it something else?
Author
Owner

@KalleOlaviNiemitalo commented on GitHub (Mar 26, 2021):

What if Terminal's doesn't support HTML copy?

It does; see the copyFormatting setting at Text format when copying.

Or what if I don't quite like the generated HTML, and I want to tweak it?

Perhaps that could be done in an extension (https://github.com/microsoft/terminal/issues/4000). However, implementing such an extension for Windows Terminal might be more difficult than customizing PSReadLine.

@KalleOlaviNiemitalo commented on GitHub (Mar 26, 2021): > What if Terminal's doesn't support HTML copy? It does; see the `copyFormatting` setting at [Text format when copying](https://docs.microsoft.com/en-us/windows/terminal/customize-settings/interaction#text-format-when-copying). > Or what if I don't quite like the generated HTML, and I want to tweak it? Perhaps that could be done in an extension (<https://github.com/microsoft/terminal/issues/4000>). However, implementing such an extension for Windows Terminal might be more difficult than customizing PSReadLine.
Author
Owner

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

Sounds like these are a lot of concerns that are best suited for "Keyboard Selection Spec #2840" 😉 I'm pretty sure we've already got arguments in that spec for expanding selection by char, word, line and buffer, as well as the ability to map the selection actions to whatever keys you want. Copying will work just like copying has always worked in the Terminal - so it'll respect the copyFormatting settings. If you don't like the generated HTML, you're free to file an issue.

What is the cause of the incompatibility? Is it the fact that the app only has access to the conpty buffer, which is only the size of the window? Or is it something else?

Basically yea, that. Any nix-line terminal application can only ever modify the viewport at the bottom of the buffer. There's no concept of a "scrollback", so there's no way for a client app to tell the Terminal "hey scroll into the scrollback".

@zadjii-msft commented on GitHub (Mar 26, 2021): Sounds like these are a lot of concerns that are best suited for "Keyboard Selection Spec #2840" 😉 I'm pretty sure we've already got arguments in that spec for expanding selection by char, word, line and buffer, as well as the ability to map the selection actions to whatever keys you want. Copying will work just like copying has always worked in the Terminal - so it'll respect the `copyFormatting` settings. If you don't like the generated HTML, you're free to file an issue. > What is the cause of the incompatibility? Is it the fact that the app only has access to the conpty buffer, which is only the size of the window? Or is it something else? Basically yea, that. Any nix-line terminal application can only ever modify the viewport at the bottom of the buffer. There's no concept of a "scrollback", so there's no way for a client app to tell the Terminal "hey scroll into the scrollback".
Author
Owner

@jazzdelightsme commented on GitHub (Mar 26, 2021):

There's no concept of a "scrollback", so there's no way for a client app to tell the Terminal "hey scroll into the scrollback".

Okay, thank you for confirming that for me. My knowledge of this stuff is larval, so I really appreciate you explaining this stuff.

Can the conpty buffer be larger than the window?

Let me explain where I'm going with this thinking.

An app can manage its own "buffer" of whatever size it likes. For example, imagine I'm running vim to edit some huge file on some remote machine (over ssh). In terms of the console, it is true that vim only has access to the screen-sized buffer that it "paints" on. But internally, it can have as big a buffer as it likes, and I can "scroll back" in it (go to the top of the file).

Now imagine that vim had a special mode where it displays a prompt at the bottom of my "document"... and when I type something and hit enter, it sends that command to an external process to execute (say pwsh)... and then the output goes into the "document" (at the bottom), and when it's done, another prompt shows up...

If this were somehow done inside vim, then it could certainly scroll back up into the document, clear back to the very beginning, until the remote machine runs out of memory. (And we know this, because we can scroll up in vim.)

So what would it take for pwsh/PSReadLine to just do this without a special copy of vim? It would have to completely manage its own "document buffer"? Is there a way we could generalize that for every app? Would this be equivalent to making the conpty buffer bigger? (I would settle for 9999 lines.)

@jazzdelightsme commented on GitHub (Mar 26, 2021): > There's no concept of a "scrollback", so there's no way for a client app to tell the Terminal "hey scroll into the scrollback". Okay, thank you for confirming that for me. My knowledge of this stuff is larval, so I really appreciate you explaining this stuff. Can the conpty buffer be larger than the window? Let me explain where I'm going with this thinking. An app can manage its own "buffer" of whatever size it likes. For example, imagine I'm running vim to edit some huge file on some remote machine (over ssh). In terms of the console, it is true that vim only has access to the screen-sized buffer that it "paints" on. But internally, it can have as big a buffer as it likes, and I can "scroll back" in it (go to the top of the file). Now imagine that vim had a special mode where it displays a prompt at the bottom of my "document"... and when I type something and hit <kbd>enter</kbd>, it sends that command to an external process to execute (say `pwsh`)... and then the output goes into the "document" (at the bottom), and when it's done, another prompt shows up... If this were somehow done inside vim, then it could certainly scroll back up into the document, clear back to the very beginning, until the remote machine runs out of memory. (And we know this, because we can scroll up in vim.) So what would it take for pwsh/PSReadLine to just do this without a special copy of vim? It would have to completely manage its own "document buffer"? Is there a way we could generalize that for *every* app? Would this be equivalent to making the conpty buffer bigger? (I would settle for 9999 lines.)
Author
Owner

@driver1998 commented on GitHub (Apr 19, 2021):

I guess it would need to do something like what tmux/screen would do, aka maintain its own terminal buffer?

@driver1998 commented on GitHub (Apr 19, 2021): I guess it would need to do something like what tmux/screen would do, aka maintain its own terminal buffer?
Author
Owner

@j4james commented on GitHub (Apr 24, 2021):

There's recently been some discussion on the terminal workgroup about an extended form of the SU and SD sequences that would actually allow an application to pan the terminal viewport up and down through the scrollback. And it occurred to me that if we supported something like that, we could actually translate certain viewport moving console APIs into VT sequences.

For example, if you wanted to move the viewport back to the very top of the buffer, you could use the extended scroll down sequence (i.e. pan up) with a very large parameter value. And if you wanted to move the viewport to a specific line number, you'd start from the top, and simply pan down the exact amount you need.

This assumes that any attempt to scroll past the ends of the viewport would be clamped, but you aren't otherwise limited in the range of the scrollback that you can access (which I should note is not what is currently proposed).

But if an agreement can be reached on how these sequences should work that's actually useful to us, is this something that Windows Terminal might willing to support? Is it worth starting a discussion with some of the third-party Windows conpty terminals to see if they'd be interested in this functionality?

@j4james commented on GitHub (Apr 24, 2021): There's recently been some discussion on the terminal workgroup about an extended form of the `SU` and `SD` sequences that would actually allow an application to pan the terminal viewport up and down through the scrollback. And it occurred to me that if we supported something like that, we could actually translate certain viewport moving console APIs into VT sequences. For example, if you wanted to move the viewport back to the very top of the buffer, you could use the extended scroll down sequence (i.e. pan up) with a very large parameter value. And if you wanted to move the viewport to a specific line number, you'd start from the top, and simply pan down the exact amount you need. This assumes that any attempt to scroll past the ends of the viewport would be clamped, but you aren't otherwise limited in the range of the scrollback that you can access (which I should note is not what is currently proposed). But if an agreement can be reached on how these sequences should work that's actually useful to us, is this something that Windows Terminal might willing to support? Is it worth starting a discussion with some of the third-party Windows conpty terminals to see if they'd be interested in this functionality?
Author
Owner

@j4james commented on GitHub (Apr 25, 2021):

On further reflection, I think this probably isn't feasible, at least as conpty is currently implemented. As I understand it, the conhost side of the conpty pipe doesn't have a scrollback, so even if the terminal could be instructed to scroll back, the conhost side wouldn't be able to, so they'd end up out of sync.

Maybe it could be made to work if we ever got a straight pass-through version of conpty, but even then you'd lose the ability for legacy console apps to read from the buffer once the viewport is moved, so it wouldn't be ideal.

@j4james commented on GitHub (Apr 25, 2021): On further reflection, I think this probably isn't feasible, at least as conpty is currently implemented. As I understand it, the conhost side of the conpty pipe doesn't have a scrollback, so even if the terminal could be instructed to scroll back, the conhost side wouldn't be able to, so they'd end up out of sync. Maybe it could be made to work if we ever got a straight pass-through version of conpty, but even then you'd lose the ability for legacy console apps to read from the buffer once the viewport is moved, so it wouldn't be ideal.
Author
Owner

@zadjii-msft commented on GitHub (Nov 2, 2022):

Hey so we discussed this a bit more as a team. I think the conclusion was that ultimately, this isn't something we should be trying to design on our side, in a silo. This is a discussion that would be better had on terminal-wg, so that the terminal community can come to a consensus opinion. Should a reasonable consensus be reached, yea, we can try and implement it.

But for the time being, I think we should close this discussion out, since we're not planning on implementing this before that.

@zadjii-msft commented on GitHub (Nov 2, 2022): Hey so we discussed this a bit more as a team. I think the conclusion was that ultimately, this isn't something we should be trying to design on our side, in a silo. This is a discussion that would be better had on [terminal-wg](https://gitlab.freedesktop.org/terminal-wg/specifications), so that the terminal community can come to a consensus opinion. Should a reasonable consensus be reached, yea, we can try and implement it. But for the time being, I think we should close this discussion out, since we're not planning on implementing this before that.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#13196