Let marks be cleared by clear (and friends) (#15686)

Move scroll marks to `TextBuffer`, so they can be cleared by
EraseInDisplay and EraseScrollback.

Also removes the namespacing on them.

## References and Relevant Issues
* see also #11000 and #15057
* Resize/Reflow _doesn't_ work yet and I'm not attempting this here. 

## Validation Steps Performed

* `cls` works
* `Clear-Host` works
* `clear` works
* the "Clear buffer" action works
* They work when there's marks above the current viewport, and clear the
scrollback
* they work if you clear multiple "pages" of output, then scroll back to
where marks previously were
* resizing doesn't totally destroy the marks

Closes #15426
This commit is contained in:
Mike Griese
2023-07-18 16:10:57 -05:00
committed by GitHub
parent 482c724de6
commit b4042eaaf0
13 changed files with 236 additions and 127 deletions

View File

@@ -2660,6 +2660,9 @@ try
// Set size back to real size as it will be taking over the rendering duties.
newCursor.SetSize(ulSize);
newBuffer._marks = oldBuffer._marks;
newBuffer._trimMarksOutsideBuffer();
return S_OK;
}
CATCH_RETURN()
@@ -2869,3 +2872,114 @@ PointTree TextBuffer::GetPatterns(const til::CoordType firstRow, const til::Coor
PointTree result(std::move(intervals));
return result;
}
const std::vector<ScrollMark>& TextBuffer::GetMarks() const noexcept
{
return _marks;
}
// Remove all marks between `start` & `end`, inclusive.
void TextBuffer::ClearMarksInRange(
const til::point start,
const til::point end)
{
auto inRange = [&start, &end](const ScrollMark& m) {
return (m.start >= start && m.start <= end) ||
(m.end >= start && m.end <= end);
};
_marks.erase(std::remove_if(_marks.begin(),
_marks.end(),
inRange),
_marks.end());
}
void TextBuffer::ClearAllMarks() noexcept
{
_marks.clear();
}
// Adjust all the marks in the y-direction by `delta`. Positive values move the
// marks down (the positive y direction). Negative values move up. This will
// trim marks that are no longer have a start in the bounds of the buffer
void TextBuffer::ScrollMarks(const int delta)
{
for (auto& mark : _marks)
{
mark.start.y += delta;
// If the mark had sub-regions, then move those pointers too
if (mark.commandEnd.has_value())
{
(*mark.commandEnd).y += delta;
}
if (mark.outputEnd.has_value())
{
(*mark.outputEnd).y += delta;
}
}
_trimMarksOutsideBuffer();
}
// Method Description:
// - Add a mark to our list of marks, and treat it as the active "prompt". For
// the sake of shell integration, we need to know which mark represents the
// current prompt/command/output. Internally, we'll always treat the _last_
// mark in the list as the current prompt.
// Arguments:
// - m: the mark to add.
void TextBuffer::StartPromptMark(const ScrollMark& m)
{
_marks.push_back(m);
}
// Method Description:
// - Add a mark to our list of marks. Don't treat this as the active prompt.
// This should be used for marks created by the UI or from other user input.
// By inserting at the start of the list, we can separate out marks that were
// generated by client programs vs ones created by the user.
// Arguments:
// - m: the mark to add.
void TextBuffer::AddMark(const ScrollMark& m)
{
_marks.insert(_marks.begin(), m);
}
void TextBuffer::_trimMarksOutsideBuffer()
{
const auto height = GetSize().Height();
_marks.erase(std::remove_if(_marks.begin(),
_marks.end(),
[height](const auto& m) {
return (m.start.y < 0) ||
(m.start.y >= height);
}),
_marks.end());
}
void TextBuffer::SetCurrentPromptEnd(const til::point pos) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.end = pos;
}
void TextBuffer::SetCurrentCommandEnd(const til::point pos) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.commandEnd = pos;
}
void TextBuffer::SetCurrentOutputEnd(const til::point pos, ::MarkCategory category) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.outputEnd = pos;
curr.category = category;
}

View File

