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′
r11                      replace 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.

Snippet Pipes

September 16th, 2008

The latest update adds an extension to the snippet format, so that you can pipe the contents of individual tabstops through shell commands. This makes it possble for snippets to be far more interactive.

The syntax is pretty straightforward. Here is a simple example that allows you to directly evaluate ruby code:

 ${1:ruby code|ruby -e "print eval STDIN.read"}

If this snippet is bound to the tabtrigger “ru”, then pressing ru[TAB]1+2[TAB] will result in 3 (without leaving any trace of the intermediate steps). Very handy for doing quick calculations without having to do a mental shift and since you have access to the full language you can do far more than simple arithmetic.

The equivalent snippet for python would be:

${1:python code|python -c "import sys; print eval(sys.stdin.read())"}

The commands are not limited to just reading from stdin. They have access to all the standard environment variables, plus a few snippet specific ones:

  • TM_SNIPPET : contains the entire snippet
  • TM_TABSTOP_n: contains the contents of the individual tabstops

This means that you can make snippets that react on quite complex input from the user. Here is a simple example of a snippet that draws a box in a user defined size:

${0:Draw box ${1:10} times ${2:10}|"$TM_BUNDLE_SUPPORT/starbox.rb"}

It works with the following script placed in the bundles support dir:

#!/usr/bin/env ruby

width = ENV['TM_TABSTOP_1'].to_i
height = ENV['TM_TABSTOP_2'].to_i

height.times do
  width.times {print “*”}
  print “\n”
end

The content is piped to the command at the moment you tab out of a tabstop. The one exception is tabstop zero (the ender tabstop). Since this completes the snippet, the piping happens on entry. In the above snippet, this is used to replace the entire snippet text with the user defined box.

This extension of the syntax is currently specific for e. But if it sees enough use then we can hope that it becomes supported in TextMate as well.

Remote Projects

February 14th, 2008

The latest updates of e has added support for remote projects. This means that you can open an ftp site directly in the project pane and use it as if it was a local project.

Working with Remote Project

In earlier versions of e, this could also be approximated with various shell plug-ins, but having it as an integrated part of e removes the reliance on external tools and gives a much nicer user experience. Implementing this features was also an opportunity to re-architect and improve a part of e that had gone a bit stale while the rest of the editor had evolved. The new underlying project framework is very flexible and extensible, and will allow for a lot of new capabilities in the near future.

Opening a remote project

To open a remote project just select ‘File/Open Remote Folder’ on the menu, create a new profile and press ‘Open’. The remote site will be opened in the project pane, and you can interact with it as if it was a local project.

Editing profile for remote project

You can also open remote files and projects directly from the command line. You just have to give it the path i url format:

e.exe ftp://ftp.mydomain.com/dir/file.txt
e.exe ftp://ftp.mydomain.com/dir/ (remember trailing slash for projects)
e.exe ftp://username:password@ftp.mydomain.com/dir/ (with login)

The remote projects feature is still very new and currently only supports the ftp, but support for protocols like sftp and webdav will be available soon.

Since the latest update of wxCocoaDialog, it has been possible to use it for making custom html dialogs. This gives you a lot more freedom when creating bundle commands as you can now use far richer and more responsive dialogs in your interaction with the user.

As an example of what is possible, and how easy it is to create interactive dialogs, I have created a bundle command version of the excellent Visibone Color Lab.

The modifications to the original html code is really minor. Mainly just moving some frames around and making it update on mouseOver. The interesting part comes where i modify it to return the color code when a color is clicked:

<area HREF=”cocoadialog://%23FFFFFF” onMouseOver=”pick(’FFFFFF’,'W’,'White’)” SHAPE=”POLYGON” COORDS=”184,200,202,168,221,200″>

By giving it a link with the protocol defined as “cocoadialog”, I instruct it to react on a click by closing the dialog and returning the links content (notice the url encoding for the # mark).

To make this into a bundle command, I just have to open the Bundle Editor and create a new command containing the following two lines:

cd "$TM_SUPPORT_PATH/Visibone"
CocoaDialog html --title "The 216-Color Webmaster's Palette" --html-from-file big.html --width 380 --height 542

By first setting the current working dir to the location of the html files (and images), I ensure that the dialog can find all it’s files.

I then set input to “None” and output to “Replace Selected Text”, so that the color code will be inserted in the text when a user clicks a color.

I hope that this has illustrated how easy it is to make html dialogs. Since you have full access to using javascript in your html, there is really no limit to how freeform and interactive you can make it.

Thanks to the kind permission of Bob Stein, the Visibone creator, I have been able to include the color lab in the latest update of e. You can find it as “Insert websafe color” in the HTML bundle.

Transpose - The MultiTool

March 21st, 2007

Transpose is a versatile command that can save you a lot of typing. What it does is to ‘reverse the order of things’, but what makes it really useful is the fact that what it reverses depends on the context:

  • If the caret is inside a word, the chars on each side of the caret are swapped, and the caret is moved to after the right char. This makes for a quick way to fix typing mistakes.

  • If the caret is between two words, the words are swapped.

  • If the caret is at the beginning of a line, the line is swapped with the line above. Similarly if the caret is at the end of a line, the line is swapped with the line below. This makes for an easy way to move lines up and down through the document.

  • If there is a selection, the contents is reversed.

  • If there are multible selections (made by holding down ctrl while selecting), the selections are swapped.

  • If there is a column selection (made by holding down alt while selecting), the order of items in the entire column is reversed.

You can access it from the menu, but to really make it a timesaver, I would recommend making it a habit to use it’s shortcut Ctrl-T.

Transpose Menu

Undo is one of the most fundamental features of modern software applications, yet it has hardly evolved since it was invented. And this is even though it widely acknowledged to be mostly useless when going beyond a few changes. This article presents a set of solutions to make undo far more useful. They not just blue sky ideas but actual features implemented and functional in e - the Collaborative Text Editor for Windows.

“By [undoing] repeatedly, you can gradually work your way back to a point before your mistake. This is convenient if you’ve made a mistake four or five commands back. It is marginally useful if you’ve made a mistake twenty or thirty characters back. And it is completely useless if your mistake is ancient history.” - Learning GNU Emacs (page 42)

Most modern software has an unlimited undo history, tracing the changes all the way back to the document creation. Yet, as the above quote attest, it is mostly useless beyond a few edits.

For some reason the introduction of unlimited undo seemed to be the end of innovations in this area. Maybe it was the because of the name. It was a convenient tick mark in the feature list, and what could you possible wish for beyond “unlimited”?

The main reason that undo has been mostly useless beyond the last few changes is that users get anxious in three ways:

  1. They lose any idea of where they are in the undo history.
    Solution: Keep them oriented with a Visual Undo History.
  2. They get unsure about what they actually just undid.
    Solution: Show the actual change in context.
  3. They get afraid of losing what they just undid.
    Solution: Ensure they never lose their old changes by branching.

A Visual Undo History

By showing a visual representation of the undo history, we help the user to keep his orientation. We can even add helpful markers like for when the document was last saved. This also makes it easy to jump around in the undo history.

Being capable of quickly jumping back and forth from a previous document state can be extremely useful. Anybody who have done some writing have probably tried to let some paragraphs, which should be deleted, stand because of a nagging feeling that parts of it might be useful later. When you know that you can always jump back and retrieve whatever parts you find useful, you can write much more freely.

Visualizing the Undo History

visual undo history in the e text editor

The undo history is shown in a separate window which updates live as the user types. The vertical line of small circles on the left shows the history of the changes. Each circle represents the document as it was at a specific point in time. By clicking on a circle the user can revert the document to the previous state.

To the right of each circle is a one-line summery of the changes that lead to it’s current state. Changes are indicated by colors: green for insertion and red for deletion. It is put in context by the gray text surrounding it. The window is resizable so you can easily enlarge it to see more of the change.

The solid blue circle indicates the users current position in the history and the small marker (in dark blue) indicates when the document was last saved.

The history is pretty terse but users quickly learn to scan over it, easily spotting the major insertions and deletions.

Showing the change in context

For the undo history to have any value, we have to show the changes in context. Showing the user that he deleted a few letters in a set of changes that could be done hours (or days) ago, doesn’t give him much idea of what really happened. But if you show it in context, with the words that the letters were part of surrounding them, it becomes much easier to remember where the change fit in the bigger picture.

Branching

branching in the visual undo history

What happens if you undo a lot of changes, start making new edits and suddenly discover that you undid too far? How do you get back what you undid by mistake? In most applications you don’t. Everything that was underneath you in the undo history was lost.

By allowing branches in the undo history any such loss can be avoided. Whenever you go back in history and start making changes a new branch is created.

Basically your work is held to be sacred, and an application should never let you accidentally lose any work. So you can always go back to a previous branch and continue to work from there, or maybe just copy the useful parts back to your current branch.

Persistence & Crash recovery

In just about all applications the undo history is lost the moment you close the document. There is really no reason for this since the undo history (if it is properly implemented) hardly takes up any space, and there is no guarantee that you won’t need it at a later time.

In e you always have the full undo history, even after reloading a document from a previous session. Should the computer crash (or lose power) while you are working, it will just start up where you left of.

Innovation

It is amazing that a feature as fundamental as undo has seen so little innovation over time. And it is even scarier that it has been implemented in a way that leaves anything beyond the last few changes mostly useless. Especially considering how many system & programmer resources that are used to keep track of the unlimited undo

It really makes you wonder how many other fundamental software features that could be radically improved if you just looked at them with new eyes.

Reality Now

So is this the pinnacle of undo functionality. Not at all. There are lots of possible improvements, like partial & selective undo or interactive diffs, which are obvious next steps and could be very useful.

But it is easy just to come up with critique and blue sky ideas which have no basis in reality. So I have limited this article to features which are actually implemented and functional, so you can try them out in the e text editor right now.

Experience with the text editor has shown that these basic improvements to the undo functionality greatly improves the writing experience. Making users much more confident in modifying and experimenting with their text.

It is my hope that showing that this is possible will raise the expectations of users, so that they will no longer accept applications that routinely lose or make inaccessible parts of their work.