Um plugin para o mundo real
Na segunda parte da nossa série vamos criar um plugin que poderá ser usado no dia-a-dia, onde iremos introduzir algumas funcionalidades legais do Neovim, como as floating windows e algumas funções da API lua.
Vamos começar relembrando a estrutura de um plugin. Nosso novo plugin vai possuir a seguinte estrutura:
weather.nvim
├── lua
│ └── weather.lua
└── plugin
└── weather.lua
A idéia do plugin é mostrar a previsão do tempo atual em uma floating window, sendo chamado a partir de um comando.
Desenhando, vamos ter algo como:
Estrutura do módulo
Nosso módulo weather.lua vai conter a seguinte estrutura:
local M = {}
local function create_command()
-- vamos criar o comando :Weather aqui
end
M.create_window = function()
-- aqui vamos criar a janela, um mapping para fechá-la e mostrar o tempo
end
M.close_window = function()
-- uma função para fechar a janela atual, que sera usada em um mapping
end
return M
Analisando uma por uma, temos:
create_command()
A função create_command()
vai criar nosso comando customizado (command!). Aqui introduzimos o vim.cmd, que pode ser utilizada para chamar comandos Ex nativos do vim, mais conhecidos como os comandos :.
defininos nosso comando como:
vim.api.nvim_create_user_command("Weather", M.create_window(), {nargs=0})
com isso, nosso commando, :Weather
, vai chamar diretamente uma função do nosso módulo lua para esse plugin
create_window()
a função create_window()
vai ser responsável por criar uma floating window no canto superior direito da tela e mostrar o conteúdo do tempo. Para criá-la, precisamos seguir os seguintes passos:
- criar um buffer “descartável”, que será usado para o conteúdo da janela
- criar as configurações da janela (tamanho de linhas, colunas, posicao x e y na tela, bordas)
- chamar o comando que “abre” a janela
- criar um mapping para poder fechar a janela
- criar o conteúdo do buffer, no nosso caso, o tempo atual.
Para o passo 1, temos:
buf = vim.api.nvim_create_buf(false, true)
Aqui temos outra novidade também, o vim.api
, um conjunto de métodos para o neovim dentro do módulo lua vim. nvim_create_buf
aceita 2 parâmetros, se o buffer vai ser listado ou não (no nosso caso não, por isso o false
) e se ele será descartável ou não (no nosso caso sim, por isso o true
). Para saber mais sobre o método, chame :help nvim_create_buf
.
O método retorna o id do novo buffer criado, e a informação desse id é importante porque ele será usado para fazer referência em outras funções mais pra frente. Note aqui também que não estamos criando a váriavel buf dentro desse método, mas uma variável “global” do módulo lua que também será usada por outros métodos dentro desse módulo.
Para o passo 2, temos:
local columns = vim.api.nvim_get_option("columns")
local lines = vim.api.nvim_get_option("lines")
local win_width = math.ceil(columns * 0.3 - 10)
local win_height = math.ceil(lines * 0.3 - 6)
local x_pos = 1
local y_pos = columns - win_width
local win_opts = {
style = "minimal",
relative = "editor",
width = win_width,
height = win_height,
row = x_pos,
col = y_pos,
border = "single",
}
Primeiro pegamos as variáveis de total de linhas e colunas do buffer atual para fazer um cálculo proporcional do tamanho da nossa floating window.
relative="editor"
é a opção que vai dizer que iremos usar as coordenadas x e y globais, relativas ao editor, tendo tamanho inicial (0,0) até (linhas-1, colunas-1)style = "minimal"
, vai deixar nossa janela com configurações mínimas, removendo a maioria das opções de UI. Isso é essencial para janelas temporárias, onde não iremos precisar fazer nenhuma alteração.width
eheight
é o calculo proporcional do tamanho da janela, adicionando um padding para que ela não fique simplesmente “grudada” no canto superior direito da tela. Cada unidade de medida corresponde a um caracterrow
ecol
vai setar a posição x e y da nossa janelaborder
vai passar a config da nossa borda da floating window, no casosingle
representa linhas simples
Para o passo 3, temos:
win = vim.api.nvim_open_win(buf, true, win_opts)
Aqui chamamos a vim.api.nvim_open_win
, o método que vai abrir nossa janela, usando o buffer que criamos, com a configuração que passamos. Nos parâmetros, podemos também ver o true, que vai setar a janela como a atual. Vamos precisar disso para chamar o comando que gera o conteúdo da mesma. Note também que nossa variável win também é “global”, pois vamos precisar da informação dela para criar os mappings que vão poder fechá-la.
Para o passo 4, temos:
vim.keymap.set("n", "q", M.close_window(), {noremap = true, silent = true, buffer = buf})
Usamos a nova api introduzida no neovim 0.7 vim.keymap
para criar um nnoremap
local (somente para o buffer criado), que basicamente irá chamar outro método do nosso módulo, para fechar a janela. Iremos explicar o método close_window()
mais pra frente.
Como parâmetros, primeiros temos o modo, no caso o modo Normal
, depois o comando que esse mapping irá chamar e finalmente temos uma table com possíveis opções para o mapping, como noremap, silent, etc. No nosso caso, só queremos que o comando não coloque nenhum output na tela e não utilize nenhum outro mapping com a letra q, caso haja algum.
Finalmente para o passo 5, temos:
local command = "curl https://wttr.in/?0"
vim.fn.termopen(command)
Aqui fazemos uma ponte entre lua e vimscript, chamando a função termopen
, que basicamente abre um terminal emulado dentro do neovim com o resultado do comando curl
close_window()
A função close window no nosso caso só vai ser uma chamada direta para o nvim_win_close
:
vim.api.nvim_win_close(win, true)
Aqui passamos a variável win
, que é o id da nossa janela criada e true fala que queremos forçar o fechamento da janela.
Conclusão
Com isso, nosso primeiro plugin “para o mundo real”, está pronto. A versão do código para esse post pode ser vista clicando aqui.
Para ver a versão completa do plugin, com mais customizações, clique aqui e já manda o star!. Para a parte 3 da nossa série, vamos mostrar como portar nossa config do neovim em vimscript totalmente para Lua. Não deixem de acompanhar!
Para ouvir
Top comments (0)