DEV Community

Cover image for Ultimate Neovim Setup Guide: lazy.nvim Plugin Manager
Alejandro Londoño
Alejandro Londoño

Posted on • Edited on

Ultimate Neovim Setup Guide: lazy.nvim Plugin Manager

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/dotfiles repo.

⚙ Requirements

✨ Features

📚 Project Structure

📂 nvim/ ├── 📂 lua/📂 slydragonn/ │ └── 📂 plugins/ │ └── 📂 lsp/ │ └── ...pluginconfigfiles │ └── 🌑 settings.lua │ └── 🌑 maps.lua │ └── 🌑 lazy.lua └── 🌑 init.lua 
Enter fullscreen mode Exit fullscreen mode

If you don’t have some requirements

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") 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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") 
Enter fullscreen mode Exit fullscreen mode

Then in the init.lua file we import the lazy config:

-- ~/nvim/init.lua require("slydragonn.settings") require("slydragonn.lazy") 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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 }, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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, } 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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>-") 
Enter fullscreen mode Exit fullscreen mode

And that's it, with this setup you should have an amazing neovim editor.

📚 Resources

Thanks for reading and see you later!

Top comments (2)

Collapse
 
omarkhatib profile image
Omar

thanks many usefull plugins indeed.

Collapse
 
justzaiyen profile image
Qazi Zarif Ul Islam

Thank you for the instructional!

Just one question. You mentioned that we should create the plugin within ~/nvim/lua/plugins/. Should it not be ~/nvim/lua/slydragonn/plugins/? as you mention later on at the top of your respective plugins's code?