Vim
Est. read time: 6 minutes | Last updated: September 23, 2024 by John Gentile
Contents
- Overview
- Normal Mode
- Command Mode
- Visual Mode
- Regular Expressions
- Advanced Vim Techniques & Customization
- References
Overview
“Your problem with Vim is that you don’t grok vi.”- StackOverflow (User Jim Dennis)
Vim is a modal text editor, meaning keystrokes and operations have different actions depending on the mode.
Mode | Key(s) | Description |
---|---|---|
Normal | Esc | Normal mode |
Insert | i | –INSERT– Insert/edit text in traditional text editor sense |
Command | : | Enter commands to execute |
Visual | v | Enter visual mode |
Note: You must be in Normal mode before going into other modes
Launching Vim
From the command line, one can open a set of files in a vertical (-O
) or a horizontal (-o
) split, and specify how many panes to split across by appending that to the command parameter; for instance, if a directory has 5 text files and we want to open them in 3 vertical panes, we can do so with:
$ vim -O3 *.txt
Learning Vim
A good way to learn Vim is by launching the built-in vimtutor
in your shell. Another is to play VimGolf to try and optimize how few keystrokes are made to accomplish a given text processing task.
Normal Mode
Typing a number before a motion repeats the motion that many times (i.e typing 3w moves the cursor 3 words forward and d2w deletes next 2 words).
Navigation
Credit for picture to Ted Naleid
Other common movement commands:
Operation | Key(s) | Description |
---|---|---|
Left/Down/Up/Right | h/j/k/l | Move cursor left, down, up or right respectively |
Scroll Screen Up/Down | Ctrl+b/Ctrl+f | |
Scroll Half-Screen Up/Down | Ctrl+u/Ctrl+d | |
Move Screen Up/Down | Ctrl+y/Ctrl+e | Screen moves 1 line at a time w/o moving cursor |
Current Line to Middle of Screen | zz | |
Current Line to Top of Screen | zt | |
Current Line to Bottom of Screen | zb | |
Next Word Beginning/End | w/e | Move cursor to beginning/end of next word |
Back a Word | b | Moves cursor back to start of last word |
Move to Start of Line | 0 or Home | Move to Start of Line |
Move to 1st Non-Blank Character in Line | ^ | Move to 1st Non-Blank Character in Line |
Move to End of Line | $ or End | Move to End of Line |
Append After Cursor | a | Moves into Insert mode after the cursor (whereas i inputs text before the cursor) |
Append End of Line | Shift+a | Moves cursor to end of line and puts Vim in Insert mode |
Insert at Start of Line | Shift+i | Moves cursor to beginning of line and puts Vim in Insert mode |
Insert New Line Above/Below | Shift+o/o | Inserts a new line above/below the cursor and puts Vim in Insert mode |
Display location in File and Status | Ctrl+g | Display location in file |
Move to bottom of file | Shift+g | |
Move to start of file | g,g | |
Move to line number | line_number ,Shift+g |
Move to line number line_number |
Exit & Write | Shift+z,Shift+z | Write file, if modified, and quit Vim |
Copy/Paste
Copy commands start with y, and keys typed after designate what to copy, similar to navigation commands; for example, use y,w to yank a word. One can also enter Visual Mode (v) to select desired text to copy before hitting y. After which, text can be pasted using the put (p) command.
Other copy & paste examples:
Operation | Key(s) | Description |
---|---|---|
Copy (yank) Current Line | y,y | Copies current line |
Put/Paste Text from Register | p | Put text in Vim’s register (such as previously deleted or yanked text) after the cursor |
g,p | Just like “p”, but leave the cursor just after the new text. |
Deletion
Delete commands start with d, and operate similar to other basic operations where keys after designate what to delete.
Other delete examples:
Operation | Key(s) | Description |
---|---|---|
Delete Character | x | Deletes character under cursor |
Delete until Found Character | d,f,character | Deletes text until character is found |
Delete Word | d,w | Deletes until start of the next word (excluding first character) after cursor |
Delete Word | d,e | Deletes until end of current word (including last character) after cursor |
Delete Line | d,d | Delete entire line at cursor |
Delete to End of Line | d,$ | Delete to end of line after cursor |
Changes and Reversals
Change commands start with c, and operate similar to other basic operations where keys after designate what to delete.
Other change examples:
Operation | Key(s) | Description |
---|---|---|
Change Word | c,w | Change rest of word after cursor and place in Insert mode |
Change Inner Word | c,i,w | Change whole word (regardless of cursor position in word) and place in Insert mode |
Change to End of Line | Shift+c | Same as c,$ |
Change Case | ~ | If in normal mode, changes the case of character at cursor but in visual mode with multiple selections changes the case of selected characters |
Search, Find & Replace
Operation | Key(s) | Description |
---|---|---|
Find Character | f,character | Finds and positions cursor at character |
Search in File | / or ? to search backwards | This opens a command line at the bottom of Vim where you can enter text, or regular expressions, to search for. Hit n to go to next find and Shift+n to search in the opposite direction. Ctrl+o goes back to original cursor position and Ctrl+i goes forward |
See Search History | q,/ | Shows past searches that you can select through and search again |
Search Commands | :set ic hls is |
These commands allow for search to ignore exact case matching, to highlight matching values and to increment search respectively. Use :set noic nohlsearch to disable ignoring case and highlighting of matches respectively |
Find Matching Bracket | % | Place cursor at any bracket and hit key to find matching bracket for types (), [], or {} |
Replace Mode | Shift+r | Acts like Insert mode in other text editors in that every typed character is inserted and delets an existing character |
For find & replace, see Substitution under the Command section
Undo, Reverse and Recording Commands
Operation | Key(s) | Description |
---|---|---|
Undo Last Edit | u | Undoes last operation (like Ctrl+z in other text editors) |
Undo Edits on Line | Shift+u | Undoes all changes made on the last line that was edited |
Reverse Preceding Command | Ctrl+r | Reverses actions taken until reaching most recent edit |
Repeat Last Change | . | Repeat last command that made a change to the text |
Replace Character | r,character | Replace character after cursor with character |
Record Commands to Register | q,character | Records a set of commands to register character and stops recording after hitting q again |
Play command held in register | @,character | Repeats recorded command(s) held in that registers character |
Pipe Command to Shell and Pipe Output into Current File | !,! | i.e. !!ls pipes the listing of files in your current directory into your current file |
Folding
Folding is useful to visually compress files based on their structure, syntax or indentation (depending on the set foldmethod
setting). Some useful default key combinations for folding are:
za
: toggle open/close a fold under the current cursor.zc
/zo
: close/open a fold, respectively.
zR
/zM
: open/close all folds in a buffer, respectively.
Command Mode
All commands are assumed to start with : while in Normal mode
Operation | Command | Description |
---|---|---|
Save Current Buffer | w (filename) |
Write any modifications to existing file or if given a filename write to that file |
Save All Open Buffers | wa |
Write any modifications to existing files in all open buffers |
Quit | q |
Quit if no modifications since last write |
Quit & Save Changes | wq |
Write changes to file and quit Vim |
Quit & Discard Changes | q! |
Override warnings and quit without writing to file |
Substitution / Search & Replace | s/old/new |
Replace first occurrence of old with new |
s/old/new/g |
Replace all occurrences of old with new in the current line | |
1,4s/old/new/g |
Same as above but change occurrences in range between line numbers 1 and 4 (inclusive) | |
%s/old/new/g or %s/old/new/gcI |
Change every occurrence of old with new in entire file. Add c to prompt to replace at each occurrence and I to match case sensitive |
|
%s/\<old\>/new/g |
Change only whole words exactly matching old to new |
|
%s//new/g |
Replace each match of the last search pattern with new |
|
%s/old/<c-r><c-w>/g |
Replace each occurrence of old with the word under the cursor. Replace <c-w> with <c-a> to use the white space delimited word under the cursor |
|
%s/old/<c-r>0/g |
Replace each match of old with contents of register 0 which contains the text from the most recent yank command |
|
Execute External Command | ! command |
Type ! at the command line to execute any operation that can be run in your shell |
Pipe/Retrieve Input to Vim | r |
This allows for operations such as piping | in Unix so that an operation such as r FILE places the contents of FILE after the cursor and r !ls reads output of the ls shell command and puts it below the cursor; similar to !! command in Normal mode |
Edit another File | e FILE |
Close current file and opens FILE for edit |
Open Help | help |
Opens help menu in Vim |
Working with Multiple Files
Operation | Key(s) | Description |
---|---|---|
Edit a file in a new buffer | :e filename |
|
Go to next open buffer | :bnext /:bn |
|
Go to previously open buffer | :bprev /:bp |
|
Delete buffer (close the file) | :bd |
|
Open a file in a new buffer and split window | :sp filename |
|
Split Windows Horizontally | Ctrl+ws | |
Split Windows Vertically | Ctrl+wv | |
Switch between open Windows | Ctrl+ww | |
Quit a Window | Ctrl+wq |
You can also use :b[uffer]
with tab-completion to show and navigate all currently open buffers (for instance if you have a lot openend).
Visual Mode
Once in visual mode, navigation causes text to be highlighted. Most normal mode operations, like yank and delete, carry over to visual mode as well and operate on the visually selected text.
Operation | Command | Description |
---|---|---|
Select by line | Shift+V | Select line by line |
Block Select | Ctrl+v | Select text by block |
Select Text and Do Stuff | : | After selecting/highlighting some text, this will enter command mode so you can do things like write selection to another file |
Delete Selection | x or d | Deletes selection |
Join Text | Shift+J | If selecting text that spans multiple lines, join puts the lines into a single line seperated by spaces |
Enter Block Visual Mode | Ctrl+v | Select visual block; useful for tables or multiple line selection |
Insert text across a block | Shift+i | Useful when in Visual Block mode to do things like insert text across multiple lines |
Delete selected text and insert across a block | c | Deletes selected text and then goes into multiple insert mode, similar to above command |
Indent Selected Lines | >/< | Indents/De-indents selected lines by amount specified by shiftwidth . = indents the text by what Vim thinks is appropriate |
Jump to definition | Ctrl+j | Jump to definition of function highlighted |
Regular Expressions
Regular expressions (aka regex) are not a Vim-specific feature, they are a sequence of characters that define a search (or even search and replace) pattern and can be found in languages like Perl and other Unix tools like sed
and awk
. Vim does have regex features that make it very powerful though, and a great overview and tutorial of using regex in Vi(m) can be found at vimregex.com.
Advanced Vim Techniques & Customization
Vim Config File
The .vimrc file (usually found in the home folder, but can be placed in other directories for per project custom features) is useful for enabling extended features of Vim and for personalization/customization of Vim. To see an example .vimrc with comments on what-does-what, see this GitHub link.
Also tools like EditorConfig can be used to keep consistent configurations on a project-to-project basis for things like tab vs. spaces, line endings, etc.
Vimscript and Plugins
Vim can also be further extended with plugins and plugin managers such as vim-plug that execute Vimscript (scripting language within Vim) to execute unique features. Learn Vimscript the Hard Way is a useful site for learning more about customizing Vim as well as developing custom Vim plugins.
Browse for Vim plugins using GitHub or sites like Vim Awesome and awesome-neovim.
Techniques for Development
C/C++ Development
Here are some useful tips when working with Vim for code development:
:set filetype=c
when you are working with a file with a non-standard file extension, you cna use this to set the syntax highlighting for the “C” filetype- Use
:set cindent
to enable C-style indentation automatically
- Use
- Search for definitions:
- [,Ctrl+i to search for word under cursor, including files that are brought in by #include directives
- Use g,d to search for a local declaration of a variable under the cursor and g,Shift+d to search for the global definition
- [,Ctrl+d to search for first definition of macro under cursor and ],Ctrl+d to search for next definition of macro under cursor
- Use [/],d to display the same thing
- Use [/],Shift+d to display all definitions of macro
- For compiling and checking for errors right from Vim, you can call
:make [args]
to call the Make program with the local Makefile. This has benefits as any generated errors can be immediately stepped through and changed via::cnext
/:cprevious
moves to the next/previous error (:clast
/:crewind
go to last/first errors):cnfile
goes to the first error message in the next file:cc
shows current error and:clist
gives a list of errors (:clist!
shows all informational messages)
- To search a regular expression across files, you can use vimgrep such as
:vi /hack/ /usr/src/linux**/*.c
; in this example, we search for the regex hack in all files that match the wildcard*.c
in the directory /usr/src/linux and all directories below it- You can use the same navigational commands for tags to navigate search matches from vimgrep
- Open file under cursor with gf; this is very useful for opening referenced
#include
files in a C/C++ file- Ctrl+Shift+o to go back
- Ctrl+Shift+f to open file in new window
- When working with source files edited/made in Windows/DOS, you’ll often come across the issue of line ending mismatches when developing in Unix based systems. Vim can simply change line endings with a command such as
:set ff=unix
(to convert a DOS file to Unix line endings) or:set ff=dos
for the opposite - Get creative with autocommands and abbreviations to insert commonly used sections of code/text automagically
- Use plugins to help aid in quicker, more effecient development (see .vimrc linked above for an example) but not those that add bloat and distraction to your development flow
- For example, YouCompleteMe is an intelligent code-completion engine for Vim that can accelerate development and makes Vim more IDE-like
- You can easily remove trailing whitespace with
:%s/\s\+$//
(or macro to a keyboard shortcut for easier use) vim -d [file1] [file2]
(orvim diff
) is an easy way to diff two files:sort
is a powerful sort feature within Vim, use often- Open the last edited file with Ctrl+o+o
- Interactive command history window
q:
- Open, edit and save compressed files with vim such as
$ vim archive.tar.gz
- Launch the man page for a command under the cursor when hitting K
Tags
To use tags in Vim, you can generate tags for your source (i.e. using exuberant ctags $ ctags *.c
) which acts as a lookup for important parts/definitions of code in a project (function definitions, constants, classes, etc.). Then use either :tag FUNCTION
or a keyboard shortcut- if the function you are looking for is under your cursor- to search across multiple files to find the tag’s definition and jump to it:
- Ctrl+]: Jump to definition
- Ctrl+t: Jump back from definition
- Ctrl+W+}: Preview definition
- g+]: List all definitions
Ctag options can be defined globably (to ignore common directories for instance) by making a config file in your home directory ~/.ctags
like:
--recurse=yes
--exclude=.git
--exclude=vendor/*
--exclude=node_modules/*
--exclude=db/*
--exclude=log/*
If there’s multiple definitions of a tag, you can:
:tn
move to next definition:tp
move to previous definition:tr
goes to first definition:tl
goes to last definition:ts
list all definitions for a tag:tj
jump to tag if only one exists
Tags can also use regular expressions to search and find definitions; any tag command starting with a /
is assumed to use regular expressions (i.e :tag /regex_function
). You can similarly use :stag FUNCTION
and Ctrl+w+j to split the current screen with your original screen and with where the tag function is defined.
Since tags are generally large and a byproduct of the development process, it’s often a good idea to ignore the generated tags
file in repos under source control.
Plugins like tagbar and gutentags are great for making Vim feel more like an IDE with tags integration.
Techniques for Writing
- To turn on spell check, use
:set spell spelllang=en_us
- To spell check only the local buffer use
:setlocal spell spelllang=en_us
- To turn off spell checking, use
:set nospell
- To spell check only the local buffer use
Other Tricks
Search & Replace Across Buffers
Using the bufdo
command applies a command across all open buffers. For example to search & replace across multiple buffers:
:bufdo %s/pattern/replace
Fix Long Line Lengths
In normal mode, you can format a long commented line to fit within your set textwidth with:
gqip
References
- Learning the vi and Vim Editors, 7th Edition by Arnold Robbins, Elbert Hannah, Linda Lamb
- VIM Book by Steve Oualline
- Neovim from Scratch - chris@machine YouTube Series
- How I Setup Neovim On My Mac To Make it AMAZING in 2024