So I am trying to set up neovim 0.5+ as a rust IDE. I am following this guide.

Except, as shown in the guide, there is not completion even after doing <c-x><c-o>.

I have kept the config in ~/.config/nvim/ftplugin/rust.vim.

My rust.vim:

call plug#begin('~/.config/nvim/plugged/rust')

" Collection of common configurations for the Nvim LSP client
Plug 'neovim/nvim-lspconfig'

" Completion framework
Plug 'hrsh7th/nvim-cmp'

" LSP completion source for nvim-cmp
Plug 'hrsh7th/cmp-nvim-lsp'

" syntax checking
Plug 'rust-lang/rust.vim'

" status bar
Plug 'vim-airline/vim-airline'

" Snippet completion source for nvim-cmp
Plug 'hrsh7th/cmp-vsnip'

" Other usefull completion sources
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-buffer'

" See hrsh7th's other plugins for more completion sources!

" To enable more of the features of rust-analyzer, such as inlay hints and more!
Plug 'simrat39/rust-tools.nvim'

" Snippet engine
Plug 'hrsh7th/vim-vsnip'

" Fuzzy finder
" Optional
Plug 'nvim-lua/popup.nvim'
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-telescope/telescope.nvim'

" Color scheme used in the GIFs!
" Plug 'arcticicestudio/nord-vim'

call plug#end()

" Set completeopt to have a better completion experience
" :help completeopt
" menuone: popup even when there's only one match
" noinsert: Do not insert text until a selection is made
" noselect: Do not select, force user to select one from the menu
set completeopt=menuone,noinsert,noselect

" Avoid showing extra messages when using completion
set shortmess+=c

" Configure LSP through rust-tools.nvim plugin.
" rust-tools will configure and enable certain LSP features for us.
" See https://github.com/simrat39/rust-tools.nvim#configuration
lua <<EOF
local nvim_lsp = require'lspconfig'

local opts = {
    tools = { -- rust-tools options
        autoSetHints = true,
        hover_with_actions = true,
        inlay_hints = {
            show_parameter_hints = false,
            parameter_hints_prefix = "",
            other_hints_prefix = "",

    -- all the opts to send to nvim-lspconfig
    -- these override the defaults set by rust-tools.nvim
    -- see https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer
    server = {
        -- on_attach is a callback called when the language server attachs to the buffer
        -- on_attach = on_attach,
        settings = {
            -- to enable rust-analyzer settings visit:
            -- https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/generated_config.adoc
            ["rust-analyzer"] = {
                -- enable clippy on save
                checkOnSave = {
                    command = "clippy"


" Setup Completion
" See https://github.com/hrsh7th/nvim-cmp#basic-configuration
lua <<EOF
local cmp = require'cmp'
  -- Enable LSP snippets
  snippet = {
    expand = function(args)
  mapping = {
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    ['<C-n>'] = cmp.mapping.select_next_item(),
    -- Add tab support
    ['<S-Tab>'] = cmp.mapping.select_prev_item(),
    ['<Tab>'] = cmp.mapping.select_next_item(),
    ['<C-d>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.close(),
    ['<CR>'] = cmp.mapping.confirm({
      behavior = cmp.ConfirmBehavior.Insert,
      select = true,

  -- Installed sources
  sources = {
    { name = 'nvim_lsp' },
    { name = 'vsnip' },
    { name = 'path' },
    { name = 'buffer' },

" Code navigation shortcuts
nnoremap <silent> <c-]> <cmd>lua vim.lsp.buf.definition()<CR>
nnoremap <silent> K     <cmd>lua vim.lsp.buf.hover()<CR>
nnoremap <silent> gD    <cmd>lua vim.lsp.buf.implementation()<CR>
nnoremap <silent> <c-k> <cmd>lua vim.lsp.buf.signature_help()<CR>
nnoremap <silent> 1gD   <cmd>lua vim.lsp.buf.type_definition()<CR>
nnoremap <silent> gr    <cmd>lua vim.lsp.buf.references()<CR>
nnoremap <silent> g0    <cmd>lua vim.lsp.buf.document_symbol()<CR>
nnoremap <silent> gW    <cmd>lua vim.lsp.buf.workspace_symbol()<CR>
nnoremap <silent> gd    <cmd>lua vim.lsp.buf.definition()<CR>

" have a fixed column for the diagnostics to appear in
" this removes the jitter when warnings/errors flow in
set signcolumn=yes

" Set updatetime for CursorHold
" 300ms of no cursor movement to trigger CursorHold
set updatetime=300

" Goto previous/next diagnostic warning/error
nnoremap <silent> g[ <cmd>lua vim.lsp.diagnostic.goto_prev()<CR>
nnoremap <silent> g] <cmd>lua vim.lsp.diagnostic.goto_next()<CR>

nnoremap <silent> ga    <cmd>lua vim.lsp.buf.code_action()<CR>


1 Answer 1


While the guide is not explicit about it, those configuration snippets are meant to be added to the main NeoVim configuration file, at ~/.config/nvim/init.vim, and not in a per-filetype file for Rust.

In particular, vim-plug configuration (the Plug statements) only work in init.vim (or the .vimrc file for Vim), since plug-ins are loaded in startup right after init.vim, so the runtime path is supposed to be set really early in startup (in init.vim) for plug-ins to be properly loaded.

Furthermore, many of the options set in those snippets are global (not buffer-local options), so while it's possible to set them in a filetype-specific script, it makes most sense to set them globally. (Setting those in ftplugin/rust.vim means they'll be set after the first Rust file is loaded, but they'll be applicable to every buffer opened after that, so in effect you'll have different behavior depending on whether a file is opened before or after a Rust file. So it makes more sense to load them in init.vim and having the behavior consistent.)

Similarly for the mappings, which are also global mappings. (The same effect of having them available everywhere after the first Rust file is loaded would apply.) Furthermore, the mappings are not Rust-specific, they're related to the LSP feature of NeoVim, so it makes sense to define these global mappings which will actually work with any language for which an LSP has been configured (which you should probably do if you work with other languages often.)

So, in short, just move that config to your init.vim. Hopefully, that's all you need to get everything to work as described in the guide.

  • Thank you but is it possible to say like only when a rust filetype is loaded execute these commands? Jan 1, 2022 at 9:51
  • For some of them, yes, it's possible to modify them. For example, the mappings, you can make them local with <buffer> to put them in an ftplugin. Some settings can be local, so you can use setlocal there. Plug-ins need to be configured globally, but vim-plug has ways to only load them when a specific filetype or command is used (but that depends a lot on how the plug-in itself works...) Overall, I'd say it's not worth the effort. (Not sure what your motivation would be for that, there are no huge efficiency gains to get from it.)
    – filbranden
    Jan 1, 2022 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.