Никто не любит конфиги (я уж точно). Они скучные и нединамичные.

Но со своим конфигом Nvim’а я ношусь, как Голлум с кольцом Всевластья. Моя прелесссссть. Я боюсь потерять свой конфиг, боюсь, что с ним что-то случится. Другие хотят забрать тебя, моя прелессссть. Саша тебя им не отдаст, нет-нет...

Если кто-то отнимет мой конфиг - я буду гнаться за ним до Роковой Горы и даже прыгну в жерло вулкана.

В этой статье я расскажу, как создать такой Конфиг Всевластья и как завоевать Гондор.

Зачем возиться с файлом конфигурации?

Потому что ничего, кроме файла конфигурации, вам не нужно.

Моя прелесссть
Моя прелесссть

Конфиг является полным хранилищем всех необходимых плагинов, настроек, горячих клавиш, скриптов. Это сердце колдовского редактора.

Установка Neovim обычно выглядит так:

  1. Одной командой устанавливаем Neovim.

  2. Копируем свой конфиг в папку с конфигами редактора.

  3. Устанавливаем менеджер пакетов (одна команда)

  4. Устанавливаем плагины (одна команда)

  5. ОПЦИОНАЛЬНО: Подключаем LSP-сервер. Одна команда.

  6. Всё

Спустя пару минут вы готовы к работе. И не просто готовы! Вы только что получили идеально точную копию той рабочей среды, к которой вы привыкли. Абсолютно всё, начиная с темы, используемых плагинов, и заканчивая горячими клавишами и нюансами настройки, будет повторять все ваши другие Nvim’ы. Рай для людей с обсессивно-компульсивным расстройством и программистов…

С недавнего времени все любители колдовского редактора дружно пересели на конфиги, написанные на Lua. А чем мы хуже?

Чуть-чуть про Lua

Lua - это простой скриптовый язык. Он предназначен для пользователей, не являющихся профессиональными программистами. Большое внимание уделено простоте дизайна и лёгкости обучения.

С помощью этого языка пишут скрипты для игр, некоторые интерфейсы, а еще пишут модульные и удобные конфиги колдовского редактора.

На Хабре про Lua есть даже целый канал.

Устанавливаем Nvim

Я разверну новую версию Neovim на Ubuntu 22.04 LTS, а конфиг будет заточен под Python. Но вы сможете легко его перенастроить под свои любимые языки программирования.

ОПЦИОНАЛЬНО: Для лучшей работы конфигурационного файла и плагинов вам понадобится Neovim как минимум 8й версии. Установить ее можно здесь (я сейчас использую Nvim 9й версии, скачиваю его через PPA).

Старые версии устанавливаются проще:

$ sudo apt install neovim

Установили? Теперь убедимся, что колдовской редактор попал в $PATH:

$ nvim --version

Откройте любой файл через:

$ nvim <file>

Выглядеть должно примерно так:

Не пугайтесь. Это чистый Nvim. Он удобен, когда вы хотите быстро отредактировать файл на сервере, но для разработки все-таки нужно что-то пофункциональнее. Для того, чтобы выйти из колдовского редактора, наберите команду ZQ (обратите внимание, что команда написана прописными буквами).

Затем создайте каталог по адресу ~/.config/nvim/ . А в нем разверните следующую структуру файлов:

nvim/
├── init.lua
├── lua/
│   ├── keymaps.lua
│   ├── plugins.lua
│   ├── settings.lua
│   └── treesitter.lua

То есть у нас в каталоге nvim/ есть отдельный файл init.lua и каталог lua/ с 4мя файлами-модулями.

Заполните все файлы:

init.lua Точка входа. Отсюда Nvim начинает читать конфигурацию.
-----------------------------------------------------------
-- Импорт модулей Lua
-----------------------------------------------------------
require('plugins')
require('settings') 
require('keymaps')
require('treesitter')

plugins.lua Подключаемые плагины
vim.cmd [[packadd packer.nvim]]

return require('packer').startup(function(use)
  -- Автоустановка пакетного менеджера
  use 'wbthomason/packer.nvim'
  ---------------------------------------------------------
  -- ПЛАГИНЫ ВНЕШНЕГО ВИДА
  ---------------------------------------------------------
  -- Информационная строка внизу
  use "kyazdani42/nvim-web-devicons"
  use { 'nvim-lualine/lualine.nvim',
      requires = {'kyazdani42/nvim-web-devicons', opt = true},
      config = function()
      require('lualine').setup()
  end, }
  -- Тема в стиле Rose Pine
  use({
    'rose-pine/neovim',
    as = 'rose-pine',
    config = function()
      vim.cmd('colorscheme rose-pine')
    end
  })
  ---------------------------------------------------------
  -- МОДУЛИ РЕДАКТОРА
  ---------------------------------------------------------
  -- Табы с вкладками сверху
  use {'akinsho/bufferline.nvim',
      requires = 'kyazdani42/nvim-web-devicons',
      config = function()
      require("bufferline").setup{}
  end, }
  -- Структура классов и функций в файле
  use 'majutsushi/tagbar'
  -- Файловый менеджер
  use { 'kyazdani42/nvim-tree.lua',
      requires = 'kyazdani42/nvim-web-devicons',
      config = function() 
      require'nvim-tree'.setup {}
  end, }
  --- popup окошки
  use 'nvim-lua/popup.nvim'
  ---------------------------------------------------------
  -- ПОИСК
  ---------------------------------------------------------
  -- Наш FuzzySearch
  use { 'nvim-telescope/telescope.nvim',
      requires = { {'nvim-lua/plenary.nvim'} },
      config = function() 
      require'telescope'.setup {}
  end, }
    
  ---------------------------------------------------------
  -- КОД
  ---------------------------------------------------------
  -- автоматические закрывающиеся скобки
  use { 'windwp/nvim-autopairs',
      config = function()
      require("nvim-autopairs").setup()
  end}
  -- Комментирует по <gc> все, вне зависимости от языка программирования
  use { 'numToStr/Comment.nvim',
      config = function() 
      require('Comment').setup() 
  end }

  ---------------------------------------------------------
  -- LSP И АВТОДОПОЛНЯЛКИ
  ---------------------------------------------------------
  -- Collection of configurations for built-in LSP client
  use 'neovim/nvim-lspconfig'
  use 'williamboman/nvim-lsp-installer'

  -- Автодополнялка
  use 'hrsh7th/nvim-cmp'
  use 'hrsh7th/cmp-nvim-lsp'
  use 'hrsh7th/cmp-buffer'
  use 'saadparwaiz1/cmp_luasnip'

  --- Автодополнлялка к файловой системе
  use 'hrsh7th/cmp-path'

  -- Snippets plugin
  use 'L3MON4D3/LuaSnip'

  -- Highlight, edit, and navigate code using a fast incremental parsing library
  use 'nvim-treesitter/nvim-treesitter'

  -- Линтер, работает для всех языков
  use 'dense-analysis/ale'
  ---------------------------------------------------------
  -- РАЗНОЕ
  ---------------------------------------------------------
  -- Даже если включена русская раскладка, то nvim-команды будут работать
  use 'powerman/vim-plugin-ruscmd'
end)

settings.lua Настройки редактора
local opt = vim.opt

-----------------------------------------------------------
-- ОБЩИЕ ОПЦИИ
-----------------------------------------------------------
opt.mouse = 'a'              --Включит мышь
opt.encoding = 'utf-8'       --Кодировка
opt.showcmd = true           --Отображение команд
vim.cmd([[
filetype indent plugin on
syntax enable
]])
opt.swapfile = false         --Не создаем свап файлы

-----------------------------------------------------------
-- ВИЗУАЛЬНЫЕ ОПЦИИ
-----------------------------------------------------------
opt.number = true            --Номер строк сбоку
opt.wrap = true              --Длинные линии будет видно
opt.expandtab = true         --???
opt.tabstop = 4              --1 tab = 4 пробела
opt.smartindent = true
opt.shiftwidth = 4           --Смещаем на 4 пробела

-- 2 spaces for selected filetypes
vim.cmd [[
autocmd FileType xml,html,xhtml,css,scss,javascript,lua,yaml,htmljinja setlocal shiftwidth=2 tabstop=2
]]

