TL;DR
Aim
Our aim is to create a single file configuration for Neovim. There are too many tutorials on nEsTeD cOnFiGs. Real men use a single file to configure an entire editor π€.
Flat is better than nested.
β The Zen of Python
Setting up Packer
Downloading
First, we are going to install Packer
on our system.
local install_path = vim.fn.stdpath('data') .. '/site/pack/packer/start/packer.nvim'
if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
vim.fn.execute(
'!git clone https://github.com/wbthomason/packer.nvim ' .. install_path
)
end
There are three things involved here:
- Specifying where to install
Packer
. - Checking if the installation directory is already empty.
- Using
Git
to downloadPacker
.
Building Packer's Lazy Loader
Next, we tell Neovim to call PackerCompile
every time the buffer has been written to.
vim.cmd [[
augroup Packer
autocmd!
autocmd BufWritePost init.lua PackerCompile
augroup end
]]
What PackerCompile
does is not essential for us to know at this stage.
Installing Plugins
We need two things for installing packages. The packer.use()
function, and the packer.startup()
function.
Note that the packer.startup()
function takes a callable as an argument.
use = require("packer").use
require("packer").startup(function()
-- Package manager
use 'wbthomason/packer.nvim'
-- our plugins go here!
end)
Now we can start filling the body of the callable.
Adding Packages
For starters, we need two things. One, something to set up Neovim's native LSP Client and two, something to download actual Language Servers.
LSP Client and Installer
You don't need to understand what LSP is. Just know that it allows you to use IDE like features like autocompletion, error checking and code suggestions.
use = require("packer").use
require("packer").startup(function()
-- ...
-- LSP Client
use 'neovim/nvim-lspconfig'
-- Language Server installer
use {
'williamboman/nvim-lsp-installer',
requires = 'neovim/nvim-lspconfig',
}
-- BONUS: Customizations over LSP
-- Show VSCode-esque pictograms
use 'onsails/lspkind-nvim'
-- show various elements of LSP as UI
use {'tami5/lspsaga.nvim', requires = {'neovim/nvim-lspconfig'}}
-- ...
end)
But note that LSP alone does not provide the cool features like code completion, hints etc. We need a separate autocomplete engine plugin for that.
Autocompletion Engine
For an autocompletion engine, we are going to use nvim-cmp
. As a bonus, we will also configure it with extra plugins like snippet expansion, Vim command autocompletion, buffer completion etc.
-- ...
require("packer").setup(function()
-- ...
-- Autocompletion plugin
use {
'hrsh7th/nvim-cmp',
requires = {
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
'hrsh7th/cmp-cmdline',
}
}
-- snippets
use {
'hrsh7th/cmp-vsnip', requires = {
'hrsh7th/vim-vsnip',
'rafamadriz/friendly-snippets',
}
}
-- ...
end)
Auto bracket pairing
Let neovim close the brackets for you.
-- ...
require("packer").setup(function()
-- ...
-- bracket autocompletion
use 'vim-scripts/auto-pairs-gentle'
-- ...
end)
-- ...
Statusline
Nothing better than a fast and feature-packed statusline.
-- ...
require("packer").setup(function()
-- ...
-- Fancier statusline
use {
'nvim-lualine/lualine.nvim',
requires = {
'kyazdani42/nvim-web-devicons',
'arkav/lualine-lsp-progress',
},
}
-- ...
end)
-- ...
Incremental Parsing
We will also use an incremental parsing library for Neovim.
-- ...
require("packer").setup(function()
-- ...
-- Fast incremental parsing library
use 'nvim-treesitter/nvim-treesitter'
-- ...
end)
-- ...
And a Treesitter powered colorscheme β¨
-- ...
require("packer").setup(function()
-- ...
-- Beautiful colorscheme
use 'navarasu/onedark.nvim'
end)
-- ...
Configuring Essential Neovim Options
Not much is here to describe. They will later prove to be useful once you start editing stuff.
-- ...
-- Do not show current vim mode since it is already shown by Lualine
vim.o.showmode = false
-- enable autowriteall
vim.o.autowriteall = true
-- Show the line numbers
vim.wo.number = true
-- Show chars at the end of line
vim.opt.list = true
-- Enable break indent
vim.o.breakindent = true
--Case insensitive searching UNLESS /C or capital in search
vim.o.ignorecase = true
vim.o.smartcase = true
-- Decrease update time
vim.o.updatetime = 250
-- Shows signs by Autocompletion plugin
vim.wo.signcolumn = 'yes'
-- Enable termguicolors. Very essential if you want 24-bit RGB color in TUI.
vim.o.termguicolors = true
-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menu,menuone'
--Remap for dealing with word wrap
vim.api.nvim_set_keymap('n', 'k', "v:count == 0 ? 'gk' : 'k'", { noremap = true, expr = true, silent = true })
vim.api.nvim_set_keymap('n', 'j', "v:count == 0 ? 'gj' : 'j'", { noremap = true, expr = true, silent = true })
-- Highlight on yank
vim.cmd [[
augroup YankHighlight
autocmd!
autocmd TextYankPost * silent! lua vim.highlight.on_yank()
augroup end
]]
-- ...
Configuring Plugins
Now comes the big part. We will configure each plugin and set it up properly.
LSP Client and Installer
First, we import the required plugins. Then, we list the Language Servers that we need. Feel free to add or remove items from the list!
-- ...
require('lspconfig')
local lsp_installer = require("nvim-lsp-installer")
-- The required servers
local servers = {
"bashls",
"pyright",
"rust_analyzer",
"sumneko_lua",
"html",
"clangd",
"vimls",
"emmet_ls",
}
-- ...
Next we tell nvim-lsp-installer
to autoinstall the required servers.
-- ...
for _, name in pairs(servers) do
local server_is_found, server = lsp_installer.get_server(name)
if server_is_found and not server:is_installed() then
print("Installing " .. name)
server:install()
end
end
-- ...
Sweet! Now we can configure the essential keymaps. The on_attach()
function given below hosts the keymaps and options that will be enabled only in the presence of an active Language Server.
Almost all of the keymaps are compatible with coc.nvim
. So for those of you who are migrating from coc.nvim
, you won't have to change anything!
Here, we are going to use our beloved lspsaga
for fancy UI over LSP!
-- ...
local on_attach = function(_, bufnr)
-- Create some shortcut functions.
-- NOTE: The `vim` variable is supplied by Neovim.
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local function buf_set_option(...)
vim.api.nvim_buf_set_option(bufnr, ...)
end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
local opts = {noremap=true, silent=true}
-- ======================= The Keymaps =========================
-- jump to definition
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
-- Format buffer
buf_set_keymap('n', '<F3>', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
-- Jump LSP diagnostics
-- NOTE: Currently, there is a bug in lspsaga.diagnostic module. Thus we use
-- Vim commands to move through diagnostics.
buf_set_keymap('n', '[g', ':Lspsaga diagnostic_jump_prev<CR>', opts)
buf_set_keymap('n', ']g', ':Lspsaga diagnostic_jump_next<CR>', opts)
-- Rename symbol
buf_set_keymap('n', '<leader>rn', "<cmd>lua require('lspsaga.rename').rename()<CR>", opts)
-- Find references
buf_set_keymap('n', 'gr', '<cmd>lua require("lspsaga.provider").lsp_finder()<CR>', opts)
-- Doc popup scrolling
buf_set_keymap('n', 'K', "<cmd>lua require('lspsaga.hover').render_hover_doc()<CR>", opts)
buf_set_keymap('n', '<C-f>', "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>", opts)
buf_set_keymap('n', '<C-b>', "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>", opts)
-- codeaction
buf_set_keymap('n', '<leader>ac', "<cmd>lua require('lspsaga.codeaction').code_action()<CR>", opts)
buf_set_keymap('v', '<leader>a', ":<C-U>lua require('lspsaga.codeaction').range_code_action()<CR>", opts)
-- Floating terminal
-- NOTE: Use `vim.cmd` since `buf_set_keymap` is not working with `tnoremap...`
vim.cmd [[
nnoremap <silent> <A-d> <cmd>lua require('lspsaga.floaterm').open_float_terminal()<CR>
tnoremap <silent> <A-d> <C-\><C-n>:lua require('lspsaga.floaterm').close_float_terminal()<CR>
]]
end
-- ...
Now that we have configured our keymaps, we are going to add some server specific options. Here a default is provided. Don't worry if it looks intimidating. You will soon find out how it works.
-- ...
local server_specific_opts = {
sumneko_lua = function(opts)
opts.settings = {
Lua = {
-- NOTE: This is required for expansion of lua function signatures!
completion = {callSnippet = "Replace"},
diagnostics = {
globals = {'vim'},
},
},
}
end,
html = function(opts)
opts.filetypes = {"html", "htmldjango"}
end,
}
-- ...
Now we instruct nvim-lsp-installer
to supply the on_attach
, extra flags and server specific options to the Language Server once it is ready.
We will also use the feature rich nvim-cmp
plugin for its extra capabilities.
-- ...
-- `nvim-cmp` comes with additional capabilities, alongside the ones
-- provided by Neovim!
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities)
lsp_installer.on_server_ready(function(server)
-- the keymaps, flags and capabilities that will be sent to the server as
-- options.
local opts = {
on_attach = on_attach,
flags = {debounce_text_changes = 150},
capabilities = capabilities,
}
-- If the current surver's name matches with the ones specified in the
-- `server_specific_opts`, set the options.
if server_specific_opts[server.name] then
server_specific_opts[server.name](opts)
end
-- And set up the server with our configuration!
server:setup(opts)
end)
-- ...
Cool! Now that we have set up the server and configured it properly, we should set the autocompletion plugin too!
Auotcompletion Plugin
Now it's time to set up the autocompletion plugin. We will start by importing the plugin and defining some helper functions.
-- ...
local lspkind = require('lspkind')
local cmp = require("cmp")
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
-- ...
Next, we will define some beautiful glyphs. These glyphs will then be shown by lspkind
.
-- ...
local cmp_kinds = {
Text = "οΎ",
Method = "ο¦",
Function = "ο",
Constructor = "ο£",
Field = "ο° ",
Variable = "οͺ",
Class = "ο΄―",
Interface = "ο¨",
Module = "ο",
Property = "ο° ",
Unit = "ο₯¬",
Value = "ο’",
Enum = "ο
",
Keyword = "ο ",
Snippet = "ο",
Color = "ο£",
File = "ο",
Reference = "ο",
Folder = "ο",
EnumMember = "ο
",
Constant = "ο£Ύ",
Struct = "ο",
Event = "ο§",
Operator = "ο",
TypeParameter = "",
}
-- ...
Next we set up formatting (and by extension, lspkind
), snippet support, completion keymaps and completion sources.
This is where all our configuration for nvim-cmp
will go:
-- ...
cmp.setup({
-- Add your configuration here!
})
-- ...
First, the snippet support. Note that this is mandatory.
-- ...
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
-- ...
})
-- ...
Next, the formatting.
-- ...
cmp.setup({
-- ...
formatting = {
format = lspkind.cmp_format({
with_text = true,
preset = 'codicons',
symbol_map = cmp_kinds, -- The glyphs will be used by `lspkind`
menu = ({
buffer = "[Buffer]",
nvim_lsp = "[LSP]",
luasnip = "[LuaSnip]",
nvim_lua = "[Lua]",
latex_symbols = "[Latex]",
}),
}),
},
-- ...
})
-- ...
Third, the custom keymaps for autocompletion suggestions. Feel free to change the keymaps as required. Note that the Tab key has been set up in such a way that you can use it to browse through the completion suggestions.
-- ...
cmp.setup({
-- ...
mapping = {
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-n>'] = cmp.mapping.select_next_item(),
['<C-d>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.close(),
['<CR>'] = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace,
select = true,
},
-- Use Tab and Shift-Tab to browse through the suggestions.
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn["vsnip#available"](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function()
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn["vsnip#jumpable"](-1) == 1 then
feedkey("<Plug>(vsnip-jump-prev)", "")
end
end, { "i", "s" }),
},
-- ...
})
-- ...
And finally, we specify the completion sources.
-- ...
cmp.setup({
-- ...
sources = {
{ name = 'nvim_lsp' },
{ name = 'vsnip' },
{ name = 'buffer' },
},
})
-- ...
And finally, we will also configure autocompletion for Vim commands and Vim search.
-- ...
-- Use buffer source for `/`
cmp.setup.cmdline('/', {
sources = {
{ name = 'buffer' }
}
})
-- Use cmdline & path source for ':'
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' }
}, {
{ name = 'cmdline' }
})
})
-- ...
Wow! That was a loooot of work for a simple autocompletion plugin's configuration. But, as we will see, our hard work will pay off!
Next, we configure the remaining plugins.
Auto Bracket Pairing
Save yourself some keystrokes!
-- ...
vim.g.AutoPairs = {
['(']=')',
['[']=']',
['{']='}',
["'"]="'",
['"']='"',
['`']='`',
['<']='>',
}
-- ...
Colorscheme β¨
Bless your eyes.
-- ...
require("onedark").setup({
style = "darker",
})
require('onedark').load()
-- ...
Status bar
A status bar that can change its colour automatically based on the colorscheme? Yes please!
-- ...
require('lualine').setup({
sections = {
lualine_c = {
{'filename', path = 1},
'lsp_progress',
},
},
})
-- ...
Treesitter
We will set up treesitter for a select number of languages. Feel free to add or remove items from the list.
-- ...
require('nvim-treesitter.configs').setup {
ensure_installed = {"python", "rust", "c", "cpp", "bash", "go", "html"},
highlight = {
enable = true, -- false will disable the whole extension
},
}
-- ...
LSPSaga
And finally, we set up some configs for LSPSaga.
-- ...
require("lspsaga").init_lsp_saga({
finder_action_keys = {
open = '<CR>',
quit = {'q', '<esc>'},
},
code_action_keys = {
quit = {'q', '<esc>'},
},
rename_action_keys = {
quit = '<esc>',
},
})
What to do next
Make sure you run :PackerInstall
once you run Neovim after configuring the init.lua
script. It will download all the configured plugins. And as a word of advice, run :PackerUpdate
from time to time.
The Entire Config
If you read through all of the above, then sit back and pat yourself on the back!
-- Packer installation
local install_path = vim.fn.stdpath('data') .. '/site/pack/packer/start/packer.nvim'
if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
vim.fn.execute(
'!git clone https://github.com/wbthomason/packer.nvim ' .. install_path
)
end
vim.cmd [[
augroup Packer
autocmd!
autocmd BufWritePost init.lua PackerCompile
augroup end
]]
-- Plugin installation
use = require("packer").use
require("packer").startup(function()
-- Package manager
use 'wbthomason/packer.nvim'
-- LSP Client
use 'neovim/nvim-lspconfig'
-- Language Server installer
use {
'williamboman/nvim-lsp-installer',
requires = 'neovim/nvim-lspconfig',
}
-- BONUS: Customizations over LSP
-- Show VSCode-esque pictograms
use 'onsails/lspkind-nvim'
-- show various elements of LSP as UI
use {'tami5/lspsaga.nvim', requires = {'neovim/nvim-lspconfig'}}
-- Autocompletion plugin
use {
'hrsh7th/nvim-cmp',
requires = {
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
'hrsh7th/cmp-cmdline',
}
}
-- snippets
use {
'hrsh7th/cmp-vsnip', requires = {
'hrsh7th/vim-vsnip',
'rafamadriz/friendly-snippets',
}
}
-- bracket autocompletion
use 'vim-scripts/auto-pairs-gentle'
-- Fancier statusline
use {
'nvim-lualine/lualine.nvim',
requires = {
'kyazdani42/nvim-web-devicons',
'arkav/lualine-lsp-progress',
},
}
-- Fast incremental parsing library
use 'nvim-treesitter/nvim-treesitter'
-- Beautiful colorscheme
use 'navarasu/onedark.nvim'
end)
-- Neovim configuration
-- Do not show current vim mode since it is already shown by Lualine
vim.o.showmode = false
-- enable autowriteall
vim.o.autowriteall = true
-- Show the line numbers
vim.wo.number = true
-- Show chars at the end of line
vim.opt.list = true
-- Enable break indent
vim.o.breakindent = true
--Case insensitive searching UNLESS /C or capital in search
vim.o.ignorecase = true
vim.o.smartcase = true
-- Decrease update time
vim.o.updatetime = 250
-- Shows signs by Autocompletion plugin
vim.wo.signcolumn = 'yes'
-- Enable termguicolors. Very essential if you want 24-bit RGB color in TUI.
vim.o.termguicolors = true
-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menu,menuone'
--Remap for dealing with word wrap
vim.api.nvim_set_keymap('n', 'k', "v:count == 0 ? 'gk' : 'k'", { noremap = true, expr = true, silent = true })
vim.api.nvim_set_keymap('n', 'j', "v:count == 0 ? 'gj' : 'j'", { noremap = true, expr = true, silent = true })
-- Highlight on yank
vim.cmd [[
augroup YankHighlight
autocmd!
autocmd TextYankPost * silent! lua vim.highlight.on_yank()
augroup end
]]
-- Plugin configuration
-- LSP and LS Installer
require('lspconfig')
local lsp_installer = require("nvim-lsp-installer")
-- The required servers
local servers = {
"bashls",
"pyright",
"rust_analyzer",
"sumneko_lua",
"html",
"clangd",
"vimls",
"emmet_ls",
}
for _, name in pairs(servers) do
local server_is_found, server = lsp_installer.get_server(name)
if server_is_found and not server:is_installed() then
print("Installing " .. name)
server:install()
end
end
local on_attach = function(_, bufnr)
-- Create some shortcut functions.
-- NOTE: The `vim` variable is supplied by Neovim.
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local function buf_set_option(...)
vim.api.nvim_buf_set_option(bufnr, ...)
end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
local opts = {noremap=true, silent=true}
-- ======================= The Keymaps =========================
-- jump to definition
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
-- Format buffer
buf_set_keymap('n', '<F3>', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
-- Jump LSP diagnostics
-- NOTE: Currently, there is a bug in lspsaga.diagnostic module. Thus we use
-- Vim commands to move through diagnostics.
buf_set_keymap('n', '[g', ':Lspsaga diagnostic_jump_prev<CR>', opts)
buf_set_keymap('n', ']g', ':Lspsaga diagnostic_jump_next<CR>', opts)
-- Rename symbol
buf_set_keymap('n', '<leader>rn', "<cmd>lua require('lspsaga.rename').rename()<CR>", opts)
-- Find references
buf_set_keymap('n', 'gr', '<cmd>lua require("lspsaga.provider").lsp_finder()<CR>', opts)
-- Doc popup scrolling
buf_set_keymap('n', 'K', "<cmd>lua require('lspsaga.hover').render_hover_doc()<CR>", opts)
buf_set_keymap('n', '<C-f>', "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>", opts)
buf_set_keymap('n', '<C-b>', "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>", opts)
-- codeaction
buf_set_keymap('n', '<leader>ac', "<cmd>lua require('lspsaga.codeaction').code_action()<CR>", opts)
buf_set_keymap('v', '<leader>a', ":<C-U>lua require('lspsaga.codeaction').range_code_action()<CR>", opts)
-- Floating terminal
-- NOTE: Use `vim.cmd` since `buf_set_keymap` is not working with `tnoremap...`
vim.cmd [[
nnoremap <silent> <A-d> <cmd>lua require('lspsaga.floaterm').open_float_terminal()<CR>
tnoremap <silent> <A-d> <C-\><C-n>:lua require('lspsaga.floaterm').close_float_terminal()<CR>
]]
end
local server_specific_opts = {
sumneko_lua = function(opts)
opts.settings = {
Lua = {
-- NOTE: This is required for expansion of lua function signatures!
completion = {callSnippet = "Replace"},
diagnostics = {
globals = {'vim'},
},
},
}
end,
html = function(opts)
opts.filetypes = {"html", "htmldjango"}
end,
}
-- `nvim-cmp` comes with additional capabilities, alongside the ones
-- provided by Neovim!
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities)
lsp_installer.on_server_ready(function(server)
-- the keymaps, flags and capabilities that will be sent to the server as
-- options.
local opts = {
on_attach = on_attach,
flags = {debounce_text_changes = 150},
capabilities = capabilities,
}
-- If the current surver's name matches with the ones specified in the
-- `server_specific_opts`, set the options.
if server_specific_opts[server.name] then
server_specific_opts[server.name](opts)
end
-- And set up the server with our configuration!
server:setup(opts)
end)
-- nvim-cmp
local lspkind = require('lspkind')
local cmp = require("cmp")
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
local cmp_kinds = {
Text = "οΎ",
Method = "ο¦",
Function = "ο",
Constructor = "ο£",
Field = "ο° ",
Variable = "οͺ",
Class = "ο΄―",
Interface = "ο¨",
Module = "ο",
Property = "ο° ",
Unit = "ο₯¬",
Value = "ο’",
Enum = "ο
",
Keyword = "ο ",
Snippet = "ο",
Color = "ο£",
File = "ο",
Reference = "ο",
Folder = "ο",
EnumMember = "ο
",
Constant = "ο£Ύ",
Struct = "ο",
Event = "ο§",
Operator = "ο",
TypeParameter = "",
}
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
formatting = {
format = lspkind.cmp_format({
with_text = true,
preset = 'codicons',
symbol_map = cmp_kinds, -- The glyphs will be used by `lspkind`
menu = ({
buffer = "[Buffer]",
nvim_lsp = "[LSP]",
luasnip = "[LuaSnip]",
nvim_lua = "[Lua]",
latex_symbols = "[Latex]",
}),
}),
},
mapping = {
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-n>'] = cmp.mapping.select_next_item(),
['<C-d>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.close(),
['<CR>'] = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace,
select = true,
},
-- Use Tab and Shift-Tab to browse through the suggestions.
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn["vsnip#available"](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function()
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn["vsnip#jumpable"](-1) == 1 then
feedkey("<Plug>(vsnip-jump-prev)", "")
end
end, { "i", "s" }),
},
sources = {
{ name = 'nvim_lsp' },
{ name = 'vsnip' },
{ name = 'buffer' },
},
})
-- Use buffer source for `/`
cmp.setup.cmdline('/', {
sources = {
{ name = 'buffer' }
}
})
-- Use cmdline & path source for ':'
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' }
}, {
{ name = 'cmdline' }
})
})
-- autopairs
vim.g.AutoPairs = {
['(']=')',
['[']=']',
['{']='}',
["'"]="'",
['"']='"',
['`']='`',
['<']='>',
}
-- onedark
require("onedark").setup({
style = "darker",
})
require('onedark').load()
-- lualine
require('lualine').setup({
sections = {
lualine_c = {
{'filename', path = 1},
'lsp_progress',
},
},
})
-- treesitter
require('nvim-treesitter.configs').setup {
ensure_installed = {"python", "rust", "c", "cpp", "bash", "go", "html"},
highlight = {
enable = true, -- false will disable the whole extension
},
}
-- lspsaga
require("lspsaga").init_lsp_saga({
finder_action_keys = {
open = '<CR>',
quit = {'q', '<esc>'},
},
code_action_keys = {
quit = {'q', '<esc>'},
},
rename_action_keys = {
quit = '<esc>',
},
})
Conclusion
I hope this article helps you in configuring your Neovim to your heart's desire.
Questions? Comments? Concerns? Please put them down below and I'd be happy to help you.
Cover Image Source: Photo by luis gomes from Pexels π
Top comments (0)