← back to latest

Do arithmetic without leaving insert mode

INSERT<C-r>=Do arithmetic without leaving insert mode

anatomy

<C-r>
In insert mode, insert the contents of a register. Vim waits for you to name which one.
=
The expression register. Instead of holding stored text, it opens a small command line with a = prompt where you type a Vim expression.
60*60*24
The expression itself. Any Vim expression works here: arithmetic, string functions, variables, option values.
<CR>
Evaluate the expression and insert the result at the cursor. You land back in insert mode, right after the inserted text.

In the buffer

Before, in insert mode at the end of line 3:

import requests

CACHE_TTL = 
            ^
MAX_UPLOAD = 25

After typing <C-r>=, then 60*60*24, then <CR>:

import requests

CACHE_TTL = 86400
                 ^
MAX_UPLOAD = 25

The = prompt appeared at the bottom of the screen, took the expression, and put the result into the buffer at the cursor. You are still in insert mode, so the next thing you type continues the line.

When you would reach for it

You are typing a config value, a timeout, a buffer size, or a column width, and the number you need is a product of things you know rather than a thing you know. Seconds in a day, 25 megabytes in bytes, 1.5 times a base spacing. Leaving the editor for a calculator breaks the line you were writing. <C-r>= turns the bottom of the screen into that calculator and drops the answer where the cursor already is.

Gotchas

  • Arithmetic between integers stays integer. 10/4 inserts 2, not 2.5. Make one side a float with 10/4.0 to get the fraction.
  • Floats come out with six decimal places by default: 1/3.0 inserts 0.333333. Wrap it in printf() to control the format, as in printf("%.2f", 1/3.0), which inserts 0.33.
  • A List result goes in one item per line. [1,2] inserts 1, a line break, 2, and another line break, which surprises you if you expected [1, 2] on one line. Use string([1,2]) to get the literal text.
  • Pressing <Esc> at the = prompt cancels and returns you to insert mode with nothing inserted. Pressing <CR> on an empty prompt does the opposite of what you might expect: it reuses the previous expression. The = prompt also keeps its own history, so <Up> recalls earlier expressions.

Variants

<C-r>=strftime("%Y-%m-%d")<CR>

Inserts today’s date. Any built-in function works, so the expression register doubles as a snippet engine for small generated values.

"=6*7<CR>p

The same register from normal mode. "= opens the prompt, <CR> evaluates, and p pastes the result, 42, after the cursor.

:put =range(8080,8083)

Puts each number on its own line below the current line: 8080 through 8083. Because a List result becomes one line per item, :put = is a quick way to generate a numbered column.

lineage

The expression register arrived in Vim 5.0 in 1998, the same release that gave Vim its scripting language. Once there was an expression evaluator, exposing it as a register meant every command that reads a register, from p in normal mode to Ctrl-r in insert mode, could also read a computed value.

-- INSERT --vim-hacks.com021-021-do-arithmetic-without-leaving-insert-mode.html
utf-81,1All