Vim tips, tricks and plugins
This post is a note-to-self type of post on Vim tips & tricks. You will also find a bunch of useful plugins listed in this post. This is the place where I write down and explaing things to my self whenever learning a new trick in Vim.
The tips and tricks are loosely organized under larger topics to try to provide some structure for the post. I hope you find something new and useful! :)
Tips are geared towards developing projects with a web focus. I am using Neovim and with VSCode through vscode-neovim (previously Onivim 2, which unfortunately died). To find more about my setup you can read OS X Design and development setup.
Regex, sorting, filtering etc
Knowing your regexes makes you feel like a magician.
Add a new line before each capital letter
%s/\u/\r\0/g
will find uppercase letters and add a newline in front. Note: this does not work in case you have scandinavian or other exotic characters in your data.
Remove empty lines from document
Quite often you end up having to clean some data for one or other purpose and it can be nice to quikcly drop all empty lines in the current buffer. Here's how you can do it fast:
:g/^$/d
Wrap lines with something
When you want to turn a column of data from an excel sheet into an array, you can do it easily by wrapping each line with the required markup. For example doing %s/.*/"&",/g
will convert nicely wrap each line with " and add a comma to the end of each line.
Sort and unique all lines
For smaller files you can do it directly in Vim with :sort u
. For larger files you might want to hop on to the command line and do sort bigfile.txt | uniq > bigfile_sorted.txt
.
Run a shell command on range of lines
This can be useful for example to run Prettier on the whole file or just part of the file.
:0,$ ! prettier
will run the whole buffer through prettier
:15-25 ! pretier
will run lines 15-25 through Prettier
:0,$ ! prettier --parser glimmer
will run whole buffer through prettier using the glimmer parser (gets those .hbs files sorted)
:0,$ ! sort | uniq
will sort the lines and then unique the lines
Macros
Macros are an essential part of Vim. You can record a macro to run a sequence of actions by hitting q + <register>
. It will record the macro to the selected copy-paste -register. When you're done recording the macro hit q
again to stop recording.
To run a macro you do @ <register>
.
Running macros on a set of lines
You often need to run a macro against a set of lines. This is easily achievable with the normal command in EX mode. Some examples to get started with:
- Execute for lines 5-10
:5,10norm! @<register>
- Execute for all lines
:%norm! @<register>
- Execute for 5-eof
:5,$norm! @<register>
- Execute for lines matching a pattern
:g/pattern/norm! @<register>
- Execute for a visual selection, select with
V + jk
and run:norm! @<register>
Switching / opening files
CTRLP
Switching files with keyboard only is hard, right? Not really with ctrlp. Ctrp is a full path, fuzzy, file, buffer, mru, tag, you name it, finder for Vim.
You hit ctrp + p
and then start typing in the name of the file you want to get to. Vim will display a list of matching files for you which you can open fast. This is a much faster way of opening files than a filetree plugin or some other such antiquated solution. Of course, this is for projects you're familiar with - exploring new projects are better done some other way.
The commands:
-
CTRL + p
- activate plugin -
CTRL + f & CTRL + b
- cycle modes
You can find it at: https://github.com/ctrlpvim/ctrlp.vim
Jump between last two open files
This is a huge timesaver. You should setup a quick shortcut for switching between last two open buffers. This is often the most used switch after all. I've mapped <leader><leader>
for this action. The following config makes the magic work:
nnoremap <leader><leader> <c-^>
Unfortunately this does not directly work in VSCode, so I've created a VSCode plugin to enable this same behaviour. The plugin provides a keyboard shortcut to jump between the last two open files. You can find the plugin here: https://marketplace.visualstudio.com/items?itemName=wingmen.alternator
Jump between related files
Often you have files that are related and you want to hop between them quikcly. Some common examples are header and source files and model/view/controller -files.
For this to work, you need to add the plugin called Projectionist and setup some patterns that define what should be the alternate files. After that you can jump to an alternative file with :A
or open the alternate in a new split for example :AV
. The plugin can also create the alternate file when it's missing - powerful stuff.
Open all certain type of files in project
When you need to open all files of a certain type in the project, you can do this:
:args ./*.html
Re-open current file
Sometimes Vim might not reload the file when it detects changes or you might accidentally cancel reloading. An easy way to get the latest version of the current file is to just re-open current file with the edit command. If you don't pass a file to the command it will default to the current file and hence you can do the following:
:edit!
Snippets
Every selfrespecting 1000x coder needs their own secret repo of snippets and a fast way to drop them into the code.
Neocomplete
Neocomplete is a nice plugin to use handy snippets in Vim. The usage is pretty simple. You expand the snippet with c + k
, hit tab for the next field in the snippet until finished.
CTAGS for easy jumping
You need CTAGS installed on your system for this trick. With CTAGS and a bit of hackery you can easily jump from a html DIVs class name to the CSS or SCSS definition of that class. For similar jumping around from function and function definition JavaScript you could use Tern.
-
Install Exuberant CTAGS with
brew install ctags
or however you install stuff on your system -
You need to add some configs to your CTAGS configuration located at
~/.ctags
.
--langdef=css --langmap=css:.css --regex-css=/^[ \t]*\.([A-Za-z0-9_-]+)/.\1/c,class,classes/ --regex-css=/^[ \t]*#([A-Za-z0-9_-]+)/#\1/i,id,ids/ --regex-css=/^[ \t]*(([A-Za-z0-9_-]+[ \t\n,]+)+)\{/\1/t,tag,tags/ --regex-css=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/m,media,medias/
--langdef=scss --langmap=scss:.scss --regex-scss=/^[ \t]*\.([A-Za-z0-9_-]+)/.\1/c,class,classes/ --regex-scss=/^[ \t]*#([A-Za-z0-9_-]+)/#\1/i,id,ids/ --regex-scss=/^[ \t]*(([A-Za-z0-9_-]+[ \t\n,]+)+)\{/\1/t,tag,tags/ --regex-scss=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/m,media,medias/ --regex-scss=/^[ \t]*\$([A-Za-z0-9_-]+)/\$\1/v,var,variables/
--recurse=yes --exclude=.git --exclude=vendor/* --exclude=node_modules/* --exclude=db/* --exclude=log/* --exclude=tmp/*
- You might want to add "tags" to your .gitignore -file(s).
Now you can index your (S)CSS with :!ctags -R .
. And after that jumping around is a matter of :tag /myClass
.
Sources:
- https://gist.github.com/dreki/da853aeb4d80c03a4448
- http://stackoverflow.com/questions/12833189/jump-to-css-selector-in-a-css-file-from-the-html-file-in-vim-using-a-single-keys/12924218#12924218
Modifying text fast
Where Vim really shines is blazing fast modifications to existing text.
Changing between/inside
Change text quickly between quotes for example.
ci"
(Change Inside ")
Replace text between characters from the paste buffer.
vi"p
(Visual Inside " Paste)
This works for HTML tags or paragraphs too. For example you can select all text between tags by placing your cursor on one of the tags and then hitting.
vit
(Visual Inside Tag)
vip
(Visual Inside Paragrahp)
You can also insted of i
use a
for all of the above examples where Vim will also include the surrounding quote or tag into the selection. When the seletion is active, you can hit o
to change cursor position between the start and the end of the selections.
Increment & decrement numbers
You can use ctlr+a
to increment and ctrl+x
to decrement numbers in normal mode when the cursor is inside the number.
The surround plugin
Change the surrounding double quotes (or any character) to single quotes.
cs"'
(Change Surrounding " to ')
To surround a visual selection with parentheses press:
S(
(Surround with ( )
Surround a word with quotes.
csw'
( Change Surroundings of Word to ')
Search & replace without having to escape special characters
This trick comes in hand when you want to do simple text replacement without any fancy regexp magic. Saves quite a few keystrokes.
:%sno/search_string/replace_string/g
Replace all occurrences of the word under cursor
This is super useful for quickly refactoring some bad variable names and is similar to the above but way faster to execute.
- In normal mode press
*
to search for all occurences of the word under cursor - Hit
:%s//newVarName/
to quickly replace all the matches
You might require a g
in the end depending on your gdefault
configuration.
Search and replace in all open files
There are two ways of doing this that I know of. Either
:argdo %s/pattern/replace/gce
or
:bufdo %s/pattern/replace/gce | update
should do the trick!
Run a normal mode command in insert mode
While in insert mode you can press ctrl + o
which let's you run one normal mode command and it pops you back to insert mode. Super handy for deleting a word or jumping the cursor location quickly. Just do ctrl + o + dw
and the pesky word is gone and you're still in insert mode.
Miscellaneous tips & tricks
Easy way to insert non-standard characters
If you work with nordic languages but have an american keyboard layout it can be tough to get those special characteres such as ä,ö,ü etc. Vim has a special digraph mode that makes easy to use these.
For example, in insert mode pressing ctrl + k
followed by u:
prints out ü
. This is super handy. You can hit :dig
to see all the available digrahps for easy reference.
Easy debugging with console.logs in JavaScript
Inspired by the Turbo Console Log plugin for VS Code here's a short snippet for your vimrc to enable inserting console logs with ease. It is not quite as smart as TCL but at least it adds the line number in. :)
In your Vim config add the following ugly line:
nnoremap gll oconsole.log("LINE: <C-r>=line('.')<Esc>","")<Esc>F"i
Then hit gll
to produce console.log("LINE: line","")
.
Filename hints in insert mode
Write any path in the editor in insert mode and hit ctrl + x + f
and Vim will suggest files in that folder. Makes it easy to find those file names.
Check the word count
The following command shows info on current cursor position in the currently open buffer - including the word count.
press g and then ctrl + g
Reload config without closing
In case you do not want to loose your session when modifying your init.vim
. Here's how you can reload the config without closing the editor:
:so %
- if you're currently editing the init.vim
file
:so $MYVIMRC
- if you're not editing the config file itself
Vim splits cheatsheet
Splits are handy when working with multiple source code files, so it's important to be able to quickly create, navigate, and delete splits.
:vsp
or ctrl + w + v
- to create vertical split
:sp
or ctrl + w + s
- to create horizontal split
ctrl + w + HJKL
- to move between splits
ctrl + w + HJKL
- to move splits around
ctrl + w + w
- to jump to next split (loops around)
ctrl + w + c
- close current split
ctrl + w + =
- equalize splits
Change line endings
Files created on WIN/DOS machines have different line endings than files created on Unix based machines. DOS uses ("\r\n") and Unix uses just ("\n"). With Vim you can easily change between line endings.
:set ff=dos
:set ff=unix
Save as
When you want to create a new file by starting with a copy of the existing one. You can save the currently open buffer as a new file by doing this:
:sav newfile.js
Repeat or reverse movements
Some movement commands can be repeated with ; and reversed with ,. The movements you can repeat/reverse are F, f, T, and t.
Navigating serach results forward and backwards can be achieved with n
and N
.
Overwrite text from copy/paste register
Often times you have something on your clipboard and you want to overwrite a word or a sentence with the text. Doing this in Vim can be a hassle as when you delete the previous entry it replaces the latest register value.
Easy way around this is to use visual selection and then paste over that. E.g. you want to replace a word with another from the latest register.
vep
Understanding registers
Vim has a register system that stores things you yank or delete/change from the document. Register 0
holds always the last yank and 1
holds the last delete or change, if you don't specify a specific register where you want to save things. Special default register "
always holds content of the last operation be it yank, delete or change.
To define a specific register you can do "ryy
for example to yank stuff to register r
. To paste from a specific register "rp
.
To paste last yanked content you can do just p
. But if you instead yank something and then delete something p
would paste in the deleted text. So to actually paste the yanked texs you can can use "0p
.
Editing multiple lines at once
If you need to edit multiple lines of text at once, you can use the block wise visual mode. To enter the mode hit CTRL + v
. Now you can select block areas and perform operations on them. Supported operations are insert before (I), append (A), change (c) and various other operators.
Changing the working dir
Sometimes you might open a file deeper inside your project directly from the command line instead of opening Vim in the project root. Vim sets the directory where the opened file is as the working directory. This can limit the visibility of files you can jump to quickly using ctrl + p
. For example to move the working directory two levels up you can just do: :cd ../..
Plugins
This section lists a bunch of the most useful plugins for Vim. Some of them were already mentioned in the above tips and tricks. These work well with Neovim. Onivim2 does not support most of these yet, but then again it offers some of the features out of the box or via VSCodde plugins.
Colorizer
Show CSS colors in the editor for those of us who don't yet see hex or rgb as colors.
https://github.com/lilydjwg/colorizer
Ctrlp
Hit ctrl + p
to open files and buffers quickly with a powerful fuzzy finder.
https://github.com/ctrlpvim/ctrlp.vim
Editorconfig
Make Vim respect the .editorconfig
file.
https://github.com/editorconfig/editorconfig-vim
Emmet
Write HTML really, really fast.
https://github.com/mattn/emmet-vim
Indent object
Adds a text object to manipulate stuff by indentation e.g. viid
to delete everything in the current indent. This is very handy for example when working on Python.
https://github.com/michaeljsmith/vim-indent-object
Gitgutter
Show GIT info in the gutter and manipulate hunks directly from your editor. You can also move between changes in the file by using [c
and ]c
. Staging a hunk is as easy as hitting <leader>hs
when your cursor is in it.
For more complex usage view the plugin docs.
https://github.com/airblade/vim-gitgutter
Lexical
Building on Vim’s spell-check and thesaurus/dictionary completion\
https://github.com/reedes/vim-lexical
Multiple cursors
More powerful way of having multiple cursors in your Vim.
https://github.com/terryma/vim-multiple-cursors
Projectionist
Define alternative files with patterns and very quickly jump between or open them in a new split. The plugin also can create the missing alternative file.
https://github.com/tpope/vim-projectionist
Repeat
Make repeating commands with .
work as intended.
https://github.com/tpope/vim-repeat
Sort motion
Adds a motion to sort selections of texts.
https://github.com/christoomey/vim-sort-motion
Surround
Manipulate surroundings like a boss e.g. cs"'
to change the surrounding "
--> '
.
https://github.com/tpope/vim-surround
Syntastic
Teaches Vim to use external syntax checkers. To have it check JS, just install JSHint globally through NPM.
npm install jshint -g
https://github.com/vim-syntastic/syntastic
Tcomment
Handle commeting in a sane way.
https://github.com/tomtom/tcomment_vim
Wildfire: text objects
Install wildfire plugin to enable quick selection of text objects in normal mode by pressing enter. Press enter a second time and it chooses one greater text object.
https://github.com/gcmt/wildfire.vim
Wordy
Uncover usage problems in your writing e.g. check text for business jargon.
https://github.com/reedes/vim-wordy
Vim configuration
In this section, you will find some interesting configurations to make life with Vim better.
Hybrid line numbers
Math is hard, so setting relative line numbers stops you from having to calculate the numbers for jumps and other operations. But it's still important to see the current line number. So using the below you will get a hybrid solution that is the best of the both worlds. The current line will show the absolute line number and the line numbers up and down show the relative numbers for easy jumps/operations.
:set number relativenumber
Make navigating splits easier
I tend to work in splits and it's important to make it easy to move around the splits. The below configurations make it slightly easier to navigate splits.
nnoremap <c-j> <c-w>j
nnoremap <c-k> <c-w>k
nnoremap <c-h> <c-w>h
nnoremap <c-l> <c-w>l
Higlight yanked area
Neovim comes with a built in function to higlight yanked area, which makes it nice and easy to see what you just yanked. You can enable it with following the following config:
vim.api.nvim_create_autocmd('TextYankPost', { group = vim.api.nvim_create_augroup('highlight_yank', {}), desc = 'Hightlight selection on yank', pattern = '*', callback = function() vim.highlight.on_yank { higroup = 'IncSearch', timeout = 200 } end, })