Equake: A drop-down console written in Emacs Lisp
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.
-
Where installation via
quelpa-use-package
is described. This method is nearly as easy using the plainuse-package
package to pull from Melpa. ↩︎ -
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. ↩︎