Полное руководство по настройке конфигурации NeoVim для разработчиков - часть 2

Полное руководство по настройке конфигурации NeoVim для разработчиков - часть 2

Перед тем как начать, рекомендую ознакомиться с первой частью, где я показал как настроить Neovim с нуля, начиная с установки и конфигурирования консоли и заканчивая множеством необходимых плагинов для работы с кодом:

Полное руководство по настройке конфигурации NeoVim для разработчиков - часть 1
Neovim (nvim) - это тот же vim, только улучшенный, переписанный и перетянувший на свою сторону большую часть комьюнити оригинального редактора. Сейчас этот проект сильно обогнал оригиналный vim по статистике на github (34 vs 75k звезд на 2024 год), так что если ты по какой-то причине решил начать программировать в консоли

Материал ниже лучше читать после прочтения и повторения того, что было описано в первой части. Но в случае, если у тебя уже есть настроенная конфигурация и тебе нужно добавить туда какой-либо плагин из описанных ниже - ты без проблем сможешь это сделать: я постарался описать все плагины в независимом друг от друга виде в отдельных подразделах.

Перед тем как приступить к конфигурации редактора, я предлагаю немного подтюнить нашу консоль - 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.

Мой конфиг несколько шире того, что я показал выше. Например, там есть плагины для работы с тестами, для более расширенной работы с гитом, решения гит-конфликтов, для более удобного поиска и отладки кода.

Но, чтобы не растягивать текст, я опишу эти плагины и их настройку в отдельных статьях.

Мой полный конфиг, который постоянно обновляется, можно найти тут:

GitHub - itxor/go-rust-nvim-config
Contribute to itxor/go-rust-nvim-config development by creating an account on GitHub.

Конфиг wezterm:

wezterm_config/wezterm.lua at main · itxor/wezterm_config
Contribute to itxor/wezterm_config development by creating an account on GitHub.

Так же я веду англоязычный telegram-канал с дайджестом материалов по Go:

https://t.me/digest_golang

И авторский телеграм-канал, куда пишу различные заметки, инструменты и делюсь опытом:

https://t.me/junsenior

И обязательно подписывайся на новые материалы на этом сайте, скоро они начнут выходить чаще :)

Subscribe to vpoltora

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe