Полное руководство по настройке конфигурации NeoVim для разработчиков - часть 2
Перед тем как начать, рекомендую ознакомиться с первой частью, где я показал как настроить Neovim с нуля, начиная с установки и конфигурирования консоли и заканчивая множеством необходимых плагинов для работы с кодом:
Материал ниже лучше читать после прочтения и повторения того, что было описано в первой части. Но в случае, если у тебя уже есть настроенная конфигурация и тебе нужно добавить туда какой-либо плагин из описанных ниже - ты без проблем сможешь это сделать: я постарался описать все плагины в независимом друг от друга виде в отдельных подразделах.
Перед тем как приступить к конфигурации редактора, я предлагаю немного подтюнить нашу консоль - wezterm, которую мы настривали и конфигурировали в первой части.
Я показываю настройку и редактора и консоли для Mac, поэтому дальнейшие действия с консолью подходит пользователям Macos. Если у тебя линукс - скорее всего, проблем с консолью, решаемых ниже, у тебя не будет и можно смело переходить к настройке плагинов.
Маппинг кнопки Command для работы с wezterm и neovim
В процессе работы я понял, что мне сильно удобней маппить различные комбинации на кнопку Command. Например, по дефолту в vim/neovim чтобы перейти на соседнее окно нужно нажать Control + w, что мягко говоря не очень удобно. Сильно удобней переопределить все комбинации с Control на Command. Установить комбинации в neovim - несложно, обычно это делается через команду
vim.api.nvim_set_keymap(mode, combination, command, options...)
Но особенность wezterm, как и большинства других консолей для mac в том, что они не передают редактору комбинацию в читаемом виде (если ты знаешь как это сделать более простым способом - пиши в комменты). Способ, которым это делаю я выглядит так: мы биндим в конфиге wezterm все нужные нам комбинации как utf8-символы, которые будут отправляться в neovim. Затем в конфиге neovim мы биндим комбинации уже на переданные utf-8 символы.
Конфиг в wezterm:
--- cmd+keys that we want to send to neovim.
local super_vim_keys_map = {
-- Command + s: saving file
s = utf8.char(0xAA),
-- Command + e: scroll downwords (ctrl + e analog)
e = utf8.char(0xAB),
-- Command + y: scroll upwords (ctrl + y analog)
y = utf8.char(0xAC),
-- Command + h: go to prev tab
h = utf8.char(0xAD),
-- Command + l: go to next tab
l = utf8.char(0xAE),
-- Command + w: close current tab
w = utf8.char(0xAF),
-- Command + t: find file toogle (NvimTree)
t = utf8.char(0xA1),
}
local function bind_super_key_to_vim(key)
return {
key = key,
mods = 'CMD',
action = wezterm.action_callback(function(win, pane)
local char = super_vim_keys_map[key]
if char and is_vim(pane) then
-- pass the keys through to vim/nvim
win:perform_action({
SendKey = { key = char, mods = nil },
}, pane)
else
win:perform_action({
SendKey = {
key = key,
mods = 'CMD'
}
}, pane)
end
end)
}
end
local keys = {
...,
bind_super_key_to_vim('s'),
bind_super_key_to_vim('h'),
bind_super_key_to_vim('l'),
bind_super_key_to_vim('w'),
bind_super_key_to_vim('e'),
bind_super_key_to_vim('y'),
bind_super_key_to_vim('t'),
bind_super_key_to_vim('['),
bind_super_key_to_vim(']'),
bind_super_key_to_vim('n'),
bind_super_key_to_vim('m')
}
config.keys = keys
return config
Полный код конфига можно найти тут.
И далее маппим эти utf8 символы уже на стороне neovim. Создаем lua-файл, где будем прописывать все маппинги - combinations.lua:
local keymap = vim.api.nvim_set_keymap
local default_opts = {noremap = true, silent = true}
-- cmd+s: save file
keymap("n", "<Char-0xAA>", "<cmd>write<cr>", default_opts)
-- cmd+e: scroll downwords
keymap("n", "<Char-0xAB>", "<C-e>", default_opts)
-- cmd+e: scroll upwords
keymap("n", "<Char-0xAC>", "<C-y>", default_opts)
-- cmd+h: next tab
keymap("n", "<Char-0xAD>", "<cmd>BufferPrevious<cr>", default_opts)
-- cmd+l: last tab
keymap("n", "<Char-0xAE>", "<cmd>BufferNext<cr>", default_opts)
-- cmd+w: close current tab
keymap("n", "<Char-0xAF>", "<cmd>BufferClose<cr>", default_opts)
-- cmd+t: find file toogle
keymap("n", "<Char-0xA1>", "<cmd>NvimTreeFindFile<cr>", default_opts)
-- cmd+1: open left bar
keymap('n', '<Char-0xA4>', '<cmd>NvimTreeToggle<cr>', default_opts)
Теперь подключаем этот файл в секции c require в init.lua:
...
require"combinations"
Теперь перезагружаем neovim и проверяем: если открыть какой-либо файл, и нажать command + t, то neovim автоматически перебросит тебя в этот файл в дереве файлов.
Теперь если вернуться в файл, и нажать Command + e, то nvim начнет скроллить файл вниз, Command + y - наверх. Command + s сохранит файл, а Command + h / Command + l будет ходить по разным вкладкам внутри neovim. Теперьм можно переходить к настройке плагинов.
Telescope - поиск по файлам и содержимому
Первый плагин, которым я пользуюсь постоянно - это Telescope. На данный момент это самый популярный плагин для поиска по файлам и по содержимому. Пользуюсь им уже пару лет и могу сказать, что в большинстве случаев плагин отлично справляется со своими задачами.
Для поиска по содержимому файлов плагин использует утилиту для консольного поиска fzf. Прежде чем переходить к плагинам, нам нужно ее установить:
brew install fzf
И после установки загрузить ее в текущую сессию терминала:
source <(fzf --zsh)
Затем в этой же сессии открываем nvim и создаем файл telescope_config.lua:
-- Use vim.keymap.set instead of vim.api.nvim_set_keymap
local keymap = vim.keymap.set
-- Map <leader>f to fzf-lua's file search
keymap("n", "<leader>f", require("fzf-lua").files, { desc = "Fzf files" })
-- Map <leader>g to fzf-lua's live grep
keymap("n", "<leader>g", require("fzf-lua").live_grep, { desc = "Fzf live grep" })
Подключаем нужные плагины и конфиг в init.lua:
...
-- Telescope
Plug('nvim-lua/plenary.nvim') --for fzf
Plug('nvim-telescope/telescope.nvim', { [ 'tag' ] = '0.1.4' })
Plug('ibhagwan/fzf-lua', {['branch'] = 'main'})
...
require"telescope_config"
Перезапускаем, скипаем ошибку нажатием на enter, и выполняем :PlugInstall. После установки перезапускаем еще раз. Теперь нажимаем комбинацию \ + f
и видим окно поиска по файлам:
Затем нажимаем комбинацию \ + g и видим окно поиска по содержимому:
Autosession
Autosession - плагин, добавляющий очень привычную нам вещь - он запоминает, какие файлы были открыты перед закрытием nvim и открывает их автоматически, когда nvim будет открыт в следующий раз.
Создаем файл autosession.lua:
require'auto-session'.setup {
suppressed_dirs = { "~/", "~/Projects", "~/Downloads", "/"},
auto_restore_last_session = true
}
Затем в init.lua подключаем файл и конфиг для него в init.lua:
Plug('rmagatti/auto-session')
...
require"autosession"
Устанавливаем, перезапускаем и проверяем:
Comment - комментарии в коде
Теперь добавим еще одну базовую возможность - возможность комментировать и раскомментировать код. Я для этого использую плагин Comment - он работает из коробки и поддерживает treesitter, что дает нам поддержку большинства языков программирования.
Создаем файл comment_config.lua:
require('Comment').setup()
Затем подключаем плагин и конфиг для него в init.lua:
...
Plug('numToStr/Comment.nvim')
...
require("comment_config")
Устанавливаем, перезапускаем, и далее, выделяя любой участок кода через визуальный режим (Shift+V + ↑/↓) комбинацией gc мы можем комментировать и раскомментировать обратно выделенный участок кода:
Trouble
Nvim имеет собственные средства для отображения ошибок в коде, но добраться до них мягко говоря не просто.
Trouble - плагин, добавляющий интерфейс для отображения всех ошибок в открытом проекте. Trouble имеет поддержку lsp-сервера, что позволяет нам видеть все ошибки в привычном виде с понятными комментариями.
Создаем конфиг trouble_config.lua:
require('trouble').setup()
vim.keymap.set("n", "<leader>xx", function() require("trouble").toggle() end)
vim.keymap.set("n", "<leader>xw", function() require("trouble").toggle("workspace_diagnostics") end)
vim.keymap.set("n", "<leader>xd", function() require("trouble").toggle("document_diagnostics") end)
vim.keymap.set("n", "<leader>xq", function() require("trouble").toggle("quickfix") end)
vim.keymap.set("n", "<leader>xl", function() require("trouble").toggle("loclist") end)
vim.keymap.set("n", "gR", function() require("trouble").toggle("lsp_references") end)
init.lua:
...
Plug('folke/trouble.nvim')
...
require"trouble_config"
...
Плагин из коробки имеет набор комбинаций, которыми можно пользоваться, но я перенастроил открытие интерфейса на связку Command + [.
Чтобы сделать так же, нужно вернуться в конфиг wezterm и добавить еще одну комбинацию для открытия Trouble через Command:
wezterm.lua:
-- Command + [: open trouble window
['['] = utf8.char(0xA2),
-- Command + ]: close trouble window
[']'] = utf8.char(0xA3),
...
bind_super_key_to_vim('['),
bind_super_key_to_vim(']'),
...
Затем добавляем эти комбинации в nvim-конфиге:
combinations.lua:
...
-- cmd+[: get troubles
keymap("n", "<Char-0xA2>", "<cmd>Trouble diagnostics toggle<cr>", default_opts)
-- cmd+]: close troubles
keymap("n", "<Char-0xA3>", "<cmd>TroubleClose<cr>", default_opts)
...
Перезапускаем и проверяем:
git-blame - интерактивная история коммитов
git-blame - минималистичный плагин, который делает тоже самое, что мы привыкли видеть в IDE когда открываем аннотации в коде: отображает автора и название коммита.
Плагин не требует конфигурации, и чтобы его включить нам достаточно подключить плагин в init.lua:
Plug 'f-person/git-blame.nvim'
И установить его. Затем наводим на любую строчку в проекте с git и видим:
Заключение
На этом настройка базового конфига завершена. Я описал самые основные плагины, дающие фундаментальные возможности, к которым мы привыкли в различных IDE.
Мой конфиг несколько шире того, что я показал выше. Например, там есть плагины для работы с тестами, для более расширенной работы с гитом, решения гит-конфликтов, для более удобного поиска и отладки кода.
Но, чтобы не растягивать текст, я опишу эти плагины и их настройку в отдельных статьях.
Мой полный конфиг, который постоянно обновляется, можно найти тут:
Конфиг wezterm:
Так же я веду англоязычный telegram-канал с дайджестом материалов по Go:
И авторский телеграм-канал, куда пишу различные заметки, инструменты и делюсь опытом:
И обязательно подписывайся на новые материалы на этом сайте, скоро они начнут выходить чаще :)