Neovim с нуля: фундамент — `init.lua` и базовые настройки
Когда я только начинал осваивать Neovim как Python‑разработчик, быстро упёрся в неприятный факт: понятных русскоязычных разборов как собрать свой конфиг с чистого листа практически нет. Есть готовые «дистрибутивы» (NvChad, LazyVim, AstroNvim), есть переводы отдельных статей, но нет последовательного объяснения, почему конфиг устроен именно так, а не просто «скопируй эти 500 строк».
Свой рабочий конфиг я собирал фрагментами: по блогам, роликам, чужим репозиториям, документации. В этом цикле статей мы пойдём в обратную сторону: спокойно и осознанно построим конфигурацию Neovim на Lua, шаг за шагом.
Для кого этот цикл
Материал будет полезен, если вы:
- Уже знакомы с базовыми концепциями Vim/Neovim: режимы, `hjkl`, базовые команды.
- Пользовались готовыми сборками и хотите перейти на собственный конфиг, который понимаете.
- Устали слепо копировать фрагменты настроек и плагины.
- Ищете минималистичный, но расширяемый фундамент под разработку.
Важно: это не учебник Vim. Мы не будем разбирать, что такое normal mode или как сохранять файл. Предполагается, что Neovim у вас уже установлен и вы умеете выполнять базовые команды.
Фокус этого цикла — современная конфигурация Neovim на Lua.
Что вы получите к концу цикла
После прохождения всех частей у вас будет:
- Чистый, логичный конфиг на Lua, где вы понимаете каждую строку.
- Подключённый менеджер плагинов `lazy.nvim`.
- Современное автодополнение через `blink.cmp`.
- Подсветка синтаксиса и парсинг кода через Treesitter.
- Настроенный встроенный LSP‑клиент.
- Форматтеры и линтеры для ваших языков.
Это не будет «чёрный ящик» в стиле готовой IDE, а именно каркас, который легко доращивать под свои задачи.
Технические детали и требования
Конкретные примеры в серии будут показываться:
- на Linux (Arch‑подобная система, но это не принципиально),
- на Neovim версии 0.11.5 (минимально — 0.10).
Вам понадобится:
- установленный Neovim 0.10+;
- Git (для менеджера плагинов);
- базовое понимание Lua (уровень: что такое функции, таблицы и модули).
Если вы Lua никогда не видели, этого вполне достаточно: большая часть кода будет очень однообразной и легко читаемой.
Начинаем с чистого листа: убираем старый конфиг
Перед тем как строить что‑то своё, важно убедиться, что предыдущие эксперименты не мешают. Если вы уже ставили готовые конфиги или настраивали Neovim ранее, безопаснее всего:
1. Найти текущий каталог настроек (чаще всего `~/.config/nvim`).
2. Сделать бэкап:
```bash
mv ~/.config/nvim ~/.config/nvim_backup
```
3. Запустить Neovim — он стартует в состоянии «почти по умолчанию».
Теперь вы уверены, что никакие старые автокоманды, плагины и непонятные маппинги не влияют на поведение.
Два подхода к конфигу: монолит против модулей
Типичный путь новичка:
- один огромный `init.lua` (или `init.vim`) на сотни/тысячи строк,
- всё — в одном файле: опции, клавиши, плагины, автокоманды.
Этот вариант рабочий, но быстро превращается в хаос: править больно, расширять страшно.
Более современный и удобный подход — модульная структура:
- каждая логическая часть настроек живёт в отдельном файле;
- файлы группируются по директориям;
- `init.lua` остаётся маленьким «оркестратором», который просто подключает нужные модули.
Мы пойдём именно этим путём.
Базовая структура конфигурации
Создадим каркас в каталоге настроек Neovim. Для Unix‑подобных систем это обычно:
```bash
mkdir -p ~/.config/nvim/lua/core
```
Стартовая структура будет такой:
- `~/.config/nvim/init.lua` — точка входа.
- `~/.config/nvim/lua/` — директория, из которой Neovim может импортировать Lua‑модули.
- `~/.config/nvim/lua/core/` — каталог с «ядром» настроек: опции, горячие клавиши, базовые вещи.
Внутри `core` создадим первый модуль:
```bash
touch ~/.config/nvim/lua/core/options.lua
```
Пока можно оставить его пустым.
Как Neovim находит Lua‑модули
Neovim автоматически добавляет каталог `lua/` вашего конфига в `package.path`. Это означает, что в Lua‑коде вы можете писать:
```lua
require("core.options")
```
и Neovim найдёт файл:
```text
~/.config/nvim/lua/core/options.lua
```
Несколько правил:
- расширение `.lua` в `require()` не указывается;
- слэши в путях заменяются точками;
- первый вызов `require` загружает модуль, последующие — используют кеш.
Заполняем `init.lua`: подключаем модули
Откроем `~/.config/nvim/init.lua` и превратим его в минимальную точку входа:
```lua
require("core.options")
```
Позже мы добавим сюда и другие модули (горячие клавиши, плагины и т.д.), но на старте нам важно лишь то, чтобы:
- `init.lua` был максимально коротким и понятным;
- внутри него не было никакой «магии» — только импорт модулей.
`options.lua`: задаём поведение редактора
Теперь откроем `~/.config/nvim/lua/core/options.lua` и начнём описывать базовое поведение Neovim.
В современном Neovim предпочтительно использовать API `vim.opt` — это удобный и типобезопасный способ выставлять опции (аналог команды `set` из Vimscript).
В начале файла удобно написать:
```lua
local opt = vim.opt
```
Теперь вместо длинного `vim.opt.number = true` мы будем использовать состояние `opt.number = true`.
Дальше логично группировать настройки по смыслу: отступы, отображение, поиск, интерфейс и т.д.
Отступы и табуляция
Отступы — одно из самых важных и спорных мест в конфиге. Базовый набор опций:
- `tabstop` — сколько пробелов воспринимать как один таб;
- `shiftwidth` — насколько смещать строку при автоотступах и командах сдвига;
- `softtabstop` — как ведёт себя клавиша `` и `` в местах отступов;
- `expandtab` — сохранять ли табы как пробелы.
Пример логики (на словах):
- выставляем ширину таба на 2 или 4 пробела (для Lua часто используют 2, для Python — 4);
- включаем `expandtab`, чтобы табы сохранялись как пробелы;
- синхронизируем `shiftwidth` и `softtabstop` с `tabstop`, чтобы поведение было предсказуемым.
Позже Treesitter и другие плагины смогут переопределять эти значения в зависимости от типа файла (например, для Makefile использовать реальные табы).
Отображение: нумерация строк и визуальные удобства
Минимальный набор для комфортного чтения кода:
- `number = true` — показывает абсолютный номер текущей строки;
- `relativenumber = true` — для остальных строк показывает номер относительно курсора;
- опции для переноса строк, отображения правого края, скрытия/показа спецсимволов.
Сочетание `number` + `relativenumber` даёт сильное ускорение навигации:
- вы видите, что нужная строка находится на `10` строк выше;
- просто жмёте `10k` вместо того, чтобы считать строки глазами.
Текущая строка при этом отображается с реальным номером в файле, остальные — как смещения.
Поиск: регистр и поведение
Комфортный поиск чаще всего настраивают так, чтобы он был:
- регистр‑независимым по умолчанию;
- но при этом «уважал» явно введённые заглавные буквы.
Для этого комбинируют:
- `ignorecase = true` — игнорировать регистр;
- `smartcase = true` — если в запросе есть заглавные буквы, искать с учётом регистра.
Пример поведения:
- запрос `/hello` найдёт `hello`, `Hello`, `HELLO`;
- запрос `/Hello` найдёт только `Hello`, но не `hello` и не `HELLO`.
Такой подход позволяет не думать о регистре, пока это не принципиально, и сохраняет точность, когда важно.
Интерфейс: цвета, мышь и комфорт
Есть несколько ключевых опций, без которых современные конфиги выглядят бледно:
- `termguicolors = true` — включает поддержку 24‑битного цвета;
- `mouse = "a"` — включает поддержку мыши во всех режимах.
`termguicolors` необходимо, чтобы полноценно работали современные цветовые схемы и плагины с подсветкой. При этом важно, чтобы ваш терминал тоже поддерживал truecolor.
Опция `mouse = "a"` позволяет:
- скроллить колесом;
- кликать по тексту;
- выделять блоки мышью.
Если вы фанат «чистого» Vim‑стиля без мыши — это можно отключить, но для многих разработчиков плавный переход удобнее с подключенной мышью.
Файлы, буферы, история
Ещё один пласт настроек — управление файлами и историей изменений:
- `undofile = true` — включение постоянного undo;
- возможно, настройка каталога для хранения undo‑файлов;
- управление swap‑файлами и backup.
Ключевой момент здесь — `undofile = true`: вы можете закрыть файл, через неделю вернуться к нему, и история отмен (undo) сохранится. Это заметно снижает страх «сломать что‑то безвозвратно».
Дополнительные удобства
В `options.lua` часто попадают и другие мелочи:
- поведение поиска при вводе (`incsearch`, `hlsearch` аналогами через `vim.opt`);
- уровень сообщений и логирования;
- ограничения по ширине текста;
- настройки для разделения окон и сплитов.
Важно держать файл структурированным: логические блоки разделять комментариями, сгруппировать родственные опции. Тогда через несколько месяцев вы без труда вспомните, за что отвечает каждая секция.
Проблема работы с несколькими файлами: буферы и окна
Одна из типичных трудностей начинающих — понимание, как в Neovim устроена работа с несколькими файлами:
- файл привязан к буферу;
- буфер может отображаться в одном или нескольких окнах;
- сверху могут быть табы, которые группируют окна.
Стандартные команды (`:bnext`, `:bprev`, `:split`, `:vsplit`) мощные, но плохо запоминаются. Поэтому в следующем шаге мы перейдём к кастомным горячим клавишам, чтобы:
- быстро переключаться между буферами;
- гибко управлять окнами;
- сократить количество команд, которые нужно держать в голове.
Для этого создадим отдельный модуль.
`core/keymaps.lua`: ускоряем повседневную работу
Логичный следующий файл в нашем ядре — `~/.config/nvim/lua/core/keymaps.lua`. В нём будут:
- базовая функция‑обёртка над `vim.keymap.set` для удобства;
- настройка «главной» клавиши — `leader`;
- минимальный набор полезных маппингов.
Подключение в `init.lua` будет выглядеть так:
```lua
require("core.options")
require("core.keymaps")
```
Функция для описания горячих клавиш
Чтобы не дублировать в каждом маппинге опции вроде `noremap = true` и `silent = true`, удобно завести небольшую вспомогательную функцию:
- принимаем на вход режим (`"n"`, `"i"`, `"v"` и т.д.), сочетание клавиш и команду;
- под капотом вызываем `vim.keymap.set` с набором общих параметров;
- добавляем возможность указывать описание (description), которое пригодится позже для подсказок.
Такой слой абстракции не обязателен, но делает файл с клавишами гораздо чище.
Leader key: ваша «главная» клавиша
Во многих конфигурациях `leader` — это точка входа в ваш личный «пространство комбинаций». Часто её ставят на:
- пробел (`" "`), или
- запятую, или
- обратный слэш.
В Neovim это настраивается через:
```lua
vim.g.mapleader = " "
```
После этого вы можете создавать собственные команды в стиле:
- `f` — найти файл;
- `e` — открыть файловый менеджер;
- `q` — аккуратно закрыть окно.
`leader` превращает набор случайных комбинаций в хорошо организованную «клавиатурную палитру», которую легче запомнить.
Базовые улучшения и навигация
В `keymaps.lua` логично добавить:
- удобные команды для сохранения (`w`) и выхода (`q`);
- переназначения для перемещения по визуально перенесённым строкам (`gj`, `gk` по умолчанию);
- быстрый чистый поиск (`h` для отключения подсветки поиска).
Для работы с несколькими файлами:
- маппинги на `:bnext` / `:bprev` для быстрого пролистывания буферов;
- сокращения для создания и закрытия буферов.
Для окон:
- комбинации для перемещения между сплитами (например, ``, ``, ``, ``);
- быстрые команды разделения окна по горизонтали / вертикали.
Так вы перестанете каждый раз думать, как именно формулируется нужная команда, и начнёте просто «летать» по проекту.
Почему модульная структура выигрывает в долгую
На старте может показаться, что разносить всё по файлам — лишняя морока, но в перспективе это даёт несколько важных преимуществ:
1. Читаемость
Конфиг превращается в набор небольших логичных файлов, каждый из которых отвечает за свою зону: опции, клавиши, плагины, LSP и т.д.
2. Управляемость
Когда что‑то ведёт себя странно, вы легко находите правильный модуль и быстро сужаете область поиска.
3. Переиспользование
Отдельные модули проще копировать между машинами и проектами. Например, вы можете иметь общие `core/options.lua` и `core/keymaps.lua` для разных рабочих окружений.
4. Расширяемость
Добавление новой функциональности выглядит как создание очередного файла и одной строки `require()` в `init.lua`, а не как попытка воткнуть ещё 200 строк в уже переполненный монолит.
О чём мы уже позаботились
К этому моменту у нас уже есть:
- чистый конфиг без наследия прошлых экспериментов;
- минимальная структура каталогов `lua/` и `core/`;
- базовый `init.lua`, который подключает модули;
- файл `options.lua` с фундаментальными настройками редактора;
- план по заведению `keymaps.lua` для ускорения работы.
Функционально ваш Neovim уже станет ощутимо удобнее стандартных настроек, даже без единого плагина.
Что будет дальше
Дальнейшие шаги логично построить так:
1. Завершить работу с `keymaps.lua`
Продумать и описать горячие клавиши для всех частых операций, чтобы не возвращаться к этому каждый день.
2. Подключить менеджер плагинов
Мы выберем `lazy.nvim` и аккуратно интегрируем его в текущую модульную структуру.
3. Добавить Treesitter и подсветку синтаксиса
Настроим базовый набор языков, посмотрим, как это влияет на отступы и форматирование.
4. Настроить LSP, форматтеры и линтеры
Чтобы Neovim превратился в полноценную среду разработки, а не просто текстовый редактор.
5. Организовать структуру конфигов плагинов
Вынесем настройки плагинов в отдельные модули, сохранив понятность и модульность ядра.
---
В результате вы получите не просто «красивый конфиг с чужого скриншота», а свою собственную, понятную вам систему, которую сможете спокойно дорабатывать, не боясь всё сломать.



