Sunday, October 2, 2011

Fixed Point Emacs Completion

One of those annoying things about GNU Emacs is that when a window is popped up containing completions, it derails what you were doing.

First, completion windows take up half the frame. I can't actually figure out how to change this easily. Think of how you use the completions window. One primary way I use it is: I try to complete a symbol, realize that it doesn't have enough information, then type more and try again. In this case, having so many options doesn't help at all. I only need to know if there the symbol can be completed or if there are multiple possibilities.

Second, the position of the cursor on the screen is almost always changed when a window is popped up, and interestingly enough, not even in a predictable way. This means that if I try to perform a completion which I expect to have only one completion, thus not popping up a window, but it actually has several possibilities, I have an annoying situation. This could happen as a result of a symbol I didn't know about making the completion ambiguous resulting in a pop-up and a partial completion or it could be due to a typo. In either case, I need to examine what is at the command prompt in order to find out the proper course of action. This is unavoidable. What is avoidable, however, is the need to move the command prompt around the screen forcing the user to go searching for the new location.

In addition to these pretty legitimate claims, I also just find the entire process to be jarring. I often find myself kicked out of my current train of thought as I search for where my cursor has gone. Here is an example of how completion tends to work in Emacs.

When these two effects combine, I got so frustrated I started leaving my frames split in half so that completions will show up in the other window without effecting the window I was editing in at all. In a recent Reddit conversation with Stassats, he states that he also always maintains a completion window. To me, this is a big waste of screen space, but at least the point doesn't jump.

There are other solutions to this problem. My guess is that many people struggle with this and each produce their own solution. For instance, here is a post of how to designate a particular window for completions in someones (rather complicated for my taste) completion window setup.

My solution

The code is here, though I can't vouch for it being bug free.

My solution is to have windows pop-up with completions but have those windows be smaller than half the screen. An important distinction is that when a completion window pops up, it will not alter the screen location of the point. In order for this to be the case, we need to pop-up a window in an area of the frame that the cursor isn't utilizing. So, we handle this by identifying where in the frame the point is, then popping up a smaller completion window in either the top or bottom of the frame depending on its location.

To be precise:

  1. See if there already is a visible completions window. If one exists, use it.
  2. See if the current frame has only one window (when not counting the minibuffer). If it does, we know that a popup is desired.
    1. If the current window is actually the minibuffer, create the popup at the bottom of the frame.
    2. If the point is above the halfway point in the frame, create the popup window at the bottom of the frame.
    3. If below the halfway point, create it at the top of the frame.
  3. If it matches none of this, let Emacs do as it would have.

Here is the result:

This works pretty well for me, but I imagine that is just because I might use Emacs in a quirky way. For instance, I usually have one desktop where all of my Emacs windows are. If they are on different desktops, perhaps the "use completions window if 'visible'" won't work very well. I don't know how Emacs handles this. What about terminal emacsclient instances and how does completion there interact with open X windows. All of these things should be configurable.

Anyhow, if anybody else finds this useful and wants to push patches back to me, please do. If anybody wants to grab this code and take over the project, or include it in your project, again, please do.

Other completion extension libraries

While I haven't found anything out there that does exactly what Fixed-Point-Completions does, there are a few libraries that also tweak completion. Most notably, popwin and icicles extend the completions functionality. Icicles is a bit heavy handed for my taste, changing many things in how Emacs functions. Popwin does a lot towards fixing my completion issues, but not enough. The thing which is really missing from both of these is that they still shift the visual location of the point at times.

No comments :

Post a Comment