Grokking the Zen of the Vi Wu-Wei

Site Section: 

Keywords: 

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

try:
    import readline, rlcompleter, os, atexit
    def savehist():
        try:
            import os, readline
            histfile_path = os.path.join(os.environ['HOME'], '.pythonhistory')
            readline.write_history_file(histfile_path)
            del os, readline, histfile_path
        except:
            pass
    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')
    atexit.register(savehist)
    readline.read_history_file(histfile_path)
    del os, histfile_path, readline, rlcompleter, atexit
except IOError:
    pass
except ImportError:
    pass

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?

13 Comments

Using `emacs --daemon` and

Using `emacs --daemon` and `emacsclient` would give you an emacs even faster starting than vim (if you have some addons). I switched a few weeks ago from vim to emacs, because of the better environment (and honestly flymake and flyspell rock) but stayed with viper-mode and vimpulse. That's IMO the best of both worlds.

Well I don't do that, but

Well I don't do that, but using screen/tmux/... in that context would help keeping the emacs daemon alive, as long as you don't shutdown. But you need to kill emacs gracefully before shutting down, it doesn't like being killed by SIGKILL (not that any other program likes that ..). viper-mode and vimpulse give you that grammar back, at least a whole deal of it - I didn't miss a command in that few weeks. Granted that combo is weak in ex-style commands because only a few are supported, but emacs comes with a nicer command-line anyway.

I was trying to use emacs for

I was trying to use emacs for a while with viper, and vimpulse, but still it doesn't feel the same, because the shortcuts feels clunky and bolted on, and a lot of the things that I know and love from vim doesn't really work too well even with vimpulse. And the configuration for emacs is a big mess, so for me, vim is the way ;)

funny, I went the opposite route

I was an exclusive Vim user for 5 - 6 years.

I think I started making the switch to Emacs when I began getting into Lisp (the two tend to go hand in hand).

The thing is, it stuck. Emacs was far easier to program for and made a lot more sense than Vim. The thing that took the most time getting over was the use of pre-fix commands. There seems to be a barrier between the modal and non-modal editors that takes some getting used to. One thing I don't miss is constantly reaching for the ESC key (though I do find myself re-configuring my keyboards more often now which pisses off anyone else who uses my computer to no end).

Vim keys are super-sweet but confusing in their own right. Once you know it though, it's freaking awesome.

Both are great editors. I just get more bang for the buck out of Emacs.

Emacs on Macs..

I use Aquamacs myself and it's definitely a first-class citizen on my Macbook. I get all of the nice OSX font goodness and it integrates into the desktop environment, respecting the Apple interface guidelines. So you can both Apple-Q and C-x C-c. If you're a little more hardcore, I used to build a nightly carbon version of emacs as well. Either way, there are lots of options.

I'm not trying to win you back to the emacs camp but it should be pointed out that emacs can be scripted with Python as well (or Perl or whatever). Pymacs provides the bridge and along with rope and flymake on top of the python-mode; emacs becomes one mean python hacking machine. An in-editor interpreter, automatically scrubbed source with pyflakes/pylint, integrated test runner... it's freaking sweet (I hack python on my day job, can you tell? :)

There are a lot of reasons to like Vim and I think you hit most of them in your post. Good stuff. :)

vi mode in readline?

I'm a somewhat proficient Vim user, using it since a few year, and loving it, however, each time I try to "set -o vi" in bash, I go back quickly, I use "alt-." a LOT (insert last parameter of last command in place), and did not find any quick equivalent, less important but still, more tan a few ctrl-.. (u,y,w,a,e,x) are in my muscle memory now, I will try again with your tips, but habits are strong ^^. (Oh, you should try Vimperator and the nice ctrl-i in textareas) Cheers, happy new Vim-er ;)

Vi is Everywhere When You Need It

Nice post. I learned to love vi and vim when I spent all day, everyday in remote console sessions on servers that I didn't control. vi was always available and always worked the same way. Of course, since I had a login I could customize it as needed but it didn't turn out to be necessary very often. I'm stuck in a Java/Groovy gig now and Eclipse and Intellij are certainly tools that help productivity in some respects but nothing about them is easier when it comes to keyboard navigation or fast operations like line copies or deletes. Your insight that vi is a language is spot on. I had to make an effort to get comfortable in vi but now that I'm considerably along the learning curve I view knowing vi as indispensable.

Humorous narrative of your

Humorous narrative of your first experiences with vi! Who hasn't had a similarly inexplicable run-in with the holy-hell-ungodliness of vi's modal nature at his try?!

Thanks so much for mentioning visual mode in bash! I have been using "set editing-mode vi" in my .inputrc for a little while, but I was not aware that it even supports visual mode?!! (Got any other nuggets?)

Also, I just added "set keymap vi" to my .inputrc, as you have it. Wth does that do in addition to the editing-mode setting?

Add new comment