language-haskell icon indicating copy to clipboard operation
language-haskell copied to clipboard

Support setting syntax highlighters for quasiquotes?

Open iand675 opened this issue 9 years ago • 11 comments

I often use quasiquoters for things like JSON, SQL queries, JavaScript code, etc. It would be great if there was a way to configure quasiquoters with specific names to syntax highlight for the syntax they implement.

Is such a thing possible now? Is it possible at all with Atom's syntax highlighting support?

iand675 avatar Sep 16 '16 01:09 iand675

Sorry for the belated reply, I somehow managed to miss this.

So, answer to your question is both yes and no. While it's entirely possible to embed other grammars into language-haskell, it comes with its own set of challenges. And it's definitely not configurable on the user-end, at least not without some dark and forbidden magic (which is fragile by definition)

So at best, I could eventually add support for TH quasiquotes, since those have rigid syntax definitions. For user-defined quasiquoters, that's just not worth it, IMO -- this would create more problems in the long run than solve, e.g. a flaky third-party grammar can easily break highlighting in Haskell files almost completely.

P.S. also, support for user-defined quasiquoters opens a whole another can of worms if it's not configurable on the user-end, which I don't want to even think about.

lierdakil avatar Nov 16 '16 20:11 lierdakil

I would also like to have this. I understand that the mappings are hard-coded into the grammar and can't be modified by the user, but I still think it would be useful. Something like this would be awesome:

capture

I've never made a Textmate/Sublime/Atom grammar before, so I mocked that one up with this simple grammar:

name: 'Haskell'
scopeName: 'source.haskell'
fileTypes: [ 'hs' ]
patterns: [
  {
    begin: '\\[json\\|'
    end: '\\|\\]'
    patterns: [ include: 'source.json' ]
  }
]

Obviously that's a bit simplistic. For the Real World :tm:, two naive solutions come to mind:

  • Add hard-coded support for all the built-in language-* packages. That would cover most of the things people would be putting in quasi quotes (CSS, HTML, JSON, SQL, and so on). The downside is ignoring popular but not built in stuff like Docker or Nix.

  • Translate the quasi quote identifier into the source language. I don't know if Atom's grammar actually supports this, but if it does: Turning [Some.language| ... |] into a source.language section would neatly solve this problem without hard-coding anything. For example [Q.json| ... |] could be tagged as source.json. If this is possible, it would allow you to choose the inner syntax highlighting by choosing the appropriate identifier. (This is similar to language-ruby's heredoc syntax of <<-SQL.)

tfausak avatar Oct 07 '17 22:10 tfausak

Add hard-coded support for all the built-in language-* packages

I really don't like the idea of hard-coding this stuff, besides this grammar is used to highlight Haskell on GitHub as well, so I wonder if talking about language-* packages in Atom is even meaningful.

Adding all the "usual suspects" (json, yaml, sql, html, javascript, etc) would be possible in theory, but then it opens a can of worms of "why isn't X included". And with hardcoded prefixes there's another can of worms of "library Y uses prefix X for language Z". I'd personally much rather keep those proverbial cans closed.

Translate the quasi quote identifier into the source language.

Not possible. You'd need to include an external grammar based on what's parsed, and I'm pretty sure Atom's grammar model doesn't support this. I suspect partly because allowing something like that could break stuff really easily, and partly because it would be horribly inefficient (because you can't build a finite automaton if there are potentially infinite states)

lierdakil avatar Oct 07 '17 23:10 lierdakil

Bummer.

For comparison, language-ruby supports a few nested heredoc syntaxes. It's been around for a while and they haven't had a bunch of requests for more grammars. In fact, I could only find two: https://github.com/atom/language-ruby/pull/187 and https://github.com/atom/language-ruby/pull/199.

I feel like a partial solution here is better than nothing at all. Properly syntax highlighting SQL inside a quasi quote is definitely "nice to have"; treating it as a string is obviously okay. In my mind, supporting a couple of languages is a nice bonus rather than a "this needs to allow embedding everything under the sun".

tfausak avatar Oct 07 '17 23:10 tfausak

I came looking for a way to use SQL highlighting with the [here||] quasiquoter. I'd love to find or gain one!

aryairani avatar Jun 24 '20 18:06 aryairani

With language-haskell v1.20 (just released), you can make a grammar package for that yourself quite easily (you could do this with earlier versions, but v1.20 makes it way easier):

  1. run the package-generator:generate-language-package command to create a new language package.
  2. Name it however you like
  3. Delete snippets, settings and spec directories (we don't need them and defaults are useless)
  4. Use the following template to write grammars/*.cson:
injectionSelector: 'quoted.quasiquotes.qq-<your-quasiquote-function-name-here>.haskell'
scopeName: '<grammar-scope>' # the same as below
patterns: [ { include: '<grammar-scope>' } ]
# <grammar-scope> is the root scope name of the grammar you 
# want to inject. To learn the root scope of any grammar,
# use `editor:log-cursor-scope` command

So, for instance to inject SQL grammar inside [here|...|] quasiquotes, one would do:

injectionSelector: 'quoted.quasiquotes.qq-here.haskell'
scopeName: 'source.sql'
patterns: [ { include: 'source.sql' } ]

Please be aware, that depending on the grammar being injected, it can easily escape the quasiquotes scope and basically "take over" the Haskell grammar with rather unappealing results: image This is not an issue with language-haskell.

lierdakil avatar Jun 24 '20 19:06 lierdakil

@lierdakil Thanks! I didn't quite get it working, but I'm very excited. Can you spot anything I'm doing wrong?

My language package: image

I used apm link to install it: image

Result, still no injected syntax highlighting; I sanity-checked the scopes: image

I also tried restarting atom, but no change. 😅

aryairani avatar Jun 24 '20 20:06 aryairani

I can't see anything incorrect in the screenshots. Atom won't usually pick up the grammar injection package without a restart (or two), but usually running window:reload command a couple of times works too.

lierdakil avatar Jun 24 '20 21:06 lierdakil

I can't make it go (I even rebooted), but thanks for looking it over for me.

aryairani avatar Jun 25 '20 14:06 aryairani

@lierdakil blindly modeling after this gist, I switched the scopeName to match the injectionSelector, meaning I switched

injectionSelector: 'quoted.quasiquotes.qq-here.haskell'
scopeName: 'source.sql'
patterns: [ { include: 'source.sql' } ]

to

injectionSelector: 'quoted.quasiquotes.qq-here.haskell'
scopeName: 'quoted.quasiquotes.qq-here.haskell'
patterns: [ { include: 'source.sql' } ]

and that worked for me after a Window: Reload: image 🎉 Thanks for your help.

aryairani avatar Jun 25 '20 17:06 aryairani

Huh. Curious. Thanks for letting me know.

lierdakil avatar Jun 25 '20 22:06 lierdakil