Home Configuring Neovim as Rust IDE
Post
Cancel

Configuring Neovim as Rust IDE

If you read my article Configuring Neovim as Python IDE, you already know that one of mi favorite editors is [neo]vim. Between other reasons, when I’m using [neo]vim I feel more focused, I don’t know why.

One of my open fronts, in my spare time, is learn Rust, and neovim (in this case) seems a great IDE to do it. I have to say that programming in rust using neovim it reminds me of the old days programming in (ANSI) C using vim.

Convert neovim in a Rust IDE it’s very fast and very straightforward. After installing Rust, we only will need rust-analyzer and three vim plugins.

rust-analyzer

rust-analyzer is an implementation of Language Server Protocol (LSP) for the Rust programming language. It provides features like completion and goto definition for many code editors.

rust-analyzer needs the sources of the standard library, we can install them via rustup:

rustup component add rust-src

Now, we can install rust-analyzer via rustup:

rustup component add rust-analyzer

[Neo]vim base configuration

As allways, I’ll part from my base configuration. This is my configuration for all, in all my computers, no matter the purpose.

~/.config/nvim/init.vim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
syntax on                               " Enable syntax highlighting
filetype plugin indent on               " Enable filetype detection, plugins, and smart indentation
set encoding=utf-8                      " Set file and terminal encoding to UTF-8

set autoindent                          " Copy indentation from the previous line
set smartindent                         " Enable smarter automatic indentation
set expandtab                           " Use spaces instead of actual tabs
set tabstop=4                           " A Tab character is rendered as 4 spaces wide
set shiftwidth=4                        " Auto-indent commands (e.g., >>) use 4 spaces
set softtabstop=4                       " Tab/Backtab keys use 4 spaces when inserting

set number                              " Show absolute line number
set showmatch                           " Briefly show the matching bracket/parenthesis
set wildmenu                            " Enhanced command-line completion menu
set mouse=                              " Disable mouse support
set updatetime=250                      " Sets the delay (ms) for showing diagnostics and tooltips (important for LSP)

set path+=**                            " Allow searching for files recursively (e.g., :find filename)
set incsearch                           " Show results as you type the search pattern (incremental search)
set hlsearch                            " Highlight all matches of the last search pattern
set ignorecase                          " Ignore case when searching
set smartcase                           " Override ignorecase if the search pattern contains uppercase letters

set backspace=indent,eol,start          " Ensures backspace works as expected
set clipboard=unnamedplus               " Integrate with system clipboard for yank/put (requires external tool like xclip/wl-copy)
set noswapfile                          " Disable swap files to prevent clutter
set undofile                            " Enable persistent undo history
set undodir=~/.config/nvim/undodir      " Specify a directory for undo files (needs to be created)

[Neo]vim plugin manager

As plugin manager, my choice is vim-plug, and its installation it’s very straightforward:

Unix/linux:

1
sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'

Plugins

I install four plugins:

  • nvim-lspconfig Configs for the Nvim LSP client.

  • nvim-cmp A completion engine plugin.

  • rust-lang Provides Rust file detection, syntax highlighting, formatting, Syntastic integration, and more.

  • Vim Better Whitespace This plugin highlights all trailing whitespaces. It’s totally optional and can be substituted by the option “lines” in the vim.init file, but I like it.

nvim-lspconfig

To install it, we add the plugin to our init.vim file, into the call plug#begin('/home/rubenhortas/.config/nvim/plugins') section, below all the lines:

1
2
3
4
5
6
call plug#begin('/home/rubenhortas/.config/nvim/plugins')
...

Plug 'neovim/nvim-lspconfig'

call plug#end()

We will also pass LSP settings to the server adding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
lua << EOF
local lspconfig = require'lspconfig'

local on_attach = function(client)
    require'completion'.on_attach(client)
end

lspconfig.rust_analyzer.setup({
    on_attach = on_attach,
    settings = {
        ["rust-analyzer"] = {
            imports = {
                granularity = {
                    group = "module",
                },
                prefix = "self",
            },
            cargo = {
                buildScripts = {
                    enable = true,
                },
            },
            procMacro = {
                enable = true
            },
        }
    }
})
EOF