@@ -64,6 +64,41 @@ namespace Microsoft::Console::Render
class Renderer;
}
enum class MarkCategory
{
Prompt = 0,
Error = 1,
Warning = 2,
Success = 3,
Info = 4
};
struct ScrollMark
{
std::optional<til::color> color;
til::point start;
til::point end; // exclusive
std::optional<til::point> commandEnd;
std::optional<til::point> outputEnd;
MarkCategory category{ MarkCategory::Info };
// Other things we may want to think about in the future are listed in
// GH#11000
bool HasCommand() const noexcept
{
return commandEnd.has_value() && *commandEnd != end;
}
bool HasOutput() const noexcept
{
return outputEnd.has_value() && *outputEnd != *commandEnd;
}
std::pair<til::point, til::point> GetExtent() const
{
til::point realEnd{ til::coalesce_value(outputEnd, commandEnd, end) };
return std::make_pair(til::point{ start }, realEnd);
}
};
class TextBuffer final
{
public:
@@ -228,6 +263,16 @@ public:
void CopyPatterns(const TextBuffer& OtherBuffer);
interval_tree::IntervalTree<til::point, size_t> GetPatterns(const til::CoordType firstRow, const til::CoordType lastRow) const;
const std::vector<ScrollMark>& GetMarks() const noexcept;
void ClearMarksInRange(const til::point start, const til::point end);
void ClearAllMarks() noexcept;
void ScrollMarks(const int delta);
void StartPromptMark(const ScrollMark& m);
void AddMark(const ScrollMark& m);
void SetCurrentPromptEnd(const til::point pos) noexcept;
void SetCurrentCommandEnd(const til::point pos) noexcept;
void SetCurrentOutputEnd(const til::point pos, ::MarkCategory category) noexcept;
private:
void _reserve(til::size screenBufferSize, const TextAttribute& defaultAttributes);
void _commit(const std::byte* row);
@@ -251,6 +296,7 @@ private:
til::point _GetWordEndForAccessibility(const til::point target, const std::wstring_view wordDelimiters, const til::point limit) const;
til::point _GetWordEndForSelection(const til::point target, const std::wstring_view wordDelimiters) const;
void _PruneHyperlinks();
void _trimMarksOutsideBuffer();
static void _AppendRTFText(std::ostringstream& contentBuilder, const std::wstring_view& text);
@@ -327,6 +373,8 @@ private:
bool _isActiveBuffer = false;
std::vector<ScrollMark> _marks;
#ifdef UNIT_TESTING
friend class TextBufferTests;
friend class UiaTextRangeTests;

View File

@@ -2111,7 +2111,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::AddMark(const Control::ScrollMark& mark)
{
::Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark m{};
::ScrollMark m{};
if (mark.Color.HasValue)
{
@@ -2140,7 +2140,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto currentOffset = ScrollOffset();
const auto& marks{ _terminal->GetScrollMarks() };
std::optional<DispatchTypes::ScrollMark> tgt;
std::optional<::ScrollMark> tgt;
switch (direction)
{
@@ -2243,7 +2243,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const til::point start = HasSelection() ? (goUp ? _terminal->GetSelectionAnchor() : _terminal->GetSelectionEnd()) :
_terminal->GetTextBuffer().GetCursor().GetPosition();
std::optional<DispatchTypes::ScrollMark> nearest{ std::nullopt };
std::optional<::ScrollMark> nearest{ std::nullopt };
const auto& marks{ _terminal->GetScrollMarks() };
// Early return so we don't have to check for the validity of `nearest` below after the loop exits.
@@ -2283,7 +2283,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const til::point start = HasSelection() ? (goUp ? _terminal->GetSelectionAnchor() : _terminal->GetSelectionEnd()) :
_terminal->GetTextBuffer().GetCursor().GetPosition();
std::optional<DispatchTypes::ScrollMark> nearest{ std::nullopt };
std::optional<::ScrollMark> nearest{ std::nullopt };
const auto& marks{ _terminal->GetScrollMarks() };
static constexpr til::point worst{ til::CoordTypeMax, til::CoordTypeMax };
@@ -2357,8 +2357,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::_contextMenuSelectMark(
const til::point& pos,
bool (*filter)(const DispatchTypes::ScrollMark&),
til::point_span (*getSpan)(const DispatchTypes::ScrollMark&))
bool (*filter)(const ::ScrollMark&),
til::point_span (*getSpan)(const ::ScrollMark&))
{
// Do nothing if the caller didn't give us a way to get the span to select for this mark.
if (!getSpan)
@@ -2391,20 +2391,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
_contextMenuSelectMark(
_contextMenuBufferPosition,
[](const DispatchTypes::ScrollMark& m) -> bool { return !m.HasCommand(); },
[](const DispatchTypes::ScrollMark& m) { return til::point_span{ m.end, *m.commandEnd }; });
[](const ::ScrollMark& m) -> bool { return !m.HasCommand(); },
[](const ::ScrollMark& m) { return til::point_span{ m.end, *m.commandEnd }; });
}
void ControlCore::ContextMenuSelectOutput()
{
_contextMenuSelectMark(
_contextMenuBufferPosition,
[](const DispatchTypes::ScrollMark& m) -> bool { return !m.HasOutput(); },
[](const DispatchTypes::ScrollMark& m) { return til::point_span{ *m.commandEnd, *m.outputEnd }; });
[](const ::ScrollMark& m) -> bool { return !m.HasOutput(); },
[](const ::ScrollMark& m) { return til::point_span{ *m.commandEnd, *m.outputEnd }; });
}
bool ControlCore::_clickedOnMark(
const til::point& pos,
bool (*filter)(const DispatchTypes::ScrollMark&))
bool (*filter)(const ::ScrollMark&))
{
// Don't show this if the click was on the selection
if (_terminal->IsSelectionActive() &&
@@ -2442,7 +2442,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// Relies on the anchor set in AnchorContextMenu
return _clickedOnMark(_contextMenuBufferPosition,
[](const DispatchTypes::ScrollMark& m) -> bool { return !m.HasCommand(); });
[](const ::ScrollMark& m) -> bool { return !m.HasCommand(); });
}
// Method Description:
@@ -2451,6 +2451,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// Relies on the anchor set in AnchorContextMenu
return _clickedOnMark(_contextMenuBufferPosition,
[](const DispatchTypes::ScrollMark& m) -> bool { return !m.HasOutput(); });
[](const ::ScrollMark& m) -> bool { return !m.HasOutput(); });
}
}

