Skip to main content

Plugins

With kickstart.nvim plugins, there will be access to useful commands starting with <leader> prefix. In my config, I have this leader key set to spacebar.

Browsing the Filesystem

Opening files can be an inefficient process if sticking to basic vim functions. For example, I always used to type in the shell nvim long-file-name.txt to open a file of interest, until I realized you could just do nvim . and navigate!

Trick

You can open neovim with nvim . or vim . to start with a directory view showing all files in the current directory. This lets you navigate and select files to open without needing to type the full filename.

Often times in my workflow I find myself in need of opening another file while editing the current one. Instead of :wq to exit out of the current file, cd-ing to the right directory and then opening the target file in neovim, I found it was much easier to have split screens so you can keep the original file open while navigating to the target file in another window.

If the file is on the same directory level as the current file, default vim has :edit file.txt command for switching over. However, if the file requires further navigation, this won't be as useful. The most convenient way if you have recently opened the file you want to navigate to is to use <leader>s. - this will open up a list of your recent files, and pressing Enter will switch to that file. However, if you have not opened the file before, you will need to use a different plugin.

My neovim setup comes installed with neo-tree which is a plugin to browse the file system while in neovim. This can be done by typing :Neotree. This by default opens a file system window on the left that displays your files starting from the current working directory. To open the bar while keeping focus on your current window use :Neotree show. If you want to navigate up a directory, you will have to provide a dir argument to neo-tree by simply passing in a directory path, so :Neotree ../ will start a directory up from the current file. You can always change the cwd of the neotree window later by typing in :Neotree somedir/ (note that relative filepaths will use your current cwd). If you want to look at your open buffers, you can also do :Neotree buffers. To close the neotree window, type :Neotree close.

Telescope

Telescope is a fzf like fuzzy finder that is useful for navigating through lists of files, buffers, git commits and more. To open up Telescope plugin in Neovim to see what commands are available type :Telescope. This will open up a window where you can click into find_files for instance and navigate files, or git_commits to navigate through git history with diffs.

The most useful of Telescope key maps is:

  • <leader>sf - searches files
  • <leader>s. - searches recent files
  • <leader>sg - searches for string recursively in files from current working directory using ripgrep tool. It's not grepping for file, but file contents, so super useful for finding code snippets or functions across project..
  • <leader><leader> - searches for open buffers
  • <leader>sw - search current word under cursor (though this searched across all files, not just the current file!)

Buffers

So why is it good to have <leader><leader> to open buffers? My first thought to opening buffers is - why would I ever be in a situation where I have a file in buffer that I have not already opened? If a file is in buffer wouldn't I already have a nvim window on it?

My mental model of what is happening with files in neovim is actually wrong. When a file is opened in neovim e.g. nvim filename.txt, neovim loads it into a buffer. The fact is that if you exit, the buffer still exists even when you're not looking at it. A window doesn't make the buffer persist. A window is just a view into a buffer. When you close a window, you close the view, but the buffer stays open!

Say you are currently on file1.txt open on neovim, and you type :edit file2.txt to switch to a different file. The current window shows file2.txt buffer, but file1.txt is actually still in buffer 1 behind the scenes. To switch back you can just do :buffer 1 or use <leader><leader> to fuzzy pick file1.txt.

Powerful LSPs

Key Idea

What is a Language Server Protocol (LSP)? It is a specification that defines the protocol of communication between an editor and a language server to allow for features like auto-complete, go to definition, etc. The language server communicates with the client which is your editor. The editor spawns the LSP process, and lets the server know about what's happening. A request to the LSP server from your editor might be "hey tell me where this thing is defined", and the LSP responds "hey this definition file, and the start and end range". Server can also send notification to the client to say "this build failed" or "there is a type error here".

This turns the M x N editor - language problem into a M + N solution! Before LSPs, each editor would have some bespoke custom implementation for working with each language. The LSPs abstract this away so each editor can just plug it in and work with any kind of language.

With LSPs you have language specific tools such as grd to jump to definition of the function, and grr to go to reference (if there exists multiple it will provide a list for you to choose). You can also use K to see documentation pop up for a function.

A list of LSP commands:

  • grn renames all references of the symbol under the cursor - super useful if you want to change a class attribute's name!
  • grr lists all references of the symbol under the cursor
  • grd jump to definition, where a variable was first declared or function defined
  • gra shows a list of code actions available in the line under the cursor
  • gri lists all the implementations for the symbol under the cursor

Autocompletion

With the LSP plugin there is also a plugin called blink.cmp which supports autocompletion while typing. With the default config, <Ctrl+y> accepts the completion. You can use arrow keys to move up and down the list of possible completions. To exit out of the completion window and get back to the original typed text, just do <Ctrl+e>. More info can be found in :help ins-completion.

Trick

The autocompletion feature can be really helpful when you are trying to type out a really long class or function name.

Toggle comments

For commenting multiple lines of code, select them in visual mode and type gc for toggle comment. The same goes for uncommenting.

Neovim Mini-Surround

One tedious motion is adding quotation marks or parentheses around a phrase or word. Instead of moving the cursor to the beginning, going into insert mode, exiting, then repeating for the end, there is a plugin mini-surround to add surrounding characters to a selection or motion with no more than a few key strokes.

The commands are sa for add surrounding, sd for delete surrounding, and sr for replace surrounding.

Pitfall

Visual selection and motion only works for adding surround character with sa. It does not work with sd and sr which are more smart and will search for the character you provide - therefore it does not take in selection or motion as input, only the character of interest!

So if you try sdip it will not delete a character around the inner paragraph, but do something funny. Instead just do sd followed by the surrounding quotation marks or character you want deleted. Same goes for sr, just type the character you want replaced immediately after, followed by the character you want to replace it with.

Examples:

  • saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
  • sais" - [S]urround [A]dd [I]nner [S]entence ["]quotes
  • saaW" - [S]urround [A]dd [A]round [W]ord ["]quotes
  • sd' - [S]urround [D]elete [']quotes
  • sr)' - [S]urround [R]eplace [)] [']

Diff View Plugin

To quickly bring up modified files in a diff split, and review changes in a git repo, use diffview.nvim plugin.

For starters, :DiffviewOpen can open diff views with a variety of arguments. Examples are :DiffviewOpen HEAD~4..HEAD~2 or :DiffviewOpen d4a7b0d for a specific commit diff. With no arguments, it simply compares against the current index. To close, type :DiffviewClose. To understand the range notation meaning with diffs, see range notation.

The :DiffviewFileHistory command also allows you to see diff view with a git log commit history window below where you can select specific commit file diffs.

Trick

To avoid cluttering the interface with untracked changes, make sure to pass the argument :DiffviewOpen -uno.

As convenience, I added the following keymaps:

  • <leader>dw - working tree vs. HEAD (with -uno flag)
  • <leader>dp - diff to previous commit HEAD^
  • <leader>df - diff history of current file
  • <leader>dF - diff history across the entire repo
  • <leader>dq - close diff view