‘The half minute which we daily devote to the winding-up of our watches is an exertion of labour almost insensible; yet, by the aid of a few wheels, its effect is spread over the whole twenty-four hours.’

Equake: A drop-down console written in Emacs Lisp

Benjamin Slade

Over the holiday break I’ve been working on developing a Quake-style drop-down console, dubbed Equake / equake. It is not yet on Melpa, but is accessible at https://gitlab.com/emacsomancer/equake.1

equake, written fully in Emacs Lisp, is designed as a ‘classic’ drop-down console interface like Yakuake, inspired by ‘cheat’ consoles in games like Quake. It provides access to various ‘shells’ implemented in Emacs, including shell (an Emacs wrapper around the current system shell), term and ansi-term, (both terminal emulators, emulating VT100-style ANSI escape codes, like xterm does), and eshell (a shell written entirely in Emacs Lisp). equake allows for multiple ‘tabs’ (which can be running different shells), and allows tabs to be re-ordered and renamed.

My impetus for creating equake was to hijack my own workflow into using John Wiegley’s fantastic eshell, an Emacs module which ‘translates “shell-like” syntax into Lisp in order to exercise the kernel in the same manner as typical system shells’, allowing for a similar working environment even in hostile, alien OSes like w32.

eshell is somewhat sparsely documented, but some useful resources exist, including a fairly extensive video overview done by Howard Abrams which I highly recommend. It has a number of great features, either inherently or via additional Emacs packages, including features from Plan 9‘s terminal, as well as Fish shell-like auto-suggestions.

equake has been successful in my personal goal of using eshell for 99% of my terminal work, and I am looking forward to making further using of a shell which can handle Lisp syntax as well.

Most of the equake code is keeping track of tabs, and frames for multi-monitor set-ups. This is trickier than it would seem at first, especially as each screen/monitor can have it own set of tabs (this allows me to recreate at least a part of AwesomeWM’s screen-independence in other environments). In theory equake should work fairly well across platforms, as it makes use of the frame.el, which includes code for MacOS and Windows (but I haven’t test either platform). Probably more work needs to be done to get equake to work properly on tiling window managers like AwesomeWM or StumpWM. But it seems to currently work fine in KDE Plasma and Gnome Shell (both X11 and Wayland).2

I learned a good deal about how Emacs manages frames. I originally used Emacs’ make-frame-(in)visible functions to hide/show the equake frames. However, the implementation of these is very odd. Applying make-frame-invisible to a frame once appears to render it invisible, but Emacs still considers it to be visible, which means that, for instance, frame-visible-p will still report the frame as being visible and, worse, functions like make-frame-visible and raise-frame will have no effect whatsoever upon the frame in question, because Emacs treats it as ‘visible’. Only a second application of make-frame-invisible will register the frame as reportably invisible to Emacs. This is easily enough worked around simply by using a ‘double tap’ of make-frame-invisible to the relevant frame. However, I ran into numerous other issues in the use of make-frame-(in)visible, including the fact that frames set at less than 100% width end up re-appearing in a position other than their original position, and frames sometimes spontaneously resize when re-appearing or being un-fullscreened. I tried for a long time to work around these issues, but found that even trying to force the frames into doing what I wanted them to do via applications of set-frame-position was a non-starter, as application of this function to malpositioned frames resulted in significant lag – which defeated the purpose of using make-frame-(in)visible in the first place, which was to gain a slight performance improvement over destroying and recreating frames. In the end, using destroy-frame and make-frame to ‘hide’ and ‘show’ the drop-down console ended up being the most performent solution.

Destroying and recreating frames means also worrying about remembering the last buffer used in a frame as well as the window-history for the frame, so these also make up a decent part of the equake code.

On single-screen set-ups, equake, once installed, is designed to have a equake console frame toggled to drop down or be rolled up by executing a command which invokes the (equake-invoke) function bound to a key like F12 via:

emacsclient -n -e '(equake-invoke)'

Getting equake to work well on multi-monitor setups ended up being rather challenging, since Emacs doesn’t know exactly which screen is ‘active’ unless that screen also has an active Emacs frame. The solution, which I managed to get to be nearly as fast as the simpler non-multi-monitor solution, is to launch ‘Emacs probes’ which are used to determine which monitor is ‘active’ and are then destroyed, invoked via:

emacsclient -n -c -e '(equake-invoke)' -F '((title . "*transient*") (alpha . (0 . 0)) (width . (text-pixels . 0)) (height . (text-pixels . 0)) (left . 0) (top . 0))'

(The title is important as it’s the key to being able to quickly destroy these ‘Emacs-probes’, and the other frame-settings are there to minimise the visibility of the probe-frame during its brief existence.)

If you’re looking for a drop-down for things other than shells/terminals, alphapapa has a similar Emacs package designed as a general-purpose drop-down (e.g. for Org mode buffers etc.); yequake; and a specialised version for org-capture.

I hope to add a few more features to equake, but at this point it seems stable and is usable for what I wanted to use it for, being a Lisp console for a Lisp shell. Comments and suggestions are, of course, most welcome.

  1. Where installation via quelpa-use-package is described. This method is nearly as easy using the plain use-package package to pull from Melpa. ↩︎

  2. Another part of the impetus for equake is wanting to increase my machines’ ‘Lisp quotient’ after moving a number of machines from AwesomeWM to KDE Plasma, rather than to StumpWM as I had originally planned. Of course, I could replace Kwin with StumpWM, and I plan to experiment with this, but I rather like some the eye-candy Kwin provides. ↩︎