Let’s talk about terminal emulators. A never ending story.
I recently wrote a blog posting about UW ttyp0, a monospaced bitmap font with great unicode coverage. This is now my font of choice in terminals.
I’ve been using XTerm as terminal emulator for many years now. One important thing to note about XTerm is that you choose a font and then XTerm uses only this font. This might sound a little confusing, yes. Some other terminals work differently: You can specify several fonts, ordered by priority. If the terminal is then asked to display a glyph which is not present in the primary font, it tries to find that glyph in the secondary font, then in the tertiary font, and so on. This is known as “font fallback” or “fallback fonts”.
As already mentioned, XTerm does not do this. This means that your font must be of extraordinarly good quality. It must provide roman, italic and bold glyphs and it must be available in several sizes. Plus, I really love bitmap fonts, so every single glyph must be hand-crafted. This sums up to a hell lot of work for the font author. So, Uwe Waldmann, the author of UW ttyp0, did a very, very good job and probably invested a great deal of time. But Unicode is so huge, Mr. Waldmann can’t possibly include every Unicode glyph. So, of course, even in UW ttyp0, I was missing some glyphs. Hum.
Now, all of that is only necessary because XTerm can’t do font fallback. This has been bugging me. I was happily using XTerm for a long time, but not having fallback fonts available felt somewhat archaic.
What other terminals are there?
First of all, there is st. It’s written by members of the suckless community, so you can expect a high code quality. This is the first terminal that you should give a try if you’re looking for an alternative to XTerm (or whatever you’re using right now). Today, st is pretty rich in features and should work very well. I’d be using it, too, if it wasn’t for one little detail.
st comes with its own terminfo entry. Almost all applications use the
terminfo database to determine the terminal’s capabilities. Problem is,
if you connect to another host via SSH, the terminfo database on that
host is being used. This means, if I install st on my machine, then its
terminfo entry is missing on all remote machines. Not even “
works properly without a matching terminfo entry.
I have to deal with hundreds of remote hosts, many of them are very old. It’s impossible (or rather, very impractical) for me to copy st’s terminfo entry to all of these hosts. Thus, everything is broken. I could disguise st as an XTerm. This feels like a dirty workaround, though, and compatibility is not guaranteed.
(I also don’t like the fact that st doesn’t have its own scrollback buffer. You need to run something like tmux or dvtm. Meh.)
Still, I am in strong favour of st. It tries to do things the right way. The code is supposed to stay clean and hackable. st is a very important project. Go, give it a try! :-)
Okay, what else is there?
rxvt and variants. Well, same problem as with st (terminfo entries). Plus, font fallback is not that good. It’s not perfect in st either, but I could actively work on improving font fallback in st because of st’s code quality. rxvt is huge. You don’t want to mess with that. I’m also worried by the fact that there’s a package called “rxvt-unicode-patched” in Arch. Isn’t the “real” rxvt-unicode good enough? Oh, and rxvt-unicode itself is a fork of rxvt, which means that urxvt was not written with unicode in mind. Why a terminal must have support for Perl extensions, is beyond me anyway.
Finally, there’s VTE. VTE is a library related to the GNOME project. It is used by the GNOME Terminal itself and many other programs. Most notably, there is sakura, LilyTerm and ROXTerm. They all claim to be somewhat lightweight and, to some degree, they are. Well, of course, their code is quite lightweight, because all the dirty work is done by VTE.
None of them felt right. They all do much more than I need. I don’t need tabs, I don’t need menus, I don’t need a runtime config file. Just give me a terminal window.
VTE, however, looked very interesting. Font fallback works very well. I guess that’s because VTE is used as a backend for GNOME Terminal and the GNOME project cares a lot about internationalization. Also, VTE tries to mimic XTerm’s escape codes, so I don’t have any problems SSH’ing into old machines – every UNIX system knows XTerm.
I tend to “reinvent the wheel” quite often and I feel the need to provide a reason for that. You see, I heavily modified dwm. I wrote lariza. Over the years, I “accidentally re-wrote” many tools that already existed. I like to write code on my own because you learn a lot by doing so. You don’t fully understand what’s going on unless you do it yourself. Yes, it’s easier to use pre-existing programs and shut the hell up. But I want to do it myself. That’s my hobby. Even when using a library like VTE, you learn things. Learning is the whole point of what I’m doing here.
After a quick glance over VTE’s manual, I was pretty confident that this is the way to go: Writing my own VTE frontend.
And so, xiate came into existence. It’s a “rather simple” terminal emulator. You get a VTE terminal window. Period. There are no tabs, no menus, no nothing. Yes, xiate is meant to be used by “power users” who probably run a tiling window manager and spend their whole day in front of terminal windows.
While xiate tries to be a minimalistic program, it certainly does not qualify as “suckless” because you need VTE. VTE needs GTK+ 3 and GTK+ 3 pulls in a lot of dependencies and huge amounts of code and what not. This is similar to lariza and even surf: The code of the “frontend” is just fine, but the library behind it is gigantic.
Still, compared to most other terminals, xiate is pretty lightweight and hackable.
There is one big problem with VTE: The initialization phase is very
expensive. Well, why wouldn’t it be? There’s so much stuff to do, all
the GTK and GLib objects, Gdk, Pango, you name it. This is not a problem
of xiate but of every VTE terminal. But slow startup times are a
“no-go”. That’s just inacceptable for “power users”. Sure, if you’re an
average GNOME user, you click on the terminal icon and then you need to
move your hand from the mouse to the keyboard and when you’re done with
that the terminal finally shows up – ideally with some fancy eye candy
which takes up some more time. It’s fine if all that takes about a
second. But me, I hit “
Super + Enter” and then I want my terminal to
be ready. This must not take more than a couple of milliseconds.
What can you do about that?
I decided to borrow the idea of a client-server model from rxvt. You run
xiate” in your “
~/.xinitrc” (or whatever startup mechanism you use)
and then tell that process to open terminal windows. xiate provides a
UNIX socket for that purpose. The default client, “
xiatec”, is just a
shell script that uses socat to write to that socket. Opening the
very first window still takes some time. All following windows are
This model could be considered an ugly workaround. And indeed, it’s somewhat problematic. The most obvious flaw is: If the daemon process crashed, all your terminals would be gone. I can’t estimate how often that happens, because I have not yet used VTE long enough. I’m pretty sure, though, that, sooner or later, VTE will crash at least once. All software has bugs. Time will tell.
Another thing to keep in mind: “
xiatec” immediately returns. You can’t
do something like this:
#!/bin/bash # ... do something ... xiatec -e vim $somefile # ... continue when the terminal window is closed ...
I think this is okay. Why would “
xiatec” need to block until the
window is closed? Just because other terminals do that (as a side effect
of not forking)? I don’t see a valid reason, but I’d be happy to hear
Either way, I’d rather ditch the client-server model.
For now, I still use UW ttyp0. In just a few weeks, I’ve become very accustomed to its look. Now, Terminus looks a little weird to me. ;-)
I’ve been using xiate for about two weeks now, both at work and at home, for many hours per day. I’m pretty satisfied with it.