Some Vim Movement Tips

  • Within-line character-based movement:
    • `h` and `l` move you left and right one character, respectively.
    • `fc` or `Fc` will take you forward to the next or back to the previous, respectively, occurrence of character “c` on the current line (e.g., `fp` will jump you forward to the next occurrence of “p” on the line, while `Fp` will jump you back to the previous occurrence of “p” on the line).
    • `tc` or `Tc` will take you forward to just before the next or back to just after the previous, respectively, occurrence of character “c` on the current line.
    • `;` or `,` repeats, forward or backward, respectively, the last `f`/`F`/`t`/`T` command.
    • `0` jumps you back to the beginning of the line while `$` jumps you to the end of the line.
    • `^` jumps you to the beginning of the first non-whitespace character on the current line.
    • Typing in a number and then typing `|` takes you to a column of that number on the current line.
  • Word-based movements:
    • `w` jumps you forward to the next “beginning-of-word”, while `b` jumps you back to the previous “beginning-of-word” (`W` and `B` for the corresponding WORD forms).
    • `e` jumps you forward to the next “end-of-word”, while `ge` jumps you back to the previous “end-of-word” (`E` and `gE` for corresponding WORD forms).
  • Line-based movements:
    • `j` and `k` move you down and up one line, respectively.
    • `+` and `-` move you to the first non-whitespace character on the next or previous line, respectively.
    • `G` jumps you to the last line of the buffer.
    • Typing in a number and then typing `G` takes you to line of that number.
    • `gg` jumps you the the first line of the buffer.
    • `+` moves you to the first non-blank character on the previous line (same effect as `k^`), while `-` moves you the the first non-blank character on the next line (same effect as `j^`).
    • `H` jumps you to the top (mnemonic=”home”) line of the current window.
    • `M` jumps you to the middle line of the current window.
    • `L` jumps you to the last line of the current window.
  • Page-based movements:
    • `<C-U>` moves you up half a page, while `<C-D>` moves you down by a half a page.
    • `<C-F>` moves you forward a full page, while `<C-B>` moves you backward a full page.
    • Go to a brace, bracket, parenthesis, quote, etc. Type `%` to jump to the matching brace, bracket, parenthesis, quote. etc.
  • Search-based movements:
    • With `:set incsearch` on, type `/` and starting typing in a search expression. As you type characters of the expression, you will be taken to the first location forward of the cursor position where that matching term appears in the buffer (use `?` to search backwards instead of forwards). Hit `<ENTER>` to start working from this new position, or `<ESC>` to cancel and return to your original location. To find the next matching expression, hit `<ENTER>` and then `N` to iterate through all matches in the buffer. If `:set wrapscan` is on, then the search will wrap around the buffer. If search highlighting is turned on (`:set hlsearch`), all occurrences of the expression will be highlighted.
    • Position the cursor over any word in an open, and (in normal mode, of course), type `*`. This will jump you to the next occurrence of the word under the buffer. If search highlighting is turned on (`:set hlsearch`), all occurrences of the word will be highlighted.
    • Now type `#`. This time, you will be taken back to the previous occurrence of the word under the cursor.
    • Typing `n` or `N` will jump to the next position in the buffer that matches the last-entered search expression (i.e., either through `/`, `?`, `*`, or `#`).
  • History-based movements:
    • “.` or `’.` will take you back to the last position or line, respectively, where you modified the file.
    • “^` or `’^` will take you back to the last position or line, respectively, where you left insert mode.
    • You can use `<C-O>` and `<C-I>` to take you backward and forward through these and other “jump” positions.
  • If you are editing source code, then:
    • `]m` takes you forward to the next “start of a method” (i.e., the beginning of the next method).
    • `[m` takes you back to the previous “start of a method” (i.e., the beginning of the current method if you are in the middle of one, or the beginning of the previous method if you are “in between” methods).
  • Window adjustment:
    • This is not a movement tip per se, but it is relevant in the sense that it changes the spatial relationship of the cursor with respect to the window: `zb`, `zt`, and `zz` scroll the screen to make the current line at the top, bottom, or middle, respectively.

Vim Regular Expression Special Characters: To Escape or Not To Escape

Vim‘s regular expression dialect is distinct from many of the other more popular ones out there today (and actually predates them).
One of the dialect differences that always leaves me fumbling has to do with which special characters need to be escaped.
Vim does have a special “very magic” mode (that is activated by “\v” in the regular expression) that makes thing very clean and simple in this regard: only letters, numbers and underscores are treated as literals without escaping.
But I have never got used to the habit of preceding my expressions with “\v“, though maybe I should.

In the mean time however, I thought I would put up a quick reference that lists all the special regular expression characters in the default “magic” mode Vim dialect, divided into those that do not need to be escaped vs. those that do.

Regular Expression Special Characters Not Requiring Escaping

The following special characters are interpreted as regular expression operators without escaping (escaping will result in them being intepreted as literals):

\ Escape next character (use “\\” for literal backslash).
^ Start-of-line (at start of pattern).
$ End-of-line.
. Matches any character.
* Matches 0 or more occurrences of the previous atom.
~ Matches last given substitute string.
[] Matches any of the characters given within the brackets.
[^] Matches any character not given within the brackets.
& In replacement pattern: insert the whole matched search pattern.

