Simple calculations with Vim's expression register
The expression register lets us evaluate a snippet of Vimscript code. This is handy when you need to perform simple calculations and insert the result into the document.
I’ll be running my Core Vim Class online on Thursday, December 5th. Tickets cost $255, but you can get the earlybird discount of $230 if you buy yours before November 29th. The price includes an exclusive screencast that summarises the material from the class.
From Insert mode, pressing
<C-r>= drops us into the expression register. We can enter any Vimscript expression. On pressing Enter, Vim evaluates the expression, and inserts the result into the document. For example, if we entered
2*21 into the expression register, Vim would insert
42 into the document.
In general, we can think of Vim’s registers as being variables that hold a string of text, but the expression register is different. This register behaves like a scratchpad that lets us evaluate Vimscript code. If the return value is a string, or if it can be coerced to a string, then Vim will use the result just as though it had been retrieved from any other register.
When we dial up the expression register, Vim drops us into Commandline mode. Usually, Vim’s command-line uses a colon as the prompt, which lets us run an Ex command. But in this context the prompt is an equals sign, which tells us we’re in the expression register. All of the functionality that is usually present in Commandline mode is available to us in the expression register, including the
Creating a mapping to perform calculations
In the video, I created a mapping on-the-fly to speed up the task of inserting the results of calculations into the document. Here’s the mapping:
nnoremap Q 0yt=A<C-r>=<C-r>"<CR><Esc>
This sets up the
Q key to perform all of the following work:
||move to the start of the line|
||yank from cursor position up to (but not including) the `=` sign|
||move to end of line and switch to Insert mode|
||dial up the expression register|
||paste the contents of the default register into the command line|
||evaluate the expression register and insert the result into the document|
||return to Normal mode|
This mapping is specialized for one particular task, so I wouldn’t save it in my vimrc. Instead, I would just create this macro on-the-fly as a throwaway helper to get me through the task at hand.
This is the final command that I demonstrated:
You can read this as follows:
:'<,'>for each selected line
normal Qexecute the Normal mode
Qcommand, using any user-defined mappings
For a discussion of the
:normal! commands, check out chapter 29 of Steve Losh’s Learn Vimscript the Hard Way. Steve suggests always using
:normal! and avoiding
:normal, which is good advice when writing a script, but it doesn’t apply in this situation. Think about it!