DEV Community

Cover image for NeoVim: init.lua, built in LSP e mais
Enrique Marques Junior
Enrique Marques Junior

Posted on

5

NeoVim: init.lua, built in LSP e mais

Preparei este post para quem quer migrar totalmente suas configurações para lua (nvim 0.5+) ou tá começando a configurar seu nvim hoje. ;)

Primeiro, você precisa escolher seu plugin management, eu escolhi usar o paq-nvim mas pode ser qualquer outro, tipo o packer.

Depois de instalar seu plugin manager, vamos criar os primeiros arquivos de configuração: init.lua, lua/settings.lua e lua/keymaps.lua.

init.lua

É a entrada da suas configurações, vamos utilizar para importar as configurações em arquivos separados, assim fica mais organizado.

-- Settings & Keys
require 'settings'
require 'keymaps'
Enter fullscreen mode Exit fullscreen mode

lua/settings.lua

Concentra as configurações mais básicas

local g = vim.g
local opt = vim.opt
local cmd = vim.cmd

-- General
opt.compatible = false
opt.mouse = 'a'
opt.clipboard = 'unnamedplus'
opt.swapfile = false
opt.hidden = true
opt.history = 100
opt.lazyredraw = true
opt.synmaxcol = 240

-- Theme
opt.termguicolors = true

-- Editor
opt.number = true
opt.wrap = false
opt.signcolumn = 'yes'
opt.showmatch = true
opt.showmode = false
opt.foldmethod = 'marker'
opt.splitright = true
opt.splitbelow = true
opt.conceallevel = 0
opt.colorcolumn = '80'
opt.cursorline = true
opt.scrolloff = 10
opt.expandtab = true
opt.shiftwidth = 2
opt.tabstop = 2
opt.smartindent = true
opt.shortmess:append {c = true}
Enter fullscreen mode Exit fullscreen mode

lua/keymaps.lua

Concentra os atalhos gerais e da maioria dos plugins. Existem casos, como o lsp, que os mappings são adicionados no on_attach no arquivo de configuração do lsp.

local set = vim.api.nvim_set_keymap
local ns = { noremap = true, silent = true }

-- Command
set("n", ";", ":", { noremap = true })

-- Clean Search
set("n", "<Leader><Space>", ":let @/=''<CR>", ns)

-- Window
set("n", "<C-j>", ":resize -2<CR>", ns)
set("n", "<C-k>", ":resize +2<CR>", ns)
set("n", "<C-h>", ":vertical resize -2<CR>", ns)
set("n", "<C-l>", ":vertical resize +2<CR>", ns)
set("n", "<Leader>h", ":<C-u>split<CR>", ns)
set("n", "<Leader>v", ":<C-u>vsplit<CR>", ns)

-- Moving
set("n", "j", "gj", ns)
set("n", "k", "gk", ns)

...
Enter fullscreen mode Exit fullscreen mode

Plugins

Pra começar, vamos criar um arquivo lua/plugins/paq.lua e adicionar paq-nvim e o nvim-lua/plenary.vim que é requisito para o funcionamento de outros plugins:

require('paq') {
  'savq/paq-nvim';
  'nvim-lua/plenary.nvim';
}
Enter fullscreen mode Exit fullscreen mode

Adicionamos o arquivo no init.lua:

...
-- Plugins
require 'plugins.paq'
...
Enter fullscreen mode Exit fullscreen mode

:luafile % para atualizar o nvim e os comandos :PaqInstall e :PaqSync estarão lá.

A seguir, separei alguns plugins como sugestão:

Editor

Para melhorar a experiência com o editor eu sugiro:

...
  -- Editor
  'windwp/nvim-autopairs';
  'tpope/vim-surround';
  'tpope/vim-commentary';
  'tpope/vim-repeat';
  'pbrisbin/vim-mkdir';
  'RRethy/vim-illuminate';
...
Enter fullscreen mode Exit fullscreen mode

Visual

Para deixar seu nvim com um visual mais interessante:

...
  -- Visual
  'glepnir/dashboard-nvim';
  'TaDaa/vimade';
  'famiu/feline.nvim';
  'kyazdani42/nvim-web-devicons';
  'kyazdani42/nvim-tree.lua';
  'nvim-telescope/telescope.nvim';
  'akinsho/bufferline.nvim';
  'Yggdroot/indentLine';
  'nvim-treesitter/nvim-treesitter';
...
Enter fullscreen mode Exit fullscreen mode

Lsp: Install e Config

Com os plugins neovim/nvim-lspconfig e williamboman/nvim-lsp-installer vamos configurar e instalar os servers de cada linguagem.

Para que algum servidor comece a funcionar é necessário que ele seja instalado e inicializado, a maneira mais fácil de fazer isso é buscando todas instaladas:

lua/plugins/lsp-config.lua

local lsp_installer = require("nvim-lsp-installer")
lsp_installer.on_server_ready(function (server) server:setup {} end)
Enter fullscreen mode Exit fullscreen mode

Para instalar:
:LspInstall <server> ou :LspInstallInfo e navegue nos servidores da lista pressionando i para instalar. Com :LspInfo você consegue ver o nome dos servidores (para adicionar ao setup).

Para os atalhos funcionarem, vamos adicionar a função on_attach no setup do lspconfig:

local ns = { noremap = true, silent = true }
local on_attach = function(_, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end

  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
  buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', ns)
  buf_set_keymap('n', 'gf', '<cmd>lua vim.lsp.buf.definition()<CR>', ns)
  buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', ns)
  buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', ns)
  buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', ns)
  buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', ns)
  buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', ns)
  buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', ns)
  buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', ns)
  buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', ns)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', ns)
  buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', ns)
  buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', ns)
  buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', ns)
  buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', ns)
  buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', ns)
end

local lsp_installer = require("nvim-lsp-installer")
lsp_installer.on_server_ready(
  function (server)
    local opts = {
      on_attach = on_attach,
    }
    server:setup(opts)
    vim.cmd [[ do User LspAttachBuffers ]]
  end
)
Enter fullscreen mode Exit fullscreen mode

:h lsp para mais informações e :checkheath para verificar se está tudo correto :)

Lsp-cmp

O lsp-cmp é responsável por adicionar a funcionalidade de “auto-complete”, exibindo sugestões ao digitar ou solicitar via comando/atalho.

Após instalar o plugin, precisamos adicionar a seguinte configuração no nosso lspconfig (lua/plugins/lsp-config.lua).

Vamos passar uma nova opção capabilities nas opções do server setup:

local capabilities = require'cmp_nvim_lsp'.update_capabilities(
  vim.lsp.protocol.make_client_capabilities()
)

...

local opts = {
  on_attach = on_attach,
  capabilities = capabilities,
}
...
Enter fullscreen mode Exit fullscreen mode

Para o funcionamento do nvim-cmp, criei um arquivo plugins/cmp.lua com as seguintes configurações:

local cmp = require'cmp'

cmp.setup{
  completion = {
    completeopt ='menu,menuone,noinsert',
  },
  experimental = {
    ghost_text = true,
  },
  mapping = {
    ['<CR>'] = cmp.mapping.confirm({
      behavior = cmp.ConfirmBehavior.Replace,
      select = true,
    }),
    ['<C-d>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.close(),
    ["<Tab>"] = cmp.select_next_item({
      behavior = cmp.SelectBehavior.Select
    }),
    ["<S-Tab>"] = cmp.select_prev_item({
      behavior = cmp.SelectBehavior.Select
    }),
  },
  sources = {
    { name = 'nvim_lsp' },
  }
}
Enter fullscreen mode Exit fullscreen mode

Desta forma a caixa de sugestão vai aparecer sempre que você começar a digitar e é possível navegar entre as opções com o Tab/S-Tab e selecionar com o Enter.

No meu repositório pessoal, o cmp.lua esta configurado com alguns adicionais como a integração com o LuaSnip.

Meu nvim-config

Você pode ver minhas configs atuais no repositório:

nvim-config

my nvim config

requirements

color scheme

install

:PaqInstall
:PaqSync

:LspInstall lua
:LspInstall typescript
:LspInstall html
:LspInstall css

:TSInstall lua
:TSInstall javascript
:TSInstall typescript
:TSInstall json
:TSInstall html
:TSInstall css
:TSInstall yaml
:TSInstall dart
Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more

Top comments (3)

Collapse
 
voyeg3r profile image
Sérgio Araújo • Edited

Aqui seguem algumas sugestões de um velho vimmer que agora só usa neovim:

Uma função na qual as opções de mapeamento tem um default, caso omitidas:

-- map helper
local function map(mode, lhs, rhs, opts)
    local options = { noremap = true }
    if opts then
        options = vim.tbl_extend("force", options, opts)
    end
    vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end

-- other interesting text objects
-- reference: https://www.reddit.com/r/vim/comments/adsqnx/comment/edjw792
local chars = { "_", "-", ".", ":", ",", ";", "<bar>", "/", "<bslash>", "*", "+", "%", "#", "`" }
for k, v in ipairs(chars) do
    map("x", "i" .. v, ":<C-u>norm! T" .. v .. "vt" .. v .. "<CR>")
    map("x", "a" .. v, ":<C-u>norm! F" .. v .. "vf" .. v .. "<CR>")
    map("o", "a" .. v, ":normal! va" .. v .. "<CR>")
    map("o", "i" .. v, ":normal! vi" .. v .. "<CR>")
end
-- por precaução altero o timeoutlen, que é o tempo de espera para que o nvim aplique um mapeamento:
opt.timeoutlen = 500
Enter fullscreen mode Exit fullscreen mode
-- com esse mapeamento mantenho a função original do Ctrl-l e de quebra o higlight search é boleano
map(
    "n",
    "<C-l>",
    [[ (&hls && v:hlsearch ? ':nohls' : ':set hls')."\n" <BAR> redraw<CR>]],
    { silent = true, expr = true }
)
Enter fullscreen mode Exit fullscreen mode

Aqui altero o undo break, de modo que cada vez que insiro um ponto, vírgula, exclamação etc o vim adiciona um undo break, assim se eu digitar algo do tipo: "Estou demonstrando a versatilidade do vim, e de quebra ajudando outras pessoas", se eu pressionar a tecla "u" em modo normal o desfazer só vai até a vírgula.

-- More molecular undo of text
-- map("i", ",", ",<c-g>u")
map("i", ".", ".<c-g>u")
map("i", "!", "!<c-g>u")
map("i", "?", "?<c-g>u")
map("i", ";", ";<c-g>u")
map("i", ":", ":<c-g>u")
map("i", "]", "]<c-g>u")
map("i", "}", "}<c-g>u")
Enter fullscreen mode Exit fullscreen mode
Collapse
 
enrsaid profile image
Enrique Marques Junior

Perfeito, certamente vou adicionar.
Muito obrigado por comentar!

Collapse
 
voyeg3r profile image
Sérgio Araújo

Henrique: Atualizei a função para mapeamentos trocando vim.api.nvim_set_keymap por vim.keymap.set e removi alguns undo breaks porque tava muito exagerado.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up