Rescript emacs support with rescript-vscode

@ryyppy patch here: https://github.com/rescript-lang/rescript-vscode/pull/88

I’m not taking for granted that this will be accepted by the way nor ignoring @yawaramin’s comment (we talked off the thread and I concluded I probably should have opened a github issue instead of raising it here – but now I’ve done it this way I guess there’s no point in raising an issue too).

But obviously I think the patch should be applied :slight_smile:

The rescript-vscode LSP server change has been merged and I’m planning to work a bit on the emacs side of this this weekend.

Only now do I remember ah yes, ReScript syntax eliminates semicolons, so I’ve probably cut out more work for myself than I expected :wink: (I still plan to do it!)

In particular, indentation from reason-mode.el (in fact, reason-indent.el) may require a bigger rewrite than I imagined (this part is unrelated to LSP and rescript-vscode, it’s pure elisp; I haven’t yet read the code but I expect it’s relying on the presence of semicolons heavily).

If anybody here has advice for how to implement indenting ReScript code I’d love to hear what you think, because right now I’m fairly clueless about it.

2 Likes

@rewrangler do you have a fork of reason-mode.el you could share? I’m interested in trying out rescript and would like to use emacs too :slight_smile:

Regarding formatting I just used the reformatter emacs package

(reformatter-define rescript
  :program "resfmt")

Where resfmt is a shim so that bsb -format can work with stdin: https://pypi.org/project/resfmt/

I’m totally interested too. Just discovered last week that Rescript happened while I was waiting for Reason to get little more friendly. I really would like to try it in my current project but it is unpleasant to work without nice editor integration.

Btw. it would be great if you can share even your uncomplete work with some TODOs. Maybe we can even give you a hand (no promises :slight_smile: ).

Regarding formatting I just used the reformatter emacs package

Another alternative is format-all package which rescript support already (I believe it is where that resfmt shim comes from too).

1 Like

On master: bsc -o MyFile.res -format MyFile.res

I’d like to still set the expectations that I’ve cleaned and merged that diff as an experiment. As long as you folks are ok with that status then go ahead. But please advertise this as an unstable thing that might break, including on these published wrapper libs. Otherwise we’ll end up having to cater to some expectation mismatches which are much more troublesome than a PR. Thanks =)

3 Likes

Thanks

Feel free to comment on any of the following if you think it’s better to do it differently.

One thing I’m not sure of from this page is whether you regard vim/neovim (etc.?) as in an intermediate category (between emacs and VS Code/Sublime), so not sure if that part of my wording below is best from your point of view.

I guess my default is to try and publish what I have quickly when it’s minimally useable (in a standalone repo) and then iterate on that, but label it loudly as unsupported by ReScript or rescript-vscode – something like:

Emacs is NOT SUPPORTED by the ReScript core team, nor rescript-vscode. The core ReScript team’s focus for editor support is currently on supporting VS Code and Sublime Text well. So, if you want something that you can be confident is going to work smoothly and will not go away, use one of the editors listed as supported by the core ReScript team (currently VS Code and Sublime Text). In particular, the emacs support here depends on the LSP server from rescript-vscode and its --stdio switch, neither of which are officially supported and could be removed in a later version.

So if you have problems with Emacs and ReScript, please report your issues here, not upstream with ReScript or rescript-vscode (neither on the forum nor the github issues) and please don’t complain if you used ReScript with Emacs and had a bad time – if you did that, you’re going it alone and you really didn’t try the official ReScript experience – that’s unfair and a good way to annoy everybody.

This code is also early pre-release software, expect to run into issues if you choose to use it.

Perhaps it’s also best if discussion were kept to github issues (and github discussions maybe) on the repo I will create rather than here on this forum (I’ll still announce in this thread when I’ve published of course).

To be clear, I believe format-all runs bsb -format (via this non-official resfmt PyPI project that kepi mentioned). No published code to my knowledge is yet using the LSP server and --stdio (except if you just point the existing lsp-mode.el at it of course).

What I personally expect these days with most languages in emacs is:

  1. Formatting: This means that you run say lsp-format-buffer (, = b in spacemacs), or one of the tools mentioned (format-all, reformatter) and your whole buffer (or some section of it that you specify maybe) is magically formatted correctly.

  2. Indentation: This means that hitting the tab key or the return key (depending how you have things configured I guess) gives you an approximation of the “official” formatting of a tool like bsc -format. It’s never identical to what something like bsc -format produces, but it stops you thinking much about formatting when writing code or having to hit the tab key much.

Item 1. works already via LSP, 2. does not because I have to write elisp code to support it.

Do you have a different expectation?

I’ll do a bit today I hope (so far today I’ve been on this forum when I hoped to be doing that :wink: )

Edit: now I recall that formatting via LSP only works because of a hack I made to lsp-mode.el that I need to fix and upstream. I did mention that here, so presumably that’s why people were posting about how to format a different way!

Yeah we’re fine with it as long as there’s such disclaimer! =)

1 Like

Today having tried some simpleminded hacks to reason-indent.el, I see that indeed it looks pretty tricky to start from there, due to the semicolon issue. js.el actually produces mostly reasonable indentation from the file I tested it on, not miles away from what bsc -format produces, at least if I remove the quoted infix operators that I just posted about elsewhere. js.el is the more simple-minded mode that comes with emacs, as opposed to the fancier and much more correct js2-mode.el. I think I should start just by doing a straight copy of the indentation code from js.el (therefore relicensing to GPL v3) and doing a release as soon as I can, rather than trying to rescue reason-indent.el.

Comments/advice about that still welcome though.

Btw, as much as I reiterate that we should advertise this as experimental, I do think it’ll be nice if we can at least replace reason-mode with your work here in the future: https://rescript-lang.org/docs/manual/latest/editor-plugins

1 Like

I gave indentation another try today: big careless copy-pastes of large chunks of js-mode resulted in something that seems to work. The JSX support there is not obviously transferrable easily (it depends on font-lock properties created by code that looks fairly hairy that presumably would have to be combined with the existing reason-mode.el font-lock code that I also shovelled over). I’ve made no effort to remove JS knowledge nor add any ReScript knowledge in this indentation code.

Indentation on my project is pretty reasonable (which it has no right to be given how I’ve “implemented” it, if you can call it that!) – except for JSX. Sometimes JSX indentation isn’t too crazy, sometimes it is. It’s never good. I think it’s better than no indentation support when you’re writing JSX, but maybe not a whole lot better. I haven’t actually been coding with this yet, just indenting existing code. You can always ask bsc to indent (, = b in spacemacs) and things look fine. It seems that sometimes emacs takes minutes to apply the formatting changes from the LSP server (this is an emacs issue with updating the emacs buffer with the new text, not an issue affecting VS code nor the LSP server code) – I haven’t investigated to see exactly what problem it’s having, but so far it seems like if you don’t let the formatting get crazy far from the official bsc -format formatting (as in the whole buffer is totally different), that doesn’t happen.

Seems close to a minimally useful version, I think I need to:

  • remove the hack I used to work around an lsp-format-buffer issue, and submit a patch upstream
  • do a very slightly more careful re-do of the js-mode indentation hack, maybe
  • put the code in a repo with basic config examples

There’ll still be plenty of bugs then I’m sure, so keep your expectations not too high!

Edit: now I recall again that people had a different way to bsc -format, so I guess I won’t wait for that to work over LSP. Probably will be at least a week before I get around to publishing it though.

3 Likes

You’re doing awesome work, even if there are bugs, a nice Emacs experience is always a boon!

2 Likes

Seems I’ve got some more coding style guidelines to read before I can push to MELPA, so the install docs won’t work yet and you probably want to wait a day until the MELPA packages show up before trying this, but I’ve pushed what I’ve done here (the LSP config is in a separate repo lsp-rescript… hm maybe I should rename the repo to have emacs in the name):

Please:

  • Keep your expectations realistic: As I mentioned, indentation is “borrowed” from js.el and I left out the JSX indentation support from that entirely.
  • Keep discussion to the github issues or discussions on the rescript-mode github project rather than here

When I’ve pushed it to MELPA and given it a test this afternoon, I’d be glad of feedback of course

I’ll push a PR for the ReScript docs that reference the old reason-mode later.

Edit: first of two MELPA packages submitted (the other one’s the LSP config): Add rescript-mode recipe by jjlee · Pull Request #7545 · melpa/melpa · GitHub done
second one: Add lsp-rescript recipe by jjlee · Pull Request #7558 · melpa/melpa · GitHub – done

6 Likes

I love you, awesome work. Just got a new job in rescript and was super sad about the fact I couldn’t work in emacs.

1 Like

I thought I should mention that since I did this, @CarlOlson has done some work on a different fork of reason-mode, which he has also named rescript-mode (same name as my mode) here:

I’ll leave Carl to describe the differences if he wants.

You should be able to use lsp-rescript with either mode (this is just the lsp-mode config for rescript-vscode + a workaround). Edit: oops, strictly true but in fact you’d have to change lsp-language-id-configuration to point to Carl’s mode in fact. I just made that dependency on my MELPA rescript-mode package explicit in the lsp-rescript package – I won’t try to remove that dependency since this package is mostly useful as installable working (I hope!) boilerplate.

I’d personally be very happy if somebody else maintained emacs support for ReScript. Perhaps it’s not ideal if there are two modes called exactly “rescript-mode”, though (open to suggestions).

2 Likes

It should be stable if indentation isn’t needed, but I’m not treating my rescript-mode as something ready to use yet. I’m removing a lot of code and trying to make it simpler (the indentation code is always a mess in Emacs).

Since the direction is a bit different, I can rename it to not cause any confusion. However, it certainly won’t be in melpa for a long time (if ever).

1 Like

The MELPA code review is done, so the install docs work now. Currently the docs still refer to bsb etc. which I believe have just been renamed in the latest release – I’ll fix that, but I don’t think it should cause any problems (emacs isn’t running any of that directly).

One niggle: you need to explicitly M-x package-install <RET> rescript-mode <RET> if you’re following the “Vanilla emacs” install instructions. The spacemacs install instructions are not affected. I just pushed a fix to lsp-rescript to depend on rescript-mode, it will propagate to MELPA in a day or so I think.

Please keep any discussion on the github project, thanks.

2 Likes