Edit/Set File Associations


#1

I’m not seeing a way to set grammar associations based on file name or file name pattern. I searched the forum to no avail. I know I can quick toggle the grammar in the status bar but I’d love to be able to set these globally and/or in a project specific file.


#2

I’ve only been able to do it in the DevTools console:

atom.syntax.grammarForScopeName('text.xml').fileTypes.push('ex_em_elle')

Still trying to figure out how to get it to work with init.coffee, though…


#3

I think this line doesn’t work because the init.coffee is evaluated after the packages are loaded/activated, this needs to be done before that.

One approach can be a PR to the language package or modifying the package (a fork?) and add the file name/extension to it.


#4

It seems that for each “window”, the init.coffee gets evaluated before any grammars are available.

alert JSON.stringify Object.keys atom.syntax.grammarsByScopeName

↑ in my init.coffee yields ["text.plain.null-grammar"].

If there were only some event that we could listen for (e.g., something like “syntax:grammarsLoaded”)…


UPDATE 1:

Oh, wait. In 0.72.0, looks like atom.syntax emits “grammar-added”.

Maybe I’m misunderstanding this:

Object.keys(atom.syntax.eventHandlersByEventName)

gives me

["grammar-added", "grammar-updated"]

And the GrammarRegistry in first-mate emits “grammar-added”


UPDATE 2:

The timing is obviously going to be different per device; but, I got it to work with 300ms delay in my init.coffee.

associateFileTypeWithGrammar = (scopeName, fileType) ->
  g = atom.syntax.grammarForScopeName scopeName
  return unless g
  g.fileTypes.push fileType
  atom.beep()

setTimeout ->
  associateFileTypeWithGrammar 'text.xml', 'ex_em_elle'
, 300

Obviously it would behoove us to ensure that the new file type hasn’t already been registered with another grammar…


UPDATE 3:

Got it working! I’m not sure whether we should be listening to the “grammar-updated” event, though.

# init.coffee
path = require 'path'

updateEditorViews = (fileType) ->
  ext = ".#{fileType}"
  atom.workspaceView.eachEditorView (view) ->
    editor = view.getEditor()
    return unless path.extname(editor.getPath()) is ext
    editor.reloadGrammar()

addFileTypeToGrammar = (g, fileType)->
  g.fileTypes.push fileType

registerFileType = (scopeName, fileType) ->
  atom.syntax.on 'grammar-added', (g) ->
    return unless g.scopeName is scopeName
    addFileTypeToGrammar g, fileType
    updateEditorViews fileType

registerFileType 'text.xml', 'ex_em_elle'

UPDATE 4:

I misunderstood how ::eachEditorView(callback) works. Here’s a better version:

# init.coffee
{extname} = require 'path'

fileTypes =
  '.ex_em_elle': 'text.xml'

atom.workspaceView.eachEditorView (view) ->
  editor = view.getEditor()
  scopeName = fileTypes[extname editor.getPath()]
  return unless scopeName?
  g = atom.syntax.grammarForScopeName scopeName
  return unless g?
  editor.setGrammar g

Stay tuned for the “file-types” package :slight_smile:


Adding file types to packages
Set a default syntax by filetype?
#6

I’ve released the file-types package!


#7

Wonderful. Thank you, just what I needed :blush:
I’ve added a myth~>css definition and don’t have to fumble with the CSS package grammar any time it’s updated anymore:

'file-types':
  'myth': 'source.css'

#8

First off - brand new to Atom and trying to customize it so I could be missing something obvious. Any idea off the top of you head on why the package doesn’t work for me when I go add an entry to my config.cson, but when I copy your code from this discussion and throw it in my init.coffee I get the desired results?


#9

I’ll echo the previous comment – I don’t think file-types works anymore on modern versions of Atom (I’m currently running 0.177.0).

It looks like basic API drift. Here’s a blob of code to add to your init.coffee that will work with 0.177.0 and hopefully above:

{extname} = require 'path'

fileTypes =
  '.dhtml': 'text.html.django'

