-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
End of line cursor position differences when app is run in Windows Terminal #8312
Comments
So, this is likely an effect of the console output modes Generally, we recommend that applications enforce the modes that work best for them 😄 since there's no guarantee that the shell that spawns them is going to set the same modes forever. |
If you interrogate the mode with |
@DHowett Thanks for the quick reply! It does look like there is a difference. Specifically, the However, it doesn't appear that changing that makes any difference in the behavior. I can modify it with I'm not positive I did it correctly - used Any thoughts? |
Hmmmm.. If you try it against the |
Ah, darnit. I even looked at the two different lists and realized I needed to be using OUTPUT but didn't notice I had only tried OK, so using But the one thing I noticed is that the difference appears to be the The descriptions for those two original flags describe what is happening very clearly. In HttpRepl, the combination of both being set would be exactly what we see - because it does move to the next line eventually on the subsequent character. So its weird that the |
Oh, oh, okay. This makes sense. First, though:
I've got really good news: this repo is also home to conhost (the window CMD lives in!) (which also hosts all other Win32 console applications) So, We made a change back in #2824 to fix #1965. The salient comments, if you want to follow along, are #1965 (comment) and #1965 (comment). In short, we made Terminal (and any application like Terminal (VSCode, ConEmu in PTY mode, WSL in interop mode ...)) automatically enable Anyway, this is roughly somewhere between "by design" and "something the application can explicitly turn off", but I do accept that a small set of applications will find the observable oddity now and again. 😁 I'm going to mark this one as question/answered/closed, but don't let that deter you from asking further questions. I love talking about this stuff! |
Yes, this is all starting to make sense now. The timing of it all too - when this chunk of our code was written, that issue you linked to, and the PR didn't even exist yet. So... assumptions were made :) Thanks for all the detail!
Well, since you asked! The question I posed in the original post was for one of two issues we ran into that impacts both conhost and wt (in slightly different ways). But since you offered, I could probably use a bit more clarification to make sure I understand it so we can properly work around it. Running our app in WT, we see that the user is typing on the last line of the window (say, line 30), and the cursor reaches the end (say, position 120), the cursor position wraps back around to slot 0 (not on the next character, but on the following one, because of the above-discussed issues). But the line number doesn't change - its still on line 30. Checking We initially thought this problem didn't exist in plain cmd.exe. But it turned out that the difference was that the It's clearly a bug on our side in how we handle that (the assumption that the row number would keep increasing in perpetuity) and I'm working on changing that code to handle it more appropriately. But I figured I could clarify if my understanding was right to make sure our fix is right. I'm assuming that this difference in behavior is related to the "virtual" terminal idea. The "buffer" is only as big as it needs to be to render to the screen, even though the actually history is longer than that. So plain cmd.exe/conhost without VT processing enabled has a large buffer tied to the actual history, and then when it is in WT, with VT processing enabled, it is virtualized. Is that all there is to it? Or is there something more going on? |
Ah yeah, so that one's gonna be a big gotcha no matter where you're running. The Terminal and the Console are actually the same beast, through-and-through[1]. The interface presented to the application--the console API--is actually serviced by an embedded instance of conhost (which when compiled out of this repository is called OpenConsole). So, behind every pane in Terminal there's a traditional console host. It's really cool! That console host is run in a specific mode that (sometimes) catches applications out. I'll get to that in a sec. That console host also handles translation from Win32 Console APIs to the standard control sequences that normal terminals everywhere except Windows understand. Terminal's built on top of that support: it doesn't need to know anything about the Win32 Console APIs, it just needs to know about VT. Together, we call these modes "ConPTY". That mode that catches applications out, though. This is where it gets "fun". We made a critical mistake approximately forty years ago (:grin:) and made the entire buffer (120x9001 or whatever the user requests) available to a console application. There's the viewport (120x30) and the buffer (120x9001), both of which the application can control. It can draw outside of its bounds, and it can know exactly where in the buffer it's printing. Pretty cool! Applications that have some amount of buffer awareness will eventually reach a point where they're on line 9001 and oops the line under 9001 is also line 9001 (because the old line 0 got destroyed and shifted off the top of the buffer.) This bit is the crux of your issue 😄. We call it "circling." Terminals have never supported that viewport/buffer split. They've only ever offered viewport control, and the buffer was an artifact owned by the terminal itself (because, like, it might have been a line printer or a serial device or a modem . . . instead of a terminal emulator application). That puts the terminal in charge of scrollback, and scrollback is stored in a place where the client application can't see (or change) it. To account for this difference, ConPTY mode restricts the buffer size to match the viewport size. This restriction applies regardless of This means that that circling behavior happens pretty much instantly. Like, after the first 25 lines are printed, the bottom line stops incrementing. It'll always be 25, or 30, or whatever the viewport height is. 1. footnote about terminal/console being the sameIt's kinda funny actually, they also share code. It's kinda like this:Terminal shares modules with conhost, and also runs a separate copy of conhost. The shared modules deal with text buffers, parsing VT, etc. because both of them have got to do it. |
If you really want to go crazy with doc reading, @miniksa wrote up our ecosystem roadmap which covers a good bit of our history and where we're taking this starship. :) |
This isn't so much a bug report as I'm hoping for clarification on some behavior we're seeing in Windows Terminal related to a bug over at HttpRepl. Rich Turner suggested I file here to get more details.
I'm trying to understand the different behavior I'm seeing around the cursor position when our app (a dotnet global tool, though it doesn't appear specific to that type of app) is run from a normal cmd.exe prompt vs when it is run from within Windows Terminal, in a profile that launches cmd.exe. Specifically, this is about how the cursor position is updated when it is at the end of a line.
When our app does a
Console.Write(char)
, in most cases we see theConsole.CursorLeft
(checked before and after the Write call) increase to the next slot after the character that was just written. Where we see the difference is when weConsole.WriteLine(char)
to the last slot on a line.Running our app in vanilla cmd.exe, the character is written and the cursor visibly moves down to the beginning of the next line. Checking
Console.CursorLeft
andConsole.CursorTop
, we can see that the former reset to 0 and the latter increased by 1.Running our app in cmd.exe launched in a Windows Terminal profile, the character is written, but the cursor disappears. Checking
Console.CursorLeft
andConsole.CursorTop
, we can see that neither of them changed - they now refer to the slot to which the character was just written.Steps to reproduce
I set up a fairly minimal repro that demonstrates the difference. Run the app, start typing characters, and watch the upper-left of the console where we are printing the current
Console.CursorLeft
/Console.CursorTop
position. Try it in both vanilla cmd.exe and cmd.exe from within Windows Terminal. Note the different behavior when you get to the last character on the line (and subsequent characters, actually, but I assume that's a derivative problem).Note that the behavior is also different (in the same way) between a vanilla powershell prompt and a powershell prompt from within Windows Terminal.
Environment
It doesn't seem tied to a particular version of Windows or Terminal, but I've confirmed it on:
Expected behavior
I'm not asserting that this is unexpected behavior, necessarily. Instead I'm looking for clarity - maybe a little bit of "why" but also if it is possible for us to detect the different behavior so we can account for it.
Actual behavior
The behavior of the cursor position within a console app differs when it is run in Windows Terminal vs not.
The text was updated successfully, but these errors were encountered: