Колдовской NeoVIM. Часть вторая. “Конфиг Всевластья”

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  6. Всё

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

27f8ca6d2272194b1df6fd9316511a0e.jpeg

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

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

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

968f2eab7472cb24c9810eea2b150100.png

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

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

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

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

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

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

$ sudo apt install neovim

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

$ nvim --version

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

$ nvim 

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

20b743c0c4658285f587050a2903dc73.png

Не пугайтесь. Это чистый 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}
  -- Комментирует по  все, вне зависимости от языка программирования
  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('', '', ':echoe "Use hjkl, bro"', {noremap = true, silent = false})
map('', '', ':echoe "Use hjkl, bro"', {noremap = true, silent = false})
map('', '', ':echoe "Use hjkl, bro"', {noremap = true, silent = false})
map('', '', ':echoe "Use hjkl, bro"', {noremap = true, silent = false})
-- Переключение вкладок с помощью TAB или shift-tab (akinsho/bufferline.nvim)
map('n', '', ':BufferLineCycleNext', default_opts)
map('n', '', ':BufferLineCyclePrev', default_opts)
--  разные вариации нумераций строк, можно переключаться на ходу
map('n', '', ':exec &nu==&rnu? "se nu!" : "se rnu!"', default_opts)

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

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

e76a0d90b8f687067dc4c83fef01c6b5.png

И тем не менее редактор пока не изменился, ведь мы не установили плагины! Для этого мы используем самый популярный менеджер плагинов/пакетов «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 покажет набираемую команду в левом-нижнем углу.

03a68f16a1adf19c7d8023312450ef4a.png

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

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

f90dec826d6976851e330c854350833c.png

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

09160fe66c21821ce55eb23c9b647643.png

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

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

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

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

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

LSP

9bf76573beac6793565f2e53c28b6c7e.png

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

b848dc7376c684b1be9ea166595d3f19.png

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

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

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

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

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

© Habrahabr.ru