Configurar Neovim para Rust

Guia completo para configurar Neovim para Rust com LSP, rust-analyzer, nvim-lspconfig, telescope, debugging com nvim-dap e plugins essenciais.

O Neovim é a escolha de muitos desenvolvedores Rust que preferem um editor rápido, leve e altamente configurável direto no terminal. Com o rust-analyzer via LSP, o Neovim oferece uma experiência de desenvolvimento comparável a IDEs completas. Neste guia, vamos configurar o Neovim com LSP, autocompletar, debugging e plugins essenciais para Rust.

Pré-requisitos

Certifique-se de ter o Rust instalado. Consulte o guia do seu sistema:

Instale o rust-analyzer como componente do rustup:

rustup component add rust-analyzer

Instalar Neovim 0.10+

O LSP nativo requer Neovim 0.5+, mas recomendamos 0.10+ para os melhores recursos:

# Ubuntu/Debian
sudo snap install nvim --classic
# ou via PPA
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update && sudo apt install neovim

# Fedora
sudo dnf install neovim

# Arch Linux
sudo pacman -S neovim

# macOS
brew install neovim

Verifique a versão:

nvim --version

Configuração com lazy.nvim (Recomendado)

O lazy.nvim é o gerenciador de plugins mais moderno para Neovim. Crie a estrutura de configuração:

mkdir -p ~/.config/nvim/lua/plugins

init.lua

Crie o arquivo ~/.config/nvim/init.lua:

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git", "clone", "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

-- Opções básicas
vim.g.mapleader = " "
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.signcolumn = "yes"
vim.opt.termguicolors = true

-- Carregar plugins
require("lazy").setup("plugins")

Configurar LSP (rust-analyzer)

Crie ~/.config/nvim/lua/plugins/lsp.lua:

return {
  {
    "neovim/nvim-lspconfig",
    dependencies = {
      "hrsh7th/nvim-cmp",
      "hrsh7th/cmp-nvim-lsp",
      "hrsh7th/cmp-buffer",
      "hrsh7th/cmp-path",
      "L3MON4D3/LuaSnip",
      "saadparwaiz1/cmp_luasnip",
    },
    config = function()
      local lspconfig = require("lspconfig")
      local capabilities = require("cmp_nvim_lsp").default_capabilities()

      -- Configurar rust-analyzer
      lspconfig.rust_analyzer.setup({
        capabilities = capabilities,
        settings = {
          ["rust-analyzer"] = {
            check = {
              command = "clippy",
            },
            cargo = {
              allFeatures = true,
            },
            procMacro = {
              enable = true,
            },
            inlayHints = {
              typeHints = { enable = true },
              parameterHints = { enable = true },
              chainingHints = { enable = true },
            },
          },
        },
      })

      -- Keymaps LSP (ativados quando um LSP se conecta)
      vim.api.nvim_create_autocmd("LspAttach", {
        callback = function(args)
          local opts = { buffer = args.buf }
          vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
          vim.keymap.set("n", "gr", vim.lsp.buf.references, opts)
          vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
          vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, opts)
          vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)
          vim.keymap.set("n", "<leader>f", function()
            vim.lsp.buf.format({ async = true })
          end, opts)
          vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts)
          vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts)
        end,
      })

      -- Configurar autocompletar
      local cmp = require("cmp")
      local luasnip = require("luasnip")

      cmp.setup({
        snippet = {
          expand = function(args)
            luasnip.lsp_expand(args.body)
          end,
        },
        mapping = cmp.mapping.preset.insert({
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<CR>"] = cmp.mapping.confirm({ select = true }),
          ["<Tab>"] = cmp.mapping.select_next_item(),
          ["<S-Tab>"] = cmp.mapping.select_prev_item(),
        }),
        sources = cmp.config.sources({
          { name = "nvim_lsp" },
          { name = "luasnip" },
        }, {
          { name = "buffer" },
          { name = "path" },
        }),
      })
    end,
  },
}

Telescope (Busca e Navegação)

Crie ~/.config/nvim/lua/plugins/telescope.lua:

return {
  {
    "nvim-telescope/telescope.nvim",
    dependencies = { "nvim-lua/plenary.nvim" },
    keys = {
      { "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Buscar arquivos" },
      { "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Grep ao vivo" },
      { "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Listar buffers" },
      { "<leader>fs", "<cmd>Telescope lsp_document_symbols<cr>", desc = "Símbolos" },
      { "<leader>fr", "<cmd>Telescope lsp_references<cr>", desc = "Referências" },
      { "<leader>fd", "<cmd>Telescope diagnostics<cr>", desc = "Diagnósticos" },
    },
    config = function()
      require("telescope").setup({
        defaults = {
          file_ignore_patterns = { "target/", ".git/" },
        },
      })
    end,
  },
}

Debugging com nvim-dap

Crie ~/.config/nvim/lua/plugins/dap.lua:

return {
  {
    "mfussenegger/nvim-dap",
    dependencies = {
      "rcarriga/nvim-dap-ui",
      "nvim-neotest/nvim-nio",
    },
    keys = {
      { "<leader>db", "<cmd>lua require('dap').toggle_breakpoint()<cr>", desc = "Breakpoint" },
      { "<leader>dc", "<cmd>lua require('dap').continue()<cr>", desc = "Continue" },
      { "<leader>ds", "<cmd>lua require('dap').step_over()<cr>", desc = "Step over" },
      { "<leader>di", "<cmd>lua require('dap').step_into()<cr>", desc = "Step into" },
      { "<leader>do", "<cmd>lua require('dap').step_out()<cr>", desc = "Step out" },
      { "<leader>du", "<cmd>lua require('dapui').toggle()<cr>", desc = "DAP UI" },
    },
    config = function()
      local dap = require("dap")
      local dapui = require("dapui")

      dapui.setup()

      -- Configurar adaptador para Rust (usando codelldb)
      dap.adapters.codelldb = {
        type = "server",
        port = "${port}",
        executable = {
          command = "codelldb",
          args = { "--port", "${port}" },
        },
      }

      dap.configurations.rust = {
        {
          name = "Debug",
          type = "codelldb",
          request = "launch",
          program = function()
            return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/target/debug/", "file")
          end,
          cwd = "${workspaceFolder}",
          stopOnEntry = false,
        },
      }

      -- Abrir/fechar DAP UI automaticamente
      dap.listeners.after.event_initialized["dapui_config"] = function()
        dapui.open()
      end
    end,
  },
}

Instale o codelldb:

# Via Mason (recomendado)
# Adicione mason.nvim à sua config e execute :MasonInstall codelldb

# Ou manualmente
# Baixe de: https://github.com/vadimcn/codelldb/releases

Plugins Adicionais para Rust

Crie ~/.config/nvim/lua/plugins/rust.lua:

return {
  -- Treesitter para syntax highlighting avançado
  {
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    config = function()
      require("nvim-treesitter.configs").setup({
        ensure_installed = { "rust", "toml", "lua" },
        highlight = { enable = true },
        indent = { enable = true },
      })
    end,
  },

  -- Crates.nvim para gerenciar dependências no Cargo.toml
  {
    "saecki/crates.nvim",
    event = { "BufRead Cargo.toml" },
    config = function()
      require("crates").setup()
    end,
  },
}

Atalhos Configurados

AtalhoAção
gdIr para definição
grListar referências
KHover (documentação)
<Space>rnRenomear símbolo
<Space>caCode actions
<Space>fFormatar código
<Space>ffBuscar arquivos
<Space>fgGrep ao vivo
<Space>dbToggle breakpoint
<Space>dcContinuar debug

Verificar a Configuração

  1. Abra um projeto Rust:
cargo new teste-nvim && cd teste-nvim
nvim src/main.rs
  1. Verifique se o LSP está ativo: :LspInfo
  2. Teste autocompletar: digite std:: e veja as sugestões
  3. Teste hover: posicione o cursor sobre uma função e pressione K

Solução de Problemas

rust-analyzer não inicia

Verifique se está instalado:

which rust-analyzer
rustup component add rust-analyzer

No Neovim, execute :LspLog para ver erros.

Autocompletar não funciona

Certifique-se de que o nvim-cmp está configurado com a fonte nvim_lsp e que o LSP está conectado (:LspInfo).

Inlay hints não aparecem

Verifique sua versão do Neovim (nvim --version). Inlay hints nativos requerem Neovim 0.10+.

Próximos Passos

Com o Neovim configurado para Rust:

Se você também configura Neovim para outras linguagens, confira o ziglang.com.br para dicas de configuração com Zig.


Última atualização: 23 de fevereiro de 2026. Para uma alternativa, veja o guia de VS Code para Rust.