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

Give Command ownership over KeyChord #9543

Closed
wants to merge 7 commits into from

Conversation

carlos-zamora
Copy link
Member

Transfers ownership of a KeyChord to Command. This includes...

  • Adding an observable getter/setter for KeyChord to Command
  • Add deserialization logic to handle keys
  • Remove recursive updating of Command::KeyChordText
  • removing Command::KeyChordText which caused...
    • Command palette needs to convert the KeyChord to a string
    • Add a few more converters to handle this in the Actions page (SUI)

KeyChordSerialization experienced a minor refactor. I introduced the ConversionTrait<KeyChord> there, and simply use the existing FromString and ToString logic to handle everything.

References

#9428 - Spec

Validation Steps Performed

Checked the following...

  • Command Palette
    • key chord text is still displayed, when applicable
  • Actions Page
    • only actions with keys are displayed

Copy link
Member Author

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

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

"blocking" myself until I fix that nested key chord text thing Fixed


if (keyChord)
{
command.KeyChordText(KeyChordSerialization::ToString(keyChord));
Copy link
Member Author

Choose a reason for hiding this comment

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

Surprisingly, we still need something like this to support the following scenario:

        {
            "name": "Test...",
            "commands": [
                { "name": "hello", "command": "copy" },
                { "name": "custom", "command": "openSettings", "keys": "ctrl+q" }
            ]
        },

In this situation, "copy" still gets the "ctrl+c" key binding, but "openSettings" does not.

A fix will be included in the upcoming commit.

Copy link
Member Author

Choose a reason for hiding this comment

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

For the record, the current implementation displays "hello" without a kbd, but "custom" with one. Exactly backwards. And ctrl+q does not actually execute the action.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is now fixed. As a part of ActionMap, it would be nice if we didn't have to do this. But I'm keeping an eye out to make sure this works as intended in the next PR.

For now, this is fine. ActionMap will probably get some tests to make sure we get the behavior we want.

Comment on lines +21 to +29
template<>
struct Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<winrt::Microsoft::Terminal::Control::KeyChord>
{
winrt::Microsoft::Terminal::Control::KeyChord FromJson(const Json::Value& json);
bool CanConvert(const Json::Value& json);
Json::Value ToJson(const winrt::Microsoft::Terminal::Control::KeyChord& val);
std::string TypeDescription() const;
};

Copy link
Member Author

Choose a reason for hiding this comment

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

@DHowett Here's the beginning of a transition to adding more ConversionTraits. Hope this looks ok to you.

@@ -39,7 +41,7 @@ the MIT License. See LICENSE in the project root for license information. -->
to make sure it takes the entire width of the line -->
<ListViewItem HorizontalContentAlignment="Stretch"
AutomationProperties.Name="{x:Bind Name, Mode=OneWay}"
AutomationProperties.AcceleratorKey="{x:Bind KeyChordText, Mode=OneWay}">
AutomationProperties.AcceleratorKey="{x:Bind Keys, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}">
Copy link
Member Author

Choose a reason for hiding this comment

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

I originally wanted to make KeyChord IStringable and call it a day. But KeyChord is owned by TerminalControl, and I felt that it doesn't really make sense to add (de)serialization logic in there. If you disagree, let me know. The change would just require me to move KeyChordSerialization to TerminalControl.

@carlos-zamora carlos-zamora marked this pull request as draft March 19, 2021 00:20
@carlos-zamora carlos-zamora marked this pull request as ready for review March 19, 2021 17:57
@zadjii-msft zadjii-msft self-assigned this Mar 30, 2021
@carlos-zamora
Copy link
Member Author

Closing and merging code changes into #9621.

carlos-zamora added a commit that referenced this pull request May 5, 2021
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.
@DHowett DHowett deleted the dev/cazamor/tsm/upgrade-command branch October 26, 2021 16:57
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.

4 participants