Saturday, October 9, 2010

Keyboard Nirvana with Eclipse and Emacs+

Introduction


Before I say anything else, let me make one thing perfectly clear: You do not need to know anything about Emacs to get maximum value from the Emacs+ plugin. You don’t have to be an Emacs user and you don’t have to know anything about Lisp. The Emacs+ plugin simply provides numerous functions that are very similar to their Emacs origins and that are very applicable to the Eclipse environment. To use them, you just execute the functions. Hopefully this will alleviate your fear that you’ll have to be an Emacs expert to make use of this.

Now that that’s out of the way, some other issues we need to talk about are how to make your keyboard usage in Eclipse more efficient, whether you use Emacs+ or not.

One of those first steps is understanding and accepting that Eclipse lets you bind arbitrary key sequences to Eclipse functions. You’ll want to determine for yourself what are convenient key bindings, and which functions you want to be easier to get to, compared to others. I’ll go over this in more detail.

If you accept that, you’ll probably come to the conclusion that you’ll be using the Control key a lot. An advanced corollary of that is that it’s perfectly reasonable to rearrange your keyboard keys so that it’s more convenient. I’m not suggesting that you use a Dvorak layout (if you do, you probably already have maximally optimized your environment), but there is a single simple change that will make your keyboard usage more convenient: getting rid of the useless CapsLock key and making it an additional Control key. I’ll talk more about this and cover a tool or two that helps with this.

Once we have these foundational elements in place, we can talk about the Emacs+ Eclipse plugin, and then I’ll talk about a recent set of features in Emacs+ that allow you to record key sequences and store them as keyboard macros that you can then also bind to keys. I’ll close with an example of a keyboard macro that you might find useful.

Binding key sequences to functions


If you go to the “General”->“Keys” section of the Eclipse preferences, you’ll see the page where you can view and change key bindings. If you click on the “Binding” header and then scroll (way) down to the first command that has a non-empty binding, you’ll initially see commands that have “simple” bindings, like the first one that I see, which is “Alt+-” (alt-dash), which in my Eclipse is bound to “Show System Menu”.

If you scroll further down, you might see the various “Debug” commands, like “Debug Java Application”, which is bound to “Alt+Shift+D, J”. This is essentially a two character sequence. The first character is “Alt+Shift+D” (pressing “d” while holding down “Alt” and “Shift”) and the second character is just “j”. There are several other multiple character bindings that begin with “Alt+Shift+D”. This works because there is no binding for the single character “Alt+Shift+D”. A character (or sequence of characters) that is used to begin a binding cannot itself be bound to a command.

The other benefit of sorting this list by “Binding” is that you can see some “gaps” that show some character sequences that are not bound to commands. For instance, starting near the top of the non-empty bindings, I see that “Alt+A” is bound to “Terminal view insert” and “Alt+C” is bound to “Copy”, but there is no binding for “Alt+B”. That means you could bind a command to “Alt+B” without disturbing any other bindings.

Also note the "When" column. This specifies the editor or context that the binding is applicable to. For instance, I mentioned that I have "Alt+C" bound to "Copy", but I also have the same key bound to "Execute Selected Text As One Statement". The difference is that the former's "When" value is "In Windows", and the latter's is "Editing SQL". So if you're in the SQL editor view, then Alt+C does one thing, but it executes "Copy" anywhere else. If you define new bindings here, you'll probably want to set "When" to "In Windows", but you might find special cases where you'll want a different value here.

You’ll want to spend a lot of time browsing through this list, sorting by “Binding” to find prefix keys and sequences that you think will be convenient for your custom bindings. My favorite key that begins several of my custom bindings is “Ctrl+;” (Control-semicolon). I don’t bind a command to that key, I use it as the first character in several two and three character sequences.

Once you start binding commands that begin with a particular character, there is another convenient feature you can use that will remind you of the bindings you have that begin with that key. If you exit the Preferences dialog and then just press that key and wait a moment, you’ll see a popup dialog that shows the bindings that begin with that key. For instance, if you press “Alt+Shift+D” and wait a moment, you’ll see the popup that shows the binding for “Debug Java Application” and other related commands.

Ctrl2Cap


Before I get into Emacs+, let’s first fix your keyboard to make extended use of the Control key more efficient and less painful.

Let me illustrate the issue with a picture:


If you have to press the Control key a zillion times a day, and this is your keyboard, how long will it take before your pinky falls off?
Here’s a related question: How many times have you actually USED the CapsLock key? Have you ever used it? Would you miss it if you didn’t have it anymore? If you never use it, why do you let it take up space on your keyboard? Get rid of it!

On my Ubuntu box, this ability is built into the interface, as I can change the “Ctrl key position” setting in my Preferences to “Make CapsLock an additional Ctrl”. There, it’s done. No more CapsLock key.

It's also very easy to do this on the Mac, just by adjusting the Modifier Keys in the Keyboard section of System Preferences.

On Windows it’s a tiny bit more difficult to do this. It’s not built into the default interface. Fortunately, there is a web site called SysInternals (founded by Mark Russinovich and others) that provides a free tool that makes this easy to do. The utility is called Ctrl2Cap. It’s a very small utility. You download it and install it and restart, and now your CapsLock key is a Control key.

By the way, there are numerous other Windows-based utilities and tools on the SysInternals site that you would probably find useful. I spend time exploring there from time to time. I use several of their tools every day.

Emacs+


We now understand how to make our keyboard usage in Eclipse more efficient by binding key sequences to functions, and making those key sequences easier to type. Now let’s learn about the Emacs+ plugin, that provides many functions that you’ll want to bind to keys.

The Emacs+ Eclipse plugin, written by Mark Feber, is one of the more popular plugins available on the Eclipse Marketplace.

Here’s a short summary of Emacs+ taken from the first page of the Emacs+ documentation:

“Emacs+ is designed to provide a more Emacs-like experience in the Eclipse text editors. Included are enhancements for keyboard driven command execution and keyboard macros, Ctrl-u, keyboard text selection, Emacs style search and query/replace, a kill ring for deleted text, balanced expressions (s-expressions), keyboard driven editor window splitting, transpositions, case conversion commands and append line-comments in the Java editor. In cases where the normal Emacs binding interferes with an Eclipse binding, the Emacs binding is preferred. “

Note that the plugin is really in multiple parts. There is a “core” plugin, and then there is the “optional bindings” plugin. The latter is only useful if you set the "Scheme" setting in your "Keys" preferences to "Emacs+ Scheme" (referred to as "the Emacs binding"). You can install just the “core” plugin and not install the “optional bindings” plugin if you don't use the "Emacs+ Scheme".

Also, if you're on the Mac, there is an additional plugin(s) that deals with the COMMAND key, if you're using the Emacs binding scheme.

Just so it's clear, if you don't use the "Emacs+ scheme", you only need the "core" plugin.

It’s helpful to read through the entire set of Emacs+ documentation to get a feel for what features it provides, and how to use them.

One tidbit that I’ll mention: The “query-replace-regexp” Emacs+ function does something that the normal query/replace functionality in Eclipse doesn’t provide, which I’ll call “intelligent case replacement”.

This function takes two regular expressions, for the “source” string and “replacement” string. This is normal so far. What’s different is that it will look at the actual pattern of characters in a particular occurrence of the “source” string and match the case of that occurrence into the replacement string.

What does that mean? Let’s say that you ask to replace “foo” with “doSomething”. You start with a block like this:
getfoo
getFoo
FOO

When this replacement completes, you’ll have this:
getdoSomething
getDoSomething
DOSOMETHING

Is that something that would be useful to you?

Emacs bindings or Eclipse bindings?


Richard Stallman at laptop
I’ve personally been using various versions of Emacs for about 25 years (not quite as long as him). I’ve been using Eclipse for about 5 of those years. When I’m using Emacs, I have a very effective set of bindings that I use to do the things I need to do. When I first installed the Emacs+ plugin, it was very easy for me to decide whether to install the “bindings” plugin. In fact, I did not. I prefer to work with the already defined conventions for Eclipse key bindings, and then add my own bindings that don’t conflict with those bindings. I urge you to make your own conscious decision about this. If you decide to use your own bindings, keep that in mind while reading the Emacs+ documentation. Much of it refers to the default Emacs+ key bindings, which may differ from what you end up using.

Keyboard Macros


Although I use many functions from Emacs+, one set of functionality that really provides a lot of promise is “keyboard macros”. In short, this gives me the ability to go into a mode where it starts to record keypresses (just keys, not mouse movement), press some keys, then “stop” recording. At that point, I have a keyboard macro that I can reexecute. More importantly, I can also give that macro a name, just like any other command name, and then I can bind a key sequence to that named macro. Even better, I can also save that macro to a file, and I can tell Eclipse to load that saved macro (or all of my saved macros) at startup.

Setting up goto-next-search-occurrence


Now that we have all of these features in place, let’s go over an example of a useful keyboard macro, and how to define it and use it.

I’m sure you use the “Search” view a great deal. You’re in the editor view and you either run a specific hand-entered search, or you search for references to the current function, or other possibilities. As soon as you run the search, the focus moves from the Editor view to the Search view. At this point, you could press “Ctrl+.” (control-period) to move to the first occurrence. When you do that, it changes the Editor view, but your focus is still in the Search view. If you have to get back to the Editor view at this point, you either use the mouse or you press the “f12” key, which is typically bound to “activate-editor”, which moves the focus to the Editor view.

Now what do you do if you want to go to the next search occurrence? You have to go BACK to the Search view and press “Ctrl+.” again. This will go on and on.

Wouldn’t it be better if you could press a key that would go to the next search occurrence, but leave you in the Editor view? Let’s see how we would do this.

Before you define a keyboard macro for a sequence of operations, you need to make sure that you can actually execute all the operations in the sequence with just keypresses. Anything that requires a mouse operation can’t be recorded.

In this case, there are really three operations. The first is putting the focus in the search view. The second is going to the next search occurrence. The third is putting the focus in the editor view. I already described the last two steps (“Ctrl+.” and “f12”). The first step is provided by the “Show View (View: Search)” command, which you can see in the “Keys” list in Preferences. In my environment, I’ve bound this command to “Ctrl+;, Ctrl+S”. This is “Control-semicolon” followed by “Control-s”. I can verify I can execute the entire sequence just by pressing these keys in order (“Ctrl+;, Ctrl+S”, then “Ctrl+.”, then “f12”).

Now let’s record the keyboard macro. In my environment, I bound “kbd-macro-start” and “kbd-macro-end” to “Ctrl+[“ and “Ctrl+]” respectively. I thought those bindings were appropriate. So, while in the editor view I press “Ctrl+[“. It says “Start Kbd Macro” in the status line. I then press the key sequence I described in the previous paragraph. I then press “Ctrl+]” and it says “Kbd Macro defined” in the status line.

Now I have a macro, but it doesn’t have a name. Let’s give it a name with the “name-last-kbd-macro” command. This is one command that I haven’t bound to any key at all. I don’t use it enough for that to be worthwhile for me. Fortunately, Emacs+ provides a way to directly execute commands without key bindings. This is done with the “execute-extended-command” command, which I have bound to “Alt+x” (just about the only command I’ve bound that has the same binding in Emacs+ as in my Emacs environment). Obviously, this is one command that you definitely have to have bound to a key if you want to execute it. After pressing “Alt+x”, I enter “name-last-kbd-macro” (actually, I just enter “nam” and press TAB, which completes it to “name-last-kbd-macro”, using another feature from Emacs, command completion).



I press Enter and it asks me “Name for last kbd macro:”. I enter “goto-next-search-occurrence”. At this point, you could manually execute “goto-next-search-occurrence” by entering it at the “Alt+X” prompt.

Now is a time that you could bind this new command to a key or key sequence. I would have liked to find a somewhat mnemonic key sequence for this, but I ended up with just “Ctr+;, A”.

Now I have a macro with a name, but it isn’t saved. In order to save macros, you should first go to the “Kbd Macros” section of the Emacs+ preferences page. You should set up a directory somewhere with a reasonable name. I created a “EmacsPlusMacros” directory off of my home directory. Enter the path to that directory in the “Save/Load Kbd Macro Storage Directory” field. Set the “All” checkbox in the “Load Saved Kbd Macros on Startup?” section. Save these settings.

Now we can save the macro. Press “Alt+x” and enter “save-k” and press TAB to complete to “save-kbd-macro”. Press Enter and it will ask “Save Kbd Macro”. Enter “goto” and press TAB to complete to “goto-next-search-occurrence” (assuming you don’t have any other commands that begin with “goto”).

Now everything is set up. Exit Eclipse and restart it. From the editor view, run a search for something. Press “Ctrl+;, A” (or whatever you bound “goto-next-search-occurrence” to). The editor view now shows the first occurrence, and your focus is still in the Editor view.

Taking Macros to the Next Level


Now that you've defined a macro, along with a key binding for that macro, it's critical to realize that that key is just like any other. You can now define additional macros that compose that first macro as one of its steps.

As a real-life example, I recently had a set of search results that represented a pattern that I needed to make changes to. Remember again that the key bindings I specify here are my bindings, which may be different from what you have.

While in the editor view looking at the first search occurrence, I pressed the key to start recording a macro (Ctrl+[). I started the macro with the "Home" key because going to a search occurrence puts the cursor at the end of the search string on the line. I then pressed the key I have bound to the Emacs+ "query-replace-regexp" function (Ctrl+;,R). I entered the source string and the replacement string and pressed "." at the next prompt to do the one replacement and exit. I then pressed "End" to go to the end of the line, then I pressed the key I bound to my "goto-next-search-occurrence" macro (Ctrl+;,A), then I ended the macro (Ctrl+]). The key to building a macro that steps through a list is to end the macro with the key that advances to the next entry.

The macro I really defined actually did three different replacements at different points in the file, all of which I did just by pressing keys.

At this point, I simply executed the macro with the "kbd-macro-call" function (Ctrl+\,E) as many times as necessary to step through all of my search occurrences. When I got to the end of my search occurrences, I had numerous modified files, so I did a "Save All" from the menubar.

I could have used the ability in Emacs+ to provide a "prefix argument" to any command, which is used to modify the behavior of the command. When you provide a prefix argument to "kbd-macro-call", it treats it as an integer that represents the number of times to run the macro consecutively. The function is called "universal-argument" (Ctrl+;,Ctrl+U).

Wrap up


This set of practices and tools should be a big help to you and your abused wrist. Be sure to mark Emacs+ as a Favorite in the Eclipse Marketplace.
Post a Comment