Add action to run multiple actions. (#11045)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Add a new action that can contain multiple other actions. <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #3992 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [x] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Creates a shortcut action that allows a list of actions to be specified as arguments. Steals a bunch of the serialization code from my other pr. Overall, because I had the serialization code written already, this was remarkably easy. I can't think of any combined action to be added to the defaults, so I think this is just a thing for the documentation unless someone else has a good example. I know there are lot of times when the recommended workaround is "make an action with commandline wt.exe ..." and this could be a good replacement for that, but that is all personalized. I didn't add this to the command line parsing, since the command line is already a way to run multiple actions. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Created a new command, confirmed that "Move right->down" showed up in the command palette, and that running it did the correct behavior (moving right one pane, then down one pane). ``` { "command": { "action": "multipleActions", "name": "Move right->down", "actions": [ {"action": "moveFocus", "direction": "right" }, {"action": "moveFocus", "direction": "down" }, ] } } ```
This commit is contained in:
parent
717ea85c9f
commit
8d81497eb7
|
@ -268,6 +268,7 @@
|
|||
"movePane",
|
||||
"swapPane",
|
||||
"moveTab",
|
||||
"multipleActions",
|
||||
"newTab",
|
||||
"newWindow",
|
||||
"nextTab",
|
||||
|
@ -825,6 +826,24 @@
|
|||
],
|
||||
"required": [ "direction" ]
|
||||
},
|
||||
"MultipleActionsAction": {
|
||||
"description": "Arguments for the multiple actions command",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "multipleActions" },
|
||||
"actions" : {
|
||||
"$ref": "#/definitions/ShortcutAction",
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "A list of other actions."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "actions" ]
|
||||
},
|
||||
"CommandPaletteAction": {
|
||||
"description": "Arguments for a commandPalette action",
|
||||
"allOf": [
|
||||
|
|
|
@ -874,4 +874,21 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleMultipleActions(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<MultipleActionsArgs>())
|
||||
{
|
||||
for (const auto& action : realArgs.Actions())
|
||||
{
|
||||
_actionDispatch->DoAction(action);
|
||||
}
|
||||
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ static constexpr std::string_view OpenWindowRenamerKey{ "openWindowRenamer" };
|
|||
static constexpr std::string_view GlobalSummonKey{ "globalSummon" };
|
||||
static constexpr std::string_view QuakeModeKey{ "quakeMode" };
|
||||
static constexpr std::string_view FocusPaneKey{ "focusPane" };
|
||||
static constexpr std::string_view MultipleActionsKey{ "multipleActions" };
|
||||
|
||||
static constexpr std::string_view ActionKey{ "action" };
|
||||
|
||||
|
@ -366,6 +367,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
{ ShortcutAction::GlobalSummon, L"" }, // Intentionally omitted, must be generated by GenerateName
|
||||
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
|
||||
{ ShortcutAction::FocusPane, L"" }, // Intentionally omitted, must be generated by GenerateName
|
||||
{ ShortcutAction::MultipleActions, L"" }, // Intentionally omitted, must be generated by GenerateName
|
||||
};
|
||||
}();
|
||||
|
||||
|
|
|
@ -35,3 +35,34 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
|||
{
|
||||
BASIC_FACTORY(ActionAndArgs);
|
||||
}
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
||||
{
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
template<>
|
||||
struct ConversionTrait<ActionAndArgs>
|
||||
{
|
||||
ActionAndArgs FromJson(const Json::Value& json)
|
||||
{
|
||||
std::vector<SettingsLoadWarnings> v;
|
||||
return *implementation::ActionAndArgs::FromJson(json, v);
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
// commands without args might just be a string
|
||||
return json.isString() || json.isObject();
|
||||
}
|
||||
|
||||
Json::Value ToJson(const ActionAndArgs& val)
|
||||
{
|
||||
return implementation::ActionAndArgs::ToJson(val);
|
||||
}
|
||||
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return "ActionAndArgs";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "RenameWindowArgs.g.cpp"
|
||||
#include "GlobalSummonArgs.g.cpp"
|
||||
#include "FocusPaneArgs.g.cpp"
|
||||
#include "MultipleActionsArgs.g.cpp"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
|
||||
|
@ -687,4 +688,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
Id())
|
||||
};
|
||||
}
|
||||
|
||||
winrt::hstring MultipleActionsArgs::GenerateName() const
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "RenameWindowArgs.g.h"
|
||||
#include "GlobalSummonArgs.g.h"
|
||||
#include "FocusPaneArgs.g.h"
|
||||
#include "MultipleActionsArgs.g.h"
|
||||
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
#include "JsonUtils.h"
|
||||
|
@ -1754,6 +1755,53 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
};
|
||||
|
||||
struct MultipleActionsArgs : public MultipleActionsArgsT<MultipleActionsArgs>
|
||||
{
|
||||
MultipleActionsArgs() = default;
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<ActionAndArgs>, Actions);
|
||||
static constexpr std::string_view ActionsKey{ "actions" };
|
||||
|
||||
public:
|
||||
hstring GenerateName() const;
|
||||
|
||||
bool Equals(const IActionArgs& other)
|
||||
{
|
||||
auto otherAsUs = other.try_as<MultipleActionsArgs>();
|
||||
if (otherAsUs)
|
||||
{
|
||||
return otherAsUs->_Actions == _Actions;
|
||||
}
|
||||
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<MultipleActionsArgs>();
|
||||
JsonUtils::GetValueForKey(json, ActionsKey, args->_Actions);
|
||||
return { *args, {} };
|
||||
}
|
||||
static Json::Value ToJson(const IActionArgs& val)
|
||||
{
|
||||
if (!val)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
Json::Value json{ Json::ValueType::objectValue };
|
||||
const auto args{ get_self<MultipleActionsArgs>(val) };
|
||||
JsonUtils::SetValueForKey(json, ActionsKey, args->_Actions);
|
||||
return json;
|
||||
}
|
||||
IActionArgs Copy() const
|
||||
{
|
||||
auto copy{ winrt::make_self<MultipleActionsArgs>() };
|
||||
copy->_Actions = _Actions;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Actions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
|
@ -1778,4 +1826,5 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
|||
BASIC_FACTORY(FocusPaneArgs);
|
||||
BASIC_FACTORY(PrevTabArgs);
|
||||
BASIC_FACTORY(NextTabArgs);
|
||||
BASIC_FACTORY(MultipleActionsArgs);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "Command.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
interface IActionArgs
|
||||
|
@ -308,4 +310,10 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
FocusPaneArgs(UInt32 Id);
|
||||
UInt32 Id { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass MultipleActionsArgs : IActionArgs
|
||||
{
|
||||
MultipleActionsArgs();
|
||||
Windows.Foundation.Collections.IVector<ActionAndArgs> Actions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,8 @@
|
|||
ON_ALL_ACTIONS(OpenWindowRenamer) \
|
||||
ON_ALL_ACTIONS(GlobalSummon) \
|
||||
ON_ALL_ACTIONS(QuakeMode) \
|
||||
ON_ALL_ACTIONS(FocusPane)
|
||||
ON_ALL_ACTIONS(FocusPane) \
|
||||
ON_ALL_ACTIONS(MultipleActions)
|
||||
|
||||
#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \
|
||||
|
@ -109,4 +110,5 @@
|
|||
ON_ALL_ACTIONS_WITH_ARGS(SplitPane) \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(SwitchToTab) \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(ToggleCommandPalette) \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(FocusPane)
|
||||
ON_ALL_ACTIONS_WITH_ARGS(FocusPane) \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(MultipleActions)
|
||||
|
|
|
@ -55,48 +55,6 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
return fmt::format("{}[]", ConversionTrait<GUID>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<winrt::Windows::Foundation::Collections::IVector<T>>
|
||||
{
|
||||
winrt::Windows::Foundation::Collections::IVector<T> FromJson(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
std::vector<T> val;
|
||||
val.reserve(json.size());
|
||||
|
||||
for (const auto& element : json)
|
||||
{
|
||||
val.push_back(trait.FromJson(element));
|
||||
}
|
||||
|
||||
return winrt::single_threaded_vector(move(val));
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) -> bool { return trait.CanConvert(json); });
|
||||
}
|
||||
|
||||
Json::Value ToJson(const winrt::Windows::Foundation::Collections::IVector<T>& val)
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
Json::Value json{ Json::arrayValue };
|
||||
|
||||
for (const auto& key : val)
|
||||
{
|
||||
json.append(trait.ToJson(key));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return fmt::format("vector ({})", ConversionTrait<T>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
|
|
|
@ -177,6 +177,47 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<std::vector<T>>
|
||||
{
|
||||
std::vector<T> FromJson(const Json::Value& json)
|
||||
{
|
||||
std::vector<T> val;
|
||||
val.reserve(json.size());
|
||||
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& element : json)
|
||||
{
|
||||
val.push_back(trait.FromJson(element));
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) mutable -> bool { return trait.CanConvert(json); });
|
||||
}
|
||||
|
||||
Json::Value ToJson(const std::vector<T>& val)
|
||||
{
|
||||
Json::Value json{ Json::arrayValue };
|
||||
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& v : val)
|
||||
{
|
||||
json.append(trait.ToJson(v));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return fmt::format("{}[]", ConversionTrait<T>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<std::unordered_map<std::string, T>>
|
||||
{
|
||||
|
@ -259,6 +300,42 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<winrt::Windows::Foundation::Collections::IVector<T>>
|
||||
{
|
||||
winrt::Windows::Foundation::Collections::IVector<T> FromJson(const Json::Value& json)
|
||||
{
|
||||
ConversionTrait<std::vector<T>> trait;
|
||||
return winrt::single_threaded_vector<T>(std::move(trait.FromJson(json)));
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<std::vector<T>> trait;
|
||||
return trait.CanConvert(json);
|
||||
}
|
||||
|
||||
Json::Value ToJson(const winrt::Windows::Foundation::Collections::IVector<T>& val)
|
||||
{
|
||||
Json::Value json{ Json::arrayValue };
|
||||
|
||||
if (val)
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& v : val)
|
||||
{
|
||||
json.append(trait.ToJson(v));
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return fmt::format("{}[]", ConversionTrait<T>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<winrt::Windows::Foundation::Collections::IMap<winrt::hstring, T>>
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue