Fix clear buffer command (#17884)

Without a VT "renderer" there's no implicit output anymore when
calling `ClearPseudoConsole`. The fix is trivial, but it works
slightly different from before: Previously, we would preserve
the line the cursor is on, while this PR doesn't do that.
I felt like there's not much merit in preserving the line,
because it may be a multi-line prompt which won't work with that.

Closes #17867

## Validation Steps Performed
Bind 3 different actions to the 3 variants of "Clear buffer"
and test them. They work. 
This commit is contained in:
Leonard Hecker 2024-09-24 21:11:27 +02:00 committed by GitHub
parent d9131c6889
commit 4259ce535f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 24 additions and 49 deletions

View File

@ -2208,19 +2208,32 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void ControlCore::ClearBuffer(Control::ClearBufferType clearType)
{
if (clearType == Control::ClearBufferType::Scrollback || clearType == Control::ClearBufferType::All)
std::wstring_view command;
switch (clearType)
{
case ClearBufferType::Screen:
command = L"\x1b[H\x1b[2J";
break;
case ClearBufferType::Scrollback:
command = L"\x1b[3J";
break;
case ClearBufferType::All:
command = L"\x1b[H\x1b[2J\x1b[3J";
break;
}
{
const auto lock = _terminal->LockForWriting();
_terminal->EraseScrollback();
_terminal->Write(command);
}
if (clearType == Control::ClearBufferType::Screen || clearType == Control::ClearBufferType::All)
{
// Send a signal to conpty to clear the buffer.
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
{
// ConPTY will emit sequences to sync up our buffer with its new
// contents.
// Since the clearing of ConPTY occurs asynchronously, this call can result weird issues,
// where a console application still sees contents that we've already deleted, etc.
// The correct way would be for ConPTY to emit the appropriate CSI n J sequences.
conpty.ClearBuffer();
}
}

View File

@ -212,12 +212,6 @@ void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
engine.Dispatch().SetCursorStyle(cursorStyle);
}
void Terminal::EraseScrollback()
{
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().EraseInDisplay(DispatchTypes::EraseType::Scrollback);
}
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
{
return _systemMode.test(Mode::BracketedPaste);

View File

@ -94,7 +94,6 @@ public:
void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance);
void SetFontInfo(const FontInfo& fontInfo);
void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle);
void EraseScrollback();
bool IsXtermBracketedPasteModeEnabled() const noexcept;
std::wstring_view GetWorkingDirectory() noexcept;

View File

@ -304,9 +304,9 @@ namespace ControlUnitTests
Log::Comment(L"Check the buffer after the clear");
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
VERIFY_ARE_EQUAL(41, core->ScrollOffset());
VERIFY_ARE_EQUAL(20, core->ViewHeight());
VERIFY_ARE_EQUAL(41, core->BufferHeight());
VERIFY_ARE_EQUAL(61, core->BufferHeight());
// In this test, we can't actually check if we cleared the buffer
// contents. ConPTY will handle the actual clearing of the buffer

View File

@ -7,6 +7,7 @@
#include "output.h"
#include "handle.h"
#include "_stream.h"
#include "../interactivity/inc/ServiceLocator.hpp"
using namespace Microsoft::Console;
@ -197,7 +198,9 @@ void PtySignalInputThread::_DoClearBuffer() const
}
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
THROW_IF_FAILED(gci.GetActiveOutputBuffer().ClearBuffer());
auto& screenInfo = gci.GetActiveOutputBuffer();
auto& stateMachine = screenInfo.GetStateMachine();
stateMachine.ProcessString(L"\x1b[H\x1b[2J");
}
void PtySignalInputThread::_DoShowHide(const ShowHideData& data)

View File

@ -2129,38 +2129,6 @@ void SCREEN_INFORMATION::SetViewport(const Viewport& newViewport,
Tracing::s_TraceWindowViewport(_viewport);
}
// Method Description:
// - Clear the entire contents of the viewport, except for the cursor's row,
// which is moved to the top line of the viewport.
// - This is used exclusively by ConPTY to support GH#1193, GH#1882. This allows
// a terminal to clear the contents of the ConPTY buffer, which is important
// if the user would like to be able to clear the terminal-side buffer.
// Arguments:
// - <none>
// Return Value:
// - S_OK
[[nodiscard]] HRESULT SCREEN_INFORMATION::ClearBuffer()
{
// Rotate the buffer to bring the cursor row to the top of the viewport.
const auto cursorPos = _textBuffer->GetCursor().GetPosition();
for (auto i = 0; i < cursorPos.y; i++)
{
_textBuffer->IncrementCircularBuffer();
}
// Erase everything below that point.
RETURN_IF_FAILED(SetCursorPosition({ 0, 1 }, false));
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().EraseInDisplay(DispatchTypes::EraseType::ToEnd);
// Restore the original cursor x offset, but now on the first row.
RETURN_IF_FAILED(SetCursorPosition({ cursorPos.x, 0 }, false));
_textBuffer->TriggerRedrawAll();
return S_OK;
}
// Routine Description:
// - Writes cells to the output buffer at the cursor position.
// Arguments:

View File

@ -203,8 +203,6 @@ public:
void SetDefaultAttributes(const TextAttribute& attributes,
const TextAttribute& popupAttributes);
[[nodiscard]] HRESULT ClearBuffer();
void UpdateBottom();
FontInfo& GetCurrentFont() noexcept;