opt.so = 5                   --Отступ курсора от края экрана
opt.foldcolumn = '2'         --Ширина колонки для фолдов
opt.colorcolumn =  '119'     --Расположение цветной колонки

-- remove line lenght marker for selected filetypes
vim.cmd [[autocmd FileType text,markdown,html,xhtml,javascript setlocal cc=0]]

opt.cursorline = true        -- Подсветка строки с курсором
opt.termguicolors = true

-- Компактный вид у тагбара и Отк. сортировка по имени у тагбара
vim.g.tagbar_compact = 1
vim.g.tagbar_sort = 0

-----------------------------------------------------------
-- НАСТРОЙКИ ПОИСКА
-----------------------------------------------------------
-- Будет игнорировать размер букв при поиске
opt.ignorecase = true        --Игнорировать размер букв
opt.smartcase = true         --Игнор прописных буквj

-----------------------------------------------------------
-- ПОЛЕЗНЫЕ ФИШКИ
-----------------------------------------------------------
-- Подсвечивает на доли секунды скопированную часть текста
vim.api.nvim_exec([[
augroup YankHighlight
autocmd!
autocmd TextYankPost * silent! lua vim.highlight.on_yank{higroup="IncSearch", timeout=300}
augroup end
]], false)

-----------------------------------------------------------
-- НАСТРОЙКИ ПЛАГИНОВ
-----------------------------------------------------------
-- LSP settings
local lsp_installer = require("nvim-lsp-installer")
lsp_installer.on_server_ready(function(server)
    local opts = {}
    if server.name == "sumneko_lua" then
        -- only apply these settings for the "sumneko_lua" server
        opts.settings = {
            Lua = {
                diagnostics = {
                    -- Get the language server to recognize the 'vim', 'use' global
                    globals = {'vim', 'use'},
                },
                workspace = {
                    -- Make the server aware of Neovim runtime files
                    library = vim.api.nvim_get_runtime_file("", true),
                },
                -- Do not send telemetry data containing a randomized but unique identifier
                telemetry = {
                    enable = false,
                },
            },
        }
    end
    server:setup(opts)
end)


-- nvim-cmp supports additional completion capabilities
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
vim.o.completeopt = 'menuone,noselect'
-- luasnip setup
local luasnip = require 'luasnip'
-- nvim-cmp setup
local cmp = require 'cmp'
cmp.setup {
    snippet = {
        expand = function(args)
            luasnip.lsp_expand(args.body)
        end,
    },
    sources = {
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
        { name = 'path' },
        { name = 'buffer', option = {
            get_bufnrs = function()
                return vim.api.nvim_list_bufs()
            end
        },
    },
},
}

keymaps.lua Переназначенные клавиши и скрипты
local map = vim.api.nvim_set_keymap
local default_opts = {noremap = true, silent = true}
-----------------------------------------------------------
-- НАВИГАЦИЯ
-----------------------------------------------------------
-- Отключаем стрелочки в Нормальном Режиме. Хардкор!
map('', '<up>', ':echoe "Use hjkl, bro"<CR>', {noremap = true, silent = false})
map('', '<down>', ':echoe "Use hjkl, bro"<CR>', {noremap = true, silent = false})
map('', '<left>', ':echoe "Use hjkl, bro"<CR>', {noremap = true, silent = false})
map('', '<right>', ':echoe "Use hjkl, bro"<CR>', {noremap = true, silent = false})
-- Переключение вкладок с помощью TAB или shift-tab (akinsho/bufferline.nvim)
map('n', '<Tab>', ':BufferLineCycleNext<CR>', default_opts)
map('n', '<S-Tab>', ':BufferLineCyclePrev<CR>', default_opts)
-- <F5> разные вариации нумераций строк, можно переключаться на ходу
map('n', '<F5>', ':exec &nu==&rnu? "se nu!" : "se rnu!"<CR>', default_opts)

