Jan 23, 2009

Contexts in Vim

One of the things I really like about Vim is how I keep discovering more stuff all the time to help me write things faster.

There are several context-based commands in Vim which are not complete commands on their own, but when combined with a context they do something depending on the context you provide. For example, dw is the d command (for delete) and the context is w which means "go to the beginning of the next word", and the combination of the two means "delete to the beginning of the next word". I knew about this one for a while, and things like d$ which is "delete to the end of the line" (an easy mnemonic for remembering: think regexes). However not too long ago I discovered what t and f do. When you type ta where a is an arbitrary character, it moves you to the character before the next a in the current line. With fa it moves the cursor to the next a.

So I thought this was kinda cool, although at the time I figured the t command was pretty useless. But that was until I discovered that you can use these as contexts in combination with a context-based command. So going dt) means "delete everything up until the character before a )" which is extremely handy. No more going delete-delete-delete... You can also use T and F to go backwards, where t and f go forwards.

Then I started playing around more. One thing that always annoyed me about Vim was when I wanted to delete several lines. You can use dnd and it will delete n lines, and so I ended up having to count all the lines and then pressing the key. Really annoying. However the "go to line" command in Vim is nG which means "go to line n". This can be used as a context for a context based command. So if you type d20G, it means "delete all the lines between the one I am on and line 20, inclusive". This goes both directions too. Now we're talking productivity.

Heck, you can even go d/hello and it will delete everything between where you are and the next string in the file that matches "hello" will be deleted. Same goes for d?hello, except it goes backwards. And these are regexes by the way, so don't be afraid to stick fancier stuff in there. Although you might need to remember that u is "undo".

It never ceases to amaze me how much you can get done with so little.

PS: I only used the d command for this post, but you can also use y or c which are two other context-based commands. There might be more, I just can't remember them at the moment.


DarthDevilous said...

They're called "motions", and are described fully in the vim tutor and under ":help motion". The commands that use motions are referred to as "operators" (again, check the documentation).

Samus_ said...

:set number

Anonymous said...

If you liked dt(, you will love di(.

Try :he object-select

Anonymous said...

try [dvc]at and [dvc]it in html for working in/around tags, and aB/ab/iB/ib for in around () and {} pairs

Rob Britton said...

@DarthDevilous: Nice, thanks for the terminology! I didn't know the true name for these things so I made up words.

@Samus_: Yup I forgot to mention you'll need line numbers enabled. I've had on by default for so long that I forgot they're not the default :)

@Anonymouses: Whoa...things get even fancier. See why I like Vim?

Anonymous said...

D is easier than d$