Создание плагинов Lua для Neovim — часть 2


Плагин для реального мира


Во второй части нашей серии мы создадим плагин, который можно использовать на ежедневной основе, где мы представим некоторые классные возможности 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() будет отвечать за создание плавающего окна в правом верхнем углу экрана и отображение содержимого погоды. Чтобы создать его, необходимо выполнить следующие действия:

  1. создать «одноразовый» буфер, который будет использоваться для содержимого окна
  2. создать настройки окна (размер строк, столбцов, положение x и y на экране, границы)
  3. вызвать команду, которая «открывает» окно
  4. создать отображение, чтобы иметь возможность закрыть окно
  5. создать содержимое буфера, в нашем случае — текущее время.

Для шага 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. Не пропустите!

Слушать

Оцените статью
Procodings.ru
Добавить комментарий