Why do so many packages ignore scope and only use grammar name?


I’ve noticed that a wide number of Atom packages seem to always use editor.getGrammar().name to limit scope, instead of editor.getGrammar().scopeName.

This is a big problem, as testing only against grammar name disregards nested scopes (e.g. text.html.someTemplatingLang). From my recollection, Textmate/Sublime packages always seemed to get this right, but it seems widespread in Atom packages.

I’m wondering if there is a reason for this, or if the packages should simply be changed?

Some examples of these issues:


Could you give some specific examples of how using grammar name instead of scope name breaks things? I looked at the Issues you’ve linked. They only explain that this is something that should be done, but not why. I’m just trying to understand :grinning:


I suppose I didn’t need to phrase my question as “Why do so many…”, as there may not be a good answer.

I just thought it was curious that coming from Textmate/Sublime this didn’t ever seem to be an issue and in Atom it seems widespread.

As a relative new-comer to Atom, I wanted to make sure I wasn’t just missing something. It seems to me these packages should be accounting for scopeName and not just grammar name and just aren’t. Is that how it seems to you?

A simple example of these shortcomings happens in Emmet (basically paraphrasing the above issue, sorry):

  • I’m using the “PostCSS” grammar, which has a scope name of source.css.postcss
  • Therefore, I would expect Emmet’s rules for “CSS” to work.
  • They don’t, because Emmet is only looking at the grammar name, and not the scope name.

Perhaps this is a non-issue, and in fact these packages authors should in fact be checking by scope. If you think that’s the case, pack this one away and forget about it!


No, I think this is a valid concern. But I’m already sold. What I hoped (and you’ve now done) is that you could describe to people why they should go through the extra work of matching based on scope rather than grammar name. The way you originally described the issue it was just a matter of style and I wanted to make sure that people understood that there really is an underlying technical issue. (And since I haven’t run into the issues you have, it would be best and most succinctly described by someone currently feeling the pain.)


Well I feel a bit better with my concern validated a bit :).

I’ll work on some PRs and reference this post. Thanks!


Over in the Linter packages everything is based on scope, linter providers only activate when a scope they define is active in the document, and the Linter package itself uses the current scope at the cursor to determine when to run which linter provider. This is helpful for things like embedded JS inside an HTML file. A linter can say "I know how to handle source.embedded.javascript", Linter will see that, and run the linter, it will perform extraction of the JS and lint that, then return any issues it finds.

This is why it’s so important for grammers to properly identify embedded scopes (and why language-gfm is so broken…).

So, not all packages fail at handling scope :wink:


It seems that perhaps editor.scopeDescriptorForBufferPosition().getScopesArray() is the right method here to use, actually: https://github.com/emmetio/emmet-atom/issues/376#issuecomment-173536921