Плагин для реального мира
Во второй части нашей серии мы создадим плагин, который можно использовать на ежедневной основе, где мы представим некоторые классные возможности Neovim, такие как плавающие окна и некоторые функции из Lua API.
Для начала давайте вспомним структуру плагина. Наш новый плагин будет иметь следующую структуру:
weather.nvim
├── lua
│ └── weather.lua
└── plugin
└── weather.lua
Идея плагина заключается в том, чтобы показывать текущий прогноз погоды в плавающем окне, вызываемом из команды.
Нарисовав его, мы получим что-то вроде этого:
Структура модуля
Наш модуль weather.lua будет содержать следующую структуру:
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
Рассматривая их по очереди, мы имеем:
create_command()
Функция create_command()
создаст нашу пользовательскую команду (command!). Здесь мы представляем vim.cmd, который можно использовать для вызова собственных команд vim Ex, более известных как : команды.
Мы определяем нашу команду следующим образом:
vim.api.nvim_create_user_command("Weather", M.create_window(), {nargs=0})
При этом наша команда, :Weather
, будет напрямую вызывать функцию из нашего модуля lua для этого плагина
create_window()
функция create_window()
будет отвечать за создание плавающего окна в правом верхнем углу экрана и отображение содержимого погоды. Чтобы создать его, необходимо выполнить следующие действия:
- создать «одноразовый» буфер, который будет использоваться для содержимого окна
- создать настройки окна (размер строк, столбцов, положение x и y на экране, границы)
- вызвать команду, которая «открывает» окно
- создать отображение, чтобы иметь возможность закрыть окно
- создать содержимое буфера, в нашем случае — текущее время.
Для шага 1 мы имеем:
buf = vim.api.nvim_create_buf(false, true)
Здесь также появилась еще одна новая возможность — vim.api
, набор методов для neovim внутри модуля lua vim. nvim_create_buf
принимает 2 параметра, будет ли буфер перечислен или нет (в нашем случае нет, отсюда false
) и будет ли он одноразовым или нет (в нашем случае да, отсюда true
). Чтобы узнать больше о методе, вызовите :help nvim_create_buf
.
Метод возвращает id вновь созданного буфера, и информация о id очень важна, поскольку в дальнейшем она будет использоваться для ссылок на другие функции. Также обратите внимание, что мы создаем не переменную buf внутри этого метода, а «глобальную» переменную из модуля lua, которая также будет использоваться другими методами внутри этого модуля.
Для шага 2 мы имеем:
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",
}
Сначала мы берем переменные общего количества строк и столбцов текущего буфера, чтобы пропорционально вычислить размер нашего плавающего окна.
-
relative="editor"
— это опция, которая говорит, что мы будем использовать глобальные координаты x и y, относительно редактора, с начальным размером (0,0) до (rows-1, columns-1). -
style = "minimal"
, оставит наше окно с минимальными настройками, удалив большинство опций пользовательского интерфейса. Это необходимо для временных окон, где нам не нужно будет вносить никаких изменений. -
width
иheight
— это пропорциональный расчет размера окна, добавление прокладки, чтобы оно не просто «прилипло» к правому верхнему углу экрана. Каждая единица измерения соответствует одному символу -
row
иcol
зададут x и y позицию нашего окна -
border
будет передавать конфигурацию границы нашего плавающего окна, в данном случаеsingle
представляет одиночные линии
Для шага 3 мы имеем:
win = vim.api.nvim_open_win(buf, true, win_opts)
Здесь мы вызываем vim.api.nvim_open_win
, метод, который откроет наше окно, используя созданный нами буфер, с переданной нами конфигурацией. В параметрах мы также видим true, который установит окно в качестве текущего. Это нам понадобится для вызова команды, которая генерирует содержимое окна. Также обратите внимание, что наша переменная win также является «глобальной», потому что нам понадобится информация о ней для создания отображений, которые смогут ее закрыть.
Для шага 4 мы имеем:
vim.keymap.set("n", "q", M.close_window(), {noremap = true, silent = true, buffer = buf})
Мы используем новый api, представленный в neovim 0.7 vim.keymap
для создания локального nnoremap
(только для созданного буфера), который в основном будет вызывать другой метод нашего модуля, чтобы закрыть окно. Метод close_window()
мы объясним позже.
В качестве параметров сначала указывается режим, в данном случае Normal
, затем команда, которую будет вызывать это отображение, и, наконец, таблица с возможными опциями для отображения, например, noremap, silent и т.д. В нашем случае мы просто хотим, чтобы команда не выводила никаких данных на экран и не использовала никакое другое отображение с буквой q, если таковое имеется.
Наконец, для шага 5 мы имеем:
local command = "curl https://wttr.in/?0"
vim.fn.termopen(command)
Здесь мы преодолеваем разрыв между lua и vimscript, вызывая функцию termopen
, которая в основном открывает эмулированный терминал внутри neovim с результатом команды curl
.
close_window()
Функция закрытия окна в нашем случае будет просто прямым вызовом nvim_win_close
:
vim.api.nvim_win_close(win, true)
Здесь мы передаем переменную win
, которая является id нашего созданного окна, а true говорит о том, что мы хотим принудительно закрыть окно.
Заключение
Таким образом, наш первый плагин «для реального мира» готов. Версию кода для этого сообщения можно посмотреть здесь.
Чтобы увидеть полную версию плагина, с большим количеством настроек, нажмите здесь и пришлите нам звезду! В третьей части нашей серии мы покажем, как перенести нашу конфигурацию neovim в vimscript на Lua. Не пропустите!
Слушать