atom.workspace.observeTextEditors (editor) ->
  scopeName = fileTypes[extname editor.getPath()]
  return unless scopeName?
  g = atom.grammars.grammarForScopeName scopeName
  return unless g?
  editor.setGrammar g

Change syntax highlighting based on file extension
#10

Thanks, @davepeck. That did the trick for making file-types work again.


#11

For anyone working with MeteorJS, I suggest the following file associations:

  fileTypes =
    '.js': 'source.js'
    '.html':'text.html.mustache'

The second association automatically solves a problem occurring when grammar is set to HTML rather than HTML (Mustache). In that case, Atom’s core language-html package preempts snippet auto-completion of the meteor-snippets package. But now, with the new .html association, tab completion on “mife” will painlessly deliver the snippet:

{{#if statement}}

{{else}}

{{/if}}

instead of the nonsense:

<mife></mife>

#12

Thank you for the script. I tweaked it a little to support file extensions that have a period in them.

atom.workspace.observeTextEditors (editor) ->
  path = editor.getPath()
  return unless path?

  fileTypes =
    '.php': 'text.html.php',
    '.blade.php': 'text.html.php.blade'

  for extension of fileTypes when path.toLowerCase().endsWith(extension.toLowerCase()) and (longestExtension ? "").length < extension.length
    longestExtension = extension

  return unless longestExtension?
  g = atom.grammars.grammarForScopeName fileTypes[longestExtension]
  return unless g?
  editor.setGrammar g

Edit: I just noticed that I am matching the longest scopeName, but it obviously should be matching the longest file extension instead. Fix underway. Fixed


#13

what blob do I need to add extensions for python (currently .py) files?

I tried this:

{extname} = require 'path'

fileTypes =
  '.myext': '.py'

atom.workspace.observeTextEditors (editor) ->
  scopeName = fileTypes[extname editor.getPath()]
  return unless scopeName?
  g = atom.grammars.grammarForScopeName scopeName
  return unless g?
  editor.setGrammar g

and

 '.myext': 'source.py'

but it did not work. I am using atom v0.188


#14

@Amleto you shouldn’t have to do anything for Atom to recognize Python files with the standard extension, the language-python package is installed by default and provides this for you.


How to (re-)Associate .h files with Objective-C
#15

@leedohm As I said, I want to add extensions, for example ‘.myext’ as given in the script snippet above.

ie I want Atom to use python language syntax highlighting for files with extension myext.

Regards


#16

@Amleto it looks like the correct scopeName for Python is source.python, so you’ll want:

fileTypes = 
    '.myext': 'source.python'

#17

thanks @davepeck, that’s got it.


#19

Because file types add-on currently has some deprecation warnings you can use this in your init.coffee

{extname} = require 'path'

fileTypes =
  '.thtml' : 'text.html.handlebars'

atom.workspace.observeTextEditors (editor) ->
  scopeName = fileTypes[extname editor.getPath()]
  return unless scopeName?
  g =  atom.grammars.grammarForScopeName scopeName
  return unless g?
  editor.setGrammar g

#20

btw in my current version of Atom (1.5.3), atom.syntax does not exist, although atom.grammar does.
Wanting to discover supported grammars and their identifiers is useful by inspecting atom.grammar. grammarsByScopeName.

My “.irbrc” and “.pryrc” files were already recognized as “Ruby” text somehow, but not my “.railsrc”. By following the information mentioned in this page GitHub - atom/atom - #1718 - Make file type -> language mapping locally configurable):

"*":
  core:
    customFileTypes:
      "source.ruby.rails": [
        ".railsrc"
      ]

#21

In case others stumble upon this thread, as of Atom 1.0.8 (released in late 2015) you can now use following syntax in your ~/atom/config.cson file.

'*':
  'core':
    'customFileTypes':
      'source.shell': [
        'sh.erb'
      ]
      'source.ruby': [
        'Cheffile'
        'rb2'
      ]
```

The above example uses shell markup for files with the `.sh.erb` extension, and ruby markup for the `Cheffile` and files with the `.rb2` extension.

#22

There’s also a FAQ for this: