reddit / emacs

Really sick of the shoddy jsx/tsx handling....would anyone be willing to help me write a major-mode for it?

tangled_up_in_blue · 2022-01-24 21:49
As react is now the most popular FE framework by a mile (and I and countless others work in it daily), it drives me crazy there's no major-mode for it. I've done a ton of googling and tried a lot of solutions people put online, and I did have some that worked decently well, but none are perfect and the one I was just using broke after an update (like many I've tried before have). I feel like the best solution would be to just write a major-mode for it, it would help keep a lot of web devs on emacs who like the extensibility but are frustrated by the amount of work it takes to just get jsx/tsx to be supported like they are in every other major editor (maybe vim aside, I never use it so I can't say). I have some basic emacs experience, I've been using it daily for about 3 years and have fiddled around with some packages and gone through elisp tutorials and even built some dumb programs to play around (like a tic-tac-toe game), but I honestly don't know the first thing about writing a major mode, and while I've read some tutorials on doing so I know people who have experience doing this have a much better idea of what would need to be done, how to break down the work required, and what modern tools (thinking treesitter) could be used to make the syntax parsing, etc much easier. I do work full time and am also doing my MBA, but I'd be more than happy to dedicate a night or two a week to get this moving. Unless there's something else out there or someone has started on something, I'd be more than happy to contribute, I just need some guidance on getting up to speed on everything required for a fully-functional major mode. Hopefully this isn't some pipe dream, I feel like with tree-sitter and lsp (and the foundational work already done for other js modes) we could come up with something really solid. Let me know your thoughts, appreciated!
nv-elisp · 2022-01-24 21:52
I would do this for money.
hvis · 2022-01-24 22:16
If we're talking JSX, `js-mode` has some fairly decent support for it starting with Emacs 27. If you have problems with it, it's the place to improve. But it doesn't support TypeScript or TSX, alas.
orzechod · 2022-01-24 22:52
what are your specific problems? `lsp`, `typescript-mode`, and `tree-sitter-mode` together give me 90% of what I need. I fixed JSX/TSX indentation with [a little tool I built](https://github.com/orzechowskid/tsi.el) (which I should really get around to publishing some day). I'm extremely happy with this setup and use it every day on professional and personal projects. https://github.com/orzechowskid/dotfiles/blob/master/init.el#L151
RogueToad · 2022-01-25 04:01
Likewise, except that I swap out `lsp` for `tide` - I've had trouble before where my lsp session starts to lag after a while in larger react projects, has that ever happened for you? Also gonna give your minor mode a go, thanks for the tip - formatting with prettier on save fixes the indentation of course but it still can be annoying in the moment.
0xMii · 2022-01-25 07:44
web-mode + tree-sitter works really well. (tree-sitter-require 'tsx) (define-derived-mode typescript-tsx-mode web-mode "TypeScript/TSX") (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-tsx-mode)) (add-to-list 'tree-sitter-major-mode-language-alist '(typescript-tsx-mode . tsx))) This works well out of the box, but you can pair it with lsp-mode and eslint to have more complex behaviours like different indentation settings in the JS-parts vs. the JSX-parts of the file working as well.
Throwaway1588442 · 2022-01-25 14:41
I use tide mode and web mode and have no major issues with it
dpassen1 · 2022-01-25 20:25
Please publish :-)
tangled_up_in_blue · 2022-01-29 01:48
Is it better than js2-mode now? I've always just used js2-mode because I heard it was better. But if they improved it and added jsx support that would be awesome
hvis · 2022-01-29 01:51
They use different approaches. There is a section about JSX in js2-mode's README, check it out: https://github.com/mooz/js2-mode/#react-and-jsx (Note the mention of rjsx-mode as an option, too.)
tangled_up_in_blue · 2022-01-29 01:53
Thanks man, this is really, really nice. I've been using it for two days straight and it's worked very well. I am curious though, why did you write your own indentation tool? (It works super well btw, amazing work) I thought tree-sitter supported tsx (and found repos like [this](https://github.com/tree-sitter/tree-sitter-typescript)) so just wondering if you tried those and they didn't work so you wrote your own. Maybe one day if I feel adventurous enough I'll make a major mode and use your project to handle indentation, if you wouldn't mind of course. Anyway, appreciate the work you did, it's great
orzechod · 2022-01-29 02:41
so [tree-sitter](https://tree-sitter.github.io/tree-sitter/) itself is just a parser that turns source code into a syntax tree based on the grammar rules of your programming language. it "supports" JS/TS in that it can take a JS or TS source file and turn its contents into a tree-sitter data structure. what users of tree-sitter do with that data structure is up to them: highlight, indent, code-fold, jump-to-definition, whatever. [emacs-tree-sitter](https://emacs-tree-sitter.github.io/) is the emacs interface to tree-sitter, exposing tree-sitter's syntax tree to the elisp world. the only user-level feature provided out-of-the-box by emacs-tree-sitter is syntax highlighting, which you use instead of any syntax highlighting built into your major mode. the thing I wrote takes the syntax tree exposed by tree-sitter (via emacs-tree-sitter) and uses it to calculate indentation for your source code. I wrote my own tool because I couldn't find one which supported JS/JSX, and because it was fun! maybe some day it will get incorporated into typescript-mode or one of the other JS/TS major modes, who knows. maybe yours? :)
stevemolitor · 2022-02-12 14:45
tsi.el is awesome thanks! If I use tree-sitter-hl-mode for syntax highlighting and tsi.el for indentation, do I even need typescript-mode.el anymore? Random question: I noticed you set up html-mode to auto-close tags on “</“. Is there a way to do that in tsx files, without using web-mode?
orzechod · 2022-02-12 20:54
> If I use tree-sitter-hl-mode for syntax highlighting and tsi.el for indentation, do I even need typescript-mode.el anymore? tree-sitter keeps a major-modes -> languages mapping at `tree-sitter-major-mode-language-alist`, so I think you still need a major mode of some sort to associate with tree-sitter's TS parser. also, typescript-mode integrates with `compilation-mode` and also provides some [utility functions](https://github.com/emacs-typescript/typescript.el/blob/master/typescript-mode.el#L701) so I do think it's more than just a highlighter+indenter. > I noticed you set up html-mode to auto-close tags on “</“. Is there a way to do that in tsx files, without using web-mode? `sgml-quick-keys` comes from `sgml-mode`, so if your major mode extends from or incorporates that one then you're good to go. and thanks for the kind words!
IntelligentFerret385 · 2022-02-12 23:39
>sgml-quick-keys comes from sgml-mode, so if your major mode extends from or incorporates that one then you're good to go. Yeah I wanted to do it in my typescript-tsx-mode which derives from typescript-mode. Anyway me asking about sgml-quick-keys is a bit off topic - sorry about that! What you say re typescript-mode makes sense. I've started using tsi.el and it works like a charm! Btw I did get this warning: `...tsi.el/tsi-typescript.el: Warning: Use keywords rather than deprecated positional arguments to \`define-minor-mode'\` I just got rid of the `nil nil` bit to fix: (define-minor-mode tsi-typescript-mode "Use tree-sitter to calculate indentation for Typescript buffers." ;; don't need nil nil here: ;; nil nil :keymap (make-sparse-keymap) (cond ;; .... The first two deprecated positional args are the `:init` and `:lighter`, which you can skip if nil. I'm using emacs 28. Err, maybe I should do a pull request!