Key-binding hell


#1

I’m sure other users have had the unhappy experience of installing a new package only to find that it’s overriding keybindings from another package. Not an easy thing to manage, I know, but I think something like this would be ideal:

  1. Create a registry of keybindings
  2. Keybindings are available on a first-come first-served basis
  3. Create a basic package validator that will check keybindings against the registry and reject those already taken

#2

This is one of the reasons I do not, as a general rule, include keybindings in my packages. I’d rather foist that little exercise off on the user of my package than try to draw a consensus out from these varying conflicts of keybinding assignment style:

  • People coming from Sublime Text
  • People coming from vim
  • People coming from Emacs
  • People coming from Windows
  • People coming from Linux
  • People coming from OS X

Each has different philosophies (with differences ranging from subtle to vast) on how keybindings should be assigned.

If someone were to undertake your suggestion, I think they would be wise to come up with a system that kept some or all of the above in mind.


Announce: Search-All-Keybindings
#3

I agree with that. This was bound to become messy, given that none of us tend to have an unlimited capacity for remembering ever weirder key combinations. So users will have to make decisions as to which combinations they would prefer for which of their package functionalities, based on their personal workflows and preferences.

It’s best to leave this out of packages.
Although, I could imagine that customizing your top 6 or so key bindings could get some kind of GUI section in the Settings View.


#4

There should be a user option to ignore all package bindings.


#5

Very fair points. However, it isn’t that easy on the user end. My latest dilemma came from installing the nice Git-Plus package, which overrides several bindings from the also nice Emmet package. I did try to resolve the conflicts with my own key-mappings, but for whatever reason, this did not work. My only recourse was to choose between the nice packages and uninstall one.
How about this as an alternative solution: check for conflicts when a package is installed, list them out, and let the user allow/disallow the overrides?


#6

It wouldn’t have to happen automatically. When requested, a package could analyze the conflicts by reading the keybindings files and then offer to change them the way you suggest.


#7

And it should allow you to enter replacement bindings right then and there.


#8

I’m thinking the most likely issue here is that Atom keybindings have a CSS like selector syntax. For example, the Dash package installs ctrl-h with a selector of .editor, and the core binding is on body. I guess .editor wins because it matches an element inside of body?

Anyway, if you use the wrong selector to override a binding, it might fail.

The keybinding resolver might help here: “Keybinding Resolver: Toggle” is the command in the pallette.


#9

I think you’re probably right – I got the selector from the keybindings in Settings, so think that was right. But the new key combinations didn’t work. Atom was in a funky mood generally at the time, so I should try again.


#10

Keybinding selectors follow the same specificity rules as CSS. dash:shortcut has a selector of .editor:not(.mini) while core:backspace is on body. If you plug these selectors into http://specificity.keegan.st you can see the specificity on each. The dash shortcut wins out because classes and pseudo-classes are more specific than elements.

It’s best to copy the default selectors for keybindings exactly if you want to replace them, to ensure you always have at least equal specificity. Since user keybindings are loaded after package bindings, as long as you have the same selector you’ll always win over the default.


#11

but still a common central place for all active keybindings would help allot.
what does it help to know that i can apply key bindings which will always win if i dont even know about them?
key resolver package is not good enough to find keybindings i may need to change.
having a central place for all registered key bindings in my atom instance is much much better than tell every developer to use specificity.
my 2cent.


#12

There is a place that shows all registered keybindings in your Atom instance. It is in the Settings View, under the Keybindings tab:


#13

hmm that is so obvious in front of my sight. i totally forget about that view.
shame on me!


Announce: web-browser
#14

This an old thread, but as more and more users are migrating to Atom, I wanted to add a bit of clarity to this issue.

@postcasio It’s best to copy the default selectors for keybindings exactly if you want to replace them, to ensure you always have at least equal specificity. Since user keybindings are loaded after package bindings, as long as you have the same selector you’ll always win over the default.

To those who are still confused (like I was - till I figured it out), I want to explain this process more clearly.
Let’s say, two packages (A and B) are having a keybinding conflict with CTRL-E.

Key Binding Resolver
The Key Binding Resolver pane displays key binding conflicts. To open it, hit CTRL + .
We want to see which of the above two is winning. Now, put the cursor in the editing area (buffer) and hit CTRL-E

