How do I scope a keymap to a grammar?


I’d like a keymap to only apply for a set of grammars. However, it seems like the CSS matchers for keymaps only apply up to div.editor.

This works, but applies the keymap globally (undesired):

  'ctrl-c ctrl-d': 'salt:docs'

I’d prefer this:

'.editor .salt .yaml .entity':
  'ctrl-c ctrl-d': 'salt:docs'

Context Menu based on Grammar Scope

I don’t believe you can, currently. But there is a thread talking about language-specific settings:

Maybe this should be part of that discussion too?


I think the requests are different. My question is related to binding a keymap to a specific grammar (and hopefully, scope).


@timcharper We don’t currently support that feature, but it is on our todo list!



Im so looking for this ability as well! it will reduce the chance of overlapping keybindings.


I have made a little simple npm module to add this feature to your plugins.

On use, you are able to make keymaps like .editor.javascript or .editor.css. NO MORE OVERLAPPING KEYBINDINGS :smiley:

check it out: atom-keymap-plus


Genius, tcarlsen! Simple solution, seems robust enough to be compatible with alternative scoping approaches, and if I were an atom dev I’d consider canonizing the approach.


@tcarlsen it seems the extension doesn’t work… fully. In 0.71.0, the event editor:grammar-changed seems to only be called when you actively change the grammar. It doesn’t get called when the initial grammar is detected and set.


@tcarlsen another unfortunate thing is that it seems my entire plugin must be loaded at run-time for it to work, since loading it on first usage will prevent it from ever being assigned the class properly.

It seems that the idea solution would be to create a package which adds support for this, that is always loaded. And then deprecate that package when atom comes out with an official solution.


im in 0.71.0 af its working fine for me. on launch, open file and change panel.

using it in all of my plugins. they all have the keymap `cmd-alt-l. this did’t work before, because the plugin that was loaded last was overwriting the others, but with this module, its working fine for me.


that is correct, and I know is ain’t the prettiest way, but I believe its the way available for now. My guess is that this module is temporarily and the atom team will provide an official way. but until that I’m using this.

A thing Im adding soon is the ability to run it later using the eachEditor function

atom.workspace.eachEditor(function (editor) {

I’m testing this and will add it later today :smiley:


I have made a topic for this module alone


I’m replying to this old thread with updated information because it’s a top hit for “atom keymap grammar” on Google (for me at least). I hope it saves someone a minute.

Atom now supports this natively. Your keymap selectors will look like this:

"atom-text-editor[data-grammar='source js']":
"atom-text-editor[data-grammar='source css']":
"atom-text-editor[data-grammar='source json']":
"atom-text-editor[data-grammar='text html basic']":

Source language based keymap

I can’t find the relevant part in the docs, do you have any pointers?
are js css json possible extensions?
But then what is source.
I also saw ~= in some snippets.

PS: what I want is: bind a key to a command but only on unsaved files or files with the .malg extension.
I have a grammar file with:

'scopeName': 'source.microalg'
'name': 'MicroAlg'
'fileTypes': ['malg', 'l']



Anything that you have a grammar for.

But then what is source.

An arbitrary word to distinguish source code scopes from “text” scopes (such as text.html.basic). It doesn’t really mean anything.

I also saw ~= in some snippets.


PS: what I want is: bind a key to a command but only on unsaved files or files with the .malg extension.

Is this a custom command? If not, then the “unsaved file” criterion is harder. There isn’t a scope for that.


Thanks for you answer.

So I should use the scopeName and not the name and not the fileTypes.

Example with ~=:

Yes, it is a custom command.

Is this covered somewhere in the docs?


Yes. The scopeName, name, and contentName keys define CSS selectors, and it’s the CSS selectors that keybindings use.

Example with ~=:

Okay, I wasn’t sure what syntax you were talking about. You can find more information about CSS attribute selectors here.

Yes, it is a custom command.

Is this covered somewhere in the docs?

You can call [atom.workspace.getActiveTextEditor().getPath()] ( to check if the active buffer has been saved to disk or atom.workspace.getActiveTextEditor().buffer.isModified() to check if it matches the file on disk.