Regular Expression Special Characters Requiring Escaping

The following special characters are interpreted as regular expression operators only when escaped (otherwise they will be interpreted as literals):

\< Matches beginning of a word (left word break/boundary).
\> Matches end of a word (right word break/boundary).
\(...\) Grouping into an atom.
\| Separating alternatives.
\_. Matches any single character or end-of-line.
\+ 1 or more of the previous atom (greedy).
\= 0 or one of the previous atom (greedy).
\? 0 or one of the previous atom (greedy).
\{ Multi-item count match specification (greedy).

\{n,m} n to m occurrences of the preceding atom (as many as possible).
\{n} Exactly n occurrences of the preceding atom.
\{n,} At least n occurrences of the preceding atom (as many as possible).
\{,m} 0 to n occurrences of the preceding atom (as many as possible).
\{} 0 or more occurrences of the preceding atom (as many as possible).
\{- Multi-item count match specification (non-greedy).

\{-n,m} n to m occurrences of the preceding atom (as few as possible).
\{-n} Exactly n occurrences of the preceding atom.
\{-n,} At least n occurrences of the preceding atom (as few as possible).
\{-,m} 0 to n occurrences of the preceding atom (as few as possible).
\{-} 0 or more occurrences of the preceding atom (as few as possible).

The Power and Precision of Vim’s Text Objects: Efficent, Elegant, Awesome.

Vim’s text objects are not only a powerful, flexible and precise way to specify a region of text, but also intuitive and efficient.
They can be used with any command that can be combined with a motion (e.g., “d“, “y“, “v“, “r“), but in this post I will be using the “c” command (“change”) to illustrate them.

Imagine you were on a line looked like this, with the cursor on the letter “r” of the word “dry”:

print “Enter run mode (‘test’, ‘dry’, or ‘full’)”

Then, after typing “c” to start the “change” command, you can type “i” or “a” followed by another character to define a text object to which to apply the “change”.

Using “i” gives you the “inner” text object (i.e., a less-inclusive or non-greedy version that excludes the wrapping characters or delimiters) while “a” gives the full object (i.e., a more-inclusive or greedy version, that includes the wrapping characters or delimiters).

The third and final character of the command sequence gives the criteria by which the text object is defined.

This is typically the initial letter of the name of the object (e.g., “w” for “word”, “s” for “sentence”) or a character that delimits/wraps a region of text (e.g. a parenthesis for text in parentheses, a quote for quoted text, a curly brace for text in curly-braces).

For example:

  • Typing “ci'” will delete the word [dry], not including the quotes, and enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


    print “Enter run mode (‘test’, ‘ ‘, or ‘full’)”
  • Typing “ca'” will delete the word [‘dry’], including the quotes, and enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


    print “Enter run mode (‘test’,  , or ‘full’)”
  • Typing “ci(” or “ci)” will delete everything inside the parentheses, but not the parentheses themselves, and enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


    print “Enter run mode ( )”
  • Typing “ca(” or “ca)” will delete the everything inside the parentheses as well as the parentheses themselves, and then enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


    print “Enter run mode  
  • Typing “ci"” will delete everything inside the double-quotes, but not the double-quotes themselves, and enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


  • Typing “ca"” will delete everything inside the double-quotes, as well as the double-quotes themselves, and enter insert mode:


    print “Enter run mode (‘test’, ‘dry’, or ‘full’)”


<p>The idiom is naturally extended to many types of different delimiting characters in the most intuitive way possible (i.e., simply by specifying the delimiting character or first character of the name of the text object):

    <li>"<code>i{</code>" or "<code>i}</code>" selects curly-brace surrounded text, with the greedier versions being "<code>a{</code>" and "<code>a}</code>", respectively.
    <li>"<code>i[</code>" or "<code>i]</code>" selects square-bracket surrounded text, with the greedier versions being "<code>a[</code>" and "<code>a]</code>" respectively.
    <li>"<code>i'</code>" selects single-quote surrounded text, with the greedier version being "<code>a'</code>".
    <li>"<code>it</code>"  selects the text within the surrounding HTML/XML tag or container, with the greedier version being "<code>at</code>".
    <li>"<code>iw</code>"  selects the surrounding word, with the greedier version being "<code>aw</code>".
    <li>"<code>is</code>"  selects the surrounding sentence, with the greedier version being "<code>as</code>".
    <li>"<code>ip</code>"  selects the surrounding paragraph, with the greedier version being "<code>ap</code>".
    <li> etc.

Once you start using Vim's <a href="">text objects</a>, there really is no going back.
The power and precision they provide to specify regions of text to pass onto other Vim commands makes for an extremely efficient and elegant <i>modus operandi</i>, for which there simply is no equivalent in any other text editor.

For more information, please refer to the Vim documentation, either online, or by typing “:help text-objects” inside Vim.

Neat Bash Trick: Open Last Command for Editing in the Default Editor and then Execute on Saving/Exiting

This is pretty slick: enter “fc” in the shell and your last command opens up for editing in your default editor (as given by “$EDITOR“). Works perfectly with vi. The”$EDITOR” variable approach does not seem to work with BBEdit though, and you have to:

$ fc -e '/usr/bin/bbedit --wait'

With vi, “:cq” aborts execution of the command.

Managing and Munging Line Endings in Vim

If you have opened a file, and see a bunch “^M” or “^J” characters in it, chances are that for some reason Vim is confused as to the line-ending type.
You can force it to interpret the file with a specific line-ending by using the “++ff” argument and asking Vim to re-read the file using the “:e” command:

:e ++ff=unix
:e ++ff=mac
:e ++ff=dos

This will not actually change any characters in the file, just the way the file is interpreted.
If you want to resave the file with the new line-ending format, you can give the “++ff” argument to the “:w” command:

:w ++ff=unix
:w ++ff=mac
:w ++ff=dos

Alternatively, you can just set the line-ending format, and the file will be written out with the new line ending format the next time it is saved:

:set ff=unix
:set ff=mac
:set ff=dos

Filesystem Management with the Full Power of Vim

Just discovered vidir, a way to manipulate filenames inside your favorite text editor (better known as Vim).

Previously, I would use complex and cumbersome BASH constructs using “for;do;done”, “sed”, “awk” etc., coupled with the operation itself:

 $ for f in *.txt;  do mv $f $(echo $f | sed -e 's/foo\(\d\+\)_\(.*\)\.txt/bar_\1_blah_\2.txt/'); done

Which almost always involved a “pre-flight” dummy run to make sure the reg-ex’s were correct:

 $ for f in *.txt;  do echo mv $f $(echo $f | sed -e 's/foo\(\d\+\)_\(.*\)\.txt/bar_\1_blah_\2.txt/'); done

This approach works well enough, but apart from being a little cumbersome (especially if there is any fiddling to get the reg-ex’s right), is a little error-prone.

Now, the whole directory gets loaded up into the editor’s buffer (the “editor” being whatever ‘$EDITOR‘ is set to), for you to edit as you wish. When done, saving and exiting results in all the changes being applied to the directory. This allows you to bring the full power of regular expressions, line- and column-based selections etc., to bulk renaming and other operations. Best of all, you get to see the final set of proposed changes in your text editor before committing to the actual operation.

All of this can be rephrased as: ‘fantastic!

To get a dose of this filesystem management awesomeness in your world:

  1. Either clone the vidir repo or download a snapshot release from here.
  2. From inside the vidir directory:
  3. $ perl Makefile.PL
    $ make
    $ sudo make install

Execute Selected Lines of (Optionally) Marked-Up Python Code in a Vim Buffer

There are a number of solutions for executing Python code in your active buffer in Vim.
All of these expect the buffer lines to be well-formatted Python code, with correct indentation.
Many times, however, I am working on program or other documentation (in, for example reStructuredTex or Markdown format), and the code fragments that I want to execute have extra indentation or line leaders.

For example, a reStructuredText buffer might look like:

        How to Wuzzle the Wookie

        The :func:`foo` function can be used to wuzzle the wookie by::

            >>> import bar
            >>> fuzzlewuzzle ="the wookie")
            >>> for fuzz in fuzzlewuzzle:
            ...     if fuzz is
            ...          bar.wuzzle(fuzz)

While a Markdown buffer might have:

        ## How to Wuzzle the Wookie

        The ``foo`` function can be used to to wuzzle the wookie by:

            import bar
            fuzzlewuzzle ="the wookie")
            for fuzz in fuzzlewuzzle:
                if fuzz is

