terminal/src/cascadia/TerminalApp/ActionArgs.h

557 lines
20 KiB
C
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
// HEY YOU: When adding ActionArgs types, make sure to add the corresponding
// *.g.cpp to ActionArgs.cpp!
#include "ActionEventArgs.g.h"
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
#include "NewTerminalArgs.g.h"
#include "CopyTextArgs.g.h"
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
#include "NewTabArgs.g.h"
#include "SwitchToTabArgs.g.h"
#include "ResizePaneArgs.g.h"
#include "MoveFocusArgs.g.h"
#include "AdjustFontSizeArgs.g.h"
#include "SendInputArgs.g.h"
#include "SplitPaneArgs.g.h"
#include "OpenSettingsArgs.g.h"
#include "SetColorSchemeArgs.g.h"
#include "SetTabColorArgs.g.h"
#include "RenameTabArgs.g.h"
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537) ## Summary of the Pull Request Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_. ## References * Related to #4472 * Related to #5400 - I need this for the commandline mode of the Command Palette * Related to #5970 ## PR Checklist * [x] Closes oh, there's not actually an issue for this. * [x] I work here * [x] Tests added/passed * [ ] Requires documentation to be updated - yes it does ## Detailed Description of the Pull Request / Additional comments One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again. We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up. This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out. This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized. ## Validation Steps Performed This was what the json blob I was using for testing evolved into ```json { "command": { "action":"wt", "commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0", }, "keys": ["ctrl+shift+n"] } ``` I also added some tests. # TODO * [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process? - Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
#include "ExecuteCommandlineArgs.g.h"
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
#include "CloseOtherTabsArgs.g.h"
#include "CloseTabsAfterArgs.g.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
#include "Utils.h"
#include "JsonUtils.h"
#include "TerminalWarnings.h"
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
#include "TerminalSettingsSerializationHelpers.h"
// Notes on defining ActionArgs and ActionEventArgs:
// * All properties specific to an action should be defined as an ActionArgs
// class that implements IActionArgs
// * ActionEventArgs holds a single IActionArgs. For events that don't need
// additional args, this can be nullptr.
namespace winrt::TerminalApp::implementation
{
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
using namespace ::TerminalApp;
using FromJsonResult = std::tuple<winrt::TerminalApp::IActionArgs, std::vector<TerminalApp::SettingsLoadWarnings>>;
struct ActionEventArgs : public ActionEventArgsT<ActionEventArgs>
{
ActionEventArgs() = default;
explicit ActionEventArgs(const TerminalApp::IActionArgs& args) :
_ActionArgs{ args } {};
GETSET_PROPERTY(IActionArgs, ActionArgs, nullptr);
GETSET_PROPERTY(bool, Handled, false);
};
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
struct NewTerminalArgs : public NewTerminalArgsT<NewTerminalArgs>
{
NewTerminalArgs() = default;
GETSET_PROPERTY(winrt::hstring, Commandline, L"");
GETSET_PROPERTY(winrt::hstring, StartingDirectory, L"");
GETSET_PROPERTY(winrt::hstring, TabTitle, L"");
GETSET_PROPERTY(Windows::Foundation::IReference<int32_t>, ProfileIndex, nullptr);
GETSET_PROPERTY(winrt::hstring, Profile, L"");
static constexpr std::string_view CommandlineKey{ "commandline" };
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
static constexpr std::string_view TabTitleKey{ "tabTitle" };
static constexpr std::string_view ProfileIndexKey{ "index" };
static constexpr std::string_view ProfileKey{ "profile" };
public:
hstring GenerateName() const;
bool Equals(const winrt::TerminalApp::NewTerminalArgs& other)
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
{
return other.Commandline() == _Commandline &&
other.StartingDirectory() == _StartingDirectory &&
other.TabTitle() == _TabTitle &&
other.ProfileIndex() == _ProfileIndex &&
other.Profile() == _Profile;
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
};
static winrt::TerminalApp::NewTerminalArgs FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<NewTerminalArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, CommandlineKey, args->_Commandline);
JsonUtils::GetValueForKey(json, StartingDirectoryKey, args->_StartingDirectory);
JsonUtils::GetValueForKey(json, TabTitleKey, args->_TabTitle);
JsonUtils::GetValueForKey(json, ProfileIndexKey, args->_ProfileIndex);
JsonUtils::GetValueForKey(json, ProfileKey, args->_Profile);
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
return *args;
}
};
struct CopyTextArgs : public CopyTextArgsT<CopyTextArgs>
{
CopyTextArgs() = default;
GETSET_PROPERTY(bool, SingleLine, false);
GETSET_PROPERTY(Windows::Foundation::IReference<Microsoft::Terminal::TerminalControl::CopyFormat>, CopyFormatting, nullptr);
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
static constexpr std::string_view SingleLineKey{ "singleLine" };
static constexpr std::string_view CopyFormattingKey{ "copyFormatting" };
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<CopyTextArgs>();
if (otherAsUs)
{
return otherAsUs->_SingleLine == _SingleLine &&
otherAsUs->_CopyFormatting == _CopyFormatting;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<CopyTextArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, SingleLineKey, args->_SingleLine);
JsonUtils::GetValueForKey(json, CopyFormattingKey, args->_CopyFormatting);
return { *args, {} };
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
}
};
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
struct NewTabArgs : public NewTabArgsT<NewTabArgs>
{
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
NewTabArgs() = default;
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<NewTabArgs>();
if (otherAsUs)
{
return otherAsUs->_TerminalArgs.Equals(_TerminalArgs);
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<NewTabArgs>();
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
args->_TerminalArgs = NewTerminalArgs::FromJson(json);
return { *args, {} };
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
}
};
struct SwitchToTabArgs : public SwitchToTabArgsT<SwitchToTabArgs>
{
SwitchToTabArgs() = default;
GETSET_PROPERTY(uint32_t, TabIndex, 0);
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
static constexpr std::string_view TabIndexKey{ "index" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<SwitchToTabArgs>();
if (otherAsUs)
{
return otherAsUs->_TabIndex == _TabIndex;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SwitchToTabArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, TabIndexKey, args->_TabIndex);
return { *args, {} };
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
}
};
struct ResizePaneArgs : public ResizePaneArgsT<ResizePaneArgs>
{
ResizePaneArgs() = default;
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None);
static constexpr std::string_view DirectionKey{ "direction" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<ResizePaneArgs>();
if (otherAsUs)
{
return otherAsUs->_Direction == _Direction;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<ResizePaneArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, DirectionKey, args->_Direction);
if (args->_Direction == TerminalApp::Direction::None)
{
return { nullptr, { TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
else
{
return { *args, {} };
}
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
}
};
struct MoveFocusArgs : public MoveFocusArgsT<MoveFocusArgs>
{
MoveFocusArgs() = default;
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None);
static constexpr std::string_view DirectionKey{ "direction" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<MoveFocusArgs>();
if (otherAsUs)
{
return otherAsUs->_Direction == _Direction;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<MoveFocusArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, DirectionKey, args->_Direction);
if (args->_Direction == TerminalApp::Direction::None)
{
return { nullptr, { TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
else
{
return { *args, {} };
}
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
}
};
struct AdjustFontSizeArgs : public AdjustFontSizeArgsT<AdjustFontSizeArgs>
{
AdjustFontSizeArgs() = default;
GETSET_PROPERTY(int32_t, Delta, 0);
static constexpr std::string_view AdjustFontSizeDelta{ "delta" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<AdjustFontSizeArgs>();
if (otherAsUs)
{
return otherAsUs->_Delta == _Delta;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<AdjustFontSizeArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, AdjustFontSizeDelta, args->_Delta);
return { *args, {} };
}
};
struct SendInputArgs : public SendInputArgsT<SendInputArgs>
{
SendInputArgs() = default;
GETSET_PROPERTY(winrt::hstring, Input, L"");
static constexpr std::string_view InputKey{ "input" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
if (auto otherAsUs = other.try_as<SendInputArgs>(); otherAsUs)
{
return otherAsUs->_Input == _Input;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SendInputArgs>();
JsonUtils::GetValueForKey(json, InputKey, args->_Input);
if (args->_Input.empty())
{
return { nullptr, { TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
return { *args, {} };
}
};
struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
{
SplitPaneArgs() = default;
GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic);
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual);
static constexpr std::string_view SplitKey{ "split" };
static constexpr std::string_view SplitModeKey{ "splitMode" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<SplitPaneArgs>();
if (otherAsUs)
{
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
return otherAsUs->_SplitStyle == _SplitStyle &&
(otherAsUs->_TerminalArgs ? otherAsUs->_TerminalArgs.Equals(_TerminalArgs) :
otherAsUs->_TerminalArgs == _TerminalArgs) &&
otherAsUs->_SplitMode == _SplitMode;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SplitPaneArgs>();
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
args->_TerminalArgs = NewTerminalArgs::FromJson(json);
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, SplitKey, args->_SplitStyle);
JsonUtils::GetValueForKey(json, SplitModeKey, args->_SplitMode);
return { *args, {} };
}
};
struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
{
OpenSettingsArgs() = default;
GETSET_PROPERTY(TerminalApp::SettingsTarget, Target, TerminalApp::SettingsTarget::SettingsFile);
static constexpr std::string_view TargetKey{ "target" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<OpenSettingsArgs>();
if (otherAsUs)
{
return otherAsUs->_Target == _Target;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<OpenSettingsArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, TargetKey, args->_Target);
return { *args, {} };
}
};
struct SetColorSchemeArgs : public SetColorSchemeArgsT<SetColorSchemeArgs>
{
SetColorSchemeArgs() = default;
GETSET_PROPERTY(winrt::hstring, SchemeName, L"");
static constexpr std::string_view NameKey{ "colorScheme" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<SetColorSchemeArgs>();
if (otherAsUs)
{
return otherAsUs->_SchemeName == _SchemeName;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SetColorSchemeArgs>();
JsonUtils::GetValueForKey(json, NameKey, args->_SchemeName);
if (args->_SchemeName.empty())
{
return { nullptr, { TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
return { *args, {} };
}
};
struct SetTabColorArgs : public SetTabColorArgsT<SetTabColorArgs>
{
SetTabColorArgs() = default;
GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, TabColor, nullptr);
static constexpr std::string_view ColorKey{ "color" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<SetTabColorArgs>();
if (otherAsUs)
{
return otherAsUs->_TabColor == _TabColor;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SetTabColorArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
if (const auto temp{ JsonUtils::GetValueForKey<std::optional<til::color>>(json, ColorKey) })
{
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
args->_TabColor = static_cast<uint32_t>(*temp);
}
return { *args, {} };
}
};
struct RenameTabArgs : public RenameTabArgsT<RenameTabArgs>
{
RenameTabArgs() = default;
GETSET_PROPERTY(winrt::hstring, Title, L"");
static constexpr std::string_view TitleKey{ "title" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<RenameTabArgs>();
if (otherAsUs)
{
return otherAsUs->_Title == _Title;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<RenameTabArgs>();
Convert most of our JSON deserializers to use type-based conversion (#6590) This pull request converts the following JSON deserializers to use the new JSON deserializer pattern: * Profile * Command * ColorScheme * Action/Args * GlobalSettings * CascadiaSettingsSerialization This is the completion of a long-term JSON refactoring that makes our parser and deserializer more type-safe and robust. We're finally able to get rid of all our manual enum conversion code and unify JSON conversion around _types_ instead of around _keys_. I've introduced another file filled with template specializations, TerminalSettingsSerializationHelpers.h, which comprises a single unit that holds all of the JSON deserializers (and eventually serializers) for every type that comes from TerminalApp or TerminalSettings. I've also moved some types out of Profile and GlobalAppSettings into a new SettingsTypes.h to improve settings locality. This does to some extent constitute a breaking change for already-broken settings. Instead of parsing "successfully" (where invalid values are null or 0 or unknown or unset), deserialization will now fail when there's a type mismatch. Because of that, some tests had to be removed. While I was on a refactoring spree, I removed a number of helpless helpers, like GetWstringFromJson (which converted a u8 string to an hstring to make a wstring out of its data pointer :|) and _ConvertJsonToBool. In the future, we can make the error types more robust and give them position and type information such that a conformant application can display rich error information ("line 3 column 3, I expected a string, you gave me an integer"). Closes #2550.
2020-07-17 03:31:09 +02:00
JsonUtils::GetValueForKey(json, TitleKey, args->_Title);
return { *args, {} };
}
};
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537) ## Summary of the Pull Request Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_. ## References * Related to #4472 * Related to #5400 - I need this for the commandline mode of the Command Palette * Related to #5970 ## PR Checklist * [x] Closes oh, there's not actually an issue for this. * [x] I work here * [x] Tests added/passed * [ ] Requires documentation to be updated - yes it does ## Detailed Description of the Pull Request / Additional comments One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again. We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up. This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out. This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized. ## Validation Steps Performed This was what the json blob I was using for testing evolved into ```json { "command": { "action":"wt", "commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0", }, "keys": ["ctrl+shift+n"] } ``` I also added some tests. # TODO * [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process? - Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
struct ExecuteCommandlineArgs : public ExecuteCommandlineArgsT<ExecuteCommandlineArgs>
{
ExecuteCommandlineArgs() = default;
GETSET_PROPERTY(winrt::hstring, Commandline, L"");
static constexpr std::string_view CommandlineKey{ "commandline" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<ExecuteCommandlineArgs>();
if (otherAsUs)
{
return otherAsUs->_Commandline == _Commandline;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<ExecuteCommandlineArgs>();
JsonUtils::GetValueForKey(json, CommandlineKey, args->_Commandline);
if (args->_Commandline.empty())
{
return { nullptr, { TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537) ## Summary of the Pull Request Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_. ## References * Related to #4472 * Related to #5400 - I need this for the commandline mode of the Command Palette * Related to #5970 ## PR Checklist * [x] Closes oh, there's not actually an issue for this. * [x] I work here * [x] Tests added/passed * [ ] Requires documentation to be updated - yes it does ## Detailed Description of the Pull Request / Additional comments One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again. We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up. This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out. This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized. ## Validation Steps Performed This was what the json blob I was using for testing evolved into ```json { "command": { "action":"wt", "commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0", }, "keys": ["ctrl+shift+n"] } ``` I also added some tests. # TODO * [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process? - Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
}
return { *args, {} };
}
};
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
struct CloseOtherTabsArgs : public CloseOtherTabsArgsT<CloseOtherTabsArgs>
{
CloseOtherTabsArgs() = default;
GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, Index, nullptr);
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
static constexpr std::string_view IndexKey{ "index" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<CloseOtherTabsArgs>();
if (otherAsUs)
{
return otherAsUs->_Index == _Index;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<CloseOtherTabsArgs>();
JsonUtils::GetValueForKey(json, IndexKey, args->_Index);
return { *args, {} };
}
};
struct CloseTabsAfterArgs : public CloseTabsAfterArgsT<CloseTabsAfterArgs>
{
CloseTabsAfterArgs() = default;
GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, Index, nullptr);
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
static constexpr std::string_view IndexKey{ "index" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<CloseTabsAfterArgs>();
if (otherAsUs)
{
return otherAsUs->_Index == _Index;
}
return false;
};
static FromJsonResult FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<CloseTabsAfterArgs>();
JsonUtils::GetValueForKey(json, IndexKey, args->_Index);
return { *args, {} };
}
};
}
namespace winrt::TerminalApp::factory_implementation
{
BASIC_FACTORY(ActionEventArgs);
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
BASIC_FACTORY(NewTerminalArgs);
}