Migrando do init.vim para o init.lua
Para fechar nossa série de criação de plugins em Lua para o Neovim, vamos mudar um pouco o foco na criação de plugins para um tutorial de como podemos migrar toda nossa configuração do Neovim usando o tradicional Vimscript, para Lua.
Mas por que Lua?
A decisão tomada pelo core team de desenvolvimento do Neovim tem várias respostas diversas, que vão desde velocidade a facilidade de escrita, pelo fato de Lua ser uma linguagem bem extensível. Para entender as principais motivações, sugiro dar uma pausa no post e apreciar a talk “We can have nice things”, do Justin M. Keyes, um dos atuais líderes de desenvolvimento do Neovim.
A migração
Caso você ainda não conheça a estrutura de diretórios do Neovim, toda configuração vai em:
Unix: ~/.config/nvim/init.vim
Windows: ~/AppData/Local/nvim/init.vim
ou, caso você queria um path de config customizado, onde $XDG_CONFIG_HOME
é definido, fica assim:
$XDG_CONFIG_HOME/nvim/init.vim
Esse arquivo é o ponto de entrada para as configurações customizadas do editor, desde cores, tamanhos de fonte, a instalação de plugins.
No nosso caso, começaremos renomeando o arquivo init.vim
para init.old
e criando um novo arquivo chamado init.lua.
Por quê precisamos renomear o init.vim?
No neovim não é possível existir 2 pontos de entrada para as configurações, então você só poderá usar o init.vim
ou o mais recente, init.lua
Para o nosso tutorial não ficar bastante extenso, iremos usar um init.vim
relativamente pequeno, explicando as principais configurações e como portá-las para a versão em lua.
Mas primeiro precisamos relembrar como a API em Lua se comporta.
O namespace vim
Na implementação da API Lua para o Neovim, existe uma variável chamada vim
, que é o ponto de entrada para todas as funções da chamada “biblioteca padrão” Lua para o Neovim. Essas funções servem diferentes propósitos, mas o principal sendo a ponte entre o código lua e o editor. Algumas APIs incluem:
vim.inspect
- uma função de debug para inspecionar resultados. Geralmente em lua, os resultados vem em tables, e esses são difíceis de ser expostos em formato de “print”. Essa função “disseca” a váriável que você gostaria de expor de uma forma mais amigável.vim.regex
- Módulo que possibilita o uso de regexes diretamente no código Lua. Para mais info:h vim.regex
vim.api
- Provavelmente o módulo mais importante dessa API. Aqui encontramos todas a funções para trabalhar com buffers, windows, chamar comandos do neovim, etc.vim.loop
- Módulo que funciona como uma camada de abstração daLibUV
, a camada de event-loop do Neovim. Pra quem quer usar concorrência, timers, etc, esse módulo é o caminho.vim.lsp
- Pra quem trabalhar diretamente na fantástica implementação nativa de um cliente LSP dentro do Neovim.vim.treesitter
- O módulo que expõe algumas funções para se trabalhar diretamente com o tree-sitter.vim.keymap
- Inclua ou remova keymaps do vim
Para este post, focaremos apenas na vim.api
e vim.keymap
Nosso arquivo init.lua
Levando em consideração que nosso init.vim
tinha a seguinte cara:
" Parte 1
set colorcolumn=80
set expandtab
set tabstop=4
set autoindent
set incsearch
set hlsearch
set termguicolors
" Parte 2
let g:minha_config = 'valor'
let g:algumnamespace#teste#variavel = "valor"
" Parte 3
nmap <leader>, <Cmd>:noh<CR>
nnoremap <leader>h <Cmd>split<CR>
vnoremap < <gv
" Parte 4
autocmd BufEnter * echo "hello nvim"
" Parte 5
function! SayHello()
echohl WarningMsg
echo "Hello World"
echohl
endfunction`
separamos a migração em 4 partes:
- options
- vars
- mappings
- autocmds
- functions
Para a parte 1, temos as seguintes funções da vim.api
:
vim.api.nvim_set_option
vim.api.nvim_buf_set_option
vim.api.nvim_win_set_option
Para facilitar a escrita, temos o atalho vim.opt
:
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab -- set expandtab
vim.opt.tabstop=4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
Continuando com a parte 2, temos uma declaração de uma variável global (escopo g:
). Na API, podemos utilizar as seguintes funções:
vim.api.nvim_set_var
e suas variações (vim.api.nvim_get_var
e vim.api.nvim_del_var
)
Aqui também temos uma versão “minimalista” com seus respectivo meta-acessor (ver :h lua-vim-variables
para mais detalhes):
vim.g
- Também funciona como um getter/setter
Temos então nosso código lua, com a parte 2:
-- parte 1
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab = true -- set expandtab
vim.opt.tabstop = 4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
-- parte 2
vim.g.minha_config = "valor"
-- o `meta-acessor` é uma table, então podemos atribuir valores usando também os colchetes
vim.g["algumnamespace#teste#variavel"] = "valor"
Para a parte 3 temos os mappings e para isso temos 2 funções que podem ser utilizadas:
-
vim.api.nvim_set_keymap
- mappings que serão atribuídos para todos os buffers -
vim.api.nvim_buf_set_keymap
- mappings que serão exclusivos de algum buffer em particular
Para facilitar ainda mais, na versão 0.7 foi introduzida a API vim.keymap
(:h lua-keymap
), que deixa as coisas bem mais fáceis quando precisamos criar os mappings.
Temos então, no nosso arquivo lua:
-- parte 1
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab = true -- set expandtab
vim.opt.tabstop = 4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
-- parte 2
vim.g.minha_config = "valor"
-- o `meta-acessor` é uma table, então podemos atribuir valores usando também os colchetes
vim.g["algumnamespace#teste#variavel"] = "valor"
-- parte 3
vim.keymap.set("n", "<leader>,", "<Cmd>:noh<CR>", nil) -- nmap <leader>, <Cmd>:noh<CR>
vim.keymap.set("n", "<leader>h", "<Cmd>split<CR>", {noremap = true}) -- nnoremap <leader>h <Cmd>split<CR>
vim.keymap.set("v", "<", "<gv", {noremap = true}) -- vnoremap < <gv
Já para a parte 4, vamos adicionar os autocmd e augroups. Para isso, iremos usar a função vim.api.nvim_create_autocmd
, introduzida também na versão 0.7. Adicionando a parte 4 na nossa configuração, temos:
-- parte 1
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab = true -- set expandtab
vim.opt.tabstop = 4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
-- parte 2
vim.g.minha_config = "valor"
-- o `meta-acessor` é uma table, então podemos atribuir valores usando também os colchetes
vim.g["algumnamespace#teste#variavel"] = "valor"
-- parte 3
vim.keymap.set("n", "<leader>,", "<Cmd>:noh<CR>", nil) -- nmap <leader>, <Cmd>:noh<CR>
vim.keymap.set("n", "<leader>h", "<Cmd>split<CR>", {noremap = true}) -- nnoremap <leader>h <Cmd>split<CR>
vim.keymap.set("v", "<", "<gv", {noremap = true}) -- vnoremap < <gv
-- parte 4
vim.api.nvim_create_autocmd("BufEnter", {
callback = function()
print("hello nvim")
end
})
Para a última parte, temos uma função vimscript que poderá ser portada utilizando a função vim.api.nvim_exec, que avalia um código vimscript contendo várias linhas. A assinatura da função é da seguinte forma:
vim.api.nvim_exec(bloco_de_codigo, retorno)
Onde:
-
bloco_de_codigo
: A string multiline ou não do bloco de código vimscript que será executado -
retorno
-true
caso deseje retornar o resultado string da execução do bloco,false
para retornar uma string vazia
Temos então a versão final da config lua:
-- parte 1
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab = true -- set expandtab
vim.opt.tabstop = 4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
-- parte 2
vim.g.minha_config = "valor"
-- o `meta-acessor` é uma table, então podemos atribuir valores usando também os colchetes
vim.g["algumnamespace#teste#variavel"] = "valor"
-- parte 3
vim.keymap.set("n", "<leader>,", "<Cmd>:noh<CR>", nil) -- nmap <leader>, <Cmd>:noh<CR>
vim.keymap.set("n", "<leader>h", "<Cmd>split<CR>", {noremap = true}) -- nnoremap <leader>h <Cmd>split<CR>
vim.keymap.set("v", "<", "<gv", {noremap = true}) -- vnoremap < <gv
Já para a parte 4, vamos adicionar os autocmd e augroups. Para isso, iremos usar a função vim.api.nvim_create_autocmd
, introduzida também na versão 0.7. Adicionando a parte 4 na nossa configuração, temos:
-- parte 1
vim.opt.termguicolors = true -- set termguicolors
vim.opt.colorcolumn = 80 -- set colorcolumn=80
vim.opt.expandtab = true -- set expandtab
vim.opt.tabstop = 4 -- set tabstop=4
vim.opt.autoindent = true -- set autoindent
vim.opt.incsearch = true -- set incsearch
vim.opt.hlsearch = true -- set hlsearch
-- parte 2
vim.g.minha_config = "valor"
-- o `meta-acessor` é uma table, então podemos atribuir valores usando também os colchetes
vim.g["algumnamespace#teste#variavel"] = "valor"
-- parte 3
vim.keymap.set("n", "<leader>,", "<Cmd>:noh<CR>", nil) -- nmap <leader>, <Cmd>:noh<CR>
vim.keymap.set("n", "<leader>h", "<Cmd>split<CR>", {noremap = true}) -- nnoremap <leader>h <Cmd>split<CR>
vim.keymap.set("v", "<", "<gv", {noremap = true}) -- vnoremap < <gv
-- parte 4
vim.api.nvim_create_autocmd("BufEnter", {
callback = function()
print("hello nvim")
end
})
-- parte 5
vim.api.nvim_exec([[
function! SayHello()
echohl WarningMsg
echo "Hello World"
echohl
endfunction
]], false)
Conclusão
Mostramos que, apesar de algumas limitações, portar uma configuração em vimscript para Lua está cada dia mais fácil com a API vigente. Para um exemplo de configuração mais extensa usando mais elementos da API Lua, visite a minha configuração do neovim, deixa seu star por lá também e caso tenha alguma dúvida, manda mensagem por aqui
Lembrando que faço lives esporádicas na Twitch! Caso deseje ver esse tipo de conteúdo ao vivo, não deixe de me seguir por lá e também acompanhar meu Twitter
Para ouvir
Top comments (0)