2020-10-06 18:56:59 +02:00
|
|
|
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Licensed under the MIT license.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
- Command.h
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
- A command represents a single entry in the Command Palette. This is an object
|
|
|
|
that has a user facing "name" to display to the user, and an associated action
|
|
|
|
which can be dispatched.
|
|
|
|
|
|
|
|
- For more information, see GH#2046, #5400, #5674, and #6635
|
|
|
|
|
|
|
|
Author(s):
|
|
|
|
- Mike Griese - June 2020
|
|
|
|
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Command.g.h"
|
|
|
|
#include "TerminalWarnings.h"
|
|
|
|
#include "Profile.h"
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
#include "ActionAndArgs.h"
|
2020-11-25 22:02:10 +01:00
|
|
|
#include "../inc/cppwinrt_utils.h"
|
2020-10-06 18:56:59 +02:00
|
|
|
#include "SettingsTypes.h"
|
|
|
|
|
|
|
|
// fwdecl unittest classes
|
|
|
|
namespace SettingsModelLocalTests
|
|
|
|
{
|
|
|
|
class DeserializationTests;
|
|
|
|
class CommandTests;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|
|
|
{
|
|
|
|
struct Command : CommandT<Command>
|
|
|
|
{
|
|
|
|
Command();
|
2020-10-17 00:14:11 +02:00
|
|
|
com_ptr<Command> Copy() const;
|
2020-10-06 18:56:59 +02:00
|
|
|
|
|
|
|
static winrt::com_ptr<Command> FromJson(const Json::Value& json,
|
|
|
|
std::vector<SettingsLoadWarnings>& warnings);
|
|
|
|
|
|
|
|
static void ExpandCommands(Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command> commands,
|
|
|
|
Windows::Foundation::Collections::IVectorView<Model::Profile> profiles,
|
|
|
|
Windows::Foundation::Collections::IVectorView<Model::ColorScheme> schemes,
|
|
|
|
Windows::Foundation::Collections::IVector<SettingsLoadWarnings> warnings);
|
|
|
|
|
|
|
|
static std::vector<SettingsLoadWarnings> LayerJson(Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command>& commands,
|
|
|
|
const Json::Value& json);
|
2021-05-20 20:44:04 +02:00
|
|
|
Json::Value ToJson() const;
|
|
|
|
|
2020-10-17 00:14:11 +02:00
|
|
|
bool HasNestedCommands() const;
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
bool IsNestedCommand() const noexcept;
|
2020-10-17 00:14:11 +02:00
|
|
|
Windows::Foundation::Collections::IMapView<winrt::hstring, Model::Command> NestedCommands() const;
|
2020-10-06 18:56:59 +02:00
|
|
|
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
bool HasName() const noexcept;
|
|
|
|
hstring Name() const noexcept;
|
|
|
|
void Name(const hstring& name);
|
|
|
|
|
|
|
|
Control::KeyChord Keys() const noexcept;
|
|
|
|
hstring KeyChordText() const noexcept;
|
|
|
|
std::vector<Control::KeyChord> KeyMappings() const noexcept;
|
|
|
|
void RegisterKey(const Control::KeyChord& keys);
|
|
|
|
void EraseKey(const Control::KeyChord& keys);
|
|
|
|
|
|
|
|
hstring IconPath() const noexcept;
|
|
|
|
void IconPath(const hstring& val);
|
|
|
|
|
2020-10-06 18:56:59 +02:00
|
|
|
winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker propertyChangedRevoker;
|
|
|
|
|
|
|
|
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
2021-03-04 20:27:03 +01:00
|
|
|
WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None);
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs);
|
2020-10-06 18:56:59 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
Json::Value _originalJson;
|
|
|
|
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command> _subcommands{ nullptr };
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
std::vector<Control::KeyChord> _keyMappings;
|
|
|
|
std::optional<std::wstring> _name;
|
|
|
|
std::optional<std::wstring> _iconPath;
|
|
|
|
bool _nestedCommand{ false };
|
2020-10-06 18:56:59 +02:00
|
|
|
|
|
|
|
static std::vector<Model::Command> _expandCommand(Command* const expandable,
|
|
|
|
Windows::Foundation::Collections::IVectorView<Model::Profile> profiles,
|
|
|
|
Windows::Foundation::Collections::IVectorView<Model::ColorScheme> schemes,
|
|
|
|
Windows::Foundation::Collections::IVector<SettingsLoadWarnings>& warnings);
|
|
|
|
friend class SettingsModelLocalTests::DeserializationTests;
|
|
|
|
friend class SettingsModelLocalTests::CommandTests;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
|
|
|
{
|
|
|
|
BASIC_FACTORY(Command);
|
|
|
|
}
|