DEV Community

David
David

Posted on

Configure neovim for rust development

nvim's 0.5.0 release includes a native lsp-client: nvim-lsp.

I have toyed with neovim for a while as a long time vim user and decided to make the switch proper. This is my current setup, and a little advice on putting all the pieces together.

First of all, the vim config:

init.vim

call plug#begin()
Plug 'neovim/nvim-lsp'
Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
Plug 'Shougo/deoplete-lsp'
Plug 'ervandew/supertab'
Plug 'Chiel92/vim-autoformat'
call plug#end()

" setup rust_analyzer LSP (IDE features)
lua require'nvim_lsp'.rust_analyzer.setup{}

" Use LSP omni-completion in Rust files
autocmd Filetype rust setlocal omnifunc=v:lua.vim.lsp.omnifunc

" Enable deoplete autocompletion in Rust files
let g:deoplete#enable_at_startup = 1

" customise deoplete                                                                                                                                                     " maximum candidate window length
call deoplete#custom#source('_', 'max_menu_width', 80)

" Press Tab to scroll _down_ a list of auto-completions
let g:SuperTabDefaultCompletionType = "<c-n>"

" rustfmt on write using autoformat
autocmd BufWrite * :Autoformat

"TODO: clippy on write
autocmd BufWrite * :Autoformat

nnoremap <leader>c :!cargo clippy

There's a fair amount going on here, but all of this is related to helping format, lint and auto-complete rust code.

I'm using rust for this example because I am loving learning rust at the moment but there are many supported languages - if you are setting yourself up for a different language (JS, python and others), try letting
nvim-lsp install the language server for you. We'll be compiling the language server from source (don't worry, cargo makes it a breeze).

Installs

First of all, nvim-lsp at the time of writing is new, and you need at least version 0.5.0 of nvim installed. Your current install is probably stable like mine was, which isn't new enough. So grab 0.5.0, tar -xzf and whack it somewhere in your path, like this (on linux):

tar -xzf nvim-linux64.tar.gz
sudo cp nvim-linux64/bin/nvim /usr/bin/nvim
nvim # this should load up 0.5.0

If you don't have nvim 0.5.0 or greater nvim-lsp won't exist, let alone work!

nvim-lsp and autoformat rely on external tooling to work their magic, so let's get it installed.

In your shell, from the top.

# install rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# install rustfmt (for formatting)
rustup component add rustfmt

# install clippy (for semantic linting)
rustup component add clippy

# hardest one last, install rust-analyzer
git clone https://github.com/rust-analyzer/rust-analyzer && cd rust-analyzer
cargo xtask install --server

To check it worked (your commit hash will likely vary!)

$ ra_lsp_server --version
rust-analyzer 823c152

Back in the world of vim plugins, start up nvim and install your plugins. If you have vim-plug that's as easy as

(inside nvim)
:PlugInstall

If you don't, it's just (in your shell)

curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

nvim

and then :PlugInstall as above. If you don't use vim-plug and don't know what a vim plugin manager is, my advice is simple: vim-plug is easily good enough and so simple. I highly recommend it.

Depending on the state of your nvim install, you might need a python module called pynvim. I think deoplete needs this.

pip install pynvim

Now you can edit some rust code!

  • auto-completion should just appear (use tab to choose a suggestion, thanks supertab)
  • run clippy by pressing <leader>c (in this case -c)
  • on each write, your code will be formatted using rustfmt (never argue about code style again)
  • Enjoy!

Let me know if you try this and run into issues and I'll update (m)any mistakes.

Would love to hear what nvim setup you are running, particularly for rust programming. I have loads to learn so let me know what you think, good or bad.

Top comments (11)

Collapse
 
drmason13 profile image
David

I'm testing this out as my "daily driver" for coding in rust. There are definitely some rough edges! I'll update with my improvements once I've smoothed things out :)

Collapse
 
maxdevjs profile image
maxdevjs • Edited

Hello, great article.

How did you install clippy (and in what OS)?

I mean, does rustup component add clippy actually (still) work for you?

Collapse
 
maxdevjs profile image
maxdevjs

Never mind, the rustup package I installed had issues with clippy.

Thread Thread
 
drmason13 profile image
David

I've not heard of that before, the rustup team might be interested in your experience. Not sure where to feed that back exactly but a GitHub issue would be a good guess :)

github.com/rust-lang/rustup/issues

I'm just on Linux, Ubuntu.

Thread Thread
 
maxdevjs profile image
maxdevjs

Thank you for the reply.

Short story: I started installing rustup as package for the distro that I use (Solus) and it has issues ending with a clippy-driver failure (everything else seems to work well).

rustup installed with the curl scripted works fine so far, actually.

Collapse
 
destynova profile image
Oisín

Hmm. I don't know why, but the autocompletion with nvim-lsp / deocomplete-lsp seems to be messed up for me.
I have a struct with a field "curr". In a function that takes an instance of that struct, I typed "self." and got the pop with its fields including "curr". When I selected that with <C-n> (same with (super)tab), it inserted an extra copy of the whole line, so I ended up with self. self.curr instead of self.curr.

Might have to go back to Neovim 0.4.3 and/or use autozimu's language client plugin again.

Collapse
 
ashoutinthevoid profile image
Full Name

New to neovim (and vi variations in general). I'm definitely feeling a bit lost here. I'm now getting this error on startup:

E5108: Error executing lua vim.lua:282: module 'vim.uri' not found:
        no field package.preload['vim.uri']

And that's with my init.vim stripped down to only the lsp plugin

call plug#begin()
" language server
Plug 'neovim/nvim-lsp'
call plug#end()

" setup rust_analyzer LSP (IDE features)
lua require'nvim_lsp'.rust_analyzer.setup{}

The closest I've found via google is a gitter message that notes "you have a borked install" and provides no further detail. Any help would be cool.

Collapse
 
ashoutinthevoid profile image
Full Name

Nvm. I ended up building and installing the current HEAD from source. Pretty painless (instructions are on the neovim repo), definitely more successful for me than whacking archive contents somewhere on my path. The rest seemed to more or less work.

One quick easy win: add the autocommands to an augroup, and start it with au! to avoid duplication if you source your vim config while running. Probably obvious to vim veterans, but new and super useful for me.
eg

augroup rust_config
  " delete any old autocommands
  au!
  " rustfmt on write using autoformat
  autocmd BufWrite *.rs :Autoformat
augroup END

In hindsight perhaps your target audience did not include new vim users, but some of these basics (i guess?) would be helpful for any of us considering a switch and coincidentally also working in Rust.

Collapse
 
thefern profile image
Fernando B 🚀

New rust user here, tempting to update nvim to 0.5.0 but don't want to break current functionality, are there any other ways pre 0.5.0? I use deoplete for python, c, c++.

Collapse
 
betoissues profile image
Alberto Castillo G.

Hi, I'm using 0.4.3 and I currently use autozimu/LanguageClient-neovim plugin. It already has direct integration with deoplete and can connect to any Language Server, for Rust you only need rls installed and provide the server initialization command. You'll find the Rust setup in the repo readme.

Collapse
 
thefern profile image
Fernando B 🚀

Thanks for the tip! I'll try that this weekend for sure. Saludos!