Skip to content

Potential improvements to keybinding registry #288

Description

@kne42

In napari, we implemented some helper functions and lookup functionality that we thought might be useful upstream for VSCode-style keybindings. Here are the differences from current app-model functionality and how they would help all users:

Convert _RegisteredKeyBinding from NamedTuple to dataclass

Why: Allows easy control of how fields are compared, if they can have defaults, etc. Also allows inheritence for user modifications, which could allow us to take in custom user keybinding classes in KeyBindingsRegistry, and allow users to add additional metadata, which could be used in their own dispatching implementations, for example.

Drawbacks: Functionality should be the same when accessing members via dot-notation (e.g. kb.weight); however it will break any code relying on tuple expansion (e.g. keybinding, command_id, weight, source, when = kb). Dataclasses are also less space-efficient than tuples.

Add negation_rule field to _RegisteredKeyBinding

Why: It makes it explicit that commands starting with - are negation rules, consistent with VSCode implementation. Also useful for program logic. See #231 and further down this issue.

Get non-cancelling entries

Why: With the addition of a negation rule, keybinding entries that are exactly the same in terms of their binding, relevant command, and conditional, with the exception that one negates the other means that we can make a helper function that cancels out these entries and returns the remainders without needing to evaluate the contexts directly. This is useful for looking up active entries for a command, which can be used to help visually construct a comprehensible keymap for the user.

Discard entries based on weight/source

Why: This gives an efficient way to dispose of entries en masse without having to save their disposal callbacks. This is most useful if user or plugin-level keybindings need to be updated: simply discard the relevant keybindings and reload them from the source. This provides a solution to #256.

See this file for an example of implementation.

Update KeyBindingsRegistry.get_context_prioritized_keybinding to factor in negation_rule

To be consistent with the new negation_rule, it would be updated to not return cancelled entries like so:

ignored_commands = []

for entry in reversed(entries):
    if entry.when is None or entry.when.eval(context):
        if entry.negate_rule:
            command_id = entry.command_id[1:]
            ignored_commands.append(command_id)
        elif entry.command_id not in ignored_commands:
            return entry

Why: It wouldn't make sense to return the first context-enabled command if it's negated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions