Getting Started
This might be a rite of passage for developers, but the hardest part about picking up Neovim (and vim, in general) is getting in the habit of using the proper key bind motions. There is a certain rhythm or pattern that vim is designed for that makes programming in the terminal effortless, but it does require a substantial amount of practice to adopt. One thing that jumps out at me all the time is the fact that there are so many different keys that it is impossible to try to memorize them - you must learn by using it over and over until it becomes muscle memory.
The best way to start is with vim tutor. In neovim you just type :Tutor and the vim tutor window will come up. It's an especially good spot to jumpstart learning when you know absolutely nothing. I even have found myself going back to it when I feel the need for a good refresher. The only caveat is that vim tutor is quite sparse and certain cool functionalities like using nvim plugins and LSPs are not included.
Basics
There are three modes to be aware of: Normal (default), Insert (toggled with i), and Visual mode (toggled with v). Normal mode is actually very powerful, although it can be frustrating at first without knowing the key commands - it allows you to jump around the file, search, delete, undo etc. and all sorts of other patterns. Insert mode is good for typing in the file, so if you want to start editing the file you might jump right to insert. Visual mode is used to select chunks of text, and then applying normal mode commands to a large chunk at once (indent, change case, delete).
An intuitive way to think about Visual mode is that it allows you to apply normal mode commands to a selected chunk of text rather than just the cursor position. Instead of a command affecting a single character or line, you can select exactly what you want to modify and then apply the same commands you'd use in normal mode.
Movement with hjkl
One of the fundamental aspects of vim is using hjkl keys for movement instead of arrow keys. The h, j, k, l keys move left, down, up, and right respectively. This might feel awkward at first, but it's crucial because it keeps your hands on the home row and allows for much faster navigation once you develop the muscle memory. In my configuration, I've actually disabled the arrow keys entirely to enforce learning proper vim movement - this forces you to build the right habits from the start rather than falling back to familiar but inefficient patterns.
Instead of holding down jk to move vertically line by line, you can move a lot faster by prefixing with a number followed by jk e.g. 10j to move 10 lines at a time vertically!
Expanded movement
One of the first things to make moving around much more efficient rather than holding down the hjkl keys is word and line movement. Move forward and back through words with w and b respectively. Move to next end of word or previous end of word with e and ge respectively. Move to start and end of file with 0 and $ respectively. Move to the top and bottom of the file with gg and G respectively, and to a specific line number with 457G. For a rough position in the file you can also use percentage 50% to go halfway. Press ^ to move to first non-blank character of a line if you are positioned at the beginning of an indented line.
Prefix with a number to repeat that movement action N times, so 10w will move 10 words down. Typing 2$ will move to the end of line of the second line. The point of using these numbers is not only to enable precision but also to accelerate movement speed around the file.
Another really important movement command is the find command with f key. This allows you to search forward in line for a single character, allowing for fast horizontal cursor movement! For instance, with fx you jump forward in line to the next x character. Combining number with operator and motion, you get 3fl for the end of the 3rd instance of l in the line. The capitalized F is used for finding in the reverse direction.
A close variant to f that you should know about is t which like f jumps to the next occurrence of the character on the right, but instead of positioning the cursor directly onto the character, it positions right before. T jumps to the character on the left, and positions the cursor after the character. A good way to remember is that t stands for till before and T till after.
A keystroke that is super useful when paired with character search commands t and f is the semicolon ; and comma ,. The semicolon or comma just repeats the previous search command you gave in forward or reverse direction respectively. So if you do fx, then ; afterwards will jump to the next x. Pressing , jumps to the previous x.
Advanced motions in vim begins with first understanding the fundamentals of using w, f, t, ;, , to improve navigation speed horizontally, which is usually the biggest bottleneck!
Inserts
Keys are also meant for speedy inserts, so you don't have to position the cursor at the correct spot in normal mode before pressing i to go into insert mode. For instance, you can jump to insert mode at the end of the line with A (think short for append). Jump to insert mode on a new line below the cursor with o (newline above with O). A good key to also know is to insert after cursor position with a as opposed to before cursor position with i (so I'll sometimes use a over i at my cursor position).
There are many other examples of useful compound short cuts like A = $a. Another common shortcut is C = c$ which replaces everything from cursor to end of line and puts you into insert mode. The shortcut I = ^i puts you into insert mode at the start of the first non whitespace character.
I also find myself often joining lines by going down one line, jumping to the start, and hitting backspace. This can be sped up by using the key J which joins the current line with the line below. A number prefix like 5J joins the current line with the next four.
Deletes
For minor character deletes, this is provided with x. But the most useful keystroke early on for deleting an entire line is dd. You can delete multiple lines with number prefixes like 5dd.
d is an operator that follows vim's operator-motion paradigm. An operator performs an action, and when combined with a motion (which defines where to apply the action), you can efficiently edit text. For example: dw deletes a word, d$ deletes to the end of line, d0 deletes to the beginning of line.
Yanking and Pasting
Yanking is vim's term for copying text, and it works seamlessly with vim's operator-motion paradigm. Use y as the yank operator followed by a motion to specify what to copy. For example: yw yanks a word, Y = y$ yanks to the end of line, yy yanks the entire current line.
You can use Visual mode to precisely select what you want to yank. Press v to enter visual mode, use movement keys to select the desired text, then press y to yank the selection. This is especially useful for copying irregular chunks of text that don't align neatly with word or line boundaries.
Once you've yanked text, use p to paste after the cursor (or below the current line for full lines). Use P to paste before the cursor (or above the current line for full lines).
When you delete with dd, the deleted text isn't just removed - it's automatically stored in vim's register, making it available for pasting with p. This means dd followed by p effectively moves a line rather than just deleting it. The same principle applies to other delete operations like dw or d$.
You can also combine yanking with number prefixes for efficiency: 3yy yanks 3 lines starting from the current line, 5yw yanks 5 words forward.
Core Concepts: Registers and Buffers
Understanding registers and buffers is essential for effective Neovim usage:
Registers are temporary storage locations for text that you copy, cut, or delete. When you yank (y) or delete (d) text, it goes into a register. You can then paste it elsewhere using p. Vim has multiple registers (named with letters, numbers, and symbols) so you can store multiple pieces of text simultaneously.
Buffers are in-memory representations of files you're editing. When you open a file in Neovim, it loads the file's contents into a buffer. You can have multiple buffers open at once, each containing a different file. Buffers are what you actually edit - changes are made to the buffer until you save (:w) to write back to the file.
The key difference is purpose: registers store copied/cut text snippets for pasting, while buffers hold entire file contents for editing. They work together but serve completely different functions in your editing workflow.
Pasting from System Clipboard
Many times I find myself needing to copy terminal output and paste it into my markdown file in neovim. To do this, copy terminal output by selecting the text with cursor and releasing (no need to Ctrl + C or Ctrl + Shift + C which does not work). Then in neovim, press "+, followed by p. Note that + is a key press here!.
The quote key " allows you to switch registers. So the form is "{register} for the register of choice for the next delete yank or put. The + key in the above case is the system clipboard.
Dot command
The . command is powerful in vim because it simply repeats the last change command (all change commands except u, redo and : commands). For example, if you want to change a word to joe multiple times, you can do cwjoe<Esc> then . as many times as you want. The dot command is also handy as it is much less tedious than counting. For instance, if you wanted to delete some consecutive words in a line you can count them and then do d7w but it is much smoother to just do dw...... and skip the counting.
This is something I underutilize, but it really can reduce the amount of repeated keystrokes in vim. Suppose you want to add a ; to the end of the next 4 lines in javascript:
var foo = 1
var bar = 'a'
var foobar = foo + bar
var barfoo = bar + foo
Then instead of doing A; on the first line, then j, then repeat over and over, we can do A;<Esc>j.j.j. - and we can keep doing this as long as we want!
Search
Search is a functionality to get acquainted with early on because it will make life much easier navigating a larger document. Simply search by typing /pattern in Normal mode, where pattern is the word that you are looking for. By default this will match any and all occurrences of the word pattern even if it is embedded within a larger word. This might be a headache say if you are looking for the word rad but then it highlights all the instances of brad, trad in traditional, rad in radical. To avoid this issue, use \< and \> for matching the start and end, so /\<pattern\>. Once you hit enter, you can toggle through next and previous search results with n and N respectively.
There is also a faster to search a word if it is already under your cursor. Just use the key *. Then automatically it will execute a search with /\<word\> and jump you to the next occurrence.
To match beginning and end of line, use ^ and $ in the pattern respectively, e.g. /^the for only matching the word the at the very beginning. Use . to match any character in the pattern like regex, so /t.e matches the as well as toe.
Undo
Undo an action with u key. Undo an entire line to its original state with U. This is useful when you've made so many changes that the line is completely corrupted, and you'd just want to reset.
Change Operations
A useful keystroke to simply replace the word under the cursor is cw or ce to change until end of word. The key c is the change operator, which will delete everything you motion it to change and then place you into insert mode. It will be useful to do c [number] motion e.g. c5$. You can also replace character at cursor position with r followed by the character you want to replace it with. For replacing larger chunks of text, use R to enter Replace mode.
Other useful change commands include cc that changes the entire line but leaves an indent. Since these commands are used often, they have shortcuts: D = d$, C = c$ and S = cc (notice now the pattern between capital shortcuts and the $ command).
Substitute
To change every occurrence of word1 to word2 in a line, run :s/word1/word2/g.To change every occurrence of word1 to word2 in the entire file, use :%s/word1/word2/g. To do this, but allow it prompt whether to substitute or not for every occurrence, have a c at the end so :%s/word1/word2/gc.
You can also limit substitutions to lines selected in Visual mode.
Split window
You can also view two parts of the same file by using :split for horizontal, and :vsplit for vertical, and jump between them using Ctrl+w+[arrow]. Close the window with :close or close all except the one with :only. Quit all windows with :qall or :wqall.
Split faster using abbreviations :sp for horizontal split and :vsp for vertical split!
You can also open a window on a new file using :new and then saving it with filename using :saveas move.c.
Toggling Case
Use ~ to toggle the case of a cursor character or selection. Use gU for uppercasing, gu for lowercasing.
Indentation
So far I am figuring out my indentation by using V to select lines and = on the selection to auto-indent. To tab, select lines with V and then > or < to indent or unindent. Note: for unknown reasons you may have to press > or < twice sometimes.
It can be really annoying if the default tab is 4 spaces when the file you are working on is 2 spaces. To solve this, use the quick local setting: :setlocal tabstop=2 shiftwidth=2 expandtab.
Resources
Useful guides to consult:
- Practical Vim by Drew Neil (pdf can be found online)
- Neovim user manual starting from page 1
- Super cool Neovim cheatsheet that summarizes all commands