danderson,
@danderson@hachyderm.io avatar

Whee, I got multi-language parsing to work, I think!

Templ is mostly plain Go, with three new top-level definitions that aren't Go. Templ's grammar is a superset of Go, but for Reasons I can only reuse go-ts-mode's go-ish stuff if the actually-go bits are handled by the Go tree-sitter parser.

danderson,
@danderson@hachyderm.io avatar

So, current approach: parse the entire buffer with the templ parser, which understands both the Go superset and templ-specific bits. Then, use a tree-sitter query to identify the subset of the buffer that contains the couple of unique-to-templ constructs, invert the selection, and set the entire rest of the buffer as a Go sub-language.

danderson,
@danderson@hachyderm.io avatar

The net result is go-ts-mode is in charge of parsing, highlighting, indenting, completing, whatever, while my mode retains responsibility for the novel portions of the language.

Not sure this is actually a good way to do it yet, in a perfect world I would instead be able to grab go-ts-mode's font locking rules and re-task them onto the templ parser, but the way go-ts-mode is written, I can't get at the rules in uncompiled form :(

creachadair,
@creachadair@mastodon.social avatar

@danderson that seems like a good use of your resources. There's no sense trying to make a whole new parser when you already have one that gives proper source ranges.

danderson,
@danderson@hachyderm.io avatar

@creachadair In practice, templ's parser already does the work of parsing Go anyway (and tree-sitter makes that efficient, templ literally defines itself as a derived parser and can reference the Go grammar as it pleases in its own grammar).

The problem is the way the treesitter font lock rules are written, from where I'm standing I can only get the "compiled" font lock rules for Go, which are welded to the language parser for Go.

danderson,
@danderson@hachyderm.io avatar

@creachadair So, I can add Go's font lock rules to my mode's... But they do nothing because my mode says it's for the language 'templ, and all the Go font locking queries interrogate the 'go parse tree... And so font locking ignores those rules.

To make it use those rules, I have to tell tree-sitter that some portion of the buffer should be delegated to the 'go parser, at which point the font-lock queries find nodes in the 'go parse tree, and font-lock properly.

danderson,
@danderson@hachyderm.io avatar

@creachadair If I could just get at the go font-lock rules before they get compiled, I could s/go/templ/ on them and get all the font locking with a single parse tree. But go-ts-mode doesn't expose the pre-compilation rules, only the post-compilation rules.

So my alternatives are doing a lot of futzing to split the buffer into Templ and Go, to be able to reuse Go's font locking (and maybe also its indent rules? Unsure), or copy-paste the Go font-lock rules into templ-mode.el. Which, icky.

danderson,
@danderson@hachyderm.io avatar

@creachadair And, annoyingly, tree-sitter doesn't make it efficient to do the parse tree splitting I'm doing. It knows how to query for "a node with this other node as a child", so I can query for "all templ-specific definition blocks" very easily... But I can't query for "everything except templ-specific blocks" easily, I'd have to explicitly name every possible valid Go tree node, of which there are very many in this parser.

So I'm having to do some icky/slow buffer range math nonsense :/

danderson,
@danderson@hachyderm.io avatar

@creachadair Really this is partly that there's a lack of solid conventions in emacs around ts-powered major modes, so derived modes end up having a bad time if they want to piggyback on stuff from their parent. I expect it'll sort itself out eventually.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • ngwrru68w68
  • rosin
  • GTA5RPClips
  • osvaldo12
  • love
  • Youngstown
  • slotface
  • khanakhh
  • everett
  • kavyap
  • mdbf
  • DreamBathrooms
  • thenastyranch
  • magazineikmin
  • megavids
  • InstantRegret
  • normalnudes
  • tacticalgear
  • cubers
  • ethstaker
  • modclub
  • cisconetworking
  • Durango
  • anitta
  • Leos
  • tester
  • provamag3
  • JUstTest
  • All magazines