Here's a topic for me to spam @Eli Dowling with questions and suggestions!
(and anyone else who's invested in syntax highlighting or semantic editing)
It looks like plain defs are mis-categorized as parameters:
inherits = "dracula"
"parameter" = "red"
"ui.text" = "grey"
"variable" = "black"
Screenshot_20250310_112103.png
(dracula colors variable.parameter
orange+italics)
What should the distinctions be between
Also, if you'd prefer I take a more "try to fix it myself" approach, I can learn the query syntax and shift to PRs.
Not a clue tbh. Early a fellow came in and made a pr making the queries more specific... and it didn't break my highlighting so I just shrugged and merged it :sweat_smile:
if you want to know the correct ones:
https://docs.helix-editor.com/themes.html#scopes
and these:
https://docs.helix-editor.com/guides/textobject.html
I think part of the problem is that neovim uses different names. So he may have just been working of that list
Totally feel free to go through and fix any that improve things on the helix side and then PR it in.
Interesting, module
doesn't appear in Helix's docs - did you get it from a different list?
I guess a bigger question is - what's the intended relationship between
because it all seems arbitrary to me.
JanCVanB said:
Interesting,
module
doesn't appear in Helix's docs - did you get it from a different list?
Same for these:
It’s hard for me to judge these until the examples have brace delimited blocks
Then I can tell how much I like a certain highlighting scheme
Oh, and of course, see it in Catppuccin Mocha
All that actually matters is what's defined in the theme within helix. Everything else is just a suggestion.
ahemNeovim
Eli Dowling said:
All that actually matters is what's defined in the theme within helix. Everything else is just a suggestion.
Sure, but I'm wondering what is this sitter's source of truth for what to name the exported keys - do you want to export a superset of anything that downstream themes want to consume, including some redundant names for the same things? Are Helix's conventions given any higher priority than Neovim's?
Anthony Bullard said:
ahemNeovim
Well Jan is editing the helix highlights.
The neovim has its own highlights file and the same rule applies there too.
Anthony Bullard said:
ahemNeovim
I'm trying to make a set of editor-agnostic themes that color .roc files in a way that matches our mental model of the syntax :grinning_face_with_smiling_eyes:
Oh, you basically just can't do that. The helix and neovim queries work different
They are interpreted in reverse order for example.
The conventions for names of things are different. It's all a total mess tbh.
That's why we maintain two sets of query files.
Yes, and I plan to generate & maintain a separate file for each editor x theme.
Now I see your neovim dir - so queries/highlights.scm
should use Helix's highlighting scopes as the source of truth?
Ahhh I think I understand now.
Well I would follow the conventions of each platform and then just add any extensions you need.
From memory the highlights have precedence so you can do type.this.that and as long as a theme has type
it'll highlight it even if it doesn't have the more specific versions.
Double check that though
Yes, the default queries are for helix. Because it closely follows the tree sitter spec... Neovim just kinda does whatever
Do you know where those 13 non-Helix-sourced scopes above came from?
If you look at the repo the very first full request is from the guy adding extra highlighting, I'd guess it's from that.
Gotttcha. Thanks!
I know he wanted to build a more precise theme that added more information. But I think he might have been working in neovim
He is probably in Zulip I'd imagine
I can start working to align that file 100% with Helix conventions.
Karl said:
I started messing with the tree-sitter grammar because I was trying to figure out why thing weren't highlighting. One thing led to another and I spent a good chunk of yesterday changing things and I now have seven reasonably sized commits. I'd like to know if you'd like them in one large PR or a set of smaller ones.
A lot of things are uncontroversial (e.g. tagging doc comments, tagging builtins) but some are more questionable like tagging match captures as parameters so that tree-sitters local analysis highlights typos.
Here's a before and after using my theme:
Screenshot-2024-04-01-at-5.06.49-PM.png
Screenshot-2024-04-01-at-5.08.03-PM.pngSome things come from extending the highlight match tags (e.g. separate colorspace for typedefs, highlighting fn defs) so other themes would need to be tweaked for full support.
Aha!
Hey nicely done
JanCVanB said:
I can start working to align that file 100% with Helix conventions.
If @Karl doesn't voice any concerns, @Eli Dowling does this sound right to you?
I think it makes more sense to fit in with someone's standards. I like that the extra fields allow for additional highlighting but I expect I'm the only one taking advantage of it.
Yeah align then as much as possible. But also feel free to keep or adapt any existing extensions to the spec for roc specific stuff
Sweet, I'll try!
This is my work-in-progress refactor of Helix Dracula, with some three-way analysis of discrepancies: https://gitlab.com/JanCVanB/rocwise-editor-themes/-/blob/main/helix/dracula.toml?ref_type=heads
@Eli Dowling What does "keep most generic types at the bottom for helix" mean? https://github.com/faldor20/tree-sitter-roc/blob/master/queries/highlights.scm#L205
I infer that higher in the file is higher priority?
Correct!
Is that just a Helix thing, hence the comment?
Yeah, neovim evaluates it the other way around. Which is why you may notice the order is kind of inverted
With regards to the evaluation order: I ran into this as well working to pull in tree-sitter for syntax-highlighting in my static site generation platform. Sharing here in case it's useful: it looks like Helix is working on flipping the order:
https://github.com/helix-editor/helix/issues/9436
The order Neovim/Zed use does appear to be the "correct" one according to tree-sitter. It's hard to find though, I believe I found mention in the code for highlighting project included in tree-sitter, also these release notes:
https://github.com/tree-sitter/tree-sitter/releases/tag/v0.21.0
So far I've refactored the highlights to make it easier to see the discrepancies: https://github.com/JanCVanB/tree-sitter-roc/blob/helixify_highlight_names/queries/highlights.scm
I'll continue by resolving them!
@Eli Dowling I see you chose to highlight tags with @constructor
and @type.enum.variant
- those make sense and seem to be colored by Helix themes. There is a @tag
name that we could use instead of @constructor
with similar coloring support in themes, but it's not clearly superior.
I am happy to leave it up to you to make the call on whether you think it looks better as a tag or a constructor. when I did it I don't believe my theme had any support for tag so I made it a constructor as that was what other languages used for unions.
Mostly I would also try and follow the conventions of other functional programming languages.
It's nice if a user coming to roc from Haskell can look at roc code and immediately see familiar colours for familiar constructs
Good call! I'll look into how Haskell's tree-sitter implementation(s?) categorize things. Any other comparables you want, in addition to Elm?
Elm, Haskell, Ocaml, Scala, elixir would probably cover like 95% of all production FP code right?
Can't forget my beloved Ocaml :stuck_out_tongue_wink:.
Unrelated, I see that almost half of the custom highlight names I listed above seem to be to facilitate coloring the same symbols/things differently if they're in typedefs - is that something you want to maintain?
All are probably worth a glance. I'd be inclined to weight the ones that are most recently created/updated with a lot more precidence.
TS norms and names have changed a fair bit over time, so it's worth taking recency into account
Also for the queries you should be looking at the queries in the helix repo rather than any queries inside the actual tree sitter grammars. Sometimes they are quite different
But helix ones are more likely to be more up to date with helix conventions/actually tested
Cool, I'll default to injecting an indication they're original, like
@punctuation.delimiter.typedef
to
@punctuation.delimiter.roc.typedef
JanCVanB said:
Unrelated, I see that almost half of the custom highlight names I listed above seem to be to facilitate coloring the same symbols/things differently if they're in typedefs - is that something you want to maintain?
I really don't care about that at all.
I think it'd be good to have a distinction between tag types and other types.
But also there isn't any harm in being more specific if people want to use them.
But yes I think prefixing them helps a lot
I really wouldn't stress about it though. Other than annoying @Karl :sweat_smile:
Oops misread your previous - understood
Yeah the only ones I'm eager to fully delete are those used instead of a standard one.
Oh sorry, yeah that was confusing. For total clarity, I did mean all the different languages highlight queries.
I trust you to make the right choice as far as weighing between being specific and just providing options that nobody will ever actually use.
I'd only suggest leaning towards simple and standard for the sake of future maintenance. Remember people can override this if they really want crazy over the top everything in rainbow.
I have more ideas, but I'll pause here! https://github.com/faldor20/tree-sitter-roc/pull/33 Feedback very welcome :smile:
Heads up, it's a nearly-total refactor. I rebased a bunch, to keep the incremental commit chain fairly readable.
Here's a preview of the nearly-ready Helix Dracula theme that plays nicely with the PR above :heart_eyes:
https://gitlab.com/JanCVanB/rocwise-editor-themes/-/blob/improve_helix_dracula/helix/dracula.toml?ref_type=heads
Screenshot_20250312_230533.png
... and that's with ui.text
still set to a super faded grey - we now have seemingly-complete coverage, because the only times I see it in code files now is with tree sitter errors
Cool! I'll take a look in the next couple of days. Mostly, so long as it still looks good with vanilla themes I'm happy :)
Sweet! No urgency, as this isn't blocking me.
Good call - I'll test it with the most popular builtins and post screenshots in the PR.
:check: Posted.
@JanCVanB Just added a comment.
@JanCVanB Sorry this took so long. I made some alterations.
very happy with it overall, there were just a few places where I wanted to align better to other langauages/helix recommendations
I made a pr to your branch:
https://github.com/JanCVanB/tree-sitter-roc/pull/1
Woohoo! Thanks, I'll review that today.
@Eli Dowling Merged! Ready for re-review on 33 :smile:
@JanCVanB you were happy with all those changes? Just letting you know I'm totally open to feedback or disagreement.
If you're happy at this point, I'm happy to and I'll merge :)
I was indeed happy with all :)
I'm confident that any room for improvement will be found by incoming PRs for the remaining TODOs
After this refactor merges, other PRs can be much more parallel
For example, you removing these is consistent with your choice to recategorize :
as punctuation. There are multiple different answers to "so now how can I color :
the same as the key before it in records", but we should leave that to follow-up discussions and not hold up this refactor.
Eli Dowling said:
Elm, Haskell, Ocaml, Scala, elixir would probably cover like 95% of all production FP code right?
if Clojure is in there then yes, but I suspect Clojure is over 5% of that by itself
See I'm always just a little leery of calling clojure FP... It's just, it feels distinct from those other languages in some ways. I recently saw an article in lobsters comparing an Ocaml and clojure implementation of the same thing and I feel like Ocaml one would be immediately understandable/ seem normal to any user of the other languages I listed. The clojure one... Not so much
Also comparing the token assignment of clojure to us probably doesn't reveal much given it's a lisp :sweat_smile:
big can of worms there haha
but yes, agreed that Clojure syntax highlighting won't have much to do with ours :big_smile:
That can of worms is why I want to learn clojure sometime... If other people are chowing down on the worms and just absolutely loving it, at some point you've gotta wonder.. maybe worms are worth trying.
I would have guessed that clojure is more fp than scala
Also, I wonder how much production code is in erlang. Just silently running the world.
Hahah mee too Brendan, me too...
It comes up anytime I feel I've been using something for a long time and I have the realisation that nothing has ever had a single failure.
I have the little, sniff sniff smells like bean... Wait, no it's BEAM
Brendan Hansknecht said:
Also, I wonder how much production code is in erlang. Just silently running the world.
90% of internet traffic runs through Erlang. See: https://x.com/guieevc/status/1002494428748140544
cc @Brendan Hansknecht
This is getting off-topic, but I'd asked this question because I was curious if, theoretically, a Roc Platform could exist that copied the behavior of the Erlang Runtime System and BEAM VM. Obviously, it's no joke to re-implement OTP/BEAM, but would a Roc Platform make it possible? (I'm new to Roc, pardon my ignorance)
Theoretically you could use a roc platform to run roc directly on the BEAM VM. Roc would be a native library and the platform would be written in erlang or elixir
Though you could also fully reimplement the BEAM VM in a roc platform instead
Last updated: Jul 06 2025 at 12:14 UTC