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

Support all the newline operations #3189

Closed
j4james opened this issue Oct 14, 2019 · 6 comments · Fixed by #3271
Closed

Support all the newline operations #3189

j4james opened this issue Oct 14, 2019 · 6 comments · Fixed by #3271
Assignees
Labels
Area-VT Virtual Terminal sequence support Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.

Comments

@j4james
Copy link
Collaborator

j4james commented Oct 14, 2019

Description of the new feature/enhancement

VT terminals support at least five newline controls that I'm aware of. There are the three control characters: LF (linefeed), VT (vertical tab), and FF (form feed). And then there are also two escape sequences: NEL (Next Line) and IND (Index).

The three control characters are simply aliases for the same operation. When the New Line Mode is reset, they perform a linefeed by itself. When the New Line Mode is set, they perform a carriage return as well as the linefeed.

The NEL and IND sequences are not affected by the mode, though. The IND escape sequence always performs a linefeed by itself, with no carriage return. And the NEL escape sequence always performs a carriage return and linefeed together.

It may not seem as if there's much value in supporting all of these sequences, but they are required to pass the Vttest Test of cursor movements, so it would be nice to have them supported in the Windows console.

Proposed technical implementation details (optional)

I'd ignore the New Line Mode to start with, since that's not essential, and introduces a whole lot more complexity. And that means we could actually implement everything in the OutputStateMachineEngine, simply with calls to the ITermDispatch::Execute method, with either LF, or CR and LF, depending on what was needed.

That said, I think it would be nicer to add a dedicated LineFeed method to the ITermDispatch interface, probably with an enum parameter specifying the required type (i.e. with carriage return, without carriage return, or mode-dependent). Then we can always add a mode condition in there at a later stage if we want to support the New Line Mode.

It may even be worth adding a dedicated method in the ConGetSet interface for implementing the newline functionality directly, instead of going through WriteCharsLegacy. This requires a little more work, but has the advantage that it would not be influenced by the DISABLE_NEWLINE_AUTO_RETURN flag (which can produce the wrong behaviour when not set).

I should also mention there is an additional complication with implementing the IND sequence, which is issue #976. My preference would be to drop those cursor movement operations for now, in favor of getting IND working. And then we can always add them back when a proper VT52 mode is implemented (which is something I still have on the back burner). But it seems pointless keeping them without the rest of the VT52 support, and without the user explicitly requesting VT52 mode.

@j4james j4james added the Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. label Oct 14, 2019
@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Oct 14, 2019
@DHowett-MSFT
Copy link
Contributor

This'll be important as we nail down #780. Thanks!

@DHowett-MSFT DHowett-MSFT added Area-VT Virtual Terminal sequence support Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase and removed Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Oct 14, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Oct 14, 2019
@DHowett-MSFT DHowett-MSFT added this to the Console Backlog milestone Oct 14, 2019
@j4james
Copy link
Collaborator Author

j4james commented Oct 15, 2019

This'll be important as we nail down #780.

Yes! I was just thinking about this. If you're in VT mode, the control characters should all already be parsed out from the regular text, so it seems really pointless to then forward them on to the WriteCharsLegacy method which has to reparse the content all over again.

If we got the OutputStateMachineEngine to handle all of the control characters itself, it should be a lot more efficient, and then the WriteCharsLegacy function would no longer need to worry about any special case handling for VT mode.

It would also mean the PrintString handler could eventually be replaced by something much simpler than WriteCharsLegacy, since it could assume that the content was always printable text that doesn't require control character handling.

@j4james
Copy link
Collaborator Author

j4james commented Oct 16, 2019

@DHowett-MSFT Is it OK if I start putting together a PR for this? Or is it likely to conflict with the work that is already being done for #780?

@DHowett-MSFT
Copy link
Contributor

@j4james sure is! @miniksa gave me his blessing to give to you, with apologies that he's been busy.

Cryptically, he said "I only want the deferred one in WriteChars(...)", which I parsed as "the only type of newline WriteChars should know about after #780 is the deferred kind".

😄

@j4james
Copy link
Collaborator Author

j4james commented Oct 17, 2019

