Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement copy and paste for keyboard shortcuts #1072

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/cascadia/TerminalApp/App.cpp
Expand Up @@ -428,6 +428,8 @@ namespace winrt::TerminalApp::implementation
bindings.ScrollDownPage([this]() { _ScrollPage(1); });
bindings.SwitchToTab([this](const auto index) { _SelectTab({ index }); });
bindings.OpenSettings([this]() { _OpenSettings(); });
bindings.CopyText([this]() { _CopyText(true); });
bindings.PasteText([this]() { _PasteText(); });
}

// Method Description:
Expand Down Expand Up @@ -875,6 +877,19 @@ namespace winrt::TerminalApp::implementation
control.CopySelectionToClipboard(trimTrailingWhitespace);
}

// Method Description:
// - Paste text from the Windows Clipboard to the focused terminal
// Arguments:
// - <none>
void App::_PasteText()
{
const int focusedTabIndex = _GetFocusedTabIndex();
std::shared_ptr<Tab> focusedTab{ _tabs[focusedTabIndex] };

const auto control = focusedTab->GetTerminalControl();
control.PasteTextFromClipboard();
}

// Method Description:
// - Sets focus to the tab to the right or left the currently selected tab.
void App::_SelectNextTab(const bool bMoveRight)
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/App.h
Expand Up @@ -103,6 +103,7 @@ namespace winrt::TerminalApp::implementation

void _Scroll(int delta);
void _CopyText(const bool trimTrailingWhitespace);
void _PasteText();
// Todo: add more event implementations here
// MSFT:20641986: Add keybindings for New Window
void _ScrollPage(int delta);
Expand Down
18 changes: 18 additions & 0 deletions src/cascadia/TerminalApp/Profile.cpp
Expand Up @@ -32,6 +32,7 @@ static constexpr std::wstring_view ACRYLICTRANSPARENCY_KEY{ L"acrylicOpacity" };
static constexpr std::wstring_view USEACRYLIC_KEY{ L"useAcrylic" };
static constexpr std::wstring_view SCROLLBARSTATE_KEY{ L"scrollbarState" };
static constexpr std::wstring_view CLOSEONEXIT_KEY{ L"closeOnExit" };
static constexpr std::wstring_view STRIPLINEFEEDSONPASTE_KEY{ L"stripLineFeedsOnPaste" };
static constexpr std::wstring_view PADDING_KEY{ L"padding" };
static constexpr std::wstring_view STARTINGDIRECTORY_KEY{ L"startingDirectory" };
static constexpr std::wstring_view ICON_KEY{ L"icon" };
Expand Down Expand Up @@ -83,6 +84,7 @@ Profile::Profile(const winrt::guid& guid):
_useAcrylic{ false },
_scrollbarState{ },
_closeOnExit{ true },
_stripLineFeedsOnPaste{ },
_padding{ DEFAULT_PADDING },
_icon{ },
_backgroundImage{ },
Expand Down Expand Up @@ -147,6 +149,12 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>&
// Fill in the remaining properties from the profile
terminalSettings.UseAcrylic(_useAcrylic);
terminalSettings.CloseOnExit(_closeOnExit);

if (_stripLineFeedsOnPaste)
{
terminalSettings.StripLineFeedsOnPaste(_stripLineFeedsOnPaste.value());
}

terminalSettings.TintOpacity(_acrylicTransparency);

terminalSettings.FontFace(_fontFace);
Expand Down Expand Up @@ -288,6 +296,12 @@ JsonObject Profile::ToJson() const
jsonObject.Insert(CLOSEONEXIT_KEY, closeOnExit);
jsonObject.Insert(PADDING_KEY, padding);

if (_stripLineFeedsOnPaste)
{
const auto stripLineFeedsOnPaste = JsonValue::CreateBooleanValue(_stripLineFeedsOnPaste.value());
jsonObject.Insert(STRIPLINEFEEDSONPASTE_KEY, stripLineFeedsOnPaste);
}

if (_scrollbarState)
{
const auto scrollbarState = JsonValue::CreateStringValue(_scrollbarState.value());
Expand Down Expand Up @@ -434,6 +448,10 @@ Profile Profile::FromJson(winrt::Windows::Data::Json::JsonObject json)
{
result._closeOnExit = json.GetNamedBoolean(CLOSEONEXIT_KEY);
}
if (json.HasKey(STRIPLINEFEEDSONPASTE_KEY))
{
result._stripLineFeedsOnPaste = json.GetNamedBoolean(STRIPLINEFEEDSONPASTE_KEY);
}
if (json.HasKey(PADDING_KEY))
{
result._padding = json.GetNamedString(PADDING_KEY);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/Profile.h
Expand Up @@ -92,6 +92,7 @@ class TerminalApp::Profile final

std::optional<std::wstring> _scrollbarState;
bool _closeOnExit;
std::optional<bool> _stripLineFeedsOnPaste;
std::wstring _padding;

std::optional<std::wstring> _icon;
Expand Down
52 changes: 45 additions & 7 deletions src/cascadia/TerminalControl/TermControl.cpp
Expand Up @@ -718,13 +718,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// paste selection, otherwise
else
{
// attach TermControl::_SendInputToConnection() as the clipboardDataHandler.
// This is called when the clipboard data is loaded.
auto clipboardDataHandler = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1);
auto pasteArgs = winrt::make_self<PasteFromClipboardEventArgs>(clipboardDataHandler);

// send paste event up to TermApp
_clipboardPasteHandlers(*this, *pasteArgs);
PasteTextFromClipboard();
}
}
}
Expand Down Expand Up @@ -981,6 +975,35 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
}

