Skip to content

Commit

Permalink
Implement and action for manually clearing the Terminal (and conpty) …
Browse files Browse the repository at this point in the history
…buffer (#10906)

## Summary of the Pull Request

![clear-buffer-000](https://user-images.githubusercontent.com/18356694/127570078-90c6089e-0430-4dfc-bcd4-a0cde20c9167.gif)

This adds a new action, `clearBuffer`. It accepts 3 values for the `clear` type:
* `"clear": "screen"`: Clear the terminal viewport content. Leaves the scrollback untouched. Moves the cursor row to the top of the viewport (unmodified).
* `"clear": "scrollback"`: Clear the scrollback. Leaves the viewport untouched.
* `"clear": "all"`: (**default**) Clear the scrollback and the visible viewport. Moves the cursor row to the top of the viewport (unmodified).

"Clear Buffer" has also been added to `defaults.json`.

## References
* From microsoft/vscode#75141 originally

## PR Checklist
* [x] Closes #1193
* [x] Closes #1882
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This is a bit tricky, because we need to plumb it all the way through conpty to clear the buffer. If we don't, then conpty will immediately just redraw the screen. So this sends a signal to the attached conpty, and then waits for conpty to draw the updated, cleared, screen back to us.

## Validation Steps Performed
* works for each of the three clear types as expected
* tests pass.
* works even with `ping -t 8.8.8.8` as you'd hope.
  • Loading branch information
zadjii-msft authored Sep 2, 2021
1 parent 13bc71d commit 6268a47
Show file tree
Hide file tree
Showing 35 changed files with 536 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,22 @@ namespace winrt::TerminalApp::implementation
}
}

void TerminalPage::_HandleClearBuffer(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
if (args)
{
if (const auto& realArgs = args.ActionArgs().try_as<ClearBufferArgs>())
{
if (const auto termControl{ _GetActiveControl() })
{
termControl.ClearBuffer(realArgs.Clear());
args.Handled(true);
}
}
}
}

void TerminalPage::_HandleMultipleActions(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
Expand Down
10 changes: 10 additions & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,16 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
}
}

void ConptyConnection::ClearBuffer()
{
// If we haven't connected yet, then we really don't need to do
// anything. The connection should already start clear!
if (_isConnected())
{
THROW_IF_FAILED(ConptyClearPseudoConsole(_hPC.get()));
}
}

void ConptyConnection::Close() noexcept
try
{
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void WriteInput(hstring const& data);
void Resize(uint32_t rows, uint32_t columns);
void Close() noexcept;
void ClearBuffer();

winrt::guid Guid() const noexcept;

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.idl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Microsoft.Terminal.TerminalConnection
{
ConptyConnection();
Guid Guid { get; };
void ClearBuffer();

static event NewConnectionHandler NewConnection;
static void StartInboundListener();
Expand Down
31 changes: 31 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_updatePatternLocations->Run();
}

// Method Description:
// - Clear the contents of the buffer. The region cleared is given by
// clearType:
// * Screen: Clear only the contents of the visible viewport, leaving the
// cursor row at the top of the viewport.
// * Scrollback: Clear the contents of the scrollback.
// * All: Do both - clear the visible viewport and the scrollback, leaving
// only the cursor row at the top of the viewport.
// Arguments:
// - clearType: The type of clear to perform.
// Return Value:
// - <none>
void ControlCore::ClearBuffer(Control::ClearBufferType clearType)
{
if (clearType == Control::ClearBufferType::Scrollback || clearType == Control::ClearBufferType::All)
{
_terminal->EraseInDisplay(::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType::Scrollback);
}

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.
conpty.ClearBuffer();
}
}
}

hstring ControlCore::ReadEntireBuffer() const
{
auto terminalLock = _terminal->LockForWriting();
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const short wheelDelta,
const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state);
void UserScrollViewport(const int viewTop);

void ClearBuffer(Control::ClearBufferType clearType);

#pragma endregion

void BlinkAttributeTick();
Expand Down
9 changes: 9 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.idl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ namespace Microsoft.Terminal.Control
IsRightButtonDown = 0x4
};


enum ClearBufferType
{
Screen,
Scrollback,
All
};