That makes sense. And I fully understand how busy you guys are, so please don't feel any pressure to deal with my issues. If I'm stepping on any toes with my PRs, or there's anything you don't like, don't hesitate to reject them. I'm on holiday at the moment, so I may be going a bit overboard with the PR submissions. 😀

@ghost ghost added the In-PR This issue has a related PR label Oct 21, 2019
@ghost ghost closed this as completed in #3271 Jan 15, 2020
ghost pushed a commit that referenced this issue Jan 15, 2020
## Summary of the Pull Request

This adds support for the `FF` (form feed) and `VT` (vertical tab) [control characters](https://vt100.net/docs/vt510-rm/chapter4.html#T4-1), as well as the [`NEL` (Next Line)](https://vt100.net/docs/vt510-rm/NEL.html) and [`IND` (Index)](https://vt100.net/docs/vt510-rm/IND.html) escape sequences.

## References

#976 discusses the conflict between VT100 Index sequence and the VT52 cursor back sequence.

## PR Checklist
* [x] Closes #3189
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3189

## Detailed Description of the Pull Request / Additional comments

I've added a `LineFeed` method to the `ITermDispatch` interface, with an enum parameter specifying the required line feed type (i.e. with carriage return, without carriage return, or dependent on the [`LNM` mode](https://vt100.net/docs/vt510-rm/LNM.html)). The output state machine can then call that method to handle the various line feed control characters (parsed in the `ActionExecute` method), as well the `NEL` and `IND` escape sequences (parsed in the `ActionEscDispatch` method).

The `AdaptDispatch` implementation of `LineFeed` then forwards the call to a new `PrivateLineFeed` method in the `ConGetSet` interface, which simply takes a bool parameter specifying whether a carriage return is required or not. In the case of mode-dependent line feeds, the `AdaptDispatch` implementation determines whether the return is necessary or not, based on the existing _AutoReturnOnNewLine_ setting (which I'm obtaining via another new `PrivateGetLineFeedMode` method).

Ultimately we'll want to support changing the mode via the [`LNM` escape sequence](https://vt100.net/docs/vt510-rm/LNM.html), but there's no urgent need for that now. And using the existing _AutoReturnOnNewLine_ setting as a substitute for the mode gives us backwards compatible behaviour, since that will be true for the Windows shells (which expect a linefeed to also generate a carriage return), and false in a WSL bash shell (which won't want the carriage return by default).

As for the actual `PrivateLineFeed` implementation, that is just a simplified version of how the line feed would previously have been executed in the `WriteCharsLegacy` function. This includes setting the cursor to "On" (with `Cursor::SetIsOn`), potentially clearing the wrap property of the line being left (with `CharRow::SetWrapForced` false), and then setting the new position using `AdjustCursorPosition` with the _fKeepCursorVisible_ parameter set to false.

I'm unsure whether the `SetIsOn` call is really necessary, and I think the way the forced wrap is handled needs a rethink in general, but for now this should at least be compatible with the existing behaviour.

Finally, in order to make this all work in the _Windows Terminal_ app, I also had to add a basic implementation of the `ITermDispatch::LineFeed` method in the `TerminalDispatch` class. There is currently no need to support mode-specific line feeds here, so this simply forwards a `\n` or `\r\n` to the `Execute` method, which is ultimately handled by the `Terminal::_WriteBuffer` implementation.

## Validation Steps Performed

I've added output engine tests which confirm that the various control characters and escape sequences trigger the dispatch method correctly. Then I've added adapter tests which confirm the various dispatch options trigger the `PrivateLineFeed` API correctly. And finally I added some screen buffer tests that check the actual results of the `NEL` and `IND` sequences, which covers both forms of the `PrivateLineFeed` API (i.e. with and without a carriage return).

I've also run the _Test of cursor movements_ in the [Vttest](https://invisible-island.net/vttest/) utility, and confirmed that screens 1, 2, and 5 are now working correctly. The first two depend on `NEL` and `IND` being supported, and screen 5 requires the `VT` control character.
@ghost ghost added Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Jan 15, 2020
@ghost
Copy link

ghost commented Feb 13, 2020

🎉This issue was addressed in #3271, which has now been successfully released as Windows Terminal Preview v0.9.433.0.:tada:

Handy links:

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-VT Virtual Terminal sequence support Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants