Skip to content

Give Command ownership over KeyChord#9543

Closed
carlos-zamora wants to merge 7 commits intomainfrom
dev/cazamor/tsm/upgrade-command
Closed

Give Command ownership over KeyChord#9543
carlos-zamora wants to merge 7 commits intomainfrom
dev/cazamor/tsm/upgrade-command

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.

<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