Skip to main content
  1. Posts/

Моя конфігурація Neovim

Після тривалого використання готових конфігурацій Neovim, таких як NvChad, LunarVim, я вирішив переглянути які плагіни вони використовують, які із них мені потрібні, та налаштувати все самостійно. Проблема яку я помітив при використанні готових конфігурацій це те що незнаючи їх конфігурації плагінів важко налаштувати редактор під себе. Тому якщо мені потрібно читати документацію плагінів щоб побачити що вони роблять і як вони працюють, то у такому випадку я можу налаштувати все самостійно. Отже, у цьому дописі я опишу свою конфігурацію neovim.

Хоча я не використовую vim як основний текстовий редактор, його знання може бути дуже корисною навичкою. Комбінації клавіш vim можна використовувати в будь-якому редакторі (IDEA, VS Code і т.д.) та у інших програмах (наприклад у браузері, файловому менеджері). На роботі я використовую Intelij IDEA з vim плагіном, і моя мета полягала в тому, щоб мати стільки ж основних функцій у vim. Ось цей список.

  • Відсутність вкладок - при використанні вкладок доводиться витрачати додатковий час на їх менеджмень (закриття/переупорядкування).
  • Глобальний пошук.
  • Швидке перемикання між файлами/буферами.
  • Автодоповнення.

Насправді нічого надзвичайного.

Список плагінів #

  • Packer - менеджер плагінів
  • NvimTree - файловий менеджер
  • TreeSitter - підсвічування синтаксису
  • Telescope - пошук файлів, перемикач буферів
  • lspconfig - конфігурації для lsp
  • nvim-cmp - автозаповнення
  • nvim-snippy - менеджер фрагментів, дозволяє вставляти шаблони коду

Структура папок #

.
├── init.lua
├── lua
│   └── vladmyh
│       ├── lspconfig.lua
│       ├── nvim-tree.lua
│       ├── nvimcmp.lua
│       ├── telescope.lua
│       └── treesitter.lua
├── plugin
│   └── packer_compiled.lua
├── undodir
└── ~

init.lua - основний конфігураційний файл. Каталог lua/vladmyh містить конфігураційні файли для плагінів. Причина існування ще однієї теки всередині lua полягає в тому, щоб запобігти зіткненням просторів імен між плагінами. Наприклад, якщо плагін telescope має файл з назвою lua/telescope.lua, то буде неоднозначно, який файл завантажувати. Ви можете знайти більше інформації про простори імен тут.

Головний файл конфігурації #

Це основний файл init.lua. Neovim підтримує як vimscript, так і lua для конфігурації, я обрав lua. Тут я розмістив деякі допоміжні функції, загальні налаштування та оголошення плагінів.

-- Helpers
function map(mode, shortcut, command)
	vim.api.nvim_set_keymap(mode, shortcut, command, { noremap = true, silent = true })
end

function map_func(shortcut, command)
	vim.keymap.set('n', shortcut, command, { noremap = true, silent = true})
end

local o = vim.o
local wo = vim.wo
local bo = vim.bo

-- Settings
vim.g.mapleader = " "
o.ignorecase = true
o.undodir = '~/.config/nvim/undodir'
o.undofile = true
o.smartcase = true
o.splitbelow = true
o.splitright = true
o.scrolloff = 4
o.mouse = 'a'
o.relativenumber = true
wo.number = true
bo.tabstop = 4
bo.softtabstop = 4
bo.expandtab = true
bo.smartindent = true

-- Keys
vim.g.mapleader = ' '
map('n', '<leader>j', ':wincmd j<cr>')
map('n', '<leader>k', ':wincmd k<cr>')
map('n', '<leader>h', ':wincmd h<cr>')
map('n', '<leader>l', ':wincmd l<cr>')