View File

@@ -372,10 +372,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _contextMenuSelectMark(
const til::point& pos,
bool (*filter)(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark&),
til::point_span (*getSpan)(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark&));
bool (*filter)(const ::ScrollMark&),
til::point_span (*getSpan)(const ::ScrollMark&));
bool _clickedOnMark(const til::point& pos, bool (*filter)(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark&));
bool _clickedOnMark(const til::point& pos, bool (*filter)(const ::ScrollMark&));
inline bool _IsClosing() const noexcept
{

View File

@@ -1344,7 +1344,7 @@ void Terminal::_updateUrlDetection()
}
// NOTE: This is the version of AddMark that comes from the UI. The VT api call into this too.
void Terminal::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark,
void Terminal::AddMark(const ScrollMark& mark,
const til::point& start,
const til::point& end,
const bool fromUi)
@@ -1354,17 +1354,18 @@ void Terminal::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes:
return;
}
DispatchTypes::ScrollMark m = mark;
ScrollMark m = mark;
m.start = start;
m.end = end;
// If the mark came from the user adding a mark via the UI, don't make it the active prompt mark.
if (fromUi)
{
_scrollMarks.insert(_scrollMarks.begin(), m);
_activeBuffer().AddMark(m);
}
else
{
_scrollMarks.push_back(m);
_activeBuffer().StartPromptMark(m);
}
// Tell the control that the scrollbar has somehow changed. Used as a
@@ -1389,15 +1390,7 @@ void Terminal::ClearMark()
start = til::point{ GetSelectionAnchor() };
end = til::point{ GetSelectionEnd() };
}
auto inSelection = [&start, &end](const DispatchTypes::ScrollMark& m) {
return (m.start >= start && m.start <= end) ||
(m.end >= start && m.end <= end);
};
_scrollMarks.erase(std::remove_if(_scrollMarks.begin(),
_scrollMarks.end(),
inSelection),
_scrollMarks.end());
_activeBuffer().ClearMarksInRange(start, end);
// Tell the control that the scrollbar has somehow changed. Used as a
// workaround to force the control to redraw any scrollbar marks
@@ -1405,23 +1398,22 @@ void Terminal::ClearMark()
}
void Terminal::ClearAllMarks() noexcept
{
_scrollMarks.clear();
_activeBuffer().ClearAllMarks();
// Tell the control that the scrollbar has somehow changed. Used as a
// workaround to force the control to redraw any scrollbar marks
_NotifyScrollEvent();
}
const std::vector<DispatchTypes::ScrollMark>& Terminal::GetScrollMarks() const noexcept
const std::vector<ScrollMark>& Terminal::GetScrollMarks() const noexcept
{
// TODO: GH#11000 - when the marks are stored per-buffer, get rid of this.
// We want to return _no_ marks when we're in the alt buffer, to effectively
// hide them. We need to return a reference, so we can't just ctor an empty
// list here just for when we're in the alt buffer.
static const std::vector<DispatchTypes::ScrollMark> _altBufferMarks{};
return _inAltBuffer() ? _altBufferMarks : _scrollMarks;
return _activeBuffer().GetMarks();
}
til::color Terminal::GetColorForMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) const
til::color Terminal::GetColorForMark(const ScrollMark& mark) const
{
if (mark.color.has_value())
{
@@ -1430,24 +1422,24 @@ til::color Terminal::GetColorForMark(const Microsoft::Console::VirtualTerminal::
switch (mark.category)
{
case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Prompt:
case MarkCategory::Prompt:
{
return _renderSettings.GetColorAlias(ColorAlias::DefaultForeground);
}
case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Error:
case MarkCategory::Error:
{
return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_RED);
}
case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Warning:
case MarkCategory::Warning:
{
return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_YELLOW);
}
case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Success:
case MarkCategory::Success:
{
return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_GREEN);
}
default:
case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Info:
case MarkCategory::Info:
{
return _renderSettings.GetColorAlias(ColorAlias::DefaultForeground);
}

View File

@@ -97,8 +97,8 @@ public:
RenderSettings& GetRenderSettings() noexcept { return _renderSettings; };
const RenderSettings& GetRenderSettings() const noexcept { return _renderSettings; };
const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark>& GetScrollMarks() const noexcept;
void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark,
const std::vector<ScrollMark>& GetScrollMarks() const noexcept;
void AddMark(const ScrollMark& mark,
const til::point& start,
const til::point& end,
const bool fromUi);
@@ -127,7 +127,7 @@ public:
void UseAlternateScreenBuffer(const TextAttribute& attrs) override;
void UseMainScreenBuffer() override;
void MarkPrompt(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) override;
void MarkPrompt(const ScrollMark& mark) override;
void MarkCommandStart() override;
void MarkOutputStart() override;
void MarkCommandFinish(std::optional<unsigned int> error) override;
@@ -140,7 +140,7 @@ public:
void ClearMark();
void ClearAllMarks() noexcept;
til::color GetColorForMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) const;
til::color GetColorForMark(const ScrollMark& mark) const;
#pragma region ITerminalInput
// These methods are defined in Terminal.cpp
@@ -393,7 +393,6 @@ private:
};
std::optional<KeyEventCodes> _lastKeyEventCodes;
std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark> _scrollMarks;
enum class PromptState : uint32_t
{
None = 0,

View File

@@ -291,7 +291,7 @@ void Terminal::UseMainScreenBuffer()
}
// NOTE: This is the version of AddMark that comes from VT
void Terminal::MarkPrompt(const DispatchTypes::ScrollMark& mark)
void Terminal::MarkPrompt(const ScrollMark& mark)
{
static bool logged = false;
if (!logged)
@@ -309,7 +309,7 @@ void Terminal::MarkPrompt(const DispatchTypes::ScrollMark& mark)
const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() };
AddMark(mark, cursorPos, cursorPos, false);
if (mark.category == DispatchTypes::MarkCategory::Prompt)
if (mark.category == MarkCategory::Prompt)
{
_currentPromptState = PromptState::Prompt;
}
@@ -320,7 +320,7 @@ void Terminal::MarkCommandStart()
const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() };
if ((_currentPromptState == PromptState::Prompt) &&
(_scrollMarks.size() > 0))
(_activeBuffer().GetMarks().size() > 0))
{
// We were in the right state, and there's a previous mark to work
// with.
@@ -333,11 +333,11 @@ void Terminal::MarkCommandStart()
// then abandon the current state, and just insert a new Prompt mark that
// start's & ends here, and got to State::Command.
DispatchTypes::ScrollMark mark;
mark.category = DispatchTypes::MarkCategory::Prompt;
ScrollMark mark;
mark.category = MarkCategory::Prompt;
AddMark(mark, cursorPos, cursorPos, false);
}
_scrollMarks.back().end = cursorPos;
_activeBuffer().SetCurrentPromptEnd(cursorPos);
_currentPromptState = PromptState::Command;
}
@@ -346,7 +346,7 @@ void Terminal::MarkOutputStart()
const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() };
if ((_currentPromptState == PromptState::Command) &&
(_scrollMarks.size() > 0))
(_activeBuffer().GetMarks().size() > 0))
{
// We were in the right state, and there's a previous mark to work
// with.
@@ -359,27 +359,27 @@ void Terminal::MarkOutputStart()
// then abandon the current state, and just insert a new Prompt mark that
// start's & ends here, and the command ends here, and go to State::Output.
DispatchTypes::ScrollMark mark;
mark.category = DispatchTypes::MarkCategory::Prompt;
ScrollMark mark;
mark.category = MarkCategory::Prompt;
AddMark(mark, cursorPos, cursorPos, false);
}
_scrollMarks.back().commandEnd = cursorPos;
_activeBuffer().SetCurrentCommandEnd(cursorPos);
_currentPromptState = PromptState::Output;
}
void Terminal::MarkCommandFinish(std::optional<unsigned int> error)
{
const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() };
auto category = DispatchTypes::MarkCategory::Prompt;
auto category = MarkCategory::Prompt;
if (error.has_value())
{
category = *error == 0u ?
DispatchTypes::MarkCategory::Success :
DispatchTypes::MarkCategory::Error;
MarkCategory::Success :
MarkCategory::Error;
}
if ((_currentPromptState == PromptState::Output) &&
(_scrollMarks.size() > 0))
(_activeBuffer().GetMarks().size() > 0))
{
// We were in the right state, and there's a previous mark to work
// with.
@@ -393,13 +393,12 @@ void Terminal::MarkCommandFinish(std::optional<unsigned int> error)
// ends here, and the command ends here, AND the output ends here. and
// go to State::Output.
DispatchTypes::ScrollMark mark;
mark.category = DispatchTypes::MarkCategory::Prompt;
ScrollMark mark;
mark.category = MarkCategory::Prompt;
AddMark(mark, cursorPos, cursorPos, false);
_scrollMarks.back().commandEnd = cursorPos;
_activeBuffer().SetCurrentCommandEnd(cursorPos);
}
_scrollMarks.back().outputEnd = cursorPos;
_scrollMarks.back().category = category;
_activeBuffer().SetCurrentOutputEnd(cursorPos, category);
_currentPromptState = PromptState::None;
}
@@ -458,29 +457,11 @@ void Terminal::NotifyBufferRotation(const int delta)
// manually erase our pattern intervals since the locations have changed now
_patternIntervalTree = {};
const auto hasScrollMarks = _scrollMarks.size() > 0;
auto& marks{ _activeBuffer().GetMarks() };
const auto hasScrollMarks = marks.size() > 0;
if (hasScrollMarks)
{
for (auto& mark : _scrollMarks)
{
// Move the mark up
mark.start.y -= delta;
// If the mark had sub-regions, then move those pointers too
if (mark.commandEnd.has_value())
{
(*mark.commandEnd).y -= delta;
}
if (mark.outputEnd.has_value())
{
(*mark.outputEnd).y -= delta;
}
}
_scrollMarks.erase(std::remove_if(_scrollMarks.begin(),
_scrollMarks.end(),
[](const auto& m) { return m.start.y < 0; }),
_scrollMarks.end());
_activeBuffer().ScrollMarks(-delta);
}
const auto oldScrollOffset = _scrollOffset;