-----------------------------------------------------------
-- РЕЖИМЫ
-----------------------------------------------------------
-- Выходим в нормальный режим через <jk>, чтобы не тянуться
map('i', 'jk', '<Esc>', {noremap = true})
-----------------------------------------------------------
-- ПОИСК
-----------------------------------------------------------
-- Выключить подсветку поиска через комбинацию ,+<space>
map('n', ',<space>', ':nohlsearch<CR>', {noremap = true})
-- Fuzzy Search. CTRL+a для поиска по файлам, CTRL+p для поиска по буфферам
map('n', '<C-a>', [[ <cmd>lua require('telescope.builtin').find_files()<cr> ]], default_opts)
map('n', '<C-p>', [[ <cmd>lua require('telescope.builtin').buffers()<cr> ]], default_opts)
-- <S-F5> Греповский поиск слова под курсором
map('n', '<S-F5>', [[<cmd>lua require('telescope.builtin').grep_string()<cr>]], default_opts)
-- <S-F4> Греповский поиск слова в модальном окошке
map('n', '<S-F4>', [[<cmd>lua require('telescope.builtin').live_grep()<cr>]], default_opts)
-----------------------------------------------------------
-- ФАЙЛЫ
-----------------------------------------------------------
-- <F8>  Показ дерева классов и функций, плагин majutsushi/tagbar
map('n', '<F8>', ':TagbarToggle<CR>', default_opts)
-- <F4> Дерево файлов. Для иконок следует установить Nerd Font
map('n', '<F4>', ':NvimTreeRefresh<CR>:NvimTreeToggle<CR>', default_opts)

treesitter.lua Настройки отдельного плагина Treesitter
require'nvim-treesitter.configs'.setup {
  -- Парсеры, которые мы собираемся использовать
  ensure_installed = { "lua", "python", "javascript", "typescript"},

  sync_install = false,

  -- Automatically install missing parsers when entering buffer
  -- Recommendation: set to false if you don't have `tree-sitter` CLI installed locally
  auto_install = true,


  highlight = {
    -- `false` will disable the whole extension
    enable = true,

    -- Setting this to true will run `:h syntax` and tree-sitter at the same time.
    -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
    -- Using this option may slow down your editor, and you may see some duplicate highlights.
    -- Instead of true it can also be a list of languages
    additional_vim_regex_highlighting = false,
  },
}

Конфиг небольшой и несложный, а еще максимально подробно закомментирован для вашего удобства! Советую почитать про синтаксис Lua, а затем попытаться разобраться в самом конфиге самостоятельно.

Пакетный менеджер

И тем не менее редактор пока не изменился, ведь мы не установили плагины! Для этого мы используем самый популярный менеджер плагинов/пакетов “Packer”.

Устанавливаем (для Ubuntu):

$ git clone --depth 1 https://github.com/wbthomason/packer.nvim\
 ~/.local/share/nvim/site/pack/packer/start/packer.nvim

После установки откроем в nvim файл plugins.lua и установим плагины командой :PackerSync

Да, нужно набрать двоеточие и “PackerSync” вместе. Для удобства Nvim покажет набираемую команду в левом-нижнем углу.

Подробнее о том, как в колдовском редакторе работает режим командной строки мы поговорим в следующей части.

После набора команды Packer установит плагины.

Затем выйдем из nvim, зайдем заново и полюбуемся результатом. Должно получиться как-то так:

То есть красивый темный фон, нет ошибок и есть распознавание синтаксиса.

Если не получилось:

  • Внимательно читайте описание ошибок. Почти всегда они прямо укажут на проблему.

  • Проверьте, что в вашем терминале установлен один из Nerd Fonts. Конфиг должен работать и без них (хотя иконки не смогут отображаться), но вы предупреждены.

  • Используйте команду :checkhealth . Она даст исчерпывающий перечень проблем, которые видит Nvim. Для большинства проблем он сразу предложит решение (например у меня стоял жутко старый node, и Nvim посоветовал обновиться).

LSP

Одна из важных механик колдовского редактора (да и почти любой IDE) - это работа с LSP.

Language Server Protocol - это формат общения Сервер-Клиент, который помогает работать с конкретным языком программирования. Благодаря LSP наш маленький (но гордый) Nvim научится делать автозаполнение, находить определения функций/классов и многое другое.

В упрощенном виде LSP-коммуникация выглядит примерно так:

Клиент → JavaScriptLanguageServer: "Расскажи, а вот в JavaScript мы блоки кода выделяем индентацией?"

JavaScriptLanguageServer → Клиент: "Нет, у нас в JS фигурные скобки."

Клиент → JavaScriptLanguageServer: "А это что такое?"

JavaScriptLanguageServer → Клиент: "Это глобальная переменная."

LSP помогает нашему редактору работать с любыми языками программирования.

Для установки серверов наберите команду :LspInstall и следуйте инструкциям. Советую для работы с Python выбрать сервер Pyright.

После этого мы получим поддержку для .lua и .py файлов.

Особенности данного конфига

  • Через <F4> мы получаем доступ к файловому менеджеру, а через <F8> к структуре нашего файла.

  • <CTRL+a> Даст доступ к fuzzy search, и позволит очень быстро находить и открывать файлы.

  • У нас есть линтинг.

  • С помощью <F5> можно выбрать формат нумерации строк в редакторе.

  • <tab> и <shift-tab> позволят переключаться между табами. И у нас вообще появятся табы!

  • И многое другое


Конфигурация колдовского редактора - невероятно объемная тема. Надеюсь, что мне удалось помочь начинающим запустить Nvim в удобном виде, который сделает переход с привычной IDE чуть легче!

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

  • Пользователь Хабра с ником Rilkener

  • Самый быстрый Nvim'ист на свете Primeagen

А в следующей части мы познакомимся с Режимами в Nvim!

Комментарии (17)


  1. ovalsky
    17.12.2022 18:55
    +1

    vim.cmd [[packadd packer.nvim]]

    я правильно понимаю, что это ввод вимовской команды в луа? Это привычка или необходимость? Я к тому что, есть ли вариант только на луа?


    1. ivlad
      18.12.2022 03:53

      Нету. Сейчас neovim не может обходится без команд vim.


      1. PATRICK17
        18.12.2022 19:43

        Так это же вызов через API. Можно так
        vim.cmd.packadd('packer.nvim')


        1. ivlad
          19.12.2022 04:28

          Это внутри будет тем же самым


  1. russarr
    17.12.2022 20:54

    Сколько чужих конфигов не посмотришь, всегда найдется для себя что-то новое. Утянул подсветку при копировании.


    1. AlexRussianPyth Автор
      17.12.2022 20:55
      +1

      Которую я в свою очередь утянул где-то еще)


    1. vtb_k
      18.12.2022 16:22

      Для любителей Емакса статья тоже полезная. После часа гугления нашел мод для этого.


  1. andreytkachenko64
    17.12.2022 20:54

    Для меня helix полностью заменил vim


    1. leorikz
      18.12.2022 00:00

      там тоже млрд плагинов?


      1. andreytkachenko64
        18.12.2022 10:01

        Там пока нет плагинов, и все реализовано "из коробки". Плагины предложены, но пака не приняты в основную ветку. А так редактор обладает всеми достоинствами vimа но значительно быстрее и стабильнее (субъективное мнение)


        1. leorikz
          18.12.2022 12:08

          спасибо, попробую внимательнее посмотреть


  1. Deq56
    17.12.2022 21:13
    +1

    А в чем преимущество табов над буфером?


    1. ovalsky
      18.12.2022 00:42

      а это не одно и тоже?


      1. ivlad
        18.12.2022 03:52

        Нет, в vim буфер - это редактируемый файл, который может отображаться в одном или нескольких окнах (window). Табы - это вариант раскладки окон, которых может быть несколько.


  1. Mitai
    18.12.2022 10:22
    +1

    -- Install packer
    local install_path = vim.fn. stdpath'data' .. '/site/pack/packer/start/packer.nvim'
    local is_bootstrap = false
    if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
     is_bootstrap = true
     vim.fn.execute('!git clone https://github.com/wbthomason/packer.nvim ' .. install_path)
     vim.cmd [[packadd packer.nvim]]
    end

    вот так он автоматом загрузит пакер если его нет на компе
    пысы: про Neovide будет?


    1. AlexRussianPyth Автор
      19.12.2022 08:24
      +1

      Я бы хотел весь материал про Nvim для новичков упаковать в цикл из 12 статей. Сейчас есть материал где-то на 10, поэтому да - постараюсь и про gui-nvim'ы рассказать. Мне и самому интересно с ними познакомиться.


      1. leorikz
        19.12.2022 08:26

        это мы ждём