Vim ale Rescript support

I use ale in vim, and was trying to configure it for Rescript. Maybe we can use this thread to discuss how to do it. There is also this issue in the ale repo.

First thing I wanted was to get formatting on save, a very quick way is to add this to your vim config:

let g:ale_fixers = {
\   'rescript': [
\     {buffers -> {
\       'command': 'bsc -color never -format %t'
\     }},
\   ],
\}

Making a proper fixer for a PR to ale seems like it wouldn’t be much work.

I still haven’t looked into making a linter from the compiler output, but @ryyppy’s vim-rescript fork has a function rescript#parsing#ParseCompilerErrorOutput(lines) that is supposed to parse errors into quickfix format, so something like that could be a good start for making a linter.

If anyone has ale experience or tooling experience please chime in, it would be good to have more options for tooling in vim.

Have a nice day!

2 Likes

I’m not familiar with ale but since it has LSP support I think you can just use rescript language server.

1 Like

I added instructions on how to hook up ReScript with coc-vim within the vim-rescript repository here: https://github.com/rescript-lang/vim-rescript#configuration-with-coc-vim-experimental

@joaking I am also not familiar with ALE, if you are just looking for reformatting functionality, use the vim-rescript extension and hook up the RescriptFormat function instead… it does exactly what you want, and if you follow the README keymappings, it also won’t collide with your existing setup.

1 Like

Has the amiralies repo moved to rescript-lang? Nice❣️

I don’t have experience with coc yet, so I’ll figure out if I want to introduce it and configure it in my config or if I want to make an ale linter + fixer.

Thank you both for the info :smiley:

2 Likes

New update, things are working!

With the last updates to vim-rescript and rescript-vscode plugin, now we can easily add a linter to vim-ale.

Setup

Install GitHub - rescript-lang/vim-rescript. For example with Plug 'rescript-lang/vim-rescript', and then running :PlugInstall

On your vim configuration folder, create plugin/rescript_ale.vim, with this content (replace the path to your vim-rescript plugin folder in the first line with yours):

call ale#Set('rescript_lsp_js_file', '~/.vim/plugged/vim-rescript/server/out/server.js')

" Give vim-ale the rescript executable to check because the LSP server is
" a non-executable JS file
call ale#Set('rescript_executable', 'rescript')
call ale#Set('rescript_use_global', get(g:, 'ale_use_global_executables', 1))


function! rescript_ale#GetRootDir(buffer) abort
    let l:config = ale#path#FindNearestFile(a:buffer, 'bsconfig.json')

    return !empty(l:config) ? fnamemodify(l:config, ':p:h') : ''
endfunction

function! FormatRescript(buffer) abort
  return {
  \   'command': 'rescript format -stdin .res'
  \}
endfunction

call ale#fix#registry#Add('rescript', 'FormatRescript', ['rescript'], 'rescript formatter')

call ale#linter#Define('rescript', {
\   'name': 'rescript',
\   'lsp': 'stdio',
\   'executable': {b -> ale#node#FindExecutable(b, 'rescript', [
\       'node_modules/.bin/rescript',
\       'rescript'
\   ])},
\   'command': {b -> 'node ' . ale#Var(b, 'rescript_lsp_js_file') . ' --stdio'},
\   'project_root': function('rescript_ale#GetRootDir'),
\   'language': 'rescript',
\})

On your vim configuration, init.vim or .vimrc for example, configure ale:

let g:ale_linters = {
\   'rescript': ['rescript'],
\}

let g:ale_fixers = {
\   'rescript': ['rescript'],
\}

And that’s it! Remember to run rescript build -w on your rescript project to get up to date diagnostics.


At this point I’m not sure if this should be in vim-ale like all the other linters, or in vim-rescript, or nowhere.

Contributions to vim-ale take a longer to get accepted and merged, so if the editor story is still a WIP and may change, it doesn’t sound like a great idea.

On the other hand the configuration is minimal, so it may be interesting to keep it at least documented or added to vim-rescript so that it can be updated as the language develops.

For now I’m just happy that this works :smiley:

It seems like rescript format with stdin like I did above prints its errors to stdout instead of stderr, so when you have a syntax error the errors with the terminal color codes end up replacing your buffer :sob:

I’ve opened rescript format should output errors to stderr instead of stdout · Issue #5131 · rescript-lang/rescript-compiler · GitHub to discuss this.

In the mean time, you can change the formatter to use the in-place formatting and it seems to behave well:

function! FormatRescript(buffer) abort
  return {
  \   'command': 'rescript format %t',
  \   'read_temporary_file': 1,
  \}
endfunction