My Neovim Plugins (April 2023)
Right now, I am moving from one Neovim plugin manager to another. While I am at it, I clean up plugins and their configurations. Sometimes, what a given plugin does is not apparent at first sight. Therefore, I decided to create a rundown of what I use. Then the idea to make a blog post out of it came. Maybe I will inspire you to introduce one of these plugins into your workflow!
What is Neovim
As an after-thought, I decided to give a quick explanation of what Neovim is. Not everyone has to know that!
Neovim is a modal text editor. Modal means several distinct modes, such as visual for selection, normal for navigation, or insert for typing input. Having different modes provides excellent configuration capabilities. You could have the same key do different things in different modes!
If you would like to learn more about Neovim and what it takes to make it an fantastic code editor, then I recommend:
- Personalized Development Environment video by TJ
- Vim As Your Editor playlist by ThePrimeagen
- bash2basics series by TJ and Bashbunni
My Plugin List
If you would like to explore what a given plugin has to offer, then click it’s name in a section header - that will take you straight to the plugin’s GitHub repository.
UI plugins
tokyonight.nvim
First goes the color scheme, or theme, if you will. Without one, you are going to be greeted by dull-looking colors when launching Neovim:
The default colorscheme looks better than it used to, but I like Tokyo Night more:
It could be even better, but there is one crucial piece of the puzzle that is missing - treesitter. Once we let treesitter handle syntax highlighting, it gets a whole lot nicer:
lualine.nvim, indent-blankline.nvim, todo-comments.nvim, and gitsigns.nvim
There is not much to say about these plugins other than showing what they do. Each of them provides a different interface part for Neovim.
nvim-treesitter
Treesitter is the backbone of many other plugins. By itself, it provides syntax highlights and parsers for numerous programming languages. Treesitter allows querying a file’s syntax tree using its query language.
I haven’t used treesitter itself much, only when I had to retrieve a treesitter node name to configure a different plugin. However, I use a couple of plugins that rely on treesitter. Read on!
Treesitter Playground
Treesitter Playground is a helpful tool for debugging and analyzing a treesitter
representation of the currently opened file. :TSPlaygroundToggle
provides a
live preview of the structure in a split.
Treesitter Playground demo
nvim-treesitter-context
nvim-treesitter-context “pins” relevant lines to the top of the current buffer. For example, if a function is too long to fit on the screen, then the treesitter context will keep that line pinned.
nvim-treesitter-context demo
nvim-ts-autotag
This simple plugin will automatically close tags for you in JSX, HTML, etc.
nvim-ts-autotag demo
telescope.nvim
Telescope is definitely a more exciting thing than treesitter. Basically, telescope is as good as fuzzy searching can get.
- Need to look for a file?
:Telescope find_file
. - Need to grep something?
:Telescope live_grep
. - Searching through command history?
:Telescope command_history
. - Looking for the right
:help
page?:Telescope help
.
You get the idea. There are even more pickers you can choose from! Telescope comes with a preview window for your convenience. Additionally, after narrowing down the results, you can send these to the quickfix list to navigate between them easily.
telescope.nvim demo
telescope-file-browser.nvim
telescope-file-browser.nvim provides an additional picker that allows creating new files and navigating through directories.
I am not a fan of this one. Likely in the near future, I will try replacing it with an alternative or just make the default NetRW good enough for my use (creating files and directories).
telescope-file-browser.nvim demo
quick-scope
quick-scope highlights unique letters within words on cursor’s line. The
highlights are helpful for f
/F
and t
/T
movements in Vim.
By default, quick-scope uses two different highlights for letters available for
f
and 2f
motions. Personally, I have only the former enabled to make it less
confusing. Additionally, I have the highlights enabled at all times instead of
displaying them after hitting f
/F
/t
/T
- this way, I don’t have to wait
to see the second key I need to press.
quick-scope demo
nvim-autopairs
The name of this plugin speaks for itself. It autocompletes pairs of brackets, quotes, etc. This plugin has some additional settings you can tweak. However, I didn’t need it so far - it is good out of the box.
nvim-autopairs demo
Comment.nvim
This plugin is simply amazing. If you have never used any comment plugin for
Vim, then you definitely should give one a go! This plugin lets you stop
thinking about the correct comment string for the file you are editing, e.g.,
#
for YAML, --
for Lua. Additionally, this plugin can comment on multiple
lines, and the comment strings are always neatly aligned. Finally, there are
mappings to start writing a comment at the end of the current line and above or
below the current line; however, I never remember to use these.
Comment.nvim demo
vim-easy-align
vim-easy-align is irreplaceable if you need to format some text. You can provide an arbitrary expression or a specific number of characters that have to be aligned. Formatting a markdown table takes less than 5 seconds.
vim-easy-align demo
vim-fugitive
tpope is a Vim plugin artist. His plugins have an outstanding user experience that fits Vim ecosystem really well. vim-fugitive is one of these plugins, perhaps the most known one.
vim-fugitive integrates an interface for managing git into a separate Vim split
and a wrapper for git
CLI to use it seamlessly from Vim. Personally, I need to
make it a habit to utilize fugitive more because it literally has it all! One of
the nicer features I would like to highlight is modifying (staging, restoring,
etc.) a small subset of lines based on visual selection within the fugitive
interface.
Another nice thing I appreciated while committing part of this blog post was having everything within a single window. I had the blog post, fugitive buffer providing a preview of current git state, and a buffer to write the commit message. This way, I could freely move between the three to check whatever I wanted before finalizing the commit message.
vim-fugitive demo
gv.vim
Continuing with git, gv.vim is a simple git history graph viewer. As simple as that. A nice touch is navigation from commit preview into specific files.
gv.vim demo
repos.nvim
repos.nvim is my very own plugin! Its premise is simple. Run a given callback function if a git remote matches provided pattern.
I have created repos.nvim, because I needed to override some settings for a specific repository. Existing solutions for per-project settings required an additional file in the project’s directory, and I didn’t want to maintain it. That’s how repos.nvim came to be, allowing me to configure overrides within my dotfiles.
vim-surround and vim-repeat
vim-surround is yet another masterpiece from tpope. As its name suggests, it is
used for surrounding. Surrounding text objects (see :h text-objects
) with…
things. This plugin has its functionality very composable. Pick ys
for adding,
cs
for changing, and ds
for deleting the surrounding. Then provide a text
object (e.g., iw
for word, iW
for continuous characters). Finally, pick the
surrounding, be it quotes, brackets, or anything else supported by the plugin.
vim-surround demo
vim-rsi
vim-rsi is a straightforward plugin. It comes with multiple mappings that will
make your life easier. Thanks to vim-rsi, I have discovered that these mappings
work in some shells in the first place! I suggest reading through :h rsi
to
see the mappings. To give a glimpse: <C-a>
/<C-e>
for moving the cursor to
the beginning or end of the current line when in insert mode or command mode
(!). Other mappings include moving by or deleting a letter or a word in either
direction.
vim-eunuch
This plugin provides a bunch of useful unix helpers. Personally, I have only
used :Remove
, :Move
, and :Rename
, but there are others!
vim-abolish
vim-abolish is one of these plugins you won’t use for ages, but then there
is that one use case where it makes things so much easier. It has three main
pillars (abbreviation, substitution, and coercion), but I have only used one -
substitution. It provides :S
command that works similarly to :s
with the
difference that it handles various cases of the word. Additionally, it allows
positional renames. I recommend reading through vim-abolish README to get the
gist of it.
Other than substitution, vim-abolish can handle switching between different word cases and setting abbreviations for numerous variants at once.
vim-abolish demo
LSP
Last but not least, there are plugins that I use for Language Server Protocol (LSP), commonly known as autocomplete et al. There are quite a few plugins that I use this in Neovim language server communication, language server installation, and completion based on LSP communication are three separate things. I started off by watching [Neovim Builtin LSP Setup Guide by TJ and Bash][].
nvim-lspconfig
This plugin is the backbone of the language server. It provides a ready-to-go
config for numerous languages as outlined in its documentation (or in :h lspconfig-server-configurations
).
mason.nvim
Since the actual server providing completions and other things is a separate program. These have to be installed manually… or you could use mason.nvim, that provides a nice interface for doing that:
With mason.nvim you still have to install these one by one, but there is a remedy to that…
mason-lspconfig.nvim
mason-lspconfig.nvim is what glues nvim-lspconfig and mason.nvim. This plugin automatically picks up what language server you have configured and, based on that, installs the required programs. It is really convenient if you use different languages and, therefore would have to install many tools across different stacks.
null-ls.nvim
null-ls.nvim is a nice addition to LSP. Basically, what it does is inject some goodies into already running LSP. These include formatters, linters, etc. It provides a convenient way to hook whatever you’d like in. For example, I have prettier with modified defaults so that it is disabled in markdown and yaml, but enabled in astro files.
mason-null-ls.nvim
The same concept as mason-lspconfig.nvim, but for null-ls.nvim.
nvim-cmp
As I mentioned, the language server is responsible for providing completions, but once we get a response, we need to provide a selection back to the editor. That’s where the completion plugin comes in. I use nvim-cmp for that. It allows having the completion suggestions from different sources such as LSP, buffer, or path.
I won’t go into details on this one as this plugin has quite a lot of boilerplate going around. If you want to set it up for yourself, you could check out my dotfiles!
I will, however, drop a list of plugins providing sources for completions:
- cmp-nvim-lsp-signature-help - function signature suggestions
- cmp-nvim-lsp - LSP completions
- cmp_luasnip - completions for LuaSnip. I don’t use snippets, but they are required by nvim-cmp to work.
nvim-cmp demo
cmp-cmdline
This source for nvim-cmp can be configured separately from the ones listed
above. It provides completions for command mode (:
-stuff).
DAP
Last but not least are DAP (Debugger Adapter Protocol) plugins. Similarly to LSP, DAP is a standard that some programs implement. In other words, DAP is the thing that allows you to set breakpoints and debug within your editor.
I have followed Debugging in Neovim video by TJ and Bash to configure DAP in Neovim. After watching the video, I haven’t tinkered with the setup too much, to the point where I haven’t settled for mappings yet, and on an occasion where I need to debug, I run things manually.
The list of plugins that do the job for me for Go is:
- nvim-dap - actual DAP implementation
- nvim-dap-ui - a nice interface with breakpoints, watchers, console, etc.
- nvim-dap-virtual-text - provides hints about current values
- nvim-dap-go - provides Go-specific configurations for DAP
Which Plugins Didn’t Make It
During the switch from packer.nvim to lazy.nvim I reviewed whether I use these plugins. Some didn’t make it, mostly because I wasn’t using them enough. Here is a list of these:
- cmp-buffer
- cmp-tabnine (I am testing copilot.lua)
- friendly-snippets
- git-worktree.nvim
- go.nvim
- harpoon
- nvim-treesitter-endwise
- rust.vim
- telescope-github.nvim
- telescope-symbols.nvim
- twilight.nvim
- undotree
- vim-gitgutter (I replaced it with gitsigns.nvim)
- zen-mode.nvim
Summary
That’s it - all the plugins I use (at the moment). Of course, there is more to Neovim than plugins - mappings, autocommands, and commands come to my mind.
Moving to lazy.nvim has been an opportunity to clean up my dotfiles. I moved the configuration for every plugin next to its definition in lazy.nvim making Neovim config much more readable. Additionally, along the way, I simplified configs of many plugins and reduced the number of files:
~/.config/nvim
changes
.
├── after
│ ├── ftplugin
- │ │ ├── GV.lua
│ │ ├── fugitive.lua
│ │ ├── gitcommit.lua
│ │ ├── go.lua
│ │ ├── mail.lua
│ │ ├── markdown.lua
- │ │ └── norg.lua
│ └── plugin
│ ├── autocmds.lua
- │ ├── colorscheme.lua
│ ├── commands.lua
- │ ├── dap.lua
! │ ├── mappings.lua
- │ ├── repos.lua
- │ └── treesitter.lua
├── lua
│ └── tymek
- │ ├── lsp
- │ │ ├── cmp.lua
- │ │ ├── init.lua
- │ │ ├── lspconfig.lua
- │ │ └── null-ls.lua
│ ├── git.lua
- │ ├── init.lua
│ ├── keymap.lua
- │ ├── packer.lua
+ │ ├── plugins.lua
- │ └── with.lua
├── plugin
! │ ├── mappings.lua
│ └── options.lua
+ ├── queries
+ │ └── go
+ │ └── context.scm
└── init.lua
- 8 directories, 25 files
+ 9 directories, 15 files
The next stop: cleaning up my mappings.