Simply passing the code lines in the above text to be evaluated in Python will not do: the extra decorators and indents required for embedding the code in the main document need to be dealt with.

Furthermore, many of the solutions that I could find (a) require Vim to have been built with Python enabled, and (b) use Vim’s internal Python to evaluate the lines.
The first seems like an unnecessary constraint, considering that native VimScript can handle the pre-processing quite well, while the second is problematical if there are external packages in your default system Python that the internal Vim Python does not have or if you prefer using the default system Python for whatever other reason.
Here I describe a pure-VimScript solution that handles the execution of optionally-marked-up visually-selected line ranges in your default system Python, and either shows the results in the command window or inserts the results in the current buffer.

Installation and Usage

Include the following code in your “~/.vimrc” or otherwise source it into your current Vim session.
Then select some lines of Python code and type “:EvalPy” to evaluate the lines in the default Python session and show the results in the command window, or “:EvalPy!” to evaluate the lines in the default Python session and insert the results in the current buffer.

Editing Remote Files With Your Local Vim Using the SCP Protocol

I love Vim!
It is so easy enough to edit a remote file with my local Vim through the Secure Copy protocol:

    $ vi scp://

However, I often find myself wishing that bash completion was available to expand/complete paths on the remote system.
Furthermore, when editing files outside of my home directory hierarchy, I have to remember to add an extra slash after the host name, e.g.:

    $ vi scp://

A solution is to write a custom wrapper function that takes scp-style remote file paths, converts them into Vim-style remote file paths, and then invokes Vim on them.
Then we can make use of the existing scp
bash completion for our wrapper function, and we get the side-benefit of not needing to juggle two different remote file path syntaxes.

The following code implements this solution. The function “vscp” is the wrapper function, while the line “complete -F _scp $nospace vscp” applies the “scp” completion function to the wrapper function. The code below needs to be sourced into your shell or placed into “~/.bashrc“.The “scp” completion function, “_scp() should already be defined if you have bash completion installed and sourced (and you should!), but just in case, it is conditionally defined here.

#! /bin/bash

function vscp() {
    if [[ -z $1 ]]
        echo "usage: vscp [[user@]host1:]file1 ... [[user@]host2:]file2"
    declare -a targs=()
    for iarg in $@
        targ="scp://$(echo $iarg | sed -e 's@:/@//@' | sed -e 's@:@/@')"
        targs=("${targs[@]}" $targ)
    vi ${targs[@]}

## Following function is from ".bash_completion". If it
## is not already defined/sourced, we define it here.
if [[ !$(declare -F _scp) ]]
        local cur userhost path

        local IFS=$'\t\n'

        _expand || return 0

        if [[ "$cur" == *:* ]]; then
            # remove backslash escape from :
            # unescape spaces
            path=${path//\\\\\\\\ / }
            if [ -z "$path" ]; then
                # default to home dir of specified user on remote host
                path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
            # escape spaces; remove executables, aliases, pipes and sockets;
            # add space at end of file names
            COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
                    command ls -aF1d "$path*" 2>/dev/null | \
                    sed -e 's/[][(){}<>",:;^&!$&=?`|\ ]/\\\\\\&/g' \
                    -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' ) )
            return 0

        [[ "$cur" == */* ]] || _known_hosts -c -a
            COMPREPLY=( ${COMPREPLY[@]} $( command ls -aF1d $cur* \
                    2>/dev/null | sed \
                    -e 's/[][(){}<>",:;^&!$&=?`|\ ]/\\&/g' \
                    -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' ) )
        return 0
complete -F _scp -o nospace vscp

The code is obviously pretty basic, and can be elaborated further (e.g., by passing custom options/arguments to Vim).


p>Once you have a remote file open in Vim, the command “:E” or “:Explorer” will open up Vim’s native remote filesystem browser. Once you have set up the function presented above, you can also invoke Vim’s native remote filesystem browser by passing in a directory path as an argument, being sure to include the trailing backslash:

    $ vscp

Of course, the obvious alternative to all of this is to login to the remote system and just edit the files through the ssh connection. Vim is, after all, ubiquitious and installed by default on most (decent) operating systems (except for the one that shall not be named). And, to be honest, this is what I do most of the time when making minor edits or tweaks.
However, there still are some benefits to using my local Vim versus a remote one over an ssh connection on a terminal emulator, especially when I have a major editing/debugging session: speed/responsiveness, and much nicer syntax coloration (16 million colors vs. the 16 colors to which I am limited using OS X’s Terminal). These may seem like minor advantages, but both make a huge difference when trawling through hundreds of lines of code!

Buffersaurus – A Vim Plugin for Searching and Indexing Across Buffers


Buffersaurus is a Vim plugin for searching and indexing the contents of buffers
for regular expression patterns or collections of regular expression patterns.
Results are displayed in separate buffer, and can be (optionally) viewed with
user-specifiable lines of context (i.e., a number of lines before and/or after
the line matching the search pattern) or filtered for specific patterns.

Global commands provided include (among others):

:Bsgrep[!] {pattern}
Search all buffers (or just current buffer if “!” given) for regular
expression pattern, {pattern}.
Construct a “table-of-contents” consisting of filetype-dependent
“important” patterns (e.g. class and method/function definitions).

Other commands include those for filtering results, jumping to next/previous
matching line without opening the catalog, searching for special user-defined
terms (“:Bsterm”) etc.

The results list can be browsed/navigated using all the usual Vim movement
commands. Selected lines can be opened in the previous window, a new window
split (vertical or horizontal), or a new tab page. Context can be toggled (i.e.
show a user-specified number of lines before or after the matching line).
Results are grouped and sorted by filename, and then by line number, but can
also be ungrouped and sorted lexically.

Search and replace as well as running arbitrary commands on the matched lines (or surrounding context lines) are also supported.

The primary distribution page for Buffersaurus is here:

Detailed usage description is given in the help file, which can be viewed
on-line here:

Source code repository can be found here:


If Pathogen is installed, you can install Buffersaurus by unpacking the source
(or cloning the Git repository) in “$VIMRUNTIME/bundle“. Otherwise, unpack the source archive and copy
buffersaurus.vim” to “$VIMRUNTIME/plugin” and “buffersaurus.txt” to

Character/Word/Line Count of Selection in Vim (a non-Vimique Vim Command) Compared to Underlining Text (a Vimique Operation)

Every day I discover at least one new thing about Vim. Sometimes useful, sometimes not. Sometimes rather prosaic, sometimes sublime.

This one falls in the useful but prosaic category: to get a count of the number of characters, lines, words etc. in the current selection, type "g CTRL-G".

This is a useful command, and good to know, but its invocation is a rather obscure key-mapping. In other words, just like most of the commands of your garden-variety “dumb” modeless editor, it can only be memorized (or looked up) and reproduced, instead of being generated based on grammatic-/syntactic- princples, like a language-based construct.

For an example of the latter, try this …

Move the cursor to a line of text, and then, in normal mode, type “yypVr-“.

This transforms:

Hello, world!


Hello, world!

A nifty little operation, and one that does not require memorization of any obscure key strokes. We are just “speaking” Vim:

  • yy“: yank (or copy) the current line
  • p“: put (or paste) the yanked/copied line
  • V“: select the (newly pasted) line
  • r-“: replace the contents with “-“, character by character

Even though more key-strokes than “g CTRL-G“, since the entire “phrase” is composed of a vocabulary of simple everyday commands/terms and can be composed from first princples, it does not need to be memorized, and hence never can be forgotten or need to be looked up. It simply is there, easily within reach of anyone who can express him- or herself in Vim.

A Tale of Two Vim Commands: ‘s’ and ‘c’

Vim continues to surprise me with its wonders. Sometimes (many times, in fact) things do not make sense, and I am perplexed as to the reasoning behind them. Then, one day, I grokked it. And from that day on, I can never imagine any other way of doing it.

An example of this was my confusion over the apparent redundancy of two fundamental commands.
In normal mode Vim, “s” (mnemonic: “substitute”) and “c” (mnemonic: “change”) are both ways to remove some existing text and then go into insert mode.
This is the equivalent of selecting some text with a mouse and beginning to type in the world of modeless editors.
For a while I was a little bit confused about the differences between the “s” and “c“, mainly because in some contexts they both behave the same way.
It took a little bit of snooping around the documentation and experimentation for me to realize the difference: “s” is the approach to use in simple situations, for replacing a single character or visual selection with typed text, while “c” is a much more powerful approach for use in more complex situations, because it is combined with motion and text object commands.

So, in general, you would use “s” in essentially one of two basic situations:

  • When you want to delete the character under the cursor, and replace it with text that you want to type in (which may be more than one character).
  • When you have text highlighted in visual select mode, and you want to delete it and replace it with new text that you want to type in.

And that is about it. In fact, in the first of these situations, i.e., replacing a single character with new text to be typed in, “s” is the most efficient way to do things.

The “c” command, on the other hand, is usually combined with a motion or text object command to provide a much broader range of target possibilities.
It can actually be used identically to “s” in the second situation above, i.e., to delete a visually selected block and replace it with new text to be typed in, but it really distinguishes itself when carrying out more complex operations than simply replacing the current visual selection.
The use of “c” with motions is straightforward: type “c” followed by a Vim movement command (e.g., “c$” or “cw“) , to delete everything from the current cursor position to the destination and enter insert mode.
The same applies with “c” and text objects: type “c” followed by a text object selection command (e.g., “ca)“, or “cis“) to delete the text object, and then enter insert mode and start typing.

Now, I not only understand the distinction beween “s” and “c“, but I also understand why Vim provides these two ways to go about doing a similar operation.
Because you combine the “c” command with a motion or text object, you can operate text regions of a broad range of sizes and scopes.
However, this means that in the simpler and more limited cases, where you just want to replace a single character or the current visual selection, using the “c” is quite inefficient, as you will be using keystrokes to describe what is the most atomic region of text (i.e., a single character) or the most obvious region of text (i.e., the current visual selection).
The “s” command exists solely to solve this problem, reducing the command to single keystroke when the region of text is irreducibly simple or absolutely unambiguous.

Vim: Making Those Arrow Keys Work for You (Or Why the Anti-Arrow-Key Propoganda is Wrong)

The Great Controversy

A standard dictum amongst experienced Vim users is not to use the arrow keys to move around your document. This dictum is often repeated again and again, in tones that range from the taken-for-granted to hysterical-zeal. The most common reason given for this is that using the arrow keys takes your hands away from the home row of your keyboard, and thus is wasteful both in terms of time and energy, whereas the standard Vim movement keys —| h, j, k, and l —| keep your hands on the home row, and therefore is far more efficient. Here is what I have discovered: this anti-arrow key argument is wrong!

The Great Experiment

When I first started using Vim, I of course found the h, j, k, and l keys to be horribly unintuitive.
But what was worse was that I could not use these keys to move in insert mode.It was this latter issue that kept me resolutely married to my arrow keys.The centi-seconds of time it took for me to move my fingers to hit an arrow key seemed far more efficient than exiting into normal mode, using the h, j, k, and l to move to where I wanted, and then i again to get back into insert mode. And so, for the longest time, not only did I continue to use the arrow keys, but I had absolutely no desire to cease doing so, just to gain what would probably accumulate to be about an hour’s worth of saved time over the course of a year.

Recently, however, on a whim, just to see what the fuss was about and if I was correct in viewing the arrow-keys-Noooooooooo!-zealots as the computing equivalent of monodimensional cladist fundamentalists, I decided to indulge in what I initially viewed as a temporary experiment in masochism.

Yes, that’s right.

I disabled my arrow keys:

inoremap  <Up>     <NOP>
  inoremap  <Down>   <NOP>
  inoremap  <Left>   <NOP>
  inoremap  <Right>  <NOP>
  noremap   <Up>     <NOP>
  noremap   <Down>   <NOP>
  noremap   <Left>   <NOP>
  noremap   <Right>  <NOP>

It did not take long (less than an hour) for me to get used to the spatial directions mapped to the h, j, k, and l keys, and so within a day I was comfortable using these keys to move around in normal mode. But the inability to move around in insert mode was incredibly annoying. It got so frustrating that I considered switching back to using arrow keys permanently, but decided to stick with the pain of trying to work in this tedious and painful environment for a little longer before giving up.

The Great Results

After a couple of days, I came to the realization that I had started working with Vim in a different way. It happened gradually, and mostly unconsciously, so that I did not notice it as first. But I did begin to notice that I was no longer tripping up or stumbling quite as much when needing to move around my document. In fact, quite the opposite, I felt like I was zipping around to places much faster and much more efficiently than I ever did before when I was using the arrow keys.

This feeling was not due to the gains from those accumulated centi-seconds shaved off my editing time by not having to move off the home row so frequently.</ on p>

It was, instead, due to the consequence of being forced to exit insert mode when I was not actually typing text.

Being forced to return to normal mode right after I edited the text at a single point in the document (sometimes just a couple of characters, sometimes a word or two, sometimes short blocks or fragments), also resulted in me being forced to use the rich suite of powerful normal mode movement commands to get to exactly where I needed to be before resuming editing. This was like suddenly beginning to use the fifth and other gears while driving on an open highway, whereas before I had been grinding along for mile after laborious mile on first.

The most remarkable and unanticipated aspect of my new way of working with Vim was not so much my usage of the h, j, k, and l keys, and other relatively “dumb” movement keys (0, $, etc.). It was my much greater usage of “smart” movement keys and commands. Due to the shift in the dominant ecology (i.e., normal mode vs. insert mode dominant), my repertoire of idioms for movement within and across the buffer evolved, and simple up/down/left/right movements were replaced by far more efficient and powerful commands. For example, I would use f/F/t/T/; etc. to jump to the exact character on a line that I wanted to get to, instead of pecking away at the left/right keys to get there. I would use :150 or 150G to jump directly to line 150 instead of using the up/down arrow keys. I would use /def or ?def to jump directly to a function line instead of tapping away a directional key like a zombie trying to signal in pseudo-Morse. I would use marks (e.g., mm) to register an “anchor” into the document that I could jump back to directly (by using, for example, 'm), before moving off to temporarily work on some other part of the document.

It is true, of course, that none of these movements are in any way more efficient when, for example, to moving a couple of characters to the left or right or up or down of the current position while in insert mode. In fact, this “local neighborhood” (i.e., one or two characters/lines on either side of my current position) is exactly where the arrow keys do come into their own by allowing you to get to these places without leaving insert mode. It is only when we start dealing with positions more than a couple of offsets away from the current position that the normal mode movement keys and commands start to yield benefits.

But the fact is, while I had arrow keys enabled I simply found it difficult to consciously make it a point to limit my use of them only within the “local neighborhood” . When in insert mode, and I needed to get anywhere that I could see in the viewable buffer, without thinking about it I would start tapping away at the arrow keys, even if the destination was several to dozens of lines/characters away. So while I had learned and started using all those “smart” movement commands that I am using now within the first couple of months of using Vim, I was just not using them enough or in all the places that I should been using them.

Disabling the arrow keys, while making “local neighborhood” movement significantly more cumbersome than before, taught and continues to teach me to view the document as a landscape, across which I can visit any point that I want directly and precisely through Vim’s normal mode movement commands. I still have not completely internalized this perspective, and often find myself reaching for the arrow keys unconsciously while editing in insert mode. So, for the time being, until this regime has been exorcized from my muscle memory, I think I am going to keep my arrow keys disabled as motion keys.

Re-Educating the Arrow Keys to Work With You: Text Shifters Instead of Cursor Movers

However, that does mean that I have 4 decent keys on my keyboard not doing anything at all. That, to me, seems just as wasteful as any of the extra energy and time required to use them. And thus I decided to put those arrow keys to work as “text movers” rather than their default role as “cursor movers”.

Editing text is like doing surgery: when you start hacking away at a bit of code, you usually open up various gashes and slashes in the surrounding area. At least with modern medical practices, it is both customary and polite to sew up these gashes and slashes, and naturally we do the same when editing code: indentation has to restored (here is a tip: see what = and == can do for you in Vim), empty lines need to be closed up, etc. etc. We probably do this dozens of times during a particular edit session, and typically it involves a lot of moving around, deleting and inserting lines all over the place. Even with the power of Vim’s normal mode commands, it still takes a lot of keystrokes, tedium and hassle to achieve this.

And so I have remapped my arrow keys to do the following:

  • The Up arrow key deletes a blank line above the current line (a non-empty line will not be deleted), while the Down arrow key inserts a blank line above the current line. The result is hitting Up or Down moves the current line up or down, in both normal as well as insert mode.
  • Typing Ctrl-Up and Ctrl-Down, instead, deletes or inserts a blank line below the current line. The result is that the text below the current line moves up or down, respectively.
  • Typing Left de-dents the current line, while Right indents it. The result is that text shifts left and right, respectively.

The following code, included in your ~/.vimrc or otherwise sourced into your session, implements this (the actual functions that do the work are copied from here):

function! DelEmptyLineAbove()
    if line(".") == 1
    let l:line = getline(line(".") - 1)
    if l:line =~ '^s*$'
        let l:colsave = col(".")
        silent normal! <C-y>
        call cursor(line("."), l:colsave)

function! AddEmptyLineAbove()
    let l:scrolloffsave = &scrolloff
    " Avoid jerky scrolling with ^E at top of window
    set scrolloff=0
    call append(line(".") - 1, "")
    if winline() != winheight(0)
        silent normal! <C-e>
    let &scrolloff = l:scrolloffsave

function! DelEmptyLineBelow()
    if line(".") == line("$")
    let l:line = getline(line(".") + 1)
    if l:line =~ '^s*$'
        let l:colsave = col(".")
        call cursor(line("."), l:colsave)

function! AddEmptyLineBelow()
    call append(line("."), "")

" Arrow key remapping: Up/Dn = move line up/dn; Left/Right = indent/unindent
function! SetArrowKeysAsTextShifters()
    " normal mode
    nmap <silent> <Left> <<
    nmap <silent> <Right> >>
    nnoremap <silent> <Up> <Esc>:call DelEmptyLineAbove()<CR>
    nnoremap <silent> <Down>  <Esc>:call AddEmptyLineAbove()<CR>
    nnoremap <silent> <C-Up> <Esc>:call DelEmptyLineBelow()<CR>
    nnoremap <silent> <C-Down> <Esc>:call AddEmptyLineBelow()<CR>

    " visual mode
    vmap <silent> <Left> <
    vmap <silent> <Right> >
    vnoremap <silent> <Up> <Esc>:call DelEmptyLineAbove()<CR>gv
    vnoremap <silent> <Down>  <Esc>:call AddEmptyLineAbove()<CR>gv
    vnoremap <silent> <C-Up> <Esc>:call DelEmptyLineBelow()<CR>gv
    vnoremap <silent> <C-Down> <Esc>:call AddEmptyLineBelow()<CR>gv

    " insert mode
    imap <silent> <Left> <C-D>
    imap <silent> <Right> <C-T>
    inoremap <silent> <Up> <Esc>:call DelEmptyLineAbove()<CR>a
    inoremap <silent> <Down> <Esc>:call AddEmptyLineAbove()<CR>a
    inoremap <silent> <C-Up> <Esc>:call DelEmptyLineBelow()<CR>a
    inoremap <silent> <C-Down> <Esc>:call AddEmptyLineBelow()<CR>a

    " disable modified versions we are not using
    nnoremap  <S-Up>     <NOP>
    nnoremap  <S-Down>   <NOP>
    nnoremap  <S-Left>   <NOP>
    nnoremap  <S-Right>  <NOP>
    vnoremap  <S-Up>     <NOP>
    vnoremap  <S-Down>   <NOP>
    vnoremap  <S-Left>   <NOP>
    vnoremap  <S-Right>  <NOP>
    inoremap  <S-Up>     <NOP>
    inoremap  <S-Down>   <NOP>
    inoremap  <S-Left>   <NOP>
    inoremap  <S-Right>  <NOP>

call SetArrowKeysAsTextShifters()

Using the arrow keys for cursor movement cripples you in terms of time and efficiency, due to the far superior alternatives found in normal mode. Using the arrow keys for shifting text, on the other hand, empowers you by wrapping up an often-used series of repetitive and stereotypical actions into a single keystroke.

Revisiting the “Don’t Use the Arrow Keys!” Dictum

Modified slightly to say “Don’t Use the Arrow Keys for Movement”, this dictum basically holds. But I think it utterly fails to capture the real issue at hand, and the customary justification offered for it (the whole “taking your hands off the home row is wasteful”) fails to make for a convincing argument.

Instead, I think that Vim tutorials, guides, advocates and propaganda everywhere should emphasize:

Don’t move around the document in insert mode!

This is because normal mode offers so much more power and flexibility to get to any part of your document precisely and quickly. The “Don’t Use the Arrow Keys for Movement” should be offered as a corollary to this, rather than a primary statement in its own right, because using arrow keys for movements leads you —| for psychological reasons —| to remain trapped in insert mode when you should be cruising and jetting about in normal mode.

Grokking the Zen of the Vim Wu-Wei

I love text editors.Which is a good thing, because I spend the overwhelming majority of my computing time (and, hence, sadly, most of my conscious life) in one text editor or another.
For years I have been an Emacs user, only relatively recently moving to BBEdit with my adoption/inheritance of a Mac as a personal machine.
Using and often administrating Linux-based systems has necessitated that I use Vi now and then, but I have long held the opinion that the only Vi command one needs to know is: ":q!", perhaps to be followed by "emacs".

This attitude was born out of some unpleasant experiences really early on in my computing history.
I distinctly remember a few occassions when I was trapped in an apparently psychotic terminal session that would not accept my typing despite dozens of increasingly-frenzied keystrokes, and then suddenly and inexplicably it started accepting my typing but refused to let me stop typing and exit. This was my introduction to the Vi editor.
After once or twice resorting to disconnecting and relogging-in as the only way break out of the grip of this insane editor, I learned how to properly quit it: ":q!".
For many years after that, those three keystrokes probably summed up 90-99% of my Vi usage: whenever I inadvertently triggered an editing session with it, I would quit it with alacrity and get on with life.
It was a long while before I stopped getting a flash of a "Arrgh! Not again!" semi-panicky feeling whenever I saw a screen with all those tildes running down the left hand side.
As far as I was concerned, a Vi session was synonymous with an operating system glitch or failure.

All that has recently radically changed …

For a couple of years now, since getting a Mac, I have been using BBEdit as my primary local editor, and my Emacs usage has been limited to systems administration tasks as well as patching, viewing, editing etc. program and data files on remote clusters/hosts.
Many times in a day, I find that I need to quickly open up a file, check or tweak a couple of lines, and retry running something.
I was getting a little irritated with having to wait one to several seconds for Emacs to fire up each time I need to do this.
Also, I was secretly a little ashamed and tired of lugging around my bloated monstrosity (>1.5K SLOC) of a "~/.emacs" configuration file, without which I was practically helpless.

So I decided to give Vim — the golden child of the Vi family — a try.
It took me a couple of hours of forced usage to get used to the modal paradigm and basic navigation.
But I was impressed enough with its speed and responsiveness (loading in micro-seconds as opposed to the several of Emacs) to stick with it.
As I did, I began to appreciate the efficiency, elegance, and, for lack of a better word, sheer poetry of its movement and editing commands.
It seemed that, without my hands leaving the keyboard, just a few strokes here and a few taps there, I was capable of dancing all over the document, and perform everything from extremely precise targetted micro-surgery to massive document-wide renovations.
I felt like I was working with a well-designed artificial intelligence that smartly and smoothly executed my commands on the document, while other (modeless) text editors began more and more to seem like dumb keystroke-sucking-and-storing buckets in contrast.

I was hooked.

But what I want to share in this post is not (just) a confession or declaration of leaving the "Church of Emacs" for the "Editor-of-the-Beast".
Rather I would like to link to another post that I believe is the most succint yet intuitive description of how to think when using Vim that I have yet read.
While I had grasped in a semi-epiphany (if an epiphany can occur over a couple of decades as opposed to an instant) the compelling sublimity that is the Vim way of doing things, I did not truly begin to grok the Vim way till I read this post:

The beginning of understanding the Zen of Vi comes when you realize that you are not memorizing key-bindings, but rather, you are learning a language.

What a beautiful concept! You are not memorizing that "d$" means "delete from here to the end of the line". You are instead learning how to tell Vi that you want to delete ("d") from here to the end of the line ("$"). The operation command, "d", can be seen as a verb, while the target of the operation, the end of the line, "$", can be seen as the object. Carrying out the same operation with different parts of the document is just learning how to refer to different "object" (in the grammatical sense) in Vi-speak: to delete to the beginning of the line means learning how to say "beginning of the line" in Vi ("0") with the same verb ("d0"), while to delete to the end of the sentence means learning how to say "to the end of the sentence" in Vi (")") with the same verb ("d)"). On the other hand, learning how to carry out different operations is just a matter of learning new "verbs" (e.g., "y" for "yank/copy", "g" for "go to"), and applying them to the same "objects" ("end of line", "beginning of line", etc.). Seen like this, coding with Vi becomes like programming a program, or, alternatively, a better analogy that more accurately captures the sense of using Vi would the one I used previously: coding with VI is like communicating with an AI. Either is bound to appeal to any programmer!

I am still digesting all this, learning the language, along with the rest of the Vim knowledge base.
Or, rather: absorbing the Zen of Vim while I (try to) act without doing with it.
I realize that I am at a bottom of a steep learning curve


… but I am amazed at not only how much I can get done with what little I already do know, but how elegantly I can get it done as well.

So, bottom of the learning curve or not, I am now a Vim-er.
This has geekoriously been made official by my "~/.bashrc" file exporting "EDITOR='vi'" instead of "EDITOR='emacs'", followed by a (relatively sparse) "~/.vimrc" file being committed to my personal environmental repository.

I have also set up my "~/.inputrc" so that readline uses Vi-mode by default:

# Be 8 bit clean.
set meta-flag on
set input-meta on
set output-meta on
set convert-meta off

# mode in everything that uses readline
set editing-mode vi
set keymap vi

As well as modifying my "~/.pythonstartup" file so that my Python shell does the same:

#! /usr/bin/env python

    import readline, rlcompleter, os, atexit
    def savehist():
            import os, readline
            histfile_path = os.path.join(os.environ['HOME'], '.pythonhistory')
            del os, readline, histfile_path
    readline.parse_and_bind('tab: tab-insert')
    readline.parse_and_bind('"\eOP": complete') # 
    readline.parse_and_bind("set editing-mode vi")
    readline.parse_and_bind("set show-all-if-ambiguous on")
    readline.parse_and_bind("set meta-flag on")
    readline.parse_and_bind("set input-meta on")
    readline.parse_and_bind("set output-meta on")
    readline.parse_and_bind("set convert-meta off")
    readline.parse_and_bind('"\C-a": beginning-of-line')
    readline.parse_and_bind('"\C-e": end-of-line')
    histfile_path = os.path.join(os.environ['HOME'], '.pythonhistory')
    del os, histfile_path, readline, rlcompleter, atexit
except IOError:
except ImportError:

Interesting side note: dozens if not hundreds of Emacs key chords that I thought were buried in muscle memory vanished without a trace within a week of using BBEdit. For future cognitive science/interface design researchers out there: the only ones that remained were “Ctrl-A” and “Ctrl-E“.
Which is why I have mapped in those Emacs keys into the Vi-mode Python shell above, as well as in my "~/.bashrc".

So what does Vi-mode readline get you in the Python and Bash shells, apart from the obvious? Here is what clinched the deal for me: in normal mode (Esc), hit "v", and a Vim session opens up with the current line for editing. Saving and exiting results in the buffer being executed, while ":cq" results in the command being canceled. How awesome is that?