alexharv074.github.io

My blog

View on GitHub
1 April 2019

My Vim Cookbook

by Alex Harvey

This is a list of my favourite productivity-enhancing vim tricks.

Table of contents

  1. Preface
  2. Cookbook

Preface

Some info that is useful to know while reading all of the Vim tricks below.

How to enter Vim visual mode

If you don’t know how to enter visual mode in vim. E.g. select the lines foo and baz in the following:

{
  "Foo": "Bar",
  "Baz": "Qux"
}

Move the cursor to line 2. SHIFT-V. j (to move down one line). :. Vim enters command mode with the beginning of a command set to :'<,'>. Now enter the rest of the command e.g. :'<,'>s/: /:/ (remove the space after the colons).

See the Vim manual.

A note about tab-completion in commands

Be aware in all of these tips that Bash tab-completion works inside the Vim command mode. E.g. suppose you are using the pbcopy tip. You can go into visual mode, select the text and then:

:'<,'> ! pbc<TAB>

It will auto-complete as:

:'<,'> ! pbcopy

Cookbook

Align equals signs

You have some code like this:

$ = jQuery.sub()
Survey = App.Survey
Sidebar = App.Sidebar
Main = App.Main

And you want the equals signs to align like this:

$       = jQuery.sub()
Survey  = App.Survey
Sidebar = App.Sidebar
Main    = App.Main

Enter visual mode and then:

:'<,'> ! column -t | sed -e 's/ = /=/'

My answer on Stack Overflow.

Auto-indent JSON code using jq

You are editing a badly indented JSON document. Vim’s built-in auto-indent feature (=) isn’t adequate to fully correct the indenting. You want to use jq . instead.

Indent the whole file:

:% ! jq .

You want a different indentation e.g. 4 spaces instead of 2:

:% ! jq --indent 4 .

See the jq manual for other options.

Auto-indent code using visual mode and equals

You have some code in any language that’s not indented properly, e.g.

while true ; do
echo "hello world"
done

And you want it indented like this:

while true ; do
  echo "hello world"
done

Enter visual mode and select the block of code. Press =.

Bulk edit files using Vimscript

You have some similar files e.g. JSON files and they all need to be edited in a similar way. You thought about writing a sed, AWK, or Perl one-liner and can’t think of a way. But the changes can be specified as a sequence of repeatable steps inside Vim.

Suppose you have this content in a file:

aaa
bbb
ccc
bbb
ccc
eee

You need to add a missing line ddd after the second occurrence of ccc. Suppose you also need to make this change in all files matching an extended glob pattern **/*.txt.

In a file /tmp/script.vim create the following Vimscript:

function! AddLine()
  call search("bbb")
  call search("bbb")
  let l:foundline = search("ccc")
  call append(l:foundline, "ddd")
  wq!
endfunction

Then execute that script on all of your files:

▶ for i in **/*.txt ; do vim -u /tmp/script.vim -c 'call AddLine()' $i ; done

In a file /tmp/script.vim create the following Vimscript:

function! AddLine()
  normal /bbb^Mn/ccc^Moddd^[
  wq!
endfunction

Note that ^M is a newline and ^[ is ESC. To enter these press CTRL-v then CTRL-M (^M) and CTRL-v then ESC (^[).

The -u option tells Vim to load from a custom vimrc file and -c tells vim to execute that command on startup. The function AddLine() meanwhile calls wq! ensuring that vim starts, runs the function, and then saves and exits. This is repeated for each file in the for loop.

In the normal mode version of the function, the characters following the normal command are the literal keystrokes you would press inside Vim, in order.

Convert a space separated string to newline separated string

You have text in a file like:

foo bar baz

You want it changed to:

foo
bar
baz

Select the line or lines in visual mode then:

:'<,'>s/ /^M/g

Convert to upper or lower case

You have variables or keywords in lower or upper case and you want the case changed. For example, you have a variable foobar and you want it changed to FOOBAR.

:%s/\(foobar\)/\U\1/

The following commands from GNU sed also work in Vim:

code description
\L Turn the replacement to lowercase until a \U or \E is found.
\l Turn the next character to lowercase.
\U Turn the replacement to uppercase until a \L or \E is found.
\u Turn the next character to uppercase.
\E Stop case conversion started by \L or \U.

Copy some lines to the clipboard

You have some lines in a file and you want them moved to the clipboard. For some reason, selecting them and doing a copy is too hard or not possible. You’d rather get them in visual mode.

Select the lines in visual mode and then:

:'<,'> ! pbcopy

Delete lines matching

You have a bunch of lines matching a pattern PATTERN in a file. You want them all deleted.

:%g/PATTERN/d

Fix inconsistent cases

You have variables, functions, etc in a file and some of them are in the incorrect case. Suppose the variable should be FooBar everywhere but has been inserted as variations of Foobar, foobar etc.

:%s/\cfoobar/FooBar/gc

Use \c to search for a string case-insensitive in vim regular expressions.

From this Stack Overflow post.

Move ahead by n characters

A command like sed fails with a message like:

gsed: -e expression #1, char 44: extra characters after command

Go to the start of the sed script, then <SPACE>44. The cursor will move ahead by 44 characters, traversing newlines.

Record a macro

You want to define a Vim Macro, to automate repeated steps within Vim.

Suppose you want a Macro to insert a Ruby debugging line:

require 'pry'; binding.pry

You want the Macro to be played back when you hit @a.

In normal mode:

qa

Vim displays that the Macro is recording. Now actually insert the text into the file. That is o to enter edit mode on the next line, type the Ruby code, and ESC to exit back to normal mode. Then press q to end recording.

To view the code of the Macro:

:reg a
"a   orequire 'pry'; binding.pry^M^[

To playback the Macro, @a.

Sort lines in a file

You have some lines in a file that you’d like ordered alphabetically, e.g.

---
Foo: Bar
Baz: Qux
  1. Use visual mode to select the lines foo and baz.
  2. Then:
:'<,'> ! sort

Just sort the entire file.

:% ! sort
tags: vim