2020-06-26 22:38:02 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
2020-06-26 22:38:02 +02:00
|
|
|
#include "JsonTestClass.h"
|
|
|
|
#include "TestUtils.h"
|
|
|
|
|
|
|
|
using namespace Microsoft::Console;
|
2020-10-06 18:56:59 +02:00
|
|
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
2021-03-17 21:47:24 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal::Control;
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
using namespace winrt::Windows::Foundation::Collections;
|
2020-06-26 22:38:02 +02:00
|
|
|
using namespace WEX::Logging;
|
|
|
|
using namespace WEX::TestExecution;
|
|
|
|
using namespace WEX::Common;
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
namespace SettingsModelLocalTests
|
2020-06-26 22:38:02 +02:00
|
|
|
{
|
|
|
|
// TODO:microsoft/terminal#3838:
|
|
|
|
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
|
|
|
|
// an updated TAEF that will let us install framework packages when the test
|
|
|
|
// package is deployed. Until then, these tests won't deploy in CI.
|
|
|
|
|
|
|
|
class CommandTests : public JsonTestClass
|
|
|
|
{
|
|
|
|
// Use a custom AppxManifest to ensure that we can activate winrt types
|
|
|
|
// from our test. This property will tell taef to manually use this as
|
|
|
|
// the AppxManifest for this test class.
|
|
|
|
// This does not yet work for anything XAML-y. See TabTests.cpp for more
|
|
|
|
// details on that.
|
|
|
|
BEGIN_TEST_CLASS(CommandTests)
|
|
|
|
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
|
|
|
|
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
|
|
|
END_TEST_CLASS()
|
|
|
|
|
|
|
|
TEST_METHOD(ManyCommandsSameAction);
|
|
|
|
TEST_METHOD(LayerCommand);
|
|
|
|
TEST_METHOD(TestSplitPaneArgs);
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
TEST_METHOD(TestSplitPaneBadSize);
|
2020-06-26 22:38:02 +02:00
|
|
|
TEST_METHOD(TestResourceKeyName);
|
|
|
|
TEST_METHOD(TestAutogeneratedName);
|
|
|
|
TEST_METHOD(TestLayerOnAutogeneratedName);
|
|
|
|
|
2021-02-20 00:51:30 +01:00
|
|
|
TEST_METHOD(TestGenerateCommandline);
|
2020-06-26 22:38:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void CommandTests::ManyCommandsSameAction()
|
|
|
|
{
|
|
|
|
const std::string commands0String{ R"([ { "name":"action0", "command": "copy" } ])" };
|
|
|
|
const std::string commands1String{ R"([ { "name":"action1", "command": { "action": "copy", "singleLine": false } } ])" };
|
|
|
|
const std::string commands2String{ R"([
|
|
|
|
{ "name":"action2", "command": "paste" },
|
|
|
|
{ "name":"action3", "command": "paste" }
|
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
const auto commands1Json = VerifyParseSucceeded(commands1String);
|
|
|
|
const auto commands2Json = VerifyParseSucceeded(commands2String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
|
|
|
}
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
|
|
|
}
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(2u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
|
|
|
}
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(4u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CommandTests::LayerCommand()
|
|
|
|
{
|
|
|
|
// Each one of the commands in this test should layer upon the previous, overriding the action.
|
|
|
|
const std::string commands0String{ R"([ { "name":"action0", "command": "copy" } ])" };
|
|
|
|
const std::string commands1String{ R"([ { "name":"action0", "command": "paste" } ])" };
|
|
|
|
const std::string commands2String{ R"([ { "name":"action0", "command": "newTab" } ])" };
|
|
|
|
const std::string commands3String{ R"([ { "name":"action0", "command": null } ])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
const auto commands1Json = VerifyParseSucceeded(commands1String);
|
|
|
|
const auto commands2Json = VerifyParseSucceeded(commands2String);
|
|
|
|
const auto commands3Json = VerifyParseSucceeded(commands3String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
|
|
|
auto command = commands.Lookup(L"action0");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<CopyTextArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
|
|
|
auto command = commands.Lookup(L"action0");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::PasteText, command.ActionAndArgs().Action());
|
|
|
|
VERIFY_IS_NULL(command.ActionAndArgs().Args());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
|
|
|
auto command = commands.Lookup(L"action0");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewTabArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// This last command should "unbind" the action.
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands3Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CommandTests::TestSplitPaneArgs()
|
|
|
|
{
|
|
|
|
// This is the same as KeyBindingsTests::TestSplitPaneArgs, but with
|
|
|
|
// looking up the action and its args from a map of commands, instead
|
|
|
|
// of from keybindings.
|
|
|
|
|
|
|
|
const std::string commands0String{ R"([
|
|
|
|
{ "name": "command1", "command": { "action": "splitPane", "split": "vertical" } },
|
|
|
|
{ "name": "command2", "command": { "action": "splitPane", "split": "horizontal" } },
|
|
|
|
{ "name": "command4", "command": { "action": "splitPane" } },
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
{ "name": "command5", "command": { "action": "splitPane", "split": "auto" } },
|
|
|
|
{ "name": "command6", "command": { "action": "splitPane", "size": 0.25 } },
|
2021-09-15 22:14:57 +02:00
|
|
|
{ "name": "command7", "command": { "action": "splitPane", "split": "right" } },
|
|
|
|
{ "name": "command8", "command": { "action": "splitPane", "split": "left" } },
|
|
|
|
{ "name": "command9", "command": { "action": "splitPane", "split": "up" } },
|
|
|
|
{ "name": "command10", "command": { "action": "splitPane", "split": "down" } },
|
2020-06-26 22:38:02 +02:00
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(9u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"command1");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"command2");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"command4");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"command5");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command6");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.25, realArgs.SplitSize());
|
|
|
|
}
|
2021-09-15 22:14:57 +02:00
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command7");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command8");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Left, realArgs.SplitDirection());
|
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command9");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Up, realArgs.SplitDirection());
|
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command10");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
|
|
|
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
|
|
|
}
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CommandTests::TestSplitPaneBadSize()
|
|
|
|
{
|
|
|
|
const std::string commands0String{ R"([
|
|
|
|
{ "name": "command1", "command": { "action": "splitPane", "size": 0.25 } },
|
|
|
|
{ "name": "command2", "command": { "action": "splitPane", "size": 1.0 } },
|
|
|
|
{ "name": "command3", "command": { "action": "splitPane", "size": 0 } },
|
|
|
|
{ "name": "command4", "command": { "action": "splitPane", "size": 50 } },
|
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(3u, warnings.size());
|
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"command1");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
VERIFY_ARE_EQUAL(0.25, realArgs.SplitSize());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
}
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
|
2020-06-26 22:38:02 +02:00
|
|
|
void CommandTests::TestResourceKeyName()
|
|
|
|
{
|
|
|
|
// This test checks looking up a name from a resource key.
|
|
|
|
|
|
|
|
const std::string commands0String{ R"([ { "name": { "key": "DuplicateTabCommandKey"}, "command": "copy" } ])" };
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
{
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
// NOTE: We're relying on DuplicateTabCommandKey being defined as
|
|
|
|
// "Duplicate Tab" here. If that string changes in our resources,
|
|
|
|
// this test will break.
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"Duplicate tab");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<CopyTextArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CommandTests::TestAutogeneratedName()
|
|
|
|
{
|
|
|
|
// This test ensures that we'll correctly create commands for actions
|
|
|
|
// that don't have given names, pursuant to the spec in GH#6532.
|
|
|
|
|
|
|
|
// NOTE: The keys used to look up these commands are partially generated
|
|
|
|
// from strings in our Resources.resw. If those string values should
|
|
|
|
// change, it's likely that this test will break.
|
|
|
|
|
|
|
|
const std::string commands0String{ R"([
|
|
|
|
{ "command": { "action": "splitPane", "split": null } },
|
2021-09-15 22:14:57 +02:00
|
|
|
{ "command": { "action": "splitPane", "split": "left" } },
|
|
|
|
{ "command": { "action": "splitPane", "split": "right" } },
|
|
|
|
{ "command": { "action": "splitPane", "split": "up" } },
|
|
|
|
{ "command": { "action": "splitPane", "split": "down" } },
|
2020-06-26 22:38:02 +02:00
|
|
|
{ "command": { "action": "splitPane", "split": "none" } },
|
|
|
|
{ "command": { "action": "splitPane" } },
|
|
|
|
{ "command": { "action": "splitPane", "split": "auto" } },
|
|
|
|
{ "command": { "action": "splitPane", "split": "foo" } }
|
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
|
|
|
|
2021-09-15 22:14:57 +02:00
|
|
|
// There are only 5 commands here: all of the `"none"`, `"auto"`,
|
2020-06-26 22:38:02 +02:00
|
|
|
// `"foo"`, `null`, and <no args> bindings all generate the same action,
|
|
|
|
// which will generate just a single name for all of them.
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(5u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"Split pane");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"Split pane, split: left");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Left, realArgs.SplitDirection());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"Split pane, split: right");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
2021-09-15 22:14:57 +02:00
|
|
|
auto command = commands.Lookup(L"Split pane, split: up");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Up, realArgs.SplitDirection());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
{
|
2021-09-15 22:14:57 +02:00
|
|
|
auto command = commands.Lookup(L"Split pane, split: down");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void CommandTests::TestLayerOnAutogeneratedName()
|
|
|
|
{
|
|
|
|
const std::string commands0String{ R"([
|
|
|
|
{ "command": { "action": "splitPane" } },
|
|
|
|
{ "name":"Split pane", "command": { "action": "splitPane", "split": "vertical" } },
|
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
VERIFY_ARE_EQUAL(1u, commands.Size());
|
2020-06-26 22:38:02 +02:00
|
|
|
|
|
|
|
{
|
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request
This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)
* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)
The above gif uses the following json:
```json
{
"name": "Split Pane...",
"commands": [
{
"iterateOn": "profiles",
"name": "Split with ${profile.name}...",
"commands": [
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
]
}
]
},
```
## References
## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.
## Detailed Description of the Pull Request / Additional comments
We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it.
We've also got to parse commands recursively, because they might have any number of child commands.
These together made the command parsing a _lot_ more complicated, but it feels good so far.
## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 23:22:46 +02:00
|
|
|
auto command = commands.Lookup(L"Split pane");
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
2020-06-26 22:38:02 +02:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
// Verify the args have the expected value
|
2021-09-15 22:14:57 +02:00
|
|
|
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-20 00:51:30 +01:00
|
|
|
|
|
|
|
void CommandTests::TestGenerateCommandline()
|
|
|
|
{
|
|
|
|
const WEX::TestExecution::DisableVerifyExceptions disableExceptionsScope;
|
|
|
|
|
|
|
|
const std::string commands0String{ R"([
|
|
|
|
{
|
|
|
|
"name":"action0",
|
|
|
|
"command": { "action": "newWindow" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action1",
|
|
|
|
"command": { "action": "newTab", "profile": "foo" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action2",
|
|
|
|
"command": { "action": "newWindow", "profile": "foo" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action3",
|
|
|
|
"command": { "action": "newWindow", "commandline": "bar.exe" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action4",
|
|
|
|
"command": { "action": "newWindow", "commandline": "pop.exe ya ha ha" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action5",
|
|
|
|
"command": { "action": "newWindow", "commandline": "pop.exe \"ya ha ha\"" }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name":"action6",
|
|
|
|
"command": { "action": "newWindow", "startingDirectory":"C:\\foo", "commandline": "bar.exe" }
|
|
|
|
},
|
2021-08-03 20:16:07 +02:00
|
|
|
{
|
|
|
|
"name":"action7_startingDirectoryWithTrailingSlash",
|
|
|
|
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
|
|
|
|
},
|
2021-09-24 18:17:16 +02:00
|
|
|
{
|
|
|
|
"name":"action8_tabTitleEscaping",
|
|
|
|
"command": { "action": "newWindow", "tabTitle":"\\\";foo\\" }
|
|
|
|
}
|
2021-02-20 00:51:30 +01:00
|
|
|
])" };
|
|
|
|
|
|
|
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
|
|
|
|
|
|
|
IMap<winrt::hstring, Command> commands = winrt::single_threaded_map<winrt::hstring, Command>();
|
|
|
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
|
|
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
|
|
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
2021-09-24 18:17:16 +02:00
|
|
|
VERIFY_ARE_EQUAL(9u, commands.Size());
|
2021-02-20 00:51:30 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action0");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
VERIFY_ARE_EQUAL(L"", cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action1");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewTabArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
VERIFY_ARE_EQUAL(L"--profile \"foo\"", cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action2");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
VERIFY_ARE_EQUAL(L"--profile \"foo\"", cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action3");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
VERIFY_ARE_EQUAL(L"-- \"bar.exe\"", cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action4");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
Log::Comment(NoThrowString().Format(
|
|
|
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
|
|
|
VERIFY_ARE_EQUAL(L"-- \"pop.exe ya ha ha\"", terminalArgs.ToCommandline());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action5");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
Log::Comment(NoThrowString().Format(
|
|
|
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
|
|
|
VERIFY_ARE_EQUAL(L"-- \"pop.exe \"ya ha ha\"\"", terminalArgs.ToCommandline());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action6");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
2021-02-20 00:51:30 +01:00
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
Log::Comment(NoThrowString().Format(
|
|
|
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
|
|
|
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\foo\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
|
|
|
}
|
2021-08-03 20:16:07 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action7_startingDirectoryWithTrailingSlash");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
Log::Comment(NoThrowString().Format(
|
|
|
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
|
|
|
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
|
|
|
}
|
2021-09-24 18:17:16 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
auto command = commands.Lookup(L"action8_tabTitleEscaping");
|
|
|
|
VERIFY_IS_NOT_NULL(command);
|
|
|
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
|
|
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
|
|
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
|
|
|
VERIFY_IS_NOT_NULL(realArgs);
|
|
|
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
|
|
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
|
|
|
auto cmdline = terminalArgs.ToCommandline();
|
|
|
|
Log::Comment(NoThrowString().Format(
|
|
|
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
|
|
|
VERIFY_ARE_EQUAL(LR"-(--title "\\\"\;foo\\")-", terminalArgs.ToCommandline());
|
|
|
|
}
|
2021-02-20 00:51:30 +01:00
|
|
|
}
|
2020-06-26 22:38:02 +02:00
|
|
|
}
|