So you enjoy coding in Haskell. And you heard kids nowadays code using this LSP thingy.
Let's cut to the chase: LSP is a spec that standardizes auto-completion, code navigation, linting, and all good stuff usually found in modern IDE's. In order to use LSP with your favorite language you'll need a language server to communicate with your editor of choice.
In this article we'll focus on haskell's language server. Not long ago the language server of choice used to be hie
but now it's deprecated.
So let's get started! Assuming you have Haskell Stack up and running:
$ stack install ghcid hspec-discover # optional but great
$ git clone https://github.com/haskell/haskell-language-server --recurse-submodules
$ cd haskell-language-server
$ stack ./install.hs help
$ stack ./install.hs hls
The binaries we'll be at the usual place: ~/.local/bin
Right, but how do I use it? Well it depends on your editor. Let me show you how I do it in my .vimrc
:
Plug 'prabirshrestha/vim-lsp'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
Plug 'mattn/vim-lsp-settings'
Please read their documentation!
" vim-lsp-settings won't detect hls automatically as of today (2020-10-26). Let's teach it:
if (executable('haskell-language-server-wrapper'))
au User lsp_setup call lsp#register_server({
\ 'name': 'haskell-language-server-wrapper',
\ 'cmd': {server_info->['haskell-language-server-wrapper', '--lsp']},
\ 'whitelist': ['haskell'],
\ })
endif
" My Mappings
function! s:on_lsp_buffer_enabled() abort
setlocal omnifunc=lsp#complete
setlocal signcolumn=yes
if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif
nmap <buffer> gd <plug>(lsp-definition)
nmap <buffer> gr <plug>(lsp-references)
nmap <buffer> gf <plug>(lsp-code-action)
nmap <buffer> gi <plug>(lsp-implementation)
nmap <buffer> gt <plug>(lsp-type-definition)
nmap <buffer> <F2> <plug>(lsp-rename)
nmap <buffer> [g <Plug>(lsp-previous-diagnostic)
nmap <buffer> ]g <Plug>(lsp-next-diagnostic)
nmap <buffer> K <plug>(lsp-hover)
xmap <buffer> f <plug>(lsp-document-range-format)
nmap <buffer> <F5> <plug>(lsp-code-lens)
" buffer format on save
" autocmd BufWritePre <buffer> LspDocumentFormatSync
endfunction
" Decorations
augroup lsp_install
au!
let g:lsp_signs_enabled = 1 " enable signs
let g:lsp_diagnostics_echo_cursor = 1 " enable echo under cursor when in normal mode
let g:lsp_signs_error = {'text': '✗'}
" let g:lsp_signs_warning = {'text': '‼', 'icon': '/path/to/some/icon'} " icons require GUI
" let g:lsp_signs_hint = {'icon': '/path/to/some/other/icon'} " icons require GUI
let g:lsp_signs_warning = {'text': '‼'}
let g:lsp_highlight_references_enabled = 1
highlight link LspErrorText GruvboxRedSign " requires gruvbox
highlight clear LspWarningLine
" highlight lspReference ctermfg=red guifg=red ctermbg=green guibg=green
highlight lspReference guibg=#303010
" call s:on_lsp_buffer_enabled only for languages that has the server registered.
autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END
The first time you start vim with a Haskell file it'll take a while (you can check vim-lsp's status with :LspStatus
). As soon as a left margin (1 character wide) shows up, you're good to go!
Now your Vim is an LSP powerhouse:
- Hover:
- Auto-complete:
etc. etc. etc.
Enjoy!
Top comments (6)
Hello there, I've been using vim since about 1999 but never really dug into the internals. I added what you have to my ~/.vimrc, but not sure where to save the next block you added to. Ideas?
Hi, I've never tried this solution on Windows, if it works for you let me know! :)
The first block (with "Plug..." lines) assumes you have installed the
vim-plug
manager. This manager has a configuration block delimited by calls toplug#begin
andplug#end
.The second block of the post (the one with the maps) can be pasted anywhere after the call to plug#end.
If you don't use vim-plug, take a look at it here github.com/junegunn/vim-plug
Good luck!
Hey thanks but I'm on MAC, not windows. :). Thanks for the plug for plug lol
I'm sorry! I don't know where I read that... 😊
I use this on Mac and Linux and it works fine.
Sweet! Thanks mate!
You can install hls with ghcup too.