The Key Binding Resolver will highlight the winning package. (The first column shows the command that is getting executed.) In our case let’s assume Package B has won. However, let’s say you want Package A to win the Keybinding. Press CTRL+. again to close Keybinding Resolver pane.

Settings window - Keybinding Menu

  • open Settings window (CTRL+,)
  • and select Keybindings Menu.
  • In the ‘Search keybindings’ field, enter CTRL-E.

All packages that use CTRL-E keybinding will be listed.

  • Locate package B (the winning package), and click on the Clipboard icon under Keystroke column. This will copy the keybinding and the command that is being executed by package B into the clipboard.
  • Then click on ‘your keymap file’ link. Atom will open the keymap.cson file.
  • Now, paste the copied text in an empty line. Then, delete the unwanted command. (The right-side part only)
  • Now, go back to Settings tab, locate package A in the keybinding list and copy its command shown under the column Command.
  • Go back to the keymap.cson file.
  • Paste the copied command in the place of old command. Please remember the command must be wrapped in single quotes. Save keymap.cson.
  • Press alt+ctrl+r to reload Atom.
  • From now on, when you press CTRL-E, package A’s command will be executed.
  • To check, use the Key Binding Resolver.

Hope this helps and my apologies if I was too elaborate. Reading this will also help.

In fact the instruction by @postcasio is very important and should be part of Atom’s documentation on resolving keybinding conflicts as it will help users to clearly solve keybinding conflict.


#15

I recently started using Atom editor.
I frequently hit situation where I want some packages keybinding completely disabled.
I don’t want consume valuable keymap resource for the command I rarely use, I’m happy if I can invoke from command pallet.

I want Atom provide.

  • Disable specific keymap for specific package.
  • Disable all keymap for specific package.
  • Or enforce every package to have mandatory method like disableKeyMap which is called when user set packagename.disablekeymap = 1.

I’ve just moved Atom from Vim, I created a lot of Vim plugin, in my vim plugin I didn’t provide any default keymap and let user set keymap since I didn’t want my plugin’s user to ovey my personal preference but not all plugin author have this principle …


#16

Use Atom package manager. Search for package ‘keyboard-localization’

author: andischerer

Worked for me.

I have no connection with this guy, I am just telling you that this plugin worked for me.


#17

‘keyboard-localization’ is not package to solve this problem.

I’ve just released https://atom.io/packages/keymap-disabler to solve this problem.
And I found https://atom.io/packages/disable-keybindings by aki77 is also solve this problem.

Since I didn’t noticed disalbe-keybindings is already exists, I created keymap-disabler.
What a reinventing the wheel!

Try whichever you want.


#19

Thank you for this. I figured this process out the hard way, wish i would have seen this earlier.

Once i figured it out i was looking for a package that would automate this, spending literal hours and hours on key bindings is shitty. Know of any?

Also are there any Jetbrains users here? I tried to look for keymaps already setup to change all normal keys from the standard Intellij, Pycharm, Webstorm etc and couldn’t find any. I was kind of surprised, the Jetbrains stuff is so popular with anyone i know if this field.


#20

I am currently in the middle of key-binding hell myself.

Pulled down Atom yesterday. On Windows I can set ctrl-d to be editor delete line and all is well. On Ubuntu 15.04 64-bit Unity desktop, no amount of overriding will fix it. .find-and-replace:select-next continues to jump in front. When I unset! it in keymap and then do ctrl-. and try ctrl-d I see the uset!, then I see .find-and-replace:select-next set it, finally I see my override for delete line.

How can one fix this without losing search&replace functionality? I don’t want to hack the indicated json file.

This is a classic chicken-and-egg problem. It appears code loads after user overrides


#21

The keybinding resolver will tell you which keybindings were eligible and which was chosen. But it has nothing to do with order. Instead, it has to do with specificity. So if you add keybinding X but Y was chosen, one way around it is to actually snarf the context of Y and use that for your X binding.

There is one exception: the keymaps are CSON files, which are key/value pairs. There can only be one value for a given key. So if you have this:

'key':
    'value1'
'key':
    'value2'

Then you only have one of the two values, not both. In the context of keybindings, I think the following helps:

'key':
    'value1'
    'value2'