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

Add support for new panes with specifc profiles and other settings overrides #3825

Merged
33 commits merged into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6752b1a
Basic POC - you can add profile, commandline, startingDirectory to ov…
zadjii-msft Nov 26, 2019
9474240
Add a 'splitPane' keybinding that can be used for splitting a pane ei…
zadjii-msft Nov 26, 2019
fb93105
Update documentation too
zadjii-msft Nov 27, 2019
451aaab
Good lord this is important
zadjii-msft Nov 27, 2019
31a9046
Add a test too, though I have no idea if it works
zadjii-msft Nov 27, 2019
b5a264b
"style" -> "split"
zadjii-msft Nov 27, 2019
e0cd014
pr comments from carlos
zadjii-msft Nov 27, 2019
de60a30
Merge remote-tracking branch 'origin/master' into dev/migrie/f/splitP…
zadjii-msft Nov 27, 2019
9f93a53
Merge remote-tracking branch 'origin/master' into dev/migrie/f/new-te…
zadjii-msft Nov 27, 2019
9eac8a6
Merge branch 'dev/migrie/f/splitPane-action' into dev/migrie/f/new-te…
zadjii-msft Nov 27, 2019
2c1742d
This almost works
zadjii-msft Nov 27, 2019
49a546e
clean up some chaotically bad code writing
zadjii-msft Nov 28, 2019
4c0b071
Merge remote-tracking branch 'origin/master' into dev/migrie/f/new-te…
zadjii-msft Dec 2, 2019
22f76e4
Add title to the terminal args too
zadjii-msft Dec 2, 2019
65f10e9
Try adding a test - remember that everything is a horrifying nightmare
zadjii-msft Dec 2, 2019
b392ba0
I this restores the functionality of the local winrt objects, not XAML
zadjii-msft Dec 2, 2019
3be37fd
I this restores the functionality of the local winrt objects, not XAML
zadjii-msft Dec 2, 2019
8a0bb8d
Fix the unit tests, add comments
zadjii-msft Dec 2, 2019
1760de2
That's what I get for not building before pushing
zadjii-msft Dec 3, 2019
7d05f34
Merge branch 'dev/migrie/3536-fix-localtests' into dev/migrie/f/new-t…
zadjii-msft Dec 3, 2019
93db1ed
write a big honkin test
zadjii-msft Dec 3, 2019
2073869
Comments are important
zadjii-msft Dec 3, 2019
9226042
update the schema too
zadjii-msft Dec 3, 2019
919f626
Merge remote-tracking branch 'origin/master' into dev/migrie/f/new-te…
zadjii-msft Dec 3, 2019
f2ad5fc
Merge remote-tracking branch 'origin/master' into dev/migrie/f/new-te…
zadjii-msft Dec 4, 2019
9fe4a71
remove this optional<int> param, it makes me sad
zadjii-msft Dec 4, 2019
b019f24
fixes from PR comments
zadjii-msft Dec 5, 2019
484e444
Suggestions from Dustin's review
zadjii-msft Dec 5, 2019
6e02caa
Merge branch 'master' into dev/migrie/f/new-terminal-args
zadjii-msft Dec 6, 2019
73715e6
update the schema too
zadjii-msft Dec 6, 2019
fcdd2cf
Some nits from Dustin
zadjii-msft Dec 6, 2019
4a99051
Merge remote-tracking branch 'origin/master' into dev/migrie/f/new-te…
zadjii-msft Dec 6, 2019
b8eecb6
Don't take a trip to beeftown on negative parameters
zadjii-msft Dec 6, 2019
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
33 changes: 28 additions & 5 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,31 @@
],
"type": "string"
},
"NewTerminalArgs": {
"properties": {
"commandline": {
"description": "A commandline to use instead of the profile's",
"type": "string"
},
"tabTitle": {
"description": "An initial tabTitle to use instead of the profile's",
"type": "string"
},
"startingDirectory": {
"description": "A startingDirectory to use instead of the profile's",
"type": "string"
},
"profile": {
"description": "Either the GUID or name of a profile to use, instead of launching the default",
"type": "string"
},
"index": {
"type": "integer",
"description": "The index of the profile in the new tab dropdown to open"
}
},
"type": "object"
},
"ShortcutAction": {
"properties": {
"action": {
Expand Down Expand Up @@ -119,13 +144,10 @@
"description": "Arguments corresponding to a New Tab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{ "$ref": "#/definitions/NewTerminalArgs" },
{
"properties": {
"action": { "type":"string", "pattern": "newTab" },
"index": {
"type": "integer",
"description": "The index in the new tab dropdown to open in a new tab"
}
"action": { "type":"string", "pattern": "newTab" }
}
}
]
Expand Down Expand Up @@ -185,6 +207,7 @@
"description": "Arguments corresponding to a Split Pane Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{ "$ref": "#/definitions/NewTerminalArgs" },
{
"properties": {
"action": { "type": "string", "pattern": "splitPane" },
Expand Down
100 changes: 35 additions & 65 deletions src/cascadia/LocalTests_TerminalApp/KeyBindingsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "../TerminalApp/ColorScheme.h"
#include "../TerminalApp/CascadiaSettings.h"
#include "JsonTestClass.h"
#include "TestUtils.h"

using namespace Microsoft::Console;
using namespace TerminalApp;
Expand Down Expand Up @@ -44,42 +45,6 @@ namespace TerminalAppLocalTests
InitializeJsonReader();
return true;
}

// Function Description:
// - This is a helper to retrieve the ActionAndArgs from the keybindings
// for a given chord.
// Arguments:
// - bindings: The AppKeyBindings to lookup the ActionAndArgs from.
// - kc: The key chord to look up the bound ActionAndArgs for.
// Return Value:
// - The ActionAndArgs bound to the given key, or nullptr if nothing is bound to it.
static const ActionAndArgs KeyBindingsTests::GetActionAndArgs(const implementation::AppKeyBindings& bindings,
const KeyChord& kc)
{
std::wstring buffer{ L"" };
if (WI_IsFlagSet(kc.Modifiers(), KeyModifiers::Ctrl))
{
buffer += L"Ctrl+";
}
if (WI_IsFlagSet(kc.Modifiers(), KeyModifiers::Shift))
{
buffer += L"Shift+";
}
if (WI_IsFlagSet(kc.Modifiers(), KeyModifiers::Alt))
{
buffer += L"Alt+";
}
buffer += static_cast<wchar_t>(MapVirtualKeyW(kc.Vkey(), MAPVK_VK_TO_CHAR));
Log::Comment(NoThrowString().Format(L"Looking for key:%s", buffer.c_str()));

const auto keyIter = bindings._keyShortcuts.find(kc);
VERIFY_IS_TRUE(keyIter != bindings._keyShortcuts.end(), L"Expected to find an action bound to the given KeyChord");
if (keyIter != bindings._keyShortcuts.end())
{
return keyIter->second;
}
return nullptr;
};
};

void KeyBindingsTests::ManyKeysSameAction()
Expand Down Expand Up @@ -231,7 +196,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `copy` without args parses as Copy(TrimWhitespace=true)"));
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
Expand All @@ -242,7 +207,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `copyTextWithoutNewlines` parses as Copy(TrimWhitespace=false)"));
KeyChord kc{ false, true, false, static_cast<int32_t>('C') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
Expand All @@ -253,7 +218,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `copy` with args parses them correctly"));
KeyChord kc{ true, false, true, static_cast<int32_t>('C') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
Expand All @@ -264,7 +229,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `copy` with args parses them correctly"));
KeyChord kc{ false, true, true, static_cast<int32_t>('C') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
Expand All @@ -275,68 +240,73 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `newTab` without args parses as NewTab(Index=null)"));
KeyChord kc{ true, false, false, static_cast<int32_t>('T') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NULL(realArgs.ProfileIndex());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NULL(realArgs.TerminalArgs().ProfileIndex());
}
{
Log::Comment(NoThrowString().Format(
L"Verify that `newTab` parses args correctly"));
KeyChord kc{ true, false, true, static_cast<int32_t>('T') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ProfileIndex());
VERIFY_ARE_EQUAL(0, realArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(0, realArgs.TerminalArgs().ProfileIndex().Value());
}
{
Log::Comment(NoThrowString().Format(
L"Verify that `newTabProfile0` parses as NewTab(Index=0)"));
KeyChord kc{ false, true, true, static_cast<int32_t>('T') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTabProfile0, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ProfileIndex());
VERIFY_ARE_EQUAL(0, realArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(0, realArgs.TerminalArgs().ProfileIndex().Value());
}
{
Log::Comment(NoThrowString().Format(
L"Verify that `newTab` with an index greater than the legacy "
L"args afforded parses correctly"));
KeyChord kc{ true, false, true, static_cast<int32_t>('Y') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ProfileIndex());
VERIFY_ARE_EQUAL(11, realArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(11, realArgs.TerminalArgs().ProfileIndex().Value());
}
{
Log::Comment(NoThrowString().Format(
L"Verify that `newTabProfile8` parses as NewTab(Index=8)"));
KeyChord kc{ false, true, true, static_cast<int32_t>('Y') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTabProfile8, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ProfileIndex());
VERIFY_ARE_EQUAL(8, realArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(8, realArgs.TerminalArgs().ProfileIndex().Value());
}

{
Log::Comment(NoThrowString().Format(
L"Verify that `copy` ignores args it doesn't understand"));
KeyChord kc{ true, false, true, static_cast<int32_t>('B') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -348,7 +318,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `copy` null as it's `args` parses as the default option"));
KeyChord kc{ true, false, true, static_cast<int32_t>('B') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -360,7 +330,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `increaseFontSize` without args parses as AdjustFontSize(Delta=1)"));
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::IncreaseFontSize, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -372,7 +342,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(
L"Verify that `decreaseFontSize` without args parses as AdjustFontSize(Delta=-1)"));
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::DecreaseFontSize, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand Down Expand Up @@ -403,7 +373,7 @@ namespace TerminalAppLocalTests

{
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitVertical, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -412,7 +382,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitHorizontal, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -421,7 +391,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -430,7 +400,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -439,7 +409,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -448,7 +418,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand All @@ -457,7 +427,7 @@ namespace TerminalAppLocalTests
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
auto actionAndArgs = GetActionAndArgs(*appKeyBindings, kc);
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
Expand Down
Loading