nvim-cmp

If you already have installed this plugin, you only need to add the set up lspconfig section for rust_analyzer:

1
2
3
  require('lspconfig')['rust_analyzer'].setup {
    capabilities = capabilities
  }

A completion engine plugin for neovim written in Lua. Completion sources are installed from external repositories and “sourced”. To install it we need to add the following to our init.vim file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
call plug#begin('/home/rubenhortas/.config/nvim/plugins')
Plug 'neovim/nvim-lspconfig'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'

" For vsnip users.
Plug 'hrsh7th/cmp-vsnip'
Plug 'hrsh7th/vim-vsnip'

call plug#end()

lua <<EOF
  -- Set up nvim-cmp.
  local cmp = require'cmp'

  cmp.setup({
    snippet = {
      -- REQUIRED - you must specify a snippet engine
      expand = function(args)
        vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
        -- require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
        -- require('snippy').expand_snippet(args.body) -- For `snippy` users.
        -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
      end,
    },
    window = {
      -- completion = cmp.config.window.bordered(),
      -- documentation = cmp.config.window.bordered(),
    },
    mapping = cmp.mapping.preset.insert({
      ['<C-b>'] = cmp.mapping.scroll_docs(-4),
      ['<C-f>'] = cmp.mapping.scroll_docs(4),
      ['<C-Space>'] = cmp.mapping.complete(),
      ['<C-e>'] = cmp.mapping.abort(),
      ['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
    }),
    sources = cmp.config.sources({
      { name = 'nvim_lsp' },
      { name = 'vsnip' }, -- For vsnip users.
      -- { name = 'luasnip' }, -- For luasnip users.
      -- { name = 'ultisnips' }, -- For ultisnips users.
      -- { name = 'snippy' }, -- For snippy users.
    }, {
      { name = 'buffer' },
    })
  })

  -- Set configuration for specific filetype.
  cmp.setup.filetype('gitcommit', {
    sources = cmp.config.sources({
      { name = 'git' }, -- You can specify the `git` source if [you were installed it](https://github.com/petertriho/cmp-git).
    }, {
      { name = 'buffer' },
    })
  })

  -- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
  cmp.setup.cmdline({ '/', '?' }, {
    mapping = cmp.mapping.preset.cmdline(),
    sources = {
      { name = 'buffer' }
    }
  })

  -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
  cmp.setup.cmdline(':', {
    mapping = cmp.mapping.preset.cmdline(),
    sources = cmp.config.sources({
      { name = 'path' }
    }, {
      { name = 'cmdline' }
    })
  })

  -- Set up lspconfig.
  local capabilities = require('cmp_nvim_lsp').default_capabilities()
  -- Replace <YOUR_LSP_SERVER> with each lsp server you've enabled.
  require('lspconfig')['rust_analyzer'].setup {
    capabilities = capabilities
  }
EOF

rust-lang

To install it, we add the plugin to our init.vim file, into the call plug#begin('/home/rubenhortas/.config/nvim/plugins') section, below all the lines:

1
2
3
4
5
6
call plug#begin('/home/rubenhortas/.config/nvim/plugins')
...

Plug 'rust-lang/rust.vim'

call plug#end()

Vim Better Whitespace

This plugin causes all trailing whitespace characters to be highlighted. Whitespace for the current line will not be highlighted while in insert mode. It is possible to disable current line highlighting while in other modes as well. A helper function :StripWhitespace is also provided to make whitespace cleaning painless.

This plugin is optional, and can be substituded by the “lines” option in the vim.init file. But, I like it, and the :StripWhitespace function is very useful.

To install it we add the plugin to our init.vim file, into the call plug#begin('/home/rubenhortas/.config/nvim/plugins') section, below all the lines:

1
2
3
4
5
6
call plug#begin('/home/rubenhortas/.config/nvim/plugins')
...

Plug 'ntpeters/vim-better-whitespace'

call plug#end()

Install the plugins

To install the plugins we open nvim and run:

:PlugInstall

Screenshots

Example of autocompletion Example of autocompletion

Example of linting errors and trailing whitespaces Example of linting errors

Enjoy! ;)

This post is licensed under CC BY 4.0 by the author.