This content originally appeared on DEV Community and was authored by Alejandro Londoño
Hello everyone! In this article I will show you how to configure the neovim editor from scratch with lazy.vim.
Lazy.nvim
A modern plugin manager for Neovim
Repo: folke/lazy.nvim
-
Outstanding features:
Manage all your Neovim plugins with a powerful UI
Fast startup times thanks to automatic caching and bytecode compilation of Lua modules
Automatic lazy-loading of Lua modules and lazy-loading on events, commands, filetypes, and key mappings
Automatically install missing plugins before starting up Neovim, allowing you to start using it right away
No need to manually compile plugins
Correct sequencing of dependencies
Configurable in multiple files
Automatically check for updates
GitHub Repository
All the code is in my Github profile at slydragonn/nvim-lazy repo.
Tutorial video
Requirements
- Neovim >= v0.10.0
- Nerd Fonts
- NodeJS with npm
- Lazy.vim
- A C compiler in your path and libstdc++ installed: Windows support
- Git
Features
- folke/lazy.nvim: A modern plugin manager for Neovim
- nvim-neo-tree/neo-tree: Neovim plugin to manage the file system and other tree like structures.
- tiagovla/tokyodark.nvim: A clean dark theme written in lua for neovim.
- nvim-tree/nvim-web-devicons: lua fork of vim-web-devicons for neovim.
- nvim-lualine/lualine.nvim: A blazing fast and easy to configure neovim statusline plugin written in pure lua.
- nvim-treesitter/nvim-treesitter: Nvim Treesitter configurations and abstraction layer.
- windwp/nvim-ts-autotag: Use treesitter to auto close and auto rename html tag.
- stevearc/conform.nvim: Lightweight yet powerful formatter plugin for Neovim.
- nvim-telescope/telescope.nvim: Highly extendable fuzzy finder over lists.
- neovim/nvim-lspconfig: Quickstart configs for Nvim LSP
- hrsh7th/nvim-cmp: A completion plugin for neovim coded in Lua.
- williamboman/mason.nvim: Portable package manager for Neovim that runs everywhere Neovim runs.
- norcalli/nvim-colorizer.lua: Color highlighter.
- akinsho/toggleterm.nvim: A neovim lua plugin to help easily manage multiple terminal windows.
- lewis6991/gitsigns.nvim: Git integration for buffers.
- windwp/nvim-autopairs: Autopairs for neovim written by lua.
- onsails/lspkind.nvim: vscode-like pictograms for neovim lsp completion items.
- L3MON4D3/LuaSnip: Snippet Engine for Neovim written in Lua.
- hrsh7th/cmp-nvim-lsp: nvim-cmp source for neovim builtin LSP client
- hrsh7th/cmp-path: nvim-cmp source for path
- hrsh7th/cmp-buffer: nvim-cmp source for buffer words
- williamboman/mason-lspconfig.nvim: Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim.
- WhoIsSethDaniel/mason-tool-installer.nvim: Install and upgrade third party tools automatically.
Project Structure
📂 nvim/
├── 📂 lua/📂 slydragonn/
│ └── 📂 plugins/
│ └── 📂 lsp/
│ └── ...pluginconfigfiles
│ └── 🌑 settings.lua
│ └── 🌑 maps.lua
│ └── 🌑 lazy.lua
└── 🌑 init.lua
If you don’t have some requirements
- Nerd Fonts: https://www.nerdfonts.com/
- Neovim: https://github.com/neovim/neovim/releases/
- Node: https://nodejs.org/en/download/package-manager
- C compiler: https://github.com/nvim-treesitter/nvim-treesitter/wiki/Windows-support
- Git: https://git-scm.com/downloads
Saving Settings
The configuration files go to a particular place, so you should create the nvim/ folder in the following path depending on your operating system:
Windows:
C:\Users\%YOUR_USERNAME%\AppData\Local\nvim
Linux:
~/.configs/nvim/
And in the nvim/ folder create the init.lua
file
with the following code:
- Note: slydragonn is my personal folder, but you can rename it whatever you want 🙂
-- ~/nvim/init.lua
require("slydragonn.settings")
Editor Settings
Then create a lua folder for our configuration and also for the plugins.
-- ~/nvim/lua/slydragonn/settings.lua
local global = vim.g
local o = vim.opt
-- Editor options
o.number = true -- Print the line number in front of each line
o.relativenumber = true -- Show the line number relative to the line with the cursor in front of each line.
o.clipboard = "unnamedplus" -- uses the clipboard register for all operations except yank.
o.syntax = "on" -- When this option is set, the syntax with this name is loaded.
o.autoindent = true -- Copy indent from current line when starting a new line.
o.cursorline = true -- Highlight the screen line of the cursor with CursorLine.
o.expandtab = true -- In Insert mode: Use the appropriate number of spaces to insert a <Tab>.
o.shiftwidth = 2 -- Number of spaces to use for each step of (auto)indent.
o.tabstop = 2 -- Number of spaces that a <Tab> in the file counts for.
o.encoding = "UTF-8" -- Sets the character encoding used inside Vim.
o.ruler = true -- Show the line and column number of the cursor position, separated by a comma.
o.mouse = "a" -- Enable the use of the mouse. "a" you can use on all modes
o.title = true -- When on, the title of the window will be set to the value of 'titlestring'
o.hidden = true -- When on a buffer becomes hidden when it is |abandon|ed
o.ttimeoutlen = 0 -- The time in milliseconds that is waited for a key code or mapped key sequence to complete.
o.wildmenu = true -- When 'wildmenu' is on, command-line completion operates in an enhanced mode.
o.showcmd = true -- Show (partial) command in the last line of the screen. Set this option off if your terminal is slow.
o.showmatch = true -- When a bracket is inserted, briefly jump to the matching one.
o.inccommand = "split" -- When nonempty, shows the effects of :substitute, :smagic, :snomagic and user commands with the :command-preview flag as you type.
o.splitright = true
o.splitbelow = true -- When on, splitting a window will put the new window below the current one
o.termguicolors = true
Add Lazy.vim
Installing Lazy is quite easy, you just have to copy this code from folke/lazy.nvim and paste it into ~/nvim/lua/slydragonn/lazy.lua
-- ~/nvim/lua/slydragonn/lazy.lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup("slydragonn.plugins")
Then in the init.lua file we import the lazy config:
-- ~/nvim/init.lua
require("slydragonn.settings")
require("slydragonn.lazy")
And create the plugins/ folder, where to add the plugin configuration files: ~/nvim/lua/plugins/
Lazy will read all the files in the plugins folder, because that’s how we set it, and Lazy will install them all automatically, or we can use the command :Lazy
to see the UI.
Lazy Commands
- Open the UI:
:Lazy
- Install:
shift
+L
- Sync:
shift
+S
- Update:
shift
+U
- Clear:
shift
+X
- Check:
shift
+C
- Log:
shift
+L
- Restore:
shift
+R
- Profile:
shift
+P
- Debug:
shift
+D
- Help:
shift
+?
It is recommended to run
:checkhealth lazy
after installation.
Plugin Configs:
treesitter.lua
nvim-treesitter/nvim-treesitter: Nvim Treesitter configurations and abstraction layer.
--- ~/nvim/lua/slydragonn/plugins/treesiter.lua
return {
"nvim-treesitter/nvim-treesitter",
event = { "BufReadPre", "BufNewFile" },
build = ":TSUpdate",
dependencies = {
"windwp/nvim-ts-autotag",
},
config = function()
local treesitter = require("nvim-treesitter.configs")
treesitter.setup({
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = { enable = true },
autotag = {
enable = true,
},
ensure_installed = {
"json",
"javascript",
"typescript",
"tsx",
"yaml",
"html",
"css",
"markdown",
"markdown_inline",
"bash",
"lua",
"vim",
"dockerfile",
"gitignore",
"c",
"rust",
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
rainbow = {
enable = true,
disable = { "html" },
extended_mode = false,
max_file_lines = nil,
},
context_commentstring = {
enable = true,
enable_autocmd = false,
},
})
end,
}
colorscheme.lua
tiagovla/tokyodark.nvim: A clean dark theme written in lua for neovim.
-- ~/nvim/lua/slydragonn/plugins/colorscheme.lua
return {
"tiagovla/tokyodark.nvim",
lazy = false,
priority = 1000,
config = function()
vim.cmd("colorscheme tokyodark")
end,
}
autopairs.lua
windwp/nvim-autopairs: Autopairs for neovim written by lua.
-- ~/nvim/lua/slydragonn/plugins/autopairs.lua
return {
"windwp/nvim-autopairs",
event = "InsertEnter",
config = function()
require("nvim-autopairs").setup({
disable_filetype = { "TelescopePrompt", "vim" },
})
end,
}
cmp.lua
hrsh7th/nvim-cmp: A completion plugin for neovim coded in Lua.
-- ~/nvim/lua/slydragonn/plugins/cmp.lua
return {
"hrsh7th/nvim-cmp",
event = "InsertEnter",
dependencies = {
"hrsh7th/cmp-buffer", -- source for text in buffer
"hrsh7th/cmp-path", -- source for file system paths
{
"L3MON4D3/LuaSnip",
version = "v2.*",
-- install jsregexp (optional!).
build = "make install_jsregexp",
},
"rafamadriz/friendly-snippets",
"onsails/lspkind.nvim", -- vs-code like pictograms
},
config = function()
local cmp = require("cmp")
local lspkind = require("lspkind")
local luasnip = require("luasnip")
require("luasnip.loaders.from_vscode").lazy_load()
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<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,
}),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "luasnip" },
{ name = "buffer" },
{ name = "path" },
}),
})
vim.cmd([[
set completeopt=menuone,noinsert,noselect
highlight! default link CmpItemKind CmpItemMenuDefault
]])
end,
}
colorizer.lua
norcalli/nvim-colorizer.lua: Color highlighter.
-- ~/nvim/lua/slydragonn/plugins/colorizer.lua
return {
"norcalli/nvim-colorizer.lua",
config = function()
require("colorizer").setup({ "*" })
end,
}
lualine.lua
nvim-lualine/lualine.nvim: A blazing fast and easy to configure neovim statusline plugin written in pure lua.
-- ~/nvim/lua/slydragonn/plugins/lualine.lua
return {
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
require("lualine").setup()
end,
}
mason.lua
williamboman/mason.nvim: Portable package manager for Neovim that runs everywhere Neovim runs.
-- ~/nvim/lua/slydragonn/plugins/mason.lua
return {
"williamboman/mason.nvim",
dependencies = {
"williamboman/mason-lspconfig.nvim",
"WhoIsSethDaniel/mason-tool-installer.nvim",
},
config = function()
require("mason").setup()
require("mason-lspconfig").setup({
automatic_installation = true,
ensure_installed = {
"cssls",
"eslint",
"html",
"jsonls",
"tsserver",
"pyright",
"tailwindcss",
},
})
require("mason-tool-installer").setup({
ensure_installed = {
"prettier",
"stylua", -- lua formatter
"isort", -- python formatter
"black", -- python formatter
"pylint",
"eslint_d",
},
})
end,
}
lspconfig.lua
williamboman/mason-lspconfig.nvim: Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim.
-- ~/nvim/lua/slydragonn/plugins/lspconfig.lua
return {
"neovim/nvim-lspconfig",
event = { "BufReadPre", "BufNewFile" },
dependencies = {
"hrsh7th/cmp-nvim-lsp",
{ "folke/neodev.nvim", opts = {} },
},
config = function()
local nvim_lsp = require("lspconfig")
local mason_lspconfig = require("mason-lspconfig")
local protocol = require("vim.lsp.protocol")
local on_attach = function(client, bufnr)
-- format on save
if client.server_capabilities.documentFormattingProvider then
vim.api.nvim_create_autocmd("BufWritePre", {
group = vim.api.nvim_create_augroup("Format", { clear = true }),
buffer = bufnr,
callback = function()
vim.lsp.buf.format()
end,
})
end
end
local capabilities = require("cmp_nvim_lsp").default_capabilities()
mason_lspconfig.setup_handlers({
function(server)
nvim_lsp[server].setup({
capabilities = capabilities,
})
end,
["tsserver"] = function()
nvim_lsp["tsserver"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["cssls"] = function()
nvim_lsp["cssls"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["tailwindcss"] = function()
nvim_lsp["tailwindcss"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["html"] = function()
nvim_lsp["html"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["jsonls"] = function()
nvim_lsp["jsonls"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["eslint"] = function()
nvim_lsp["eslint"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
["pyright"] = function()
nvim_lsp["pyright"].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end,
})
end,
}
formatter.lua
stevearc/conform.nvim: Lightweight yet powerful formatter plugin for Neovim.
-- ~/nvim/lua/slydragonn/plugins/formatter.lua
return {
"stevearc/conform.nvim",
event = { "BufReadPre", "BufNewFile" },
config = function()
local conform = require("conform")
conform.setup({
formatters_by_ft = {
javascript = { "prettier" },
typescript = { "prettier" },
javascriptreact = { "prettier" },
typescriptreact = { "prettier" },
css = { "prettier" },
html = { "prettier" },
json = { "prettier" },
yaml = { "prettier" },
markdown = { "prettier" },
lua = { "stylua" },
python = { "isort", "black" },
},
format_on_save = {
lsp_fallback = true,
async = false,
timeout_ms = 1000,
},
})
vim.keymap.set({ "n", "v" }, "<leader>f", function()
conform.format({
lsp_fallback = true,
async = false,
timeout_ms = 1000,
})
end, { desc = "Format file or range (in visual mode)" })
end,
}
gitsigns.lua
lewis6991/gitsigns.nvim: Git integration for buffers.
-- ~/nvim/lua/slydragonn/plugins/gitsigns.lua
return {
"lewis6991/gitsigns.nvim",
config = function()
local gitsigns = require("gitsigns")
gitsigns.setup({
signs = {
add = { text = "│" },
change = { text = "│" },
delete = { text = "_" },
topdelete = { text = "‾" },
changedelete = { text = "~" },
untracked = { text = "┆" },
},
signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff`
watch_gitdir = {
interval = 1000,
follow_files = true,
},
attach_to_untracked = true,
current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame`
current_line_blame_opts = {
virt_text = true,
virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align'
delay = 1000,
ignore_whitespace = false,
},
current_line_blame_formatter = "<author>, <author_time:%Y-%m-%d> - <summary>",
sign_priority = 6,
update_debounce = 100,
status_formatter = nil, -- Use default
max_file_length = 40000, -- Disable if file is longer than this (in lines)
preview_config = {
-- Options passed to nvim_open_win
border = "single",
style = "minimal",
relative = "cursor",
row = 0,
col = 1,
},
yadm = {
enable = false,
},
})
end,
}
neotree.lua
nvim-neo-tree/neo-tree: Neovim plugin to manage the file system and other tree like structures.
-- ~/nvim/lua/slydragonn/plugins/neotree.lua
return {
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
-- "3rd/image.nvim", -- Optional image support in preview window: See `# Preview Mode` for more information
},
}
telescope.lua
nvim-telescope/telescope.nvim: Highly extendable fuzzy finder over lists.
-- ~/nvim/lua/slydragonn/plugins/telescope.lua
return {
"nvim-telescope/telescope.nvim",
tag = "0.1.6",
dependencies = { "nvim-lua/plenary.nvim" },
config = function()
require("telescope").setup()
-- set keymaps
local keymap = vim.keymap
keymap.set("n", "<leader>ff", "<cmd>Telescope find_files<cr>", { desc = "Fuzzy find files in cwd" })
keymap.set("n", "<leader>fg", "<cmd>Telescope live_grep<cr>", { desc = "Fuzzy find recent files" })
keymap.set("n", "<leader>fb", "<cmd>Telescope buffers<cr>", { desc = "Find string in cwd" })
keymap.set("n", "<leader>fs", "<cmd>Telescope git_status<cr>", { desc = "Find string under cursor in cwd" })
keymap.set("n", "<leader>fc", "<cmd>Telescope git commits<cr>", { desc = "Find todos" })
end,
}
toggleterm.lua
akinsho/toggleterm.nvim: A neovim lua plugin to help easily manage multiple terminal windows.
-- ~/nvim/lua/slydragonn/plugins/toggleterm.lua
return {
'akinsho/toggleterm.nvim',
version = "*",
config = function()
require("toggleterm").setup({
size = 10,
open_mapping = [[<F7>]],
shading_factor = 2,
direction = "float",
float_opts = {
border = "curved",
highlights = {
border = "Normal",
background = "Normal",
},
},
})
end,
}
When all plugins are added, we write the command :Lazy
and we press shift
+ L
to Install or shift
+ S
to sync.
Editor Key bindings
Inside of init.lua requires the maps file.
-- ~/nvim/init.lua
require("slydragonn.settings")
require("slydragonn.lazy")
require("slydragonn.maps") -- key bindings
maps.lua
-- ~/nvim/lua/slydragonn/maps.lua
vim.g.mapleader = " "
local function map(mode, lhs, rhs)
vim.keymap.set(mode, lhs, rhs, { silent = true })
end
-- Save
map("n", "<leader>w", "<CMD>update<CR>")
-- Quit
map("n", "<leader>q", "<CMD>q<CR>")
-- Exit insert mode
map("i", "jk", "<ESC>")
-- NeoTree
map("n", "<leader>e", "<CMD>Neotree toggle<CR>")
map("n", "<leader>r", "<CMD>Neotree focus<CR>")
-- New Windows
map("n", "<leader>o", "<CMD>vsplit<CR>")
map("n", "<leader>p", "<CMD>split<CR>")
-- Window Navigation
map("n", "<C-h>", "<C-w>h")
map("n", "<C-l>", "<C-w>l")
map("n", "<C-k>", "<C-w>k")
map("n", "<C-j>", "<C-w>j")
-- Resize Windows
map("n", "<C-Left>", "<C-w><")
map("n", "<C-Right>", "<C-w>>")
map("n", "<C-Up>", "<C-w>+")
map("n", "<C-Down>", "<C-w>-")
And that’s it, with this setup you should have an amazing neovim editor.
Resources
- My neovim setup with lazy.vim: https://github.com/slydragonn/nvim-lazy
- Youtube Video:
- Lazy.vim: https://github.com/folke/lazy.nvim
- Neovim resources: https://neovim.io/doc/user/lua.html#lua-intro
- Lua resources: https://www.lua.org/manual/5.4/
Thanks for reading and see you later!
This content originally appeared on DEV Community and was authored by Alejandro Londoño