зеркало из https://github.com/microsoft/terminal.git
Introduce `switchSelectionEndpoint` action (#13370)
## Summary of the Pull Request Introduces the `switchSelectionEndpoint` action which switches whichever selection endpoint is targeted when a selection is present. For example, if you are targeting "start", `switchSelectionEndpoint` makes it so that now you are targeting "end". This also updates the selection markers appropriately. ## References Spec - #5804 #13358 Closes #3663 ## Detailed Description of the Pull Request / Additional comments Most of the code is just standard code of adding a new action. Other than that, we have... - if there is no selection, the action fails and the keybinding is passed through (similar to `copy()`) - when we update the selection endpoint, we need to also update the "pivot". This ensures that future calls of `UpdateSelection()` respect this swap. - [Corner Case] if the cursor is being moved, we make it so that you basically "anchored" an endpoint and you don't have to hold shift anymore.
This commit is contained in:
Родитель
d6a9e9ffb6
Коммит
7b8a53c030
|
@ -354,6 +354,7 @@
|
|||
"toggleFocusMode",
|
||||
"selectAll",
|
||||
"setFocusMode",
|
||||
"switchSelectionEndpoint",
|
||||
"toggleFullscreen",
|
||||
"setFullScreen",
|
||||
"setMaximized",
|
||||
|
|
|
@ -1112,4 +1112,14 @@ namespace winrt::TerminalApp::implementation
|
|||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleSwitchSelectionEndpoint(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
const auto handled = control.SwitchSelectionEndpoint();
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1089,6 +1089,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return static_cast<Control::SelectionInteractionMode>(_terminal->SelectionMode());
|
||||
}
|
||||
|
||||
bool ControlCore::SwitchSelectionEndpoint()
|
||||
{
|
||||
if (_terminal->IsSelectionActive())
|
||||
{
|
||||
_terminal->SwitchSelectionEndpoint();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Pre-process text pasted (presumably from the clipboard)
|
||||
// before sending it over the terminal's connection.
|
||||
|
|
|
@ -86,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
bool ToggleBlockSelection();
|
||||
void ToggleMarkMode();
|
||||
Control::SelectionInteractionMode SelectionMode() const;
|
||||
bool SwitchSelectionEndpoint();
|
||||
|
||||
void GotFocus();
|
||||
void LostFocus();
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace Microsoft.Terminal.Control
|
|||
void ClearSelection();
|
||||
Boolean ToggleBlockSelection();
|
||||
void ToggleMarkMode();
|
||||
Boolean SwitchSelectionEndpoint();
|
||||
void ClearBuffer(ClearBufferType clearType);
|
||||
|
||||
void SetHoveredCell(Microsoft.Terminal.Core.Point terminalPosition);
|
||||
|
|
|
@ -1929,6 +1929,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_core.ToggleMarkMode();
|
||||
}
|
||||
|
||||
bool TermControl::SwitchSelectionEndpoint()
|
||||
{
|
||||
return _core.SwitchSelectionEndpoint();
|
||||
}
|
||||
|
||||
void TermControl::Close()
|
||||
{
|
||||
if (!_IsClosing())
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void SelectAll();
|
||||
bool ToggleBlockSelection();
|
||||
void ToggleMarkMode();
|
||||
bool SwitchSelectionEndpoint();
|
||||
void Close();
|
||||
Windows::Foundation::Size CharacterDimensions() const;
|
||||
Windows::Foundation::Size MinimumSize();
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace Microsoft.Terminal.Control
|
|||
void SelectAll();
|
||||
Boolean ToggleBlockSelection();
|
||||
void ToggleMarkMode();
|
||||
Boolean SwitchSelectionEndpoint();
|
||||
void ClearBuffer(ClearBufferType clearType);
|
||||
void Close();
|
||||
Windows.Foundation.Size CharacterDimensions { get; };
|
||||
|
|
|
@ -48,6 +48,7 @@ Terminal::Terminal() :
|
|||
_selectionMode{ SelectionInteractionMode::None },
|
||||
_selection{ std::nullopt },
|
||||
_selectionEndpoint{ static_cast<SelectionEndpoint>(0) },
|
||||
_anchorInactiveSelectionEndpoint{ false },
|
||||
_taskbarState{ 0 },
|
||||
_taskbarProgress{ 0 },
|
||||
_trimBlockSelection{ false },
|
||||
|
|
|
@ -271,6 +271,7 @@ public:
|
|||
void UpdateSelection(SelectionDirection direction, SelectionExpansion mode, ControlKeyStates mods);
|
||||
void SelectAll();
|
||||
SelectionInteractionMode SelectionMode() const noexcept;
|
||||
void SwitchSelectionEndpoint();
|
||||
void ToggleMarkMode();
|
||||
|
||||
using UpdateSelectionParams = std::optional<std::pair<SelectionDirection, SelectionExpansion>>;
|
||||
|
@ -349,6 +350,7 @@ private:
|
|||
SelectionExpansion _multiClickSelectionMode;
|
||||
SelectionInteractionMode _selectionMode;
|
||||
SelectionEndpoint _selectionEndpoint;
|
||||
bool _anchorInactiveSelectionEndpoint;
|
||||
#pragma endregion
|
||||
|
||||
std::unique_ptr<TextBuffer> _mainBuffer;
|
||||
|
|
|
@ -309,6 +309,33 @@ void Terminal::ToggleMarkMode()
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - switch the targeted selection endpoint with the other one (i.e. start <--> end)
|
||||
void Terminal::SwitchSelectionEndpoint()
|
||||
{
|
||||
if (IsSelectionActive())
|
||||
{
|
||||
if (WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::Start) && WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::End))
|
||||
{
|
||||
// moving cursor --> anchor start, move end
|
||||
_selectionEndpoint = SelectionEndpoint::End;
|
||||
_anchorInactiveSelectionEndpoint = true;
|
||||
}
|
||||
else if (WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::End))
|
||||
{
|
||||
// moving end --> now we're moving start
|
||||
_selectionEndpoint = SelectionEndpoint::Start;
|
||||
_selection->pivot = _selection->end;
|
||||
}
|
||||
else if (WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::Start))
|
||||
{
|
||||
// moving start --> now we're moving end
|
||||
_selectionEndpoint = SelectionEndpoint::End;
|
||||
_selection->pivot = _selection->start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Terminal::UpdateSelectionParams Terminal::ConvertKeyEventToUpdateSelectionParams(const ControlKeyStates mods, const WORD vkey) const
|
||||
{
|
||||
if ((_selectionMode == SelectionInteractionMode::Mark || mods.IsShiftPressed()) && !mods.IsAltPressed())
|
||||
|
@ -365,6 +392,12 @@ Terminal::UpdateSelectionParams Terminal::ConvertKeyEventToUpdateSelectionParams
|
|||
// - mods: the key modifiers pressed when performing this update
|
||||
void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion mode, ControlKeyStates mods)
|
||||
{
|
||||
// This is a special variable used to track if we should move the cursor when in mark mode.
|
||||
// We have special functionality where if you use the "switchSelectionEndpoint" action
|
||||
// when in mark mode (moving the cursor), we anchor an endpoint and you can use the
|
||||
// plain arrow keys to move the endpoint. This way, you don't have to hold shift anymore!
|
||||
const bool shouldMoveBothEndpoints = _selectionMode == SelectionInteractionMode::Mark && !_anchorInactiveSelectionEndpoint && !mods.IsShiftPressed();
|
||||
|
||||
// 1. Figure out which endpoint to update
|
||||
// [Mark Mode]
|
||||
// - shift pressed --> only move "end" (or "start" if "pivot" == "end")
|
||||
|
@ -372,7 +405,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
|
|||
// [Quick Edit]
|
||||
// - just move "end" (or "start" if "pivot" == "end")
|
||||
_selectionEndpoint = static_cast<SelectionEndpoint>(0);
|
||||
if (_selectionMode == SelectionInteractionMode::Mark && !mods.IsShiftPressed())
|
||||
if (shouldMoveBothEndpoints)
|
||||
{
|
||||
WI_SetAllFlags(_selectionEndpoint, SelectionEndpoint::Start | SelectionEndpoint::End);
|
||||
}
|
||||
|
@ -405,7 +438,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
|
|||
|
||||
// 3. Actually modify the selection state
|
||||
_selectionMode = std::max(_selectionMode, SelectionInteractionMode::Keyboard);
|
||||
if (_selectionMode == SelectionInteractionMode::Mark && !mods.IsShiftPressed())
|
||||
if (shouldMoveBothEndpoints)
|
||||
{
|
||||
// [Mark Mode] + shift unpressed --> move all three (i.e. just use arrow keys)
|
||||
_selection->start = targetPos;
|
||||
|
@ -598,6 +631,7 @@ void Terminal::ClearSelection()
|
|||
_selection = std::nullopt;
|
||||
_selectionMode = SelectionInteractionMode::None;
|
||||
_selectionEndpoint = static_cast<SelectionEndpoint>(0);
|
||||
_anchorInactiveSelectionEndpoint = false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -82,6 +82,7 @@ static constexpr std::string_view RestoreLastClosedKey{ "restoreLastClosed" };
|
|||
static constexpr std::string_view SelectAllKey{ "selectAll" };
|
||||
static constexpr std::string_view MarkModeKey{ "markMode" };
|
||||
static constexpr std::string_view ToggleBlockSelectionKey{ "toggleBlockSelection" };
|
||||
static constexpr std::string_view SwitchSelectionEndpointKey{ "switchSelectionEndpoint" };
|
||||
|
||||
static constexpr std::string_view ActionKey{ "action" };
|
||||
|
||||
|
@ -400,6 +401,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
{ ShortcutAction::SelectAll, RS_(L"SelectAllCommandKey") },
|
||||
{ ShortcutAction::MarkMode, RS_(L"MarkModeCommandKey") },
|
||||
{ ShortcutAction::ToggleBlockSelection, RS_(L"ToggleBlockSelectionCommandKey") },
|
||||
{ ShortcutAction::SwitchSelectionEndpoint, RS_(L"SwitchSelectionEndpointCommandKey") },
|
||||
};
|
||||
}();
|
||||
|
||||
|
|
|
@ -95,7 +95,8 @@
|
|||
ON_ALL_ACTIONS(RestoreLastClosed) \
|
||||
ON_ALL_ACTIONS(SelectAll) \
|
||||
ON_ALL_ACTIONS(MarkMode) \
|
||||
ON_ALL_ACTIONS(ToggleBlockSelection)
|
||||
ON_ALL_ACTIONS(ToggleBlockSelection) \
|
||||
ON_ALL_ACTIONS(SwitchSelectionEndpoint)
|
||||
|
||||
#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \
|
||||
|
|
|
@ -564,4 +564,7 @@
|
|||
<data name="ToggleBlockSelectionCommandKey" xml:space="preserve">
|
||||
<value>Toggle block selection</value>
|
||||
</data>
|
||||
<data name="SwitchSelectionEndpointCommandKey" xml:space="preserve">
|
||||
<value>Switch selection endpoint</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -388,6 +388,7 @@
|
|||
{ "command": "selectAll", "keys": "ctrl+shift+a" },
|
||||
{ "command": "markMode", "keys": "ctrl+shift+m" },
|
||||
{ "command": "toggleBlockSelection" },
|
||||
{ "command": "switchSelectionEndpoint" },
|
||||
|
||||
// Scrollback
|
||||
{ "command": "scrollDown", "keys": "ctrl+shift+down" },
|
||||
|
|
Загрузка…
Ссылка в новой задаче