ReasonML Development With Vim
Tags: vim, reason, editors
Published: 2019-09-21 16:23:53

---
title: ReasonML Development With Vim
published: true
tags: Vim,Reason,editors
canonical_url: https://www.rockyourcode.com/reason-ml-development-with-vim
---

Vim is my favorite editor, and I prefer it over VS Code.

(Neo)Vim offers a light-weight, fast experience where I can quickly navigate via keyboard shortcuts and use the terminal to its fullest.

[Reason offers superb editor support for Vim][reasoneditor].

_From the vim-reason-plus README:_

> To have the complete Vim/Neovim Reason experience, there are two plugins to install: [vim-reason-plus], and the language-server.
>
> [vim-reason-plus] provides syntax highlight, snippets for Reason and allows related features to recognize the Reason syntax.
>
> Language-server provides all the others (autocompletion, type hint, jump-to-definition, etc.).

## Install Reason and BuckleScript

The easiest way is to install the packages globally:

```bash
$ npm install -g bs-platform reason-cli@latest-linux

// or `reason-cli@latest-macos`
```

(Windows users should check out these [instructions][windows].)

# VIM Setup

The [official instructions are very helpful][vimreasonplus], and you should look them up.

You'll need Vim with Python 3 support, or NeoVim (I prefer [NeoVim][neovim]).

In your Vim configuration file (`.vimrc` or similar):

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

syntax on
filetype plugin indent on

set laststatus=2
set wildmenu
set hidden
```

You'll need **[vim-reason-plus][vimreasonplus]**.

I use [minpac][minpac] as my package manager, but [vim-plug](https://github.com/junegunn/vim-plug) seems to be another popular choice.

Add this to `.vimrc` (or `~/.config/nvim/init.vim` for NeoVim):

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

" Using minpac
call minpac#add('reasonml-editor/vim-reason-plus')

" If using Vim-Plug
Plug 'reasonml-editor/vim-reason-plus'
```

## Language Server & Language Client

For optimal language support with auto-completion, type hints, etc., you'll need a language server plugin.

If you're interested in the Language Server Protocol, you should check out this [Reddit post: **A guide to LSP in VIM**][lspguide].

**[LanguageClient-neovim][languageclient]** suits my needs: it provides documentation to help you with your setup, and it works fine after some minor configuration.

### LanguageClient-neovim Installation

The language client plugin works with NeoVim and Vim8.

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

" Using minpac
call minpac#add('autozimu/LanguageClient-neovim', {'rev': 'next', 'do': '!bash install.sh'})

" Vim-Plug
Plug 'autozimu/LanguageClient-neovim', {'branch': 'next', 'do': '!bash install.sh'}
```

You have to install a protocol for _each language_. (That's a bit of a hassle, I admit.)

For Reason, you should use **[Reason Language Server][reasonlanguageserver]**.

Unfortunately, you have to manually [download the latest release](https://github.com/jaredly/reason-language-server#vim). Then point your language client plugin to the location of the executable.

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

let g:LanguageClient_serverCommands = {
    \ 'reason': ['/absolute/path/to/reason-language-server.exe']
    \ }

```

Some example key bindings:

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

nnoremap <F5> :call LanguageClient_contextMenu()<CR>
" Or map each action separately
nnoremap <silent> K :call LanguageClient#textDocument_hover()<CR>
nnoremap <silent> gd :call LanguageClient#textDocument_definition()<CR>
nnoremap <silent> <F2> :call LanguageClient#textDocument_rename()<CR>
```

# Optional: ALE

**[ALE][ale]** is another favorite module which helps with linting (syntax checking and semantic errors) and fixing/formatting files.

For me, the tool lessens the cognitive overhead of having to format my files correctly.

ALE also comes with language server protocol features. But those are not as fleshed out as with dedicated LSP plugins.

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

" Using minpac
call minpac#add('dense-analysis/ale')

" Using vim-plug
Plug 'dense-analysis/ale'
```

Add the following to your configuration file:

```vimscript
" in `.vimrc` or `~/.config/nvim/init.vim`

let g:ale_reason_ls_executable = <path-to-your-reason-language-server.exe>
let g:ale_linters = {
\   'reason': ['reason-language-server'],
\}
let g:ale_fixers = {
\   'reason': ['refmt'],
\}

" Optional (but useful) configuration
let g:ale_sign_error                  = '✘'
let g:ale_sign_warning                = '⚠'
highlight ALEErrorSign ctermbg        =NONE ctermfg=red
highlight ALEWarningSign ctermbg      =NONE ctermfg=yellow
let g:ale_linters_explicit            = 1
let g:ale_lint_on_text_changed        = 'never'
let g:ale_lint_on_enter               = 0
let g:ale_lint_on_save                = 1
let g:ale_fix_on_save                 = 1

" Example key bindings
nmap <leader>ag <plug>(ale_go_to_definition)
nmap <leader>at <plug>(ale_go_to_type_definition)
nmap <leader>ah <plug>(ale_hover)
nmap <leader>ad <plug>(ale_documentation)
nmap <leader>ap <plug>(ale_detail)
nmap <leader>af <plug>(ale_fix)
nmap <leader>al <plug>(ale_lint)
nmap <leader>ar <plug>(ale_find_references)
imap <c-c> <plug>(ale_complete)
"Move between linting errors
nmap ]r <plug>(ale_next_wrap)
nmap [r <plug>(ale_previous_wrap)
```

### Further Reading

- [ReasonML Editor Plugins][reasoneditor]
- [autozimu/LanguageClient-neovim][languageclient]
- [A guide to LSP (auto completion) in VIM][lspguide]

[languageclient]: https://github.com/autozimu/LanguageClient-neovim
[reasoneditor]: https://reasonml.github.io/docs/en/editor-plugins
[windows]: https://github.com/reasonml/reasonml.github.io/issues/195
[vimreasonplus]: https://github.com/reasonml-editor/vim-reason-plus
[minpac]: https://github.com/k-takata/minpac
[neovim]: https://github.com/neovim/neovim
[lspguide]: https://www.reddit.com/r/vim/comments/b33lc1/a_guide_to_lsp_auto_completion_in_vim/
[reasonlanguageserver]: https://github.com/jaredly/reason-language-server#vim
[ale]: https://github.com/dense-analysis/ale