// Method Description:
// - Pre-process (if necessary) text pasted (presumably from the clipboard)
// before sending it over the terminal's connection, respecting
// appropriate terminal settings
void TermControl::_SendPastedTextToConnection(const std::wstring& wstr)
{
// Check settings to see if we should be stripping
// out line feeds
if (_settings.StripLineFeedsOnPaste())
{
std::wstring stripped(wstr);

std::wstring::size_type pos = 0;

// Lament that the stl string does not have
// a search/replace method
while ((pos = stripped.find(L'\r', pos)) != std::wstring::npos)
{
stripped.replace(pos, 1, L"");
}
d-bingham marked this conversation as resolved.
Show resolved Hide resolved

_SendInputToConnection(stripped);
}
else
{
_SendInputToConnection(wstr);
}
}

void TermControl::_SendInputToConnection(const std::wstring& wstr)
{
_connection.WriteInput(wstr);
Expand Down Expand Up @@ -1162,6 +1185,21 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_clipboardCopyHandlers(copiedData);
}

// Method Description:
// - Initiate a paste operation.
// Arguments:
// - <none>
void TermControl::PasteTextFromClipboard()
{
// attach TermControl::_SendInputToConnection() as the clipboardDataHandler.
// This is called when the clipboard data is loaded.
auto clipboardDataHandler = std::bind(&TermControl::_SendPastedTextToConnection, this, std::placeholders::_1);
auto pasteArgs = winrt::make_self<PasteFromClipboardEventArgs>(clipboardDataHandler);

// send paste event up to TermApp
_clipboardPasteHandlers(*this, *pasteArgs);
}

void TermControl::Close()
{
if (!_closing)
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Expand Up @@ -40,6 +40,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

hstring Title();
void CopySelectionToClipboard(bool trimTrailingWhitespace);
void PasteTextFromClipboard();
void Close();

void ScrollViewport(int viewTop);
Expand Down Expand Up @@ -112,6 +113,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

void _BlinkCursor(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _SendInputToConnection(const std::wstring& wstr);
void _SendPastedTextToConnection(const std::wstring& wstr);
void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args);
void _DoResize(const double newWidth, const double newHeight);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.idl
Expand Up @@ -32,6 +32,7 @@ namespace Microsoft.Terminal.TerminalControl

String Title { get; };
void CopySelectionToClipboard(Boolean trimTrailingWhitespace);
void PasteTextFromClipboard();
void Close();

void ScrollViewport(Int32 viewTop);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettings/IControlSettings.idl
Expand Up @@ -21,6 +21,7 @@ namespace Microsoft.Terminal.Settings
{
Boolean UseAcrylic;
Boolean CloseOnExit;
Boolean StripLineFeedsOnPaste;
Double TintOpacity;
ScrollbarState ScrollState;

Expand Down
11 changes: 11 additions & 0 deletions src/cascadia/TerminalSettings/TerminalSettings.cpp
Expand Up @@ -22,6 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_cursorHeight{ DEFAULT_CURSOR_HEIGHT },
_useAcrylic{ false },
_closeOnExit{ true },
_stripLineFeedsOnPaste{ false },
_tintOpacity{ 0.5 },
_padding{ DEFAULT_PADDING },
_fontFace{ DEFAULT_FONT_FACE },
Expand Down Expand Up @@ -156,6 +157,16 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_closeOnExit = value;
}

bool TerminalSettings::StripLineFeedsOnPaste()
{
return _stripLineFeedsOnPaste;
}

void TerminalSettings::StripLineFeedsOnPaste(bool value)
{
_stripLineFeedsOnPaste = value;
}

double TerminalSettings::TintOpacity()
{
return _tintOpacity;
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalSettings/terminalsettings.h
Expand Up @@ -51,6 +51,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
void UseAcrylic(bool value);
bool CloseOnExit();
void CloseOnExit(bool value);
bool StripLineFeedsOnPaste();
void StripLineFeedsOnPaste(bool value);
double TintOpacity();
void TintOpacity(double value);
hstring Padding();
Expand Down Expand Up @@ -97,6 +99,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation

bool _useAcrylic;
bool _closeOnExit;
bool _stripLineFeedsOnPaste;
double _tintOpacity;
hstring _fontFace;
int32_t _fontSize;
Expand Down