Neovim has become such a rich product that even though it is a very fast command-line tool (unlike VS Code), I still use it extensively because you don’t need a mouse. You can do all this in VS Code, but if you want to be that Ferrari 1960s vintage driver with no assist at all, read on. (Before we are off using warp, cline, cursor or windsurf), I thought I would see what is going on.
LazyVim as an easy entry point
Until last year, I was completely a vim fan and had a huge vimscript catalog and some nice tools that worked, but given the complexity of the environment and that the speed (or lack thereof) of vim with all the plugins moving to Neovim was smart. And Lazyvim is a bundler on top that gives you all kinds of opinionated plugins.
The main things to understand are the commands:
:LazyExtras - Gives you all the extra tools
:Lazy - Where you do updates and installations
:LazyHealth - To make sure it's all installed correctly
Obscure Bugs Importing Lazyvi.plugin.extras
The most significant different between vim and neovim is the use of lua scripting, where you get a massive set of scripts that you can run. The system is a little strange, but basically,y in your ~/.config/nvim You get config and plugins and a calling system.
OK, this is an obscure one. I started getting this very strange error:
The order of your `lazy.nvim` imports is incorrect:
- `lazyvim.plugins` should be first
- followed by any `lazyvim.plugins.extras`
- and finally your own `plugins`
Looking at the code, it was added February 8 but it is because now if you add plugin extras imports into your own plugins files this can cause bugs.
Instead, you should manage the extras with :LazyExtras
and it will put them in the JSON configuration called config.json
instead of the configuration in lua.
So this led me to wonder what I should do with the 80+ plugins that are there. I think that things are changing, so here’s a quick list of the plugins and how to use them.
Finding Keymaps
There are literally so many keystroke commands that they are impossible to find. The Keymaps section is really the best resource because many of the keys on LazyVim are changed compared with the underlying plugin defaults. Note that the default for <leader>
in LazyVim is the <space>
bar, but I change this to \
because I like to use space to just move to the next character. Old habits
The default or core plugins
It’s a good idea to first figure out the many default plugins that LazyVim uses and evaluate them to see what needs a change. Many of these are part of large libraries
They categorized them into different categories:
- Coding plugins. for highlighting coding
- Colorschemes. for changing the look
- Editor. For search and edits.
- Formatting. Doing formatting of text based on language in the file. Using Mason to load your Language Server Protocol (LSP) backends. Linting. Static check of code (using underlying programs and LSPs) and LSP configuration.
- Treesitter. This should really be called syntax highlighting using Treesitter, the idea is that every document gets an abstract syntax tree so you can jump to logical parts (like code blocks)
- User Interface. Make the Vi interface complete (aka busy!)
- Utilities. Miscellaneous stuff
Coding plugins
These help when you are writing software:
- Mini.nvim. Is a collection of fast and small modules. mini.pairs which highlights the matching other character like
(
will mean)
will flash - ts-comments.nvim. Takes care of comments across a bunch of different languages from C to Jupyter to Typescript
- mini.ai. Add more to append and insert text objects. So fir instance
an
mean around next,in
is insidde-next andal
andil
is around and inside last andg[(
andg])
which means finr the next ( and ) means more to the next object - lazydev.nvim. Faster auto-complete with lazy workspace library updates. I’m not sure I completely understand what this does. But seems to be speed-oriented.
Colorscheme
This loads gruvbox and tokyo night color schemes with :colorscheme gruvbox
and :colorscheme tokyonight
and :colorscheme catppuccin
Editor plugins
These are for editing
- grug-far.nvim. Search and replace across multiple files. Open a vertical split buffer with :GrugFar And then type a ripgrep command and the lower buffer with
\sr
- flash.nvim. Enhance the
f
andt
motions and integrates with Treesitter. with `f{char} just hit f again to go to next for F to previous same with t multiple times or T to reverse. Integrates with Tressite as well (see the Treesitter section) - which-key.nvim. When you type a character sequence, it shows you what is valid next, so if you type,
leader
then it will show all the available commands next. - gitsigns.nvim. Highlight on the left gutter what has changed and not changes,
Gitsigns
with change and delete likeGitsigns previe
w_hunk or\ghs
to stage or\ghr
to unstage to see a set of code about to be committed. Or,Gitsigns blame
or `\hbto see on the left tile who committed each line and]
and[h
to move forward to each changed line. Note that LazyVim changes the default keymaps which you can see in the Full Spec section in LazyVim.
Formatting and Linting with LSPs
These are mainly about “conform” for formatting, nvim-lint to check for static errors. Then the tools mason to load and unload the right plugins and lsp-config to change the keymaps of those LSPs. The specific configuration is handled by Mason thank goodness:
- conform.nvim.
\cF
to format and uses LSP plugins to do the real work. You can set the formatters in the lua plugin config. - mason.nvim. This manages the LSP, DAP, linters and formatters. It can use it with
:Mason
or\cm
and can install a Language Server Protocol or a DAP (for running code). - nvim-lint. It spawns interest parses their output and send to the
vim.diagnostic
. You need to set linters for each language in the ./lua/plugins entry. - nvim-lspconfig. And this tool handles the mapping of keys so the disparate things loaded by mason and used by conform.nvim and nvim-lint are consistent like using
]d
and[d
to navigate from error to error.
Syntax highlighting based on AST
This is the way that you can navigate “logically”. Not just by lines but by things like paragraphs, or code blocks and also highlight correctly
- which-key.nvim. I’m not quite sure why this is categorized here, but this is the tools that given a partial key sequence can show you want is next.
- nvim-treesitter. This uses language parsers underneath to highlight things and you can install with
TSInstall <language>
and this is handle by LazyVim automatically and adds]f
and[f
to move from one function to another. While[F
and]F
get you to the bottom of a function. - nvim-treesitter-textobjects. This uses treesitter to handle bigger logical objects like
ip
orap
to get inside a paragraph and around one - nvim-ts-autotag. This automatically adds closing tags for HTML, Svelte or other JSX
User Interface
Vanilla vi
was incredible terse, this is how you get it filled with icons 🙂
- bufferline.nvim. This let’s you get to the various buffers (that is different files and other windows) and adds
]b
and[b
to move back and forth. And adds a bunch more like[B
and]B
to a host of\b
commands to close buffers the current, the left or right of the current tab/buffer, all other buffers with\bd
,\bl
,\br
and\bo
. - lualine.nvim. The pretty status line
- mini.icons. Gives you GIFs like a document for markdown.
- noice.nvim. This is what makes errors and things appear in dialog boxes rather than just on the last line. And you get
\snl
to find the last message,snh
for previous,\sna
for all messages,\snd
to dismiss a messages andsnt
to pick a message. - nui.nvim. These help with highlighting
- snacks.nvim. Little tools like animation, handling big files, deleting buffers more easily, git utilities etc. and adds command like
\un
to hide notifications from snacks. or see them with\n
. This also provides the title screen if no file is opened
Utilities
These are more helpers:
- snacks.nvim. More things like
C-h
,C-j
,C-k
andC-l
to go to next windows so better than the cumbersoneC-W
commands. Also\.
to go to the scratch or temporary buffer to copy things into and\S
to find all your scratch buffers. These are sort of like registers but visible - persistence.nvim. This is great because you can restore where you were rather than reopening all files so
\qs
loads a sesisson,\qS
select one,ql
loads the last sessions andqd
deletes sessions. It automagically remembers all the previous times you’ve opened nvim! - plenary.nvim. These a bunch of helper functions
LazyVim Extras Recommended
These are the many extras that it is blinding, but to go over the ones that are recommended first so you can think as the minimum recommends set including the pre-installed ones above.
- Coding.blink. blink.cmp handles completions, so when you type, it does fuzzy matching to provide options for what is next. It’s inspired by nvim-cmp. It has auto-bracket support so do not load Nvim-cmp and this together.
- lang.markdown. This loads a collection of markdown-aware utilities, including marksman for lining, markdown-preview.nvim so
:MarkdownPreview
or\cp
and render-markdown.nvim which renders headings and code blocks with coloring that looks very nice. And add to conform.nvim a markdown-toc format when it finds<!%-%- toc %-%->
in the document and it runs markdownlint-cli2 as well with nvim-lint. - lang.toml. This adds toml to nvim-lspconfig
- coding.yanky. The adds a yank history with
[y
and]y
to go through it. And a bunch of\p
commands to look at history.[p
and]p
does the same thing for putting - editor.dial. This adds increment and decrement of numbers, day of the week, dates, or changing && to ||. Use
C-a
to increament andC-x
to decrement andg<C-a>
org<C-x>
- editor.inc-rename. This allows renaming a symbol (like a variable) everywhere with
\cr
for code rename (which doesn’t seem to work). - editor.snacks_explorer. When you open a directory with neovim, then this starts snacks.explorer. You can start it at the root directory with
\e
or in the current working directory with\E
- editor.snacks_picker. This starts snacks.picker which is a fuzzy finder so it is like fzf-lua, telescope.nvim and mini.pick. This isn’t the Noice pikcer
\snt
but provides conveniences like\<space>
or\ff
which is like\e
for Find files at the root,\,
for buffers,\/
for grep[ing the root directory. The difference is the\ff
has fuzzy search while\e
is just a direcotry tree, then there is\g
for searching git status,\s
for search registers, search, autocmds, etc. And then\uC
for color schemes. - test.core. This is for adding tests with neotest that used nvim-nio (for co-routines), plenary.nvim and nvim-dap so that you can use the debug adapter protocol to debug code inside neovim. It uses pytest for example, so
\t
is for testing,\tr
to run a test and\tl
runs the last test. And\td
uses nvim-dap to debug it after running the tests. - util.dot. This make editing the configuration files simpler. It installs bashls in nvim-lspconfig, installs shellcheck with mason.nvim and tells nvim-treesitter about specific files like waybar, mako, This is part of the mini.nvim library
- util.mini-hipatterns. Highights patterns with configurable groups
LazyExtras Useful
There are so many plugins its almost impossible to figure out what is compatible or incompatible with what, but some useful ones are:
- util.chezmoi. A very useful tool to log dotfiles
AI Plugins
There are five different (yikes!) plugins that you can use, so here’s a quick review of how the dependencies work. I had been using Code Companion for a long time, but it is time to look again:
- Codeium. You need an :Codeium Auth, and then acceptance is handled by nvim-cmp or blink.cmp. Blink Completion is a completion plugin for LSPs that updates on every keystroke and is supposed to be very fast. Nvim-cmp is an older completion manager that I’ve used for a long time and is more popular but
coding.blink
is the new default andcoding.nvim-cmp
is now no longer selected. I’ve used this for a long time since it is free, but they’ve moved on to Windsurf and are not adding big features to it. - Copilot Chat. This brings GitHub Copilot Chat integrating GPT-4o, Claude 3.7 as well as Ollama backends. The optional features need
tiktoken_core
,git
,ripgrep
,lynx
. And will integrate with the many pickers:fzf-lua
,telescope
,snacks.picker
,mini.pick
. The key mappings include<Tab>
for completions,<C-c>
to close the window, <C-l>
reset the chat window,<C-s>
submit prompt,grr
sticky prompt,<C-y>
accept nearest diff,gj
jump to nearest diff,gqa
Add from chat to quixfix list,gqd
add all diffs to list,gy
yank nearest diff to register,gd
show diff,gi
current chat info,gc
Show current chat. Here are the predefined prompt templates,Explain
selected code,Review
selected code,Fix
rewrite code,Optimize
code,Docs
document in comments,Tests
generate,Commit
messages written. Use:CopilotChatModels
to change the model,:CopilotChatAgents
of which there are a huge number. There seems to be quite a few hard coded model - Copilot. This is a Lua replacement that just plugs in GitHub Copilot and is actually required for Copilot Chat, so make sure to install it.
- Supermaven. This is a dedicated freemium copilot with their own proprietary model
- Tabnine. I’ve also used these folks.
- Code Companion. Before Copilot Chat, I was using Code Companion, but will try Copilot Chat now.
The confusing that is Copilot Chat
Of these, Copilot Chat seems the richest, but it’s confusing how to change models. With Code Companion, you had to set up something in your lua script to get different models, but here you get a prebaked lis,t and it is not clear how they are called. One confusing thing is that you have to run :CopilotChat once to get it to load as it is lazy loaded.
They have a collection of model providers (and you can add your own with your lua setup). If you use the ollama model, then you get all models that are currently running, but note that you don’t get the things behind the colon, so only models with the latest tag, I think.
One thing that is not clear is that out of the box, it only supports
- Copilot. Your usage depends on your Copilot plan; with the free tier, you are rate limited
- GitHub Marketplace. This stuff is very experimental, but there is a Copilot model farm now so that other providers can plug in. I’ve found this to have all kinds of context length issues, but Deathbeam just fixed this. But it is heavily rate limited
Additional providers. You have to create a $XDGCONFIG/nvim/lua/plugins/copilotcompanion.lua
to add these
The command lines are in two places, the LazyVim configuration and assuming your Leader key is the default backslash. There are also default key mappings in the plugin itself. One of the nice things about default LazyVim is that if you type a partial key like just Leader, it will show you all the available commands, so you don’t have to memorize all this (at least not immediately):
# From LazyVim
<leader>aa - This opens and closes the Copilot Chat window that is to the right of your code
<leader>ax - This resets Copilot Chat
<leader>aq - Quick Chat
<leader>ap - Select the preprogrammed prompt you want
# Defaults from plugin when chat is open, so for insert and normal
<Tab> - Trigger or accept completion
<C-c> or q - Close chat
<C-l> - Clear all the chats
<C-s> or <CR> - Submit prompt to model
grr - Sticky prompt for the line under the cursove
grx - clear all sticky prompts
<C-y> - Accept nearest diff
gj - Jump to nearest diff
gqa - add all answers from chat to quickfix list
gqd - Add all diffs from chat to quickfix
gy - Yank diff to register
gd - Show current diff from source
gi - info on current chat
gc - context of current chat
gh - Help
# There are predefined prompts you can use in the chat window
/Explain - explain the code
/Review - review the selected code in buffer
/Fix - Fix the bugs
/Optimize - optimize for readability
/Docs - Add comments
/Tests - Test Generation
/Commit - Write commit message with commitizen format
# Sticky prompts work across chat sessions and are set like this
> #files
> List all files
# Insert parts of what you are editing into the context
#buffer:2 - Insert buffer number 2
#buffers - Insert all buffers
#files:\*.lua - insert all files ending with .lua
#file:foo.py - insert foo.py
#filenames - all files you are editing
#git - the git diff
#url:https://tne.ai - insert a web page
#register:a - insert register a contents
#quickfix - all the files being fixed
#system:ls - run a system command and return output
# To set up the model for the chat, just hit $ to get a list
$gemma3:70b
# to run an agent just go to https://github.com/marketplace?type=apps&copilot_app=true
# then choose Add and it will appear when hit the @ sign
@perplexity
To add the other providers, you need to edit that magic file. See the section on Code Companion coming up, but here are some samples from Jellydn, but basically if you just want to take the defaults and add providers, it’s pretty simple because LazyVim just adds what you put in your plugin into the defaults, so you can add Ollama. Note that the current documentation has an extra set of braces, so remove those and then you set the model in the function for the default
return {
"CopilotC-Nvim/CopilotChat.nvim",
opts = function()
return {
model = "deepseek-r1:70b",
providers = {
-- insert provider code here
ollama = {},
mistral = {...},
openrouter = {...}
},
}
end,
}
You do need to replace the picker with something fancier.
Leave a Reply
Only people in my network can comment.