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

Fixed #3799: Introduce sendInput command #7249

Merged
4 commits merged into from
Aug 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/cascadia/SettingsSchema.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ For commands with arguments:
| `scrollUp` | Move the screen up. | | | |
| `scrollUpPage` | Move the screen up a whole page. | | | |
| `scrollDownPage` | Move the screen down a whole page. | | | |
| `sendInput` | Sends some text input to the shell. | `input` | string | The text input to feed into the shell.<br>ANSI escape sequences may be used. Escape codes like `\x1b` must be written as `\u001b`.<br>For instance the input `"text\n"` will write "text" followed by a newline. `"\u001b[D"` will behave as if the left arrow button had been pressed. |
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this classify as "Documentation updated"? Do I need to submit a PR to the docs repo?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, you do!

| `splitPane` | Halve the size of the active pane and open another. Without any arguments, this will open the default profile in the new pane. | 1. `split`*<br>2. `commandLine`<br>3. `startingDirectory`<br>4. `tabTitle`<br>5. `index`<br>6. `profile`<br>7. `splitMode` | 1. `vertical`, `horizontal`, `auto`<br>2. string<br>3. string<br>4. string<br>5. integer<br>6. string<br>7. string | 1. How the pane will split. `auto` will split in the direction that provides the most surface area.<br>2. Executable run within the pane.<br>3. Directory in which the pane will open.<br>4. Title of the tab when the new pane is focused.<br>5. Profile that will open based on its position in the dropdown (starting at 0).<br>6. Profile that will open based on its GUID or name.<br>7. Controls how the pane splits. Only accepts `duplicate` which will duplicate the focused pane's profile into a new pane. |
| `switchToTab` | Open a specific tab depending on index. | `index`* | integer | Tab that will open based on its position in the tab bar (starting at 0). |
| `toggleFullscreen` | Switch between fullscreen and default window sizes. | | | |
Expand Down
24 changes: 24 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"scrollDownPage",
"scrollUp",
"scrollUpPage",
"sendInput",
"splitPane",
"switchToTab",
"toggleFocusMode",
Expand Down Expand Up @@ -230,6 +231,28 @@
],
"required": [ "direction" ]
},
"SendInputAction": {
"description": "Arguments corresponding to a Send Input Action",
"allOf": [
{
"$ref": "#/definitions/ShortcutAction"
},
{
"properties": {
"action": {
"type": "string",
"pattern": "sendInput"
},
"input": {
"type": "string",
"default": "",
"description": "The text input to feed into the shell. ANSI escape sequences may be used. Escape codes like \\x1b must be written as \\u001b."
}
}
}
],
"required": [ "input" ]
},
"SplitPaneAction": {
"description": "Arguments corresponding to a Split Pane Action",
"allOf": [
Expand Down Expand Up @@ -390,6 +413,7 @@
{ "$ref": "#/definitions/SwitchToTabAction" },
{ "$ref": "#/definitions/MoveFocusAction" },
{ "$ref": "#/definitions/ResizePaneAction" },
{ "$ref": "#/definitions/SendInputAction" },
{ "$ref": "#/definitions/SplitPaneAction" },
{ "$ref": "#/definitions/OpenSettingsAction" },
{ "$ref": "#/definitions/SetTabColorAction" },
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ static constexpr std::string_view ScrolluppageKey{ "scrollUpPage" };
static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" };
static constexpr std::string_view SwitchToTabKey{ "switchToTab" };
static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings
static constexpr std::string_view SendInputKey{ "sendInput" };
static constexpr std::string_view SplitPaneKey{ "splitPane" };
static constexpr std::string_view TogglePaneZoomKey{ "togglePaneZoom" };
static constexpr std::string_view ResizePaneKey{ "resizePane" };
Expand Down Expand Up @@ -90,6 +91,7 @@ namespace winrt::TerminalApp::implementation
{ ToggleFocusModeKey, ShortcutAction::ToggleFocusMode },
{ ToggleFullscreenKey, ShortcutAction::ToggleFullscreen },
{ ToggleAlwaysOnTopKey, ShortcutAction::ToggleAlwaysOnTop },
{ SendInputKey, ShortcutAction::SendInput },
{ SplitPaneKey, ShortcutAction::SplitPane },
{ TogglePaneZoomKey, ShortcutAction::TogglePaneZoom },
{ SetTabColorKey, ShortcutAction::SetTabColor },
Expand Down Expand Up @@ -125,6 +127,8 @@ namespace winrt::TerminalApp::implementation

{ ShortcutAction::AdjustFontSize, winrt::TerminalApp::implementation::AdjustFontSizeArgs::FromJson },

{ ShortcutAction::SendInput, winrt::TerminalApp::implementation::SendInputArgs::FromJson },

{ ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson },

{ ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson },
Expand Down Expand Up @@ -284,6 +288,7 @@ namespace winrt::TerminalApp::implementation
{ ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") },
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
{ ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") },
{ ShortcutAction::SendInput, L"" },
{ ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") },
{ ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") },
{ ShortcutAction::Invalid, L"" },
Expand Down
13 changes: 13 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ResizePaneArgs.g.cpp"
#include "MoveFocusArgs.g.cpp"
#include "AdjustFontSizeArgs.g.cpp"
#include "SendInputArgs.g.cpp"
#include "SplitPaneArgs.g.cpp"
#include "OpenSettingsArgs.g.cpp"
#include "SetColorSchemeArgs.g.cpp"
Expand All @@ -21,6 +22,8 @@
#include "ExecuteCommandlineArgs.g.cpp"
#include "ToggleTabSwitcherArgs.g.h"

#include "Utils.h"

#include <LibraryResources.h>

namespace winrt::TerminalApp::implementation
Expand Down Expand Up @@ -167,6 +170,16 @@ namespace winrt::TerminalApp::implementation
}
}

winrt::hstring SendInputArgs::GenerateName() const
{
// The string will be similar to the following:
// * "Send Input: ...input..."

auto escapedInput = VisualizeControlCodes(_Input);
auto name = fmt::format(std::wstring_view(RS_(L"SendInputCommandKey")), escapedInput);
return winrt::hstring{ name };
}

winrt::hstring SplitPaneArgs::GenerateName() const
{
// The string will be similar to the following:
Expand Down
32 changes: 32 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ResizePaneArgs.g.h"
#include "MoveFocusArgs.g.h"
#include "AdjustFontSizeArgs.g.h"
#include "SendInputArgs.g.h"
#include "SplitPaneArgs.g.h"
#include "OpenSettingsArgs.g.h"
#include "SetColorSchemeArgs.g.h"
Expand Down Expand Up @@ -270,6 +271,37 @@ namespace winrt::TerminalApp::implementation
}
};

struct SendInputArgs : public SendInputArgsT<SendInputArgs>
{
SendInputArgs() = default;
GETSET_PROPERTY(winrt::hstring, Input, L"");

static constexpr std::string_view InputKey{ "input" };

public:
hstring GenerateName() const;

bool Equals(const IActionArgs& other)
{
if (auto otherAsUs = other.try_as<SendInputArgs>(); otherAsUs)
{
return otherAsUs->_Input == _Input;
}
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<SendInputArgs>();
JsonUtils::GetValueForKey(json, InputKey, args->_Input);
lhecker marked this conversation as resolved.
Show resolved Hide resolved
if (args->_Input.empty())
{
return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
return { *args, {} };
}
};

struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
{
SplitPaneArgs() = default;
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ namespace TerminalApp
Int32 Delta { get; };
};

[default_interface] runtimeclass SendInputArgs : IActionArgs
{
String Input { get; };
};

[default_interface] runtimeclass SplitPaneArgs : IActionArgs
{
SplitState SplitStyle { get; };
Expand Down
15 changes: 15 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ namespace winrt::TerminalApp::implementation
args.Handled(true);
}

void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& args)
{
if (args == nullptr)
{
args.Handled(false);
}
else if (const auto& realArgs = args.ActionArgs().try_as<TerminalApp::SendInputArgs>())
{
const auto termControl = _GetActiveControl();
termControl.SendInput(realArgs.Input());
args.Handled(true);
}
}

void TerminalPage::_HandleSplitPane(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& args)
{
Expand Down
26 changes: 3 additions & 23 deletions src/cascadia/TerminalApp/DebugTapConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "pch.h"
#include "DebugTapConnection.h"
#include "Utils.h"

using namespace ::winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::winrt::Windows::Foundation;
Expand Down Expand Up @@ -91,36 +92,15 @@ namespace winrt::Microsoft::TerminalApp::implementation
return ConnectionState::Failed;
}

static std::wstring _sanitizeString(const std::wstring_view str)
{
std::wstring newString{ str.begin(), str.end() };
for (auto& ch : newString)
{
if (ch < 0x20)
{
ch += 0x2400;
}
else if (ch == 0x20)
{
ch = 0x2423; // replace space with ␣
}
else if (ch == 0x7f)
{
ch = 0x2421; // replace del with ␡
}
}
return newString;
}

void DebugTapConnection::_OutputHandler(const hstring str)
{
_TerminalOutputHandlers(_sanitizeString(str));
_TerminalOutputHandlers(VisualizeControlCodes(str));
}

// Called by the DebugInputTapConnection to print user input
void DebugTapConnection::_PrintInput(const hstring& str)
{
auto clean{ _sanitizeString(str) };
auto clean{ VisualizeControlCodes(str) };
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };
_TerminalOutputHandlers(formatted);
}
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,10 @@
<data name="NewTabCommandKey" xml:space="preserve">
<value>New tab</value>
</data>
<data name="SendInputCommandKey" xml:space="preserve">
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
<value>Send Input: "{0}"</value>
<comment>{0} will be replaced with a string of input as defined by the user</comment>
</data>
<data name="SplitPaneCommandKey" xml:space="preserve">
<value>Split pane</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ namespace winrt::TerminalApp::implementation
break;
}

case ShortcutAction::SendInput:
{
_SendInputHandlers(*this, *eventArgs);
break;
}

case ShortcutAction::SplitVertical:
case ShortcutAction::SplitHorizontal:
case ShortcutAction::SplitPane:
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(SwitchToTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(SendInput, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(TogglePaneZoom, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.idl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace TerminalApp
PrevTab,
SplitVertical,
SplitHorizontal,
SendInput,
SplitPane,
TogglePaneZoom,
SwitchToTab,
Expand Down Expand Up @@ -71,6 +72,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SwitchToTab;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> NextTab;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> PrevTab;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SendInput;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SplitPane;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> TogglePaneZoom;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> AdjustFontSize;
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,7 @@ namespace winrt::TerminalApp::implementation
_actionDispatch->ScrollDown({ this, &TerminalPage::_HandleScrollDown });
_actionDispatch->NextTab({ this, &TerminalPage::_HandleNextTab });
_actionDispatch->PrevTab({ this, &TerminalPage::_HandlePrevTab });
_actionDispatch->SendInput({ this, &TerminalPage::_HandleSendInput });
_actionDispatch->SplitPane({ this, &TerminalPage::_HandleSplitPane });
_actionDispatch->TogglePaneZoom({ this, &TerminalPage::_HandleTogglePaneZoom });
_actionDispatch->ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage });
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ namespace winrt::TerminalApp::implementation
void _HandleScrollDown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleNextTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandlePrevTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleSendInput(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleSplitPane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleTogglePaneZoom(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleScrollUpPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
Expand Down
25 changes: 25 additions & 0 deletions src/cascadia/TerminalApp/Utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// Licensed under the MIT license.

#include "pch.h"
#include "Utils.h"

std::wstring VisualizeControlCodes(std::wstring str) noexcept
{
for (auto& ch : str)
{
if (ch < 0x20)
{
ch += 0x2400;
}
else if (ch == 0x20)
{
ch = 0x2423; // replace space with ␣
}
else if (ch == 0x7f)
{
ch = 0x2421; // replace del with ␡
}
}
return str;
}
7 changes: 7 additions & 0 deletions src/cascadia/TerminalApp/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,10 @@ TIconSource GetColoredIcon(const winrt::hstring& path)

return nullptr;
}

std::wstring VisualizeControlCodes(std::wstring str) noexcept;

inline std::wstring VisualizeControlCodes(std::wstring_view str) noexcept
{
return VisualizeControlCodes(std::wstring{ str });
}
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
<ClCompile Include="../Pane.LayoutSizeNode.cpp" />
<ClCompile Include="../ColorHelper.cpp" />
<ClCompile Include="../DebugTapConnection.cpp" />
<ClCompile Include="../Utils.cpp" />
<ClCompile Include="../TerminalSettings.cpp">
<DependentUpon>../TerminalSettings.idl</DependentUpon>
</ClCompile>
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<ClCompile Include="../Commandline.cpp" />
<ClCompile Include="../ColorHelper.cpp" />
<ClCompile Include="../DebugTapConnection.cpp" />
<ClCompile Include="../Utils.cpp" />
<ClCompile Include="../TerminalSettings.cpp">
<Filter>settings</Filter>
</ClCompile>
Expand Down Expand Up @@ -202,4 +203,4 @@
<Filter>app</Filter>
</ApplicationDefinition>
</ItemGroup>
</Project>
</Project>
Loading