Bare bones vimrc (neovim) template for Rust

Bare bones vimrc (neovim) template for Rust

In preparing for a talk on Rust training for beginners, I thought of creating a very basic setup using vim. Instead of putting a textbook for .vimrc, with all the floatsam and jetsam of my 15 years of vim usage in different stacks, I’ve decided to remove all the fluff and kept the most basic things needed to get started with rust. Period.

All code on github here : https://github.com/tek-shinobi/rust-vimrc-starter-template

What you will get

Once you are done with this tutorial, you would have configured your vim to get started with rust. You will have:

  1. rust syntax highlighting
  2. rust code autocomplete
  3. rust linter (for compilation error, warnings etc)
  4. rust code help (like going to definitions for macros, getting function signature info)
  5. basic code help like bracket matching, highlighting of yanked code, some eye candy for different vim modes
  6. Basically a bare bones starter template of only the needed vim plugins to get you a decent, definitely miles better than VSCode, like IDE setup, sans any personalization. You can customize it as you like.

The idea is to have under 50 lines of .vimrc, comments included.

Everything I mention here comes from Rust’s official list of plugins for vim based rust setup.

My OS: Ubuntu 20.04

Text Editor used: Neovim (install via sudo apt install neovim)

Plugin Manager: Vundle

Getting started: Basic vimrc

Create an empty .vimrc in your home directory: ~/.vimrc

If you have ~/.vim folder, make a backup of it and then remove it and then do mkdir ~/.vim

Clone the vundle plugin manager there like so:
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

My preference is to have .vimrc linked to neovim, so that I don’t have to use a separate config for neovim. The way to link .vimrc to neovim is
open: ~/.config/nvim/init.vim and paste this:

set runtimepath^=~/.vim runtimepath+=~/.vim/after
let &packpath=&runtimepath
source ~/.vimrc

Note the last line, which is sourcing my .vimrc file.

Moving on, paste this in .vimrc:

" https://github.com/VundleVim/Vundle.vim
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'

" =======================================================
" Load Plugins Start
" =======================================================
" GUI Related
Plugin 'itchyny/lightline.vim'
Plugin 'machakann/vim-highlightedyank'
Plugin 'andymass/vim-matchup'

" All of your Plugins must be added before the following line
call vundle#end()            " required
" =======================================================
" Load Plugins End
" =======================================================

Now install the plugins by :PluginInstall.

Here you have installed 3 basic plugins that are needed for general coding. Point 5 in the section What you will get.

Ok, you should now be able to :checkhealth and get all OK (yes, very handy tool to make sure all plugins got installed OK in neovim).

We are now all set to get started with Rust specific setup

Rust setup for vim

To install the rust provided vim plugin, we need node installed. I install node using nvm. I am assuming that you have node>12 installed.

Now, we need syntastic vim plugin installed. This is a generic syntax checker for which rust provides bindings. Then we will also install the rust provided vim plugin.

So our .vimrc looks like this now:

" https://github.com/VundleVim/Vundle.vim
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'

" =======================================================
" Load Plugins Start
" =======================================================
" GUI Related
Plugin 'itchyny/lightline.vim'
Plugin 'machakann/vim-highlightedyank'
Plugin 'andymass/vim-matchup'

" Syntax checking generic
Plugin 'vim-syntastic/syntastic'

" Rust
Plugin 'rust-lang/rust.vim'

" All of your Plugins must be added before the following line
call vundle#end()            " required
" =======================================================
" Load Plugins End
" =======================================================

" Rust formatting
let g:rustfmt_autosave = 1


" =======================================================
" # Editor settings
" =======================================================
filetype plugin indent on    " required
set autoindent
set encoding=utf-8

Again do the :PluginInstall to install syntastic and rust.vim plugins. let g:rustfmt_autosave = 1 This line auto formats your rust code whenever you save. (Rust comes with a code formatter out of the box). The settings in Editor settings become relevant in later steps as we install rust-analyzer.

Now, if you create a new rust binary project via cargo new my_proj and then open the main.rs file, you will be able to see rust syntax highlighting, rust syntax checking (try by making a syntax error and save the file, you will see linter errors). rust.vim plugin that we installed comes with syntax highlighter and rust specific bindings for syntastic to provide syntax checking.

What we still lack is a VSCode like ability for auto code-completion, ability to get function signature as tooltip when you hover on it, even jump to function/macro under cursor, some ability to see docstrings for code. Enter the rust language server. This will provide all these features. Note, for extremely large code bases, it can slow down your system, but if you are reading this blog, chances are that this is not your problem yet for at least a while. When you reach that point, you can turn Language Server off if you see any sluggish performance.

We will be using rust-analyzer which is one of a couple of rust language server protocol implementations available (other being rls).

First let us get our code-completion setup done. We will use neovim port of Conquer of Completion called coc.nvim

Our .vimrc looks like this now

" https://github.com/VundleVim/Vundle.vim
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'

" =======================================================
" Load Plugins Start
" =======================================================
" GUI Related
Plugin 'itchyny/lightline.vim'
Plugin 'machakann/vim-highlightedyank'
Plugin 'andymass/vim-matchup'

" fzf
Plugin 'airblade/vim-rooter'
Plugin 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plugin 'junegunn/fzf.vim'

" Syntax checking generic
Plugin 'vim-syntastic/syntastic'

" Autocomplete
Plugin 'neoclide/coc.nvim'

" Rust
Plugin 'rust-lang/rust.vim'


" All of your Plugins must be added before the following line
call vundle#end()            " required
" =======================================================
" Load Plugins End
" =======================================================

" Rust formatting
let g:rustfmt_autosave = 1


" =======================================================
" # Editor settings
" =======================================================
filetype plugin indent on    " required
set autoindent
set encoding=utf-8

Again, do :PluginInstall to install the coc.nvim.

Now we need to configure coc.nvim. Very easy. Goto the github page of coc.nvim and copy the provided Example vim configuration. This config will go here: ~/.config/nvim/plugin-config/coc.vim

You might need to create plugin-config directory. The name is not important, just that I like to give names that make sense. And I keep all of nvim plugin configs in plugin-config directory.

So, now, you have pasted the contents of Example vim configuration into coc.vim. But nvim needs to know about this config file. So here is what our init.vim looks like after we have added the path for coc.vim (all other plugin configs will be added to this file similarly)

set runtimepath^=~/.vim runtimepath+=~/.vim/after
let &packpath=&runtimepath
source ~/.vimrc
source $HOME/.config/nvim/plugin-config/coc.vim

Now, coc.nvim has the ability to install extensions using :CocInstall. We will install a coc.nvim extension called coc-rust-analyzer. This extension will enable us to download and install the rust-analyzer very easily. So on vim command prompt, :CocInstall coc-rust-analyzer

Now coc-rust-analyzer is installed. Now we are almost there. We just need to actually have coc-rust-analyzer install the rust-analyzer. There are multiple ways of doing this. The easiet way is, just open a rust file in vim. Right now vim will complain that there is no rust language server path specified and will give us the option to download by itself. Choose it. Wait for sometime. It might throw some weird error message. Fear not. Close vim. Reopen the same rust file with vim. Voila! your autocompletes, and code helper suggestions will be working now. You are good to go.

I have completely removed all personalizations and additionals like leader key mapping, tmux configs, nerd tree, ripgrep, fzf (fuzzy file search), custom syntax highlighting theme, yada yada yada. Here is the basic config template as promised. You can build on it. BTW, rust uses 4 spaces and not tab.