-- Plugins
require('packer').startup(function()
	use {
		'kyazdani42/nvim-tree.lua',
		requires = {
			'kyazdani42/nvim-web-devicons', -- optional, for file icons
		}
	}
	use { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate' }
    	use 'nvim-treesitter/playground'
	use 'neovim/nvim-lspconfig'
	use {
		'nvim-telescope/telescope.nvim',
		requires = { {'nvim-lua/plenary.nvim'} }
	}
	use 'hrsh7th/nvim-cmp'
	use 'hrsh7th/cmp-nvim-lsp'

	use 'dcampos/nvim-snippy'
	use 'dcampos/cmp-snippy'
	use {
		'rose-pine/neovim',
		as = 'rose-pine',
		config = function()
			vim.cmd('colorscheme rose-pine')
		end
	}

end)
require('vladmyh/telescope')
require('vladmyh/lspconfig')
require('vladmyh/nvimcmp')
require('vladmyh/treesitter')
require('vladmyh/nvim-tree')

-- NvimTree
map('n', '<leader>n', ':NvimTreeToggle<cr>')

-- Telescope
map('n', '<leader>ff', ':Telescope find_files<cr>')
map('n', '<leader>fb', ':Telescope buffers<cr>')
map('n', '<leader>fg', ':Telescope git_files<cr>')
map('n', '<leader>fp', ':Telescope grep_string<cr>')

Конфігурація LSP #

Тут ми визначаємо ряд прив’язок клавіш у функції on_attach, які використовуються тільки на буферах з активним lsp. Це означає, що якщо я відкрию файл, для якого у мене не налаштовано lsp, то прив’язка клавіш не буде встановлена. Я використовую прив’язку клавіш за замовчуванням і використовую map_func з основного файла init.lua.

map_func('<leader>e', vim.diagnostic.open_float)
--map_func('<C-e>', vim.diagnostic.open_float)
map_func('[d', vim.diagnostic.goto_prev, opts)
map_func(']d', vim.diagnostic.goto_next, opts)
map_func('<leader>q', vim.diagnostic.setloclist, opts)

local on_attach = function(client, bufnr)
  -- Enable completion triggered by <c-x><c-o>
  vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')

  -- See `:help vim.lsp.*` for documentation on any of the below functions
  local bufopts = { noremap=true, silent=true, buffer=bufnr }
  map_func('gD', vim.lsp.buf.declaration, bufopts)
  map_func('gd', vim.lsp.buf.definition, bufopts)
  map_func('K', vim.lsp.buf.hover, bufopts)
  map_func('gi', vim.lsp.buf.implementation, bufopts
  map_func('<C-k>', vim.lsp.buf.signature_help, bufopts)
  map_func('<leader>wa', vim.lsp.buf.add_workspace_folder, bufopts)
  map_func('<leader>wr', vim.lsp.buf.remove_workspace_folder, bufopts)
  map_func('<leader>wl', function()
    print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
  end, bufopts)
  map_func('<leader>D', vim.lsp.buf.type_definition, bufopts)
  map_func('<leader>vrn', vim.lsp.buf.rename, bufopts)
  map_func('<leader>ca', vim.lsp.buf.code_action, bufopts)
  map_func('gr', vim.lsp.buf.references, bufopts)
  map_func('<leader>f', vim.lsp.buf.formatting, bufopts)
end
--
-- Setup lspconfig.
local capabilities = require('cmp_nvim_lsp').default_capabilities(vim.lsp.protocol.make_client_capabilities())

local lsp_flags = {
  -- This is the default in Nvim 0.7+
  debounce_text_changes = 150,
}
require('lspconfig')['gopls'].setup{
    on_attach = on_attach,
    flags = lsp_flags,
    capabilities = capabilities
}
require('lspconfig')['elixirls'].setup{
    on_attach = on_attach,
    flags = lsp_flags,
    capabilities = capabilities,
    cmd = {"/usr/bin/elixir-ls"}
}

Nvim tree #

require('nvim-tree').setup()

Nvimcmp #

local cmp = require('cmp')
cmp.setup{
	snippet = {
		expand = function(args)
			require('snippy').expand_snippet(args.body)
		end,
	},
	window = {
      -- completion = cmp.config.window.bordered(),
      -- documentation = cmp.config.window.bordered(),
    	},
	mapping = cmp.mapping.preset.insert({
		['<C-b>'] = cmp.mapping.scroll_docs(-4),
      		['<C-f>'] = cmp.mapping.scroll_docs(4),
      		['<C-Space>'] = cmp.mapping.complete(),
      		['<C-e>'] = cmp.mapping.abort(),
      		['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
    	}),
    	sources = cmp.config.sources({
      		{ name = 'nvim_lsp' },
      		{ name = 'snippy' }, -- For snippy users.
    	}, 
    	{
      		{ name = 'buffer' },
    	})
}

Telescope #

Крім налаштування клавіш я встановив властивість sort_mru в true, щоб отримати список буферів з останніх використаних, та властивість initial_mode в normal для того щоб відкривати вікно буферів у нормальному режимі (по замовченню режим редагування). Опис параметру можна знайти тут.

require('telescope').setup {
  pickers = {
    buffers = {
      sort_mru = true, --sort buffers by mru
      initial_mode = "normal" --start buffer picker in normal mode
    }
  }
}

Treesitter #

require'nvim-treesitter.configs'.setup {
  ensure_installed = { 'lua', 'go', 'rust', 'elixir', 'erlang' },
  sync_install = false,
  auto_install = true,

  highlight = {
    enable = true,
    additional_vim_regex_highlighting = false,
  },
}

Корисні скорочення клавіш #

Ось список деяких корисних комбінацій клавіш, які я намагаюся додавати в свою роботу.

  • yap копіювати до символа нового рядка
  • dap видалити до символа нового рядка вниз
  • vap/kvap виділення вниз/вгору до символа нового рядка
  • va{ виділити до закриття ‘}’ (va(, va’, va" і т.д.)
  • o вставити і редагувати рядок нижче, O - вище
  • I перейти на початок рядка і почати редагувати
  • A перейти в кінець рядка і почати редагувати
  • VY скопіювати весь рядок
  • Ctrl + a інкрементувати число під курсором
  • Ctrl + x декрементувати число під курсором
  • Ctrl + v виділити кілька рядків, I перейти в режим редагування
  • '{'/'}' перехід вгору/вниз між символами нового рядка