Time for some self-VIMprovement! As you might know, the thoughtbot crew uses Vim a lot (one, two, and three).
I sit next to Ben and Mike, two great Vim users, and I learned a lot just from being around them. I’ve said before that I could probably sell our conversations as an advanced Vim book. Movements are just one of the concepts that has improved my Vimming. Note that in my Vim examples, I’m performing each motion with my cursor on the beginning of the phrase.
Movements are a key part of using Vim effectively. Vim commands function as simple phrases, e.g. “change this word” or “delete until end of line”. I knew the verbs, but didn’t know how to complete the phrase: “dd” (delete current line) and “yy” (yank current line) were my mainstays. To delete 4 characters, I’d hit “x” 4 times in a row. Turns out there’s a much better way: motions!
You see, “d” and “y” are the verbs: “delete” and “yank”. They need to know what to delete or yank. And that’s where motions come in. They offer fine-grained control over verbs so you can yank a single word, or an entire
paragraph (or method block).
“t” and “f” are two of my most frequently used motions. “t” means “‘til” and
performs the action ‘til a given character. So “dtl” turns “hi darling”
into “ling”. “f” can be thought of as “first occurrence”. It deletes up to
and including a given character, so one character more than “t”. So “dfl” turns
“hi darling” into “ing”. “T” and “F” do the same thing as “t” and “f”,
except backwards. So “dTa” deletes backwards til “a”, while “dFa” deletes
backwards up to and including the “a”.
I recently learned about the even more useful “i” and “a” motions. “i” means “inside” and unsurprisingly it moves inside characters. For example, given “(hello world)”, “di(” from anywhere inside the parentheses deletes inside the parentheses and gives you “()”. It erases the text inside the parentheses, but not the parentheses themselves.
“a” means “around” and it’s kind of like the “f” to “i“‘s “t”, in that “a” includes a bit more characters than “i” does. So “da(” changes “(hello world)” into “” (an empty string). To delete a paragraph, use dap. In code, a paragraph means a method definition - so you can delete entire method definitions with three keys!
For more on motions, check out the official documentation: :help navigation. It can tell you about the motions (like a) as well as the “noun”, like the p in dap.
And don’t forget about the first Boston Vim Meetup on October 24th!
Mike just schooled us with some “vim by example.” His use case:
I want to delete the line “Did not get valid lat and long”, the line before it, and the line after it, everywhere in this text file, from within vim.
Here’s how he did it:
:g/Did not get valid lat and long/-,/Did not get valid lat and long/+ d
How’s it work?
:g is the global command:
:[range]g/<pattern>/cmd
This executes a command on the specified range (defaults to whole file) for each line matching the pattern. It also supports this format:
:g/<pattern1>/,/<pattern2>/d
So, :g/<p1>/,/<p2>/d deletes inclusively from /<p1>/ to /<p2>/.
Additionally, /<p>/- and /<p>/+ mean “the line before and after the match”.
Put it all together and “voilà.” Thanks, Mike.
A recent straw poll of text editor fonts at thoughtbot found these results. Not all thoughtbot precincts have reported in. Perhaps you’d like to explore some new font options for those walls of text you stare at for 8+ hours daily.
Some links to these fonts:
I recently switched to MacVim for front-end development. Coming from Panic Software’s Coda, I was feeling extremely limited by my text editors capabilities. Two weeks into Vim, this designer has discovered the following:
Textmate/Coda/etc. are like the automatic transmission Volkswagen Jetta of text editors. The VW Jetta has just enough horsepower for daily tasks, some flexibility, but most of all it’s easy enough for most drivers to jump into and drive away.
Vim is like the manual transmission Lamborghini Aventador—the pinnacle of supercars. You can’t just jump into the Aventador and drive away, you have to learn how to control the 700hp, 6.5 liter V12 engine—quite a powerful beast. Learn the intricacies of the clutch, get used to the touch sensitive carbon-ceramic brakes. The tight steering and low suspension are a hell of a change from a VW Jetta.
I’ve been lucky to have expert Vim users around to teach me tips, tricks, and share their general knowledge on its power.
Have you tamed a supercar?
Many at thoughtbot run their editor+shell combos inside of tmux. Some remote pair program with ssh, vim, and tmux.
Getting started with tmux, these are the questions I’ve had.
Install tmux, read the documentation, and fire it up.
brew install tmux
man tmux
tmux -u
Yes. We have these lines in tmux.conf in thoughtbot/dotfiles:
# improve colors
set -g default-terminal "screen-256color"
# soften status bar color from harsh green to light gray
set -g status-bg '#666666'
set -g status-fg '#aaaaaa'
# remove administrative debris (session name, hostname, time) in status bar
set -g status-left ''
set -g status-right ''
The “prefix” namespaces tmux commands. By default it is Ctrl+b. In our tmux.conf in thoughtbot/dotfiles, we bound it to Ctrl+a:
# act like GNU screen
unbind C-b
set -g prefix C-a
This was non-obvious to me.
Enter “copy mode”:
prefix+[
Use vim bindings to page up and down:
Ctrl+b
Ctrl+f
Add this to your tmux.conf:
# enable copy-paste http://goo.gl/DN82E
# enable RubyMotion http://goo.gl/WDlCy
set -g default-command "reattach-to-user-namespace -l zsh"
Add this to your tmux.conf to use vim’s home-row keys for movement between windows and panes:
# act like vim
setw -g mode-keys vi
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind-key -r C-h select-window -t :-
bind-key -r C-l select-window -t :+
One day I might work on Airbrake. Another day, a client project. I’d like to name my tmux sessions so I can leave one, drop into another, and go back to the original with all my state maintained (files still open in my editor, console/logs I want open, etc.).
Create a new session:
tmux new -s airbrake
Attach to a session:
tmux attach -t airbrake
Create a window:
prefix c
Move to window 1:
prefix 1
Move to window 2:
prefix 2
Kill a window:
prefix x
I believe in setting my mouse free but it takes time for muscle memory to make this fast.
~/.tmux.conf?After editing ~/.tmux.conf, execute this from a shell:
tmux source-file ~/.tmux.conf
I’ve had a love-hate relationship with tmux in my first week using it, but the brief moments of flow I’ve experienced so far are enough to keep trying it.
Give tmux a shot and if you have any other tips, I’d love to hear them.
Written by Dan Croak.