View File

@@ -435,7 +435,7 @@ void ConhostInternalGetSet::NotifyBufferRotation(const int delta)
}
}
void ConhostInternalGetSet::MarkPrompt(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& /*mark*/)
void ConhostInternalGetSet::MarkPrompt(const ::ScrollMark& /*mark*/)
{
// Not implemented for conhost.
}

View File

@@ -69,7 +69,7 @@ public:
void NotifyAccessibilityChange(const til::rect& changedRect) override;
void NotifyBufferRotation(const int delta) override;
void MarkPrompt(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) override;
void MarkPrompt(const ScrollMark& mark) override;
void MarkCommandStart() override;
void MarkOutputStart() override;
void MarkCommandFinish(std::optional<unsigned int> error) override;

View File

@@ -654,39 +654,4 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
constexpr VTInt s_sDECCOLMSetColumns = 132;
constexpr VTInt s_sDECCOLMResetColumns = 80;
enum class MarkCategory : size_t
{
Prompt = 0,
Error = 1,
Warning = 2,
Success = 3,
Info = 4
};
struct ScrollMark
{
std::optional<til::color> color;
til::point start;
til::point end; // exclusive
std::optional<til::point> commandEnd;
std::optional<til::point> outputEnd;
MarkCategory category{ MarkCategory::Info };
// Other things we may want to think about in the future are listed in
// GH#11000
bool HasCommand() const noexcept
{
return commandEnd.has_value() && *commandEnd != end;
}
bool HasOutput() const noexcept
{
return outputEnd.has_value() && *outputEnd != *commandEnd;
}
std::pair<til::point, til::point> GetExtent() const
{
til::point realEnd{ til::coalesce_value(outputEnd, commandEnd, end) };
return std::make_pair(til::point{ start }, realEnd);
}
};
}

