Closed stevemolitor closed 1 year ago
tsx-ts-mode
is really nice, isn't it? I've spent a little time working on a CSS-in-JS minor mode compatible with it. indentation and syntax highlighting seem to work well; capf for the CSS bits is not quite there. I do seem to be causing emacs to segfault a lot though, so that's exciting :)
I have an .el file as a gist here and I'd be curious to hear your thoughts on it: https://gist.github.com/orzechowskid/15c2e45e3ce390bfa4a56f516d788d31
the plan is to polish that up and eventually release it as a minor-mode. there doesn't appear to be a seamless way to get grammar binaries onto your machine (though this article on leveraging straight.el seems really useful), so I think this minor-mode should expose a function to fetch the correct binary from this repository and write it to the correct place on disk for your OS:
(use-package 'css-in-js-mode
:config
(css-in-js-fetch-and-store-dylib))
I think some stuff from tree-sitter-css-in-js.el
in this repo can be re-used here, and I'd love the help if you have the bandwidth!
Yeah tsx-ts-mode
is nice. It fixes a few niggling edge case TypeScript indentation issues with tsx-mode
that I'd been meaning to fix but hadn't gotten around to. Then I tried tsx-ts-mode
and it handled them perfectly!
I'd be happy to help when I can. I'm out for the next 2 weeks.
I tried your gist. It highlighted CSS correctly, but not TypeScript:
EDIT - I didn't realize css-in-js-mode
was a minor mode at first. Here's what I get running tsx-ts-mode
and css-in-js-mode
:
I lose much of the TypeScript highlighting. Without css-in-js mode I see this:
Initial indentation in a styled section was 2 spaces to the left of where it should be - flush fully to the left. That might be an easy hack to fix.
CSS completion did work for me at least sometimes:
I used a css-in-js.dylib
that I built on August 23. I copied it to libtree-sitter-css-in-js.dylib
in my treesit-extra-load-path
. Not sure if I need to rebuild to pick up the latest changes.
thanks for the quick feedback.
I lose much of the TypeScript highlighting. Without css-in-js mode I see this:
probably due to the value of treesit-font-lock-feature-list
. that variable stores a list of lists, each corresponding to a different level of font-locking. I've currently set it to only the css-in-js bits.
Initial indentation in a styled section was 2 spaces to the left of where it should be - flush fully to the left.
and here I was thinking a default indent amount of css-indent-offset
would be nice :) I think this should be made a configurable option.
Not sure if I need to rebuild to pick up the latest changes.
the latest change to the grammar was made in this commit from September 13, so it might be worth pulling and rebuilding.
probably due to the value of treesit-font-lock-feature-list
Oh ok. I tried slapping the lists from tsx-ts-mode
in their as well and got different but still incorrect results. ;) Not sure how to fiddle with that yet.
the latest change to the grammar was made in this commit from September 13, so it might be worth pulling and rebuilding.
Thanks. I rebuilt from latest and now I too can make emacs segfault. ;) Not sure if that's related or coincidental.
I've added a css-in-js-mode.el
on the next
branch of this repo. it's the gist from earlier plus some stuff we've noticed didn't work quite right.
css-in-js-mode-leading-indentation
lets you control the amount of leading indentation for CSS-in-JS regions. (you might need to customize this value before enabling css-in-js-mode
due to how treesit does its magic?)inline
, block
, etc. for the display
rule)css-ts-mode
I've added a css-in-js-mode.el on the next branch of this repo
Is it in the main
branch now?
I tried the latest css-in-js-mode.el
from the main
branch but it consistently segfaults for me when I turn on css-in-js-mode
. :(
I have an M1 machine and am using libtree-sitter-css-in-js.dylib
that I build locally.
Is it in the main branch now?
it is, yep
I tried the latest css-in-js-mode.el from the main branch but it consistently segfaults for me when I turn on css-in-js-mode. :(
oof, really? that's a rude surprise. I'm not immediately sure what would cause that to happen; I don't think the elisp code is using any features implemented in C whch it wasn't using prior to now. I was able to cross-compile an arm64 dylib inside of a Github Action; want to give that a try and see if you get different results?
https://github.com/orzechowskid/tree-sitter-css-in-js/releases/tag/latest
@orzechowskid using the arm64 dylib you built did the trick! Actually I put both the macos .so
and the .dylib
file in my treesit-extra-load-path
. It's working great now!
I haven't quite figured out the indentation. When I use newline-and-indent
/ C-j
, the new line is flush all the way to the left. If however I use indent-for-tab-command
/ TAB
, it works as expected. By default it indents 2 spaces, the same as my typescript-ts-mode-indent-offset
. If I set css-in-js-mode-leading-indentation
to 2
, it indents 4 spaces. I get it now, but sorry for the confusion or any extra work there. My problem is actually with C-j
. Fwiw, C-j
does work as expected for me in a .css
file in css-ts-mode
.
This is minor and maybe outside of your control, but re css-in-js-mode-show-color-values
I noticed that color names like red
are colorized, but hex values like #FF0000
are not, as you can see from the screenshot above.
But anyways this is looking fantastic!
Ok now I'm getting greedy ;) :
In a .css
file using css-ts-mode
and lsp-mode
I can get CSS documentation:
Any thoughts on how do get that working in css-in-js-mode? This might be outside the scope of this project! It relates to this tsx-mode
issue.
Can you point me in the direction of how to extend the grammar to support other CSS-in-JS flavors? My current project is using emotion which looks like this, not supported yet by tree-sitter-in-js
yet:
import { css } from '@emotion/react';
const myCss = css`
display: flex;
flex-direction: column;
gap: 40px;
`;
using the arm64 dylib you built did the trick!
oh, great news! saves me from having to spend $600 on hardware to test a free side-project :)
My problem is actually with C-j. Fwiw, C-j does work as expected for me in a .css file in css-ts-mode.
since this minor mode uses its own indentation rules, I'm not surprised that it works elsewhere but not here. I don't fully understand treesit-based indentation just yet but I believe it should be a matter of adding a new indentation rule to this minor mode which uses the no-node
matcher to check for empty lines and apply an offset of css-indent-offset
.
I noticed that color names like red are colorized, but hex values like #FF0000 are not
oh, whoops - I was only applying that font-locking function to treesit nodes of type plain_value
, not color_value
(a distinct node type recognized by the base CSS treesit grammar). should be fixed next time I push.
Any thoughts on how do get [css-in-js documentation] working in css-in-js-mode?
I'm pretty sure that's the responsibility of the LSP server (and possibly client) you're using. you'll need to configure your server to understand CSS-in-JS syntax, or you might be able to run multiple LSP servers and send CSS-in-JS buffers or substrings to a CSS server? not sure.
Can you point me in the direction of how to extend the grammar to support other CSS-in-JS flavors?
just FYI the CSS-in-JS grammar and the emacs support for CSS-in-JS libraries are two different things. if you need to apply this minor mode to more regions of a .js file then all you should have to do is extend css-in-js-mode--region-queries
to match more stuff. if you need to update the actual grammar because you're seeing error nodes in your treesit tree then that's a little more involved.
extend css-in-js-mode--region-queries to match more stuff
Thanks, this worked perfectly:
(add-to-list css-in-js-mode--region-queries
'((call_expression ((identifier) @id) (:match "css" @id) (template_string) @ts)))
There are more variations in using emotion which I'll play with, but it should be easy enough to adjust if needed.
I did notice that styled
objects with props did not work:
export const Div = styled.div<{ isRed: boolean }>`
background-color: ${({ isRed }) => (isRed ? 'red' : 'green')};
`;
Completion worked but highlighting did not. Maybe more adjustments to css-in-js-mode--region-queries
will fix? I'm not using styled
in my current project so it may be a while before I exercise it fully with this mode. I will be using emotion with this mode a lot though.
This is a great mode, very flexible! Thanks for working on it!
I think I'm going to close this issue as there's been no activity for a while and things do seem to be working with treesit in emacs 29. if there are any enhancement requests to this library or minor mode specifically then definitely open a new issue!
Any idea what it would take to adapt
tree-sitter-css-in-js
for use with Emacs 29 built-in tree-sitter support?I started playing around with a hacked version of the typescript-ts-mode.el that comes with Emacs 29. I got it to use
css-in-js.dylib
built from this repo, and using the newtreesit-explore-mode
I could see tree-sitter correctly parsing embedded CSS as CSS nodes, and TSX as TSX nodes.I couldn't quite get font-lock for CSS to work though (it still highlighted as plain TypeScript strings). I didn't spend too much time on it however.
Happy to help out or spike stuff - was just wondering if you had any pointers or had played around with this.
Thanks!