tree-sitter / tree-sitter-embedded-template

Tree-sitter grammar for embedded template languages like ERB, EJS
MIT License
60 stars 18 forks source link

Does this work with any file type? .yml.ejs? #14

Open NullVoxPopuli opened 2 years ago

NullVoxPopuli commented 2 years ago

I'm writing some .ejs on top of yml, and am wondering how to configure this package?

Atm, I setup

local parser_config = require("nvim-treesitter.parsers").get_parser_configs()

parser_config.ejs = {
  install_info = {
    url = "https://github.com/tree-sitter/tree-sitter-embedded-template",
    files = { "src/parser.c" },
    requires_generate_from_grammar = true,
  },
  filetype = "ejs",
}

but when I open an ejs file, no highlighting occurs.

AlanWarren commented 2 years ago

I barely know what I'm doing here, but I can share how I was able to get *.js.erb to work.

I started with the guide on creating parsers here. (using the tree-sitter cli from npm) to initialize my own parser project.

I took the grammar.js defined here in the embedded_template repo, made a few basic edits and ran npx tree-sitter generate and it worked. (generated the parser + bindings)

Next I tossed in a tiny example .js.erb file from a rails project with a small bit of erb template.

var cart = document.getElementById("cart");
cart.innerHTML = "<%= j render(@cart) %>"

I ran npx tree-sitter parse example-file and it looked good.

I created a queries directory in my parser project and copied the highlights.scm and injections.scm from the embedded_template repo. My injections was named injections-jsruby.scm with the following content.

((content) @injection.content
 (#set! injection.language "javascript")
 (#set! injection.combined))

((code) @injection.content
 (#set! injection.language "ruby")
 (#set! injection.combined))

I also hand edited the package.json a bit so that it included a 'tree-sitter' section, like so:

  "tree-sitter": [
    {
      "scope": "text.js.erb",
      "file-types": [
        "jsruby"
      ],
      "injections": "queries/injections-jsruby.scm",
      "injection-regex": "erb"
    }
  ]

(I noticed the embedded_template project's package.json had this, and I'm not sure if it was added by hand or if the tree-sitter CLI somehow adds it. anyhow... I'm guessing nvim treesitter uses this but not sure to what extent)

From this point, my plan was to create my own filetype so I could easily target my parser, so I expanded my nvim-treesitter lua config with the following.

local parser_config_erb  = require('nvim-treesitter.parsers').get_parser_configs()
parser_config_erb.jsruby = {
  install_info = {
    url = '~/dev/build/tree-sitter-jsruby',
    files =  { 'src/parser.c' },
    branch = "master",
    requires_generate_from_grammar  = true,
  },
  filetype = 'jsruby'
}
-- autocmd to define a custom filetype 
vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
  pattern = "*.js.erb",
  command = "set filetype=jsruby"
})

This part confused me a bit, but I still had to add queries. I went into my nvim runtime dir and created these 2 files.

~/.config/nvim/after/queries/jsruby/injections.scm

;; extends
(output_directive) @embedded_template @combined
(content) @javascript @combined
(code) @ruby @combined

I added (output_directive), as I couldn't get the <% %> tags to highlight using the below highlights.scm It's still a bit flakey, as larger js.erb files with many ruby injections don't always highlight the <% %>.

~/.config/nvim/after/queries/jsruby/highlights.scm

;; extends
(comment_directive) @comment
[
  "<%#"
  "<%"
  "<%="
  "<%_"
  "<%-"
  "%>"
  "-%>"
  "_%>"
] @keyword

After this, I opened an *.js.erb file and ran :TSInstall jsruby and everything highlighted as I expected it to.

That may be a terrible way to achieve what I wanted, but I couldn't figure out how to get JS + Ruby injections to work using this parser by itself.

I considered forking this repo and adding the additional injections, so I may try that next. I expect this was the missing piece of the puzzle for the OP here, as embedded_template doesn't include an injection for yaml + javascript.

Is there an easier way?

sjdonado commented 1 year ago

This worked for me https://github.com/nikvdp/ejs-syntax