-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Add reflection to the ActionArgs in the settings model #18915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
static Windows.Foundation.Collections.IMap<Microsoft.Terminal.Settings.Model.ShortcutAction, String> AvailableShortcutActionsAndNames { get; }; | ||
static IActionArgs GetEmptyArgsForAction(Microsoft.Terminal.Settings.Model.ShortcutAction shortcutAction); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ActionMap
already contains:
Windows.Foundation.Collections.IMapView<String, ActionAndArgs> AvailableActions { get; };
I feel like these make more sense to be over there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would swing hard in the other direction actually.
Since they're static, they don't need to be on an existing class at all.
We could put them on a new static class. That way nobody has to instantiate one OR know about CascadiaSettings to do it.
static runtimeclass ActionArgFactory {
static ...;
}
_ActionMap.erase(oldID); | ||
_ActionMap.emplace(newID, senderCmd); | ||
|
||
// update _KeyMap so that all keys that pointed to the old ID now point to the new ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably do the same thing for action IDs in the new tab menu (not accessible via ActionMap, but it's something we'll need).
_##name{ name##Param }, | ||
|
||
// append this argument's description to the internal vector | ||
#define APPEND_ARG_DESCRIPTION(type, name, jsonKey, required, tag, ...) \ | ||
_argDescriptions.push_back({ L## #name, L## #type, std::wstring_view(L## #required) != L"false", tag }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::wstring_view(L## #required) != L"false"
wait... why are we converting/comparing required
as a string? It looks like it's already a bool in the other macros. Can't we just pass the bool directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's because the term required
in these macros is a little misleading - it's not an actual bool, it's a validation check. For example, the ResizeDirection
arg has the required
parameter as args->ResizeDirection() == ResizeDirection::None
, which checks the current actual value of the arg, it's not a general "this arg is required" bool.
Tbh we should probably find a way at some point to transfer over the actual validation check in the ArgDescription
so the Settings Editor can use it and display correct error messaging, but for now I think it makes sense to just go with this
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr); | ||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, can we keep it as nullptr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I am leaving the "allow editing different new content types (like creating a snippets pane or a markdown pane etc)" as a future todo, so for that reason we need to initialize this as a NewTerminalArgs
here but it shouldn't change anything functionally anywhere else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noted
@@ -5,12 +5,32 @@ import "Command.idl"; | |||
|
|||
namespace Microsoft.Terminal.Settings.Model | |||
{ | |||
enum ArgTag |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ArgTypeHint
ColorScheme | ||
}; | ||
|
||
struct ArgDescription |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very-nit: more commonly something like this would be called a Descriptor
@@ -168,6 +188,11 @@ namespace Microsoft.Terminal.Settings.Model | |||
UInt64 ContentId{ get; set; }; | |||
|
|||
String ToCommandline(); | |||
|
|||
UInt32 GetArgCount(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be better to put these four methods in their own interface (IActionArgsDescriptorAccess
), and inherit that interface in IActionArgs and NewTerminalArgs.
Right now, they look the same but they cannot be used in the same way.
If it is literally the same interface
, you can unify any codepaths that try to access INewTerminalArgs.GetArgCount
and IActionArgs.GetArgCount
(et al).
The true benefit of IDL is that you can define interfaces that encapsulate common behavior, after all. :)
@@ -741,6 +816,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation | |||
} | |||
} | |||
|
|||
void ActionMap::AddKeyBinding(Control::KeyChord keys, const winrt::hstring& cmdID) | |||
{ | |||
_KeyMap.insert_or_assign(keys, cmdID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_KeyMap.insert_or_assign(keys, cmdID); | |
_KeyMap.insert_or_assign(keys, cmdID); | |
_changeLog.emplace(KeysKey); |
We probably want to update the settings logger here to say that we've changed keys
.
@@ -757,6 +838,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation | |||
AddAction(*cmd, keys); | |||
} | |||
|
|||
void ActionMap::DeleteUserCommand(const winrt::hstring& cmdID) | |||
{ | |||
_ActionMap.erase(cmdID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ActionMap.erase(cmdID); | |
_ActionMap.erase(cmdID); | |
_changeLog.emplace(IDKey) |
This one I'm iffy on, so I want to discuss here.
Currently, there isn't a place where we're tracking if a user added an ID. In the JSON, the user would be using "id" in two cases for Action Map:
- create a new action in the
"actions"
block (i.e.{"command": "terminalChat", "id": "User.terminalChat"}
)- That's fine? We care about action arg usage and that's already being handled.
- create a key binding in the
"keybindings"
block (i.e.{"id": "User.terminalChat", "keys": "ctrl+?}
)- That's fine too. We care about "keys" usage and that's already being handled.
(related: "id"
is used in the new tab menu, but we're just tracking "action"
there which is sufficient)
Long-term, however, we want _changeLog
to be a way for us to know if the user changed anything. So maybe we do want to apply the code suggestion and update case 1 to add "id"
too? Thoughts?
@@ -740,4 +740,274 @@ | |||
<data name="OpenCWDCommandKey" xml:space="preserve"> | |||
<value>Open current working directory</value> | |||
</data> | |||
<data name="CopyText" xml:space="preserve"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lightly pushing back on the capitalization of these. We should probably capitalize the first letter of the first word and that's it.
<data name="QuickFix" xml:space="preserve"> | ||
<value>Quick Fix</value> | ||
</data> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the type here is "Quick Fix", but there's no action args and the generated name is "Open quick fix menu". Should we just use the generated name here?
Generalize this comment to all the other actions that have no args. I think the list can basically be found in ActionAndArgs.cpp by looking at GenerateName()
//////////////////////////////////////////////////////////////////////////////// | ||
#define NEW_TERMINAL_ARGS(X) \ | ||
X(winrt::hstring, Commandline, "commandline", false, ArgTag::None, L"") \ | ||
X(winrt::hstring, StartingDirectory, "startingDirectory", false, ArgTag::None, L"") \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
X(winrt::hstring, StartingDirectory, "startingDirectory", false, ArgTag::None, L"") \ | |
X(winrt::hstring, StartingDirectory, "startingDirectory", false, ArgTag::FilePath, L"") \ |
Or maybe we need a new one for directory path?
…/pabhoj/settings_model_reflection
Summary of the Pull Request
Implements reflection to the various ActionArg types in the settings model, which allows these structs to provide information about themselves (i.e. what args they contain and what types they are). This is necessary as a pre-requisite for the Settings Editor to display and modify these arg values.
Detailed Description of the Pull Request / Additional comments
IActionArgs
interface now has additional methods:ActionArgsMagic
have been updated to support the new interfaceActionMap
has been updated to support adding/editing/deleting actions and keybindings from outside the SettingsModelCommand
has been updated to allow setting its values from outside the SettingsModelValidation Steps Performed
Bug bashed in conjunction with #18917
PR Checklist