[default_interface] runtimeclass ControlCore : ICoreState
{
ControlCore(IControlSettings settings,
Expand Down Expand Up @@ -49,6 +57,7 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.Core.ControlKeyStates modifiers);
void SendInput(String text);
void PasteText(String text);
void ClearBuffer(ClearBufferType clearType);

void SetHoveredCell(Microsoft.Terminal.Core.Point terminalPosition);
void ClearHoveredCell();
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
_core.SendInput(wstr);
}
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
{
_core.ClearBuffer(clearType);
}

void TermControl::ToggleShaderEffects()
{
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::point GetFontSize() const;

void SendInput(const winrt::hstring& input);
void ClearBuffer(Control::ClearBufferType clearType);

void ToggleShaderEffects();

winrt::fire_and_forget RenderEngineSwapChainChanged(IInspectable sender, IInspectable args);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/TermControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "IControlSettings.idl";
import "IDirectKeyListener.idl";
import "EventArgs.idl";
import "ICoreState.idl";
import "ControlCore.idl";

namespace Microsoft.Terminal.Control
{
Expand Down Expand Up @@ -46,6 +47,7 @@ namespace Microsoft.Terminal.Control

Boolean CopySelectionToClipboard(Boolean singleLine, Windows.Foundation.IReference<CopyFormat> formats);
void PasteTextFromClipboard();
void ClearBuffer(ClearBufferType clearType);
void Close();
Windows.Foundation.Size CharacterDimensions { get; };
Windows.Foundation.Size MinimumSize { get; };
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static constexpr std::string_view OpenWindowRenamerKey{ "openWindowRenamer" };
static constexpr std::string_view GlobalSummonKey{ "globalSummon" };
static constexpr std::string_view QuakeModeKey{ "quakeMode" };
static constexpr std::string_view FocusPaneKey{ "focusPane" };
static constexpr std::string_view ClearBufferKey{ "clearBuffer" };
static constexpr std::string_view MultipleActionsKey{ "multipleActions" };

static constexpr std::string_view ActionKey{ "action" };
Expand Down Expand Up @@ -367,6 +368,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{ ShortcutAction::GlobalSummon, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
{ ShortcutAction::FocusPane, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::ClearBuffer, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::MultipleActions, L"" }, // Intentionally omitted, must be generated by GenerateName
};
}();
Expand Down
19 changes: 19 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "RenameWindowArgs.g.cpp"
#include "GlobalSummonArgs.g.cpp"
#include "FocusPaneArgs.g.cpp"
#include "ClearBufferArgs.g.cpp"
#include "MultipleActionsArgs.g.cpp"

#include <LibraryResources.h>
Expand Down Expand Up @@ -688,6 +689,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Id())
};
}
winrt::hstring ClearBufferArgs::GenerateName() const
{
// "Clear Buffer"
// "Clear Viewport"
// "Clear Scrollback"
switch (Clear())
{
case Control::ClearBufferType::All:
return RS_(L"ClearAllCommandKey");
case Control::ClearBufferType::Screen:
return RS_(L"ClearViewportCommandKey");
case Control::ClearBufferType::Scrollback:
return RS_(L"ClearScrollbackCommandKey");
}

// Return the empty string - the Clear() should be one of these values
return winrt::hstring{ L"" };
}

winrt::hstring MultipleActionsArgs::GenerateName() const
{
Expand Down
53 changes: 53 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "RenameWindowArgs.g.h"
#include "GlobalSummonArgs.g.h"
#include "FocusPaneArgs.g.h"
#include "ClearBufferArgs.g.h"
#include "MultipleActionsArgs.g.h"

#include "../../cascadia/inc/cppwinrt_utils.h"
Expand Down Expand Up @@ -1755,6 +1756,56 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
};

struct ClearBufferArgs : public ClearBufferArgsT<ClearBufferArgs>
{
ClearBufferArgs() = default;
ClearBufferArgs(winrt::Microsoft::Terminal::Control::ClearBufferType clearType) :
_Clear{ clearType } {};
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ClearBufferType, Clear, winrt::Microsoft::Terminal::Control::ClearBufferType::All);
static constexpr std::string_view ClearKey{ "clear" };

public:
hstring GenerateName() const;

bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<ClearBufferArgs>();
if (otherAsUs)
{
return otherAsUs->_Clear == _Clear;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<ClearBufferArgs>();
JsonUtils::GetValueForKey(json, ClearKey, args->_Clear);
return { *args, {} };
}
static Json::Value ToJson(const IActionArgs& val)
{
if (!val)
{
return {};
}
Json::Value json{ Json::ValueType::objectValue };
const auto args{ get_self<ClearBufferArgs>(val) };
JsonUtils::SetValueForKey(json, ClearKey, args->_Clear);
return json;
}
IActionArgs Copy() const
{
auto copy{ winrt::make_self<ClearBufferArgs>() };
copy->_Clear = _Clear;
return *copy;
}
size_t Hash() const
{
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Clear);
}
};