View File

@@ -81,7 +81,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual void NotifyAccessibilityChange(const til::rect& changedRect) = 0;
virtual void NotifyBufferRotation(const int delta) = 0;
virtual void MarkPrompt(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) = 0;
virtual void MarkPrompt(const ScrollMark& mark) = 0;
virtual void MarkCommandStart() = 0;
virtual void MarkOutputStart() = 0;
virtual void MarkCommandFinish(std::optional<unsigned int> error) = 0;

View File

@@ -3145,6 +3145,12 @@ bool AdaptDispatch::_EraseScrollback()
auto& cursor = textBuffer.GetCursor();
const auto row = cursor.GetPosition().y;
// Clear all the marks below the new viewport position.
textBuffer.ClearMarksInRange(til::point{ 0, height },
til::point{ bufferSize.width, bufferSize.height });
// Then scroll all the remaining marks up. This will trim ones that are now "outside" the buffer
textBuffer.ScrollMarks(-top);
// Scroll the viewport content to the top of the buffer.
textBuffer.ScrollRows(top, height, -top);
// Clear everything after the viewport.
@@ -3227,6 +3233,10 @@ bool AdaptDispatch::_EraseAll()
// Also reset the line rendition for the erased rows.
textBuffer.ResetLineRenditionRange(newViewportTop, newViewportBottom);
// Clear any marks that remain below the start of the
textBuffer.ClearMarksInRange(til::point{ 0, newViewportTop },
til::point{ bufferSize.Width(), bufferSize.Height() });
// GH#5683 - If this succeeded, but we're in a conpty, return `false` to
// make the state machine propagate this ED sequence to the connected
// terminal application. While we're in conpty mode, when the client
@@ -3633,8 +3643,8 @@ bool AdaptDispatch::DoITerm2Action(const std::wstring_view string)
if (action == L"SetMark")
{
DispatchTypes::ScrollMark mark;
mark.category = DispatchTypes::MarkCategory::Prompt;
ScrollMark mark;
mark.category = MarkCategory::Prompt;
_api.MarkPrompt(mark);
return true;
}
@@ -3681,8 +3691,8 @@ bool AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
case L'A': // FTCS_PROMPT
{
// Simply just mark this line as a prompt line.
DispatchTypes::ScrollMark mark;
mark.category = DispatchTypes::MarkCategory::Prompt;
ScrollMark mark;
mark.category = MarkCategory::Prompt;
_api.MarkPrompt(mark);
return true;
}

View File

@@ -215,7 +215,7 @@ public:
Log::Comment(L"NotifyBufferRotation MOCK called...");
}
void MarkPrompt(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& /*mark*/) override
void MarkPrompt(const ScrollMark& /*mark*/) override
{
Log::Comment(L"MarkPrompt MOCK called...");
}