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

Selection of which keybinding to show in UI from a keymap configuration is based on lexicographic order #23015

Open
mgsloan opened this issue Jan 11, 2025 · 1 comment
Labels
bug [core label]

Comments

@mgsloan
Copy link
Contributor

mgsloan commented Jan 11, 2025

This arises from use of a BTreeMap here to represent the bindings. Within a block's bindings, bindings that come later lexicographically take precedence when choosing a binding for display.

Looking at the current default keymap it looks like earlier binding should be preferred:

      "backspace": "editor::Backspace",
      "shift-backspace": "editor::Backspace",

Fix alternative 1: prefer earlier match

I think this makes sense because textual search for an action should cause you to arrive at the higher precedence binding. It matches

So, a potential fix is to switch to IndexMap and iterate the blocks and their bindings in reverse order (since later bindings take precedence - #23014). However, this will cause other behavior changes:

  1. Before this, bindings defined in a later block at the same context depth would be preferred. Now it would be the earlier block.
  2. Before this, for bindings which have different strings but are actually the same, like ctrl-alt-i and alt-ctrl-i, the binding defined later would have been preferred. Now it will prefer the earlier binding.

For (2) I thought maybe this should just be an error. However, catching all cases fully would require some doing some tricky logic on context predicates. It's potentially useful to have shadowing semantics for that anyway. Maybe now is the time to update the shadowing semantics?

Fix alternative 2: reverse iteration order of blocks

One way to avoid (1) is to not reverse the iteration order of blocks. However, this has the weird consequence that:

  {
    "context": "Editor",
    "bindings": {
      "backspace": "editor::Backspace",
    }
  }
   {
    "context": "Editor",
    "bindings": {
      "shift-backspace": "editor::Backspace",
    }
  }

Would actually prefer shift-backspace, whereas when combined it would prefer backspace:

  {
    "context": "Editor",
    "bindings": {
      "backspace": "editor::Backspace",
      "shift-backspace": "editor::Backspace",
    }
  }

Fix alternative 3:

Another alternative is to maintain the current precedence behavior when the same binding at the same depth is made for an action, and be consistent with the precedence order for keybinding display.

This would mean updating the default keymaps to have the primary keybinding come last. After writing this all out I'm leaning towards it, even though I don't like giving up the property that text search visits the "primary" definition first.

@mgsloan mgsloan added bug [core label] triage Maintainer needs to classify the issue admin read Pending admin review and removed triage Maintainer needs to classify the issue admin read Pending admin review labels Jan 11, 2025
@mgsloan
Copy link
Contributor Author

mgsloan commented Jan 12, 2025

Found one more spot that is dependent on binding order - the docs preprocessor. In that case it's using the first matching keybinding for an action in lexicographic sort order.

block.bindings().iter().find_map(|(keystroke, a)| {

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

No branches or pull requests

1 participant