struct MultipleActionsArgs : public MultipleActionsArgsT<MultipleActionsArgs>
{
MultipleActionsArgs() = default;
Expand Down Expand Up @@ -1787,6 +1838,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return {};
}
Json::Value json{ Json::ValueType::objectValue };

const auto args{ get_self<MultipleActionsArgs>(val) };
JsonUtils::SetValueForKey(json, ActionsKey, args->_Actions);
return json;
Expand Down Expand Up @@ -1826,5 +1878,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(FocusPaneArgs);
BASIC_FACTORY(PrevTabArgs);
BASIC_FACTORY(NextTabArgs);
BASIC_FACTORY(ClearBufferArgs);
BASIC_FACTORY(MultipleActionsArgs);
}
8 changes: 7 additions & 1 deletion src/cascadia/TerminalSettingsModel/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,15 @@ namespace Microsoft.Terminal.Settings.Model
UInt32 Id { get; };
};

[default_interface] runtimeclass ClearBufferArgs : IActionArgs
{
ClearBufferArgs(Microsoft.Terminal.Control.ClearBufferType clear);
Microsoft.Terminal.Control.ClearBufferType Clear { get; };
};

[default_interface] runtimeclass MultipleActionsArgs : IActionArgs
{
MultipleActionsArgs();
Windows.Foundation.Collections.IVector<ActionAndArgs> Actions;
}
};
}
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/AllShortcutActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
ON_ALL_ACTIONS(GlobalSummon) \
ON_ALL_ACTIONS(QuakeMode) \
ON_ALL_ACTIONS(FocusPane) \
ON_ALL_ACTIONS(ClearBuffer) \
ON_ALL_ACTIONS(MultipleActions)

#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
Expand Down Expand Up @@ -111,4 +112,5 @@
ON_ALL_ACTIONS_WITH_ARGS(SwitchToTab) \
ON_ALL_ACTIONS_WITH_ARGS(ToggleCommandPalette) \
ON_ALL_ACTIONS_WITH_ARGS(FocusPane) \
ON_ALL_ACTIONS_WITH_ARGS(ClearBuffer) \
ON_ALL_ACTIONS_WITH_ARGS(MultipleActions)
12 changes: 12 additions & 0 deletions src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,18 @@
<value>Focus pane {0}</value>
<comment>{0} will be replaced with a user-specified number</comment>
</data>
<data name="ClearAllCommandKey" xml:space="preserve">
<value>Clear Buffer</value>
<comment>A command to clear the entirety of the Terminal output buffer</comment>
</data>
<data name="ClearViewportCommandKey" xml:space="preserve">
<value>Clear Viewport</value>
<comment>A command to clear the active viewport of the Terminal</comment>
</data>
<data name="ClearScrollbackCommandKey" xml:space="preserve">
<value>Clear Scrollback</value>
<comment>A command to clear the part of the buffer above the viewport</comment>
</data>
<data name="InboxWindowsConsoleAuthor" xml:space="preserve">
<value>Microsoft Corporation</value>
<comment>Paired with `InboxWindowsConsoleName`, this is the application author... which is us: Microsoft.</comment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,22 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::MonitorBehavior)
};
};

JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::ClearBufferType)
{
JSON_MAPPINGS(3) = {
pair_type{ "all", ValueType::All },
pair_type{ "screen", ValueType::Screen },
pair_type{ "scrollback", ValueType::Scrollback },
};
};

JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::IntenseStyle)
{
static constexpr std::array<pair_type, 4> mappings = {
pair_type{ "none", AllClear },
pair_type{ "bold", ValueType::Bold },
pair_type{ "bright", ValueType::Bright },
pair_type{ "all", AllSet },

};
};
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@
{ "command": "scrollUpPage", "keys": "ctrl+shift+pgup" },
{ "command": "scrollToTop", "keys": "ctrl+shift+home" },
{ "command": "scrollToBottom", "keys": "ctrl+shift+end" },
{ "command": { "action": "clearBuffer", "clear": "all" } },

// Visual Adjustments
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+plus" },
Expand Down
Loading

0 comments on commit 6268a47

Please sign in to comment.