Beyond vi - Towards a modern command mode
September 7th, 2010
When it comes to editors, the modal interface of vi has long been the epitome of high productivity. Once you get fluent in it, you can navigate and transform text with an unmatched speed and ease, using only a minimum of key presses for each action. The backside is an extreme learning curve, and the fact that it over the decades since its conception, have only grown more and more extensive and complex. It is really overdue for an evolution, which is why e version 2.0 introduces a totally redesigned new command mode.
It is not just a copy of vi’s command mode, even though that was the main inspiration. It integrates it with structural regular expressions (as in Rob Pikes editor Sam) and TextMates scope awareness, ending up with at far more powerful and coherent interface.
Obviously this enables the quick navigation that vi is known for, but the fact that you can make selections, and then enter the selections and have the following commands constrained to these ranges, makes it effortless to do actions that would otherwise be extremely cumbersome.
A Quick Example
Lets say you want to replace all occurrences of the number ‘10′ with ‘11′, but only in the comments of your program. Just type the following:
<esc> enter command mode Vtc select contents of all comments (syntax aware) \ enter selections V/10/ select all matches of ‘10′ r11replace with ‘11′
or a slightly more advanced example. Lets say you want swap ‘foo’ and ‘bar’ in your entire source, except in comments and strings:
<esc> enter command mode Yac select everything but comments \ enter selections Ya” select everything but strings \ enter selections V/(foo)|(bar)/ select all instances of foo and bar r(?1:bar)(?2:foo)<enter> replace with opposites
At this point it may all read like gibberish, but read on and it will soon be clear. Also note that the editor will give live feedback as you type, interactively showing the selections and ranges, making it much easier to follow what is happening.
Usability
In vi the command mode is expected to be your normal mode from day one, setting up a monumentuous learning curve. In contrast, e expects you to start out with using it just like any other modern editor, using the mouse, menus and keyboard shortcuts, and then only occasionally dipping into the command mode when you really need it’s power. This allows you to gradually get your feet wet and get used to the commands, and as time goes you might find yourself using it more and more, eventually becoming so fluent that it becomes your preferred mode of editing.
Coherence
One of the most important factors when learning a new skill, is the ability to build a mental model of the domain. With vi this can be exceptionally hard, as it has over the years build layers upon layers and a multiple of modes, some of which are totally orthogonal to each other (like the ex cmd line).
In e’s command mode there are only four basic concepts to understand: movements, selections, ranges and actions.
Movements
The movement commands allow for quick navigation in the text. They allow you to keep your fingers on the home row rather than using the arrow keys and gives you a much more expressive way to say exactly where you want to go in the text. All the movement commands can be prefixed with a count that repeats it that number of times. So you could for example use 10w to move ten words ahead or 4/test to move to the fourth instance of the string ‘test’.
The movement commands in e are essentially similar to those in vi, and as there, huge productivity gains can be made by becoming familiar with them and gradually starting to use them during editing. This allows you to avoid constantly having to move your hands back and forth between the keyboard and the mouse.
h/j/k/l left/down/up/right (arrows)
0/^/$ beginning/soft beg./end of line
w/W beginning of next word/WORD
e/E end of next word/WORD
b/B beginning of prev word/WORD
(/) beginning of prev/next sentence
{/} beginning of cur./next paragraph
+/- go to next/previous line
G go to line (count), default is eod
| go to column (count), default is bol
% go to matching bracket
fc/Fc find char/backwards
/pattern find string
?pattern find string backwards
n/N repeat search/backwards
*/# find next/prev instance of current word
Selections
Selections are the doorway to the real power of e’s command mode. Using the basic selection commands you can quickly make the selection you need without needing the mouse:
/pattern/ select pattern vmovements select from current pos n,n select range of lines atype select object (inclusive) ttype select object (exclusive)
The object selectors allow you to quickly select a logical unit of text. The inclusive version select the entire object including delimiters (think a block) and the exclusive only the contents. Notice that an object type like c (comments), uses the TextMate scope awareness to be correct no matter what language you are using. Here are the available object types:
w word
s sentence
p paragraph
c comment
" "string"
' 'string'
( (block)
{ {block}
[ [block]
< <block>
Often you will want to make repeated selections. You can do this with either the V command which selects everything matching it’s specification or the Y command which selects everything not matching:
V/pattern select all matches
V|pattern select all lines with match
V{scope select all matching scopes
Vatype select all objects (inclusive)
Vttype select all objects (exclusive)
Y/pattern select everything but matches
Y|pattern select all lines without match
Y{scope select everything but scope
Yatype select everything but objects (inclusive)
Yttype select everything but objects (exclusive)
Ranges
Ranges allow you to gradually refine your searches and selections in a way that is both intuitive and easy to follow visually. They are created by entering selections with the \ command. The selections can have been made by previous commands or manually selected with the mouse. When you are inside ranges, all following commands, be it movements, selections or actions will be restricted to the range and happen in all ranges at the same time.
Let’s say you have an html document where you want to replace ‘ref’ with ’source’ in all paths. One straightforward way to do it would be like this:
<esc> enter command mode V/href=”(.*?)”/ select all hrefs 1\ enter capture 1 /ref/ select ‘ref’ rsource<enter> replace with ’source’
As you can see in the example above, you can also enter a specific capture by prefixing the enter selection command with a count.
Actions
Actions can be grouped in three types: Actions that enter insert mode, actions that operate on text and actions that operate on selections.
The actions that enter insert mode allows you to go back to normal editing in the editor. Usually they first do a movement or somehow prepare the text for editing:
i enter insert mode I/A insert at beg./end of line o/O insert new line below/above cmovement change from current pos C change to end-of-line cc change current line
The text actions modifies the text at the current caret location:
x delete current char X backspace dmovement delete from current pos dd delete current line rc replace char ymovement copy yy copy current line p paste
If there are one or more selections available, the actions will operate on them:
\ enter selections rsubstitution replace selections d delete selections y copy selections p paste over selections n/N move selection to next/prev n,n keep a range of selections Vpattern keep selections with match Ypattern keep selections without match x select all matches like current X select everything but matches like current o move caret to opposite end
Dealing with structured files
One thing that can be really difficult with traditional editors that only offer regular expressions for searching, is dealing with files containing structured data. An example could be a list of books in the refer format, where each record is composed of multiple lines starting with an identifier (like %A for author or %T for title), and records are separated by empty lines.
With e’s command mode this becomes pretty effortless. Let’s say you want find all the titles of books authored by Pike:
<esc> enter command mode Y/^\n/ select all records (between empty lines) V%A.*Pike<enter> only keep those written by Pike \ enter selections V|^%T select lines with titles
Conclusion
The new command mode in e does not claim to be as comprehensive or complete as vi’s. After all, vi and it’s descendants has had decades to accumulate features. But it does claim to be simpler and easier to understand while at the same time having the potential for even more powerful interactions with the text.