Erik Ramsgaard Wognsen

Thoughts & technology

Entering Dates and Times in Vim

As a young Windows user, I learned that if you write .LOG as the first line of a text file, then each time you open it in Notepad, it appends the current time and date to the file. That was pretty cool. And useful for logging things, as .LOG implies. Later I became a Vim user and started enjoying all the customization I can do to my editor. Or perhaps I became a Vim user because I enjoy customizing! Either way, I like my date and time shortcuts in Vim. For example:

noremap! <expr> ,t strftime("%H:%M")

This means: Map the key sequence ,t (comma followed by ’t’) to the result of the expression strftime("%H:%M") in the insert and command line modes. So if I write “The package arrived ,t”, what I will see is “The package arrived 13:43”, or whatever the time was. I use capital T for further precision (seconds), ,d to insert the date (of course in ISO 8601 format), and ,l to insert date and time together (‘l’ for log, as with .LOG):

noremap! <expr> ,T strftime("%H:%M:%S")
noremap! <expr> ,d strftime("%Y-%m-%d")
noremap! <expr> ,l strftime("%Y-%m-%d %H:%M")

There are only so many shortcuts you can make with the Control and Alt keys, but if you use key sequences, you have many more. I have chosen comma as a “leader” key because I rarely write it without following it by a space. In case I do want to write literally “,t” without a space, I have to type “,,t”, where the double comma is a command to insert a single comma:

noremap! ,, ,

The “nore” part of “noremap” means “no remapping”, i.e., don’t use the output of this mapping as input to another mapping. If it did remap, the one comma produced here would be interpreted as the start of one of the mappings starting with comma, including itself.

I use these functions daily, for example at work, where I keep a log of which tasks I start when. I also use it a lot with todotxt when writing due dates or threshold dates. Finally, I added a mapping to insert the first of the next month.

noremap! <expr> ,D
          \ strftime("%Y") + strftime("%m") / 12 . "-" .
          \ repeat('0', 2-len((strftime("%m") + 1) % 12)) .
          \ (strftime("%m") + 1) % 12 .
          \ "-01"

Typing “,D” today would yield 2016-05-01, for example.

Entered times and dates can also be manipulated with Vim’s Ctrl-A and Ctrl-X increment and decrement commands. Want to add two weeks? Type 14 followed by Ctrl-X to add 14 days.

My duplicate increment line mappings also come in handy:

nnoremap <silent>       <F2>  @='yyp<c-v><c-a>'<cr>
nnoremap <silent>       <F3>  @='yypE<c-v><c-x>'<cr>

If I write “2016-04-20 Plan:” followed by 10 and then the F3 key, I immediately have:

2016-04-20 Plan:
2016-04-21 Plan:
2016-04-22 Plan:
2016-04-23 Plan:
2016-04-24 Plan:
2016-04-25 Plan:
2016-04-26 Plan:
2016-04-27 Plan:
2016-04-28 Plan:
2016-04-29 Plan:
2016-04-30 Plan:

Actually, Vim just thinks it’s decrementing the integer -19 to -20 and so on, but Tim Pope’s speeddating.vim plugin adds date and time awareness, so typing Ctrl-A on 2016-04-30 would result in 2016-05-01 and not 2016-04-31. Happy Vimming!