Skip to content
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

Refactor ActionMap and Command to use ActionIDs #17162

Open
wants to merge 78 commits into
base: main
Choose a base branch
from

Conversation

PankajBhojwani
Copy link
Contributor

@PankajBhojwani PankajBhojwani commented Apr 30, 2024

Summary of the Pull Request

As outlined in #16816, refactor ActionMap to use the new action IDs added in #16904

Detailed description of the pull request

See the spec!
 

Validation steps performed

  • Legacy style commands are parsed correctly (and rewritten to the new format)
  • Actions are still layered correctly and their IDs can be used to 'overwrite' actions in earlier layers
  • Keybindings that refer to an ID defined in another layer work correctly
  • User-defined actions without an ID have one generated for them (and their settings file is edited with it)
  • Schema updated

References and Relevant Issues

#16816

PR Checklist

{
if (cmd.ActionAndArgs().Action() != ShortcutAction::Invalid)
// Only populate AvailableActions with actions that haven't been visited already.
const auto actionID = Hash(cmd.ActionAndArgs());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we still have to use InternalActionID to populate the available action dropdown in the SUI since we don't have a Terminal.<> id for every configuration of each shortcut action and its args

This comment has been minimized.

Copy link
Member

@lhecker lhecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits, and 1 bug.
I'm not sure I understood how all the changes fit together in the grand scheme of things. I'm not so deep into the ActionMap code. 🙈

Comment on lines +128 to +133
auto toJson = [&keybindingsList](const KeyChord kc, const winrt::hstring cmdID) {
Json::Value keyIDPair{ Json::ValueType::objectValue };
JsonUtils::SetValueForKey(keyIDPair, KeysKey, kc);
JsonUtils::SetValueForKey(keyIDPair, IDKey, cmdID);
keybindingsList.append(keyIDPair);
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lambda seems unnecessary.

{
warnings.push_back(SettingsLoadWarnings::TooManyKeysForChord);
}
else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early-return and unnest the rest?

{
Control::KeyChord keys{ nullptr };
winrt::hstring idJson;
if (JsonUtils::GetValueForKey(json, KeysKey, keys))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

_KeyMap.insert_or_assign(keys, idJson);

// make sure the command registers these keys
if (!idJson.empty())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

else
{
// this is not a command block, so it is a keybinding block
_AddKeyBindingHelper(jsonBlock, warnings);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you invert the if condition, you can flip the branches and use continue here. It would still make sense that way IMO, because it would read "if it has no commands and no actions, then add an error and continue".

const auto parentActions{ parent->_GetCumulativeActions() };
cumulativeActions.reserve(cumulativeActions.size() + parentActions.size());
cumulativeActions.insert(cumulativeActions.end(), parentActions.begin(), parentActions.end());
if (actionMap.find(cmdID) == actionMap.end())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same here)

}

return cumulativeActions;
for (const auto parent : _parents)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same here)


for (const auto& [keys, cmd] : keyBindingsMap)
for (const auto [keys, cmdID] : accumulatedKeybindingsMap)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same here)

Comment on lines +579 to 586
if (cmd.ActionAndArgs().Action() == ShortcutAction::Invalid)
{
// Update inner Command with new key chord
auto oldCmdImpl{ get_self<Command>(oldCmd) };
oldCmdImpl->RegisterKey(keys);
_KeyMap.insert_or_assign(keys, L"");
}

// Additive operation:
// Register the new key chord with maskingCmd (an existing _maskingAction entry)
// Example:
// parent: { "command": "copy", "keys": "ctrl+c" } --> register "ctrl+c" to parent._ActionMap (different branch in a different layer)
// current: { "command": "copy", "keys": "ctrl+shift+c" } --> also register "ctrl+shift+c" to the same Command (maskingCmd)
if (maskingCmd)
else
{
// Update inner Command with new key chord
auto maskingCmdImpl{ get_self<Command>(maskingCmd) };
maskingCmdImpl->RegisterKey(keys);
_KeyMap.insert_or_assign(keys, cmd.ID());
}
Copy link
Member

@lhecker lhecker May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be something like

hstring id;
if (cmd.ActionAndArgs().Action() == ShortcutAction::Invalid)
{
    id = cmd.ID();
}
_KeyMap.insert_or_assign(keys, id);

or

const auto action = cmd.ActionAndArgs().Action();
const auto id = action == ShortcutAction::Invalid ? hstring{} : cmd.ID();
_KeyMap.insert_or_assign(keys, id);

I'm not sure I understand why we want to store an empty string in the map for invalid actions though. Shouldn't we want to remove the key entirely?

Comment on lines +629 to +637
if (const auto cmdID = keyIDPair->second; !cmdID.empty())
{
return cmdID;
}
else
{
// the keychord is defined in this layer, but points to an empty string - explicitly unbound
return L"";
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's basically the same as just return keyIDPair->second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pre-seeded actions from userDefaults.json should be removed after adding IDs
2 participants