From f685720cacc59c6e84d1e9788f259497da4d63be Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 9 Jun 2022 17:42:44 -0500 Subject: [PATCH] Implement the FTCS_PROMPT sequence for marking the start of the prompt (#13163) Implements the **FTCS_PROMPT** sequence, `OSC 133 ; A ST`. In this PR, it's just used to set a simple Prompt mark on the current line, in the same way that the iTerm2 sequence works. There's rumination in #11000 on how to implement the rest of the FTCS sequences. This is broken into its own PR at the moment. [Quoth j4james](https://github.com/microsoft/terminal/pull/12948#issuecomment-1136360132): > That should be just as easy, and I've noticed a couple of other terminals that are doing that, so it's not unprecedented. If we don't have any immediate use for the other options, there shouldn't be any harm in ignoring them initially. > > And the benefit of going with the more widely supported sequence is that we're more likely to benefit from any shells that have this functionality built in. Otherwise they're forced to try and detect the terminal, which is practically impossible for Windows Terminal. Even iTerm2 supports the `OSC 133` sequence, so we'd probably be the only odd one out. This part of the plumbing is super easy, so I thought it would be valuable to add regardless if we get to the whole of FTCS in 1.15. * [x] I work here * [x] Tested manually - in my pwsh `$PROFILE`: ```pwsh function prompt { $loc = $($executionContext.SessionState.Path.CurrentLocation); $out = "PS $loc$('>' * ($nestedPromptLevel + 1)) "; $out += "$([char]27)]9;9;`"$loc`"$([char]07)"; $out += "$([char]27)]133;A;$([char]7)"; # add the FTCS_PROMPT to the... well, end, but you get the point return $out } ``` * See also #11000 --- .github/actions/spelling/allow/allow.txt | 1 + src/terminal/adapter/ITermDispatch.hpp | 2 + src/terminal/adapter/adaptDispatch.cpp | 50 +++++++++++++++++++ src/terminal/adapter/adaptDispatch.hpp | 2 + src/terminal/adapter/termDispatch.hpp | 2 + .../parser/OutputStateMachineEngine.cpp | 5 ++ .../parser/OutputStateMachineEngine.hpp | 1 + 7 files changed, 63 insertions(+) diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt index 60b57274c84..d4147344705 100644 --- a/.github/actions/spelling/allow/allow.txt +++ b/.github/actions/spelling/allow/allow.txt @@ -26,6 +26,7 @@ EDDC Enum'd Fitt formattings +FTCS ftp fvar gcc diff --git a/src/terminal/adapter/ITermDispatch.hpp b/src/terminal/adapter/ITermDispatch.hpp index 17c7374c309..082e9607df0 100644 --- a/src/terminal/adapter/ITermDispatch.hpp +++ b/src/terminal/adapter/ITermDispatch.hpp @@ -137,6 +137,8 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch virtual bool DoITerm2Action(const std::wstring_view string) = 0; + virtual bool DoFinalTermAction(const std::wstring_view string) = 0; + virtual StringHandler DownloadDRCS(const VTInt fontNumber, const VTParameter startChar, const DispatchTypes::DrcsEraseControl eraseControl, diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index a94b4f0c6a4..6a3a1847176 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -2509,6 +2509,56 @@ bool AdaptDispatch::DoITerm2Action(const std::wstring_view string) return false; } +// Method Description: +// - Performs a FinalTerm action +// - Currently, the actions we support are: +// * `OSC133;A`: mark a line as a prompt line +// - Not actually used in conhost +// - The remainder of the FTCS prompt sequences are tracked in GH#11000 +// Arguments: +// - string: contains the parameters that define which action we do +// Return Value: +// - false in conhost, true for the SetMark action, otherwise false. +bool AdaptDispatch::DoFinalTermAction(const std::wstring_view string) +{ + // This is not implemented in conhost. + if (_api.IsConsolePty()) + { + // Flush the frame manually, to make sure marks end up on the right line, like the alt buffer sequence. + _renderer.TriggerFlush(false); + return false; + } + + if constexpr (!Feature_ScrollbarMarks::IsEnabled()) + { + return false; + } + + const auto parts = Utils::SplitString(string, L';'); + + if (parts.size() < 1) + { + return false; + } + + const auto action = til::at(parts, 0); + + if (action == L"A") // FTCS_PROMPT + { + // Simply just mark this line as a prompt line. + DispatchTypes::ScrollMark mark; + mark.category = DispatchTypes::MarkCategory::Prompt; + _api.AddMark(mark); + return true; + } + + // When we add the rest of the FTCS sequences (GH#11000), we should add a + // simple state machine here to track the most recently emitted mark from + // this set of sequences, and which sequence was emitted last, so we can + // modify the state of that mark as we go. + return false; +} + // Method Description: // - DECDLD - Downloads one or more characters of a dynamically redefinable // character set (DRCS) with a specified pixel pattern. The pixel array is diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index ca6a221fc76..9ad57a5c55b 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -132,6 +132,8 @@ namespace Microsoft::Console::VirtualTerminal bool DoITerm2Action(const std::wstring_view string) override; + bool DoFinalTermAction(const std::wstring_view string) override; + StringHandler DownloadDRCS(const VTInt fontNumber, const VTParameter startChar, const DispatchTypes::DrcsEraseControl eraseControl, diff --git a/src/terminal/adapter/termDispatch.hpp b/src/terminal/adapter/termDispatch.hpp index 49c690aabbd..7d3b302941f 100644 --- a/src/terminal/adapter/termDispatch.hpp +++ b/src/terminal/adapter/termDispatch.hpp @@ -130,6 +130,8 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons bool DoITerm2Action(const std::wstring_view /*string*/) override { return false; } + bool DoFinalTermAction(const std::wstring_view /*string*/) override { return false; } + StringHandler DownloadDRCS(const VTInt /*fontNumber*/, const VTParameter /*startChar*/, const DispatchTypes::DrcsEraseControl /*eraseControl*/, diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index 08972476e7e..38f79ed5b9e 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -842,6 +842,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, success = _dispatch->DoITerm2Action(string); break; } + case OscActionCodes::FinalTermAction: + { + success = _dispatch->DoFinalTermAction(string); + break; + } default: // If no functions to call, overall dispatch was a failure. success = false; diff --git a/src/terminal/parser/OutputStateMachineEngine.hpp b/src/terminal/parser/OutputStateMachineEngine.hpp index f37843e2495..346c642d608 100644 --- a/src/terminal/parser/OutputStateMachineEngine.hpp +++ b/src/terminal/parser/OutputStateMachineEngine.hpp @@ -188,6 +188,7 @@ namespace Microsoft::Console::VirtualTerminal ResetForegroundColor = 110, // Not implemented ResetBackgroundColor = 111, // Not implemented ResetCursorColor = 112, + FinalTermAction = 133, ITerm2Action = 1337, };