XTerm: It's Better Than You Thought

(Day 10 of 30 Days of Blogging)

A couple months back I switched my terminal from xfce4-terminal to the venerable xterm. For some reason I always put xterm in the same bucket as xclock, xmessage, or any other prehistoric command starting with X that comes pre-installed on any graphical Linux distribution.

It was surprising to learn that xterm is still very much actively developed. Even more surprisingly, it turns out xterm has incredibly low input latency compared to modern terminals. This is easy to test at home, try typing in xterm compared to any other terminal and feel how much snappier it is.

The lower latency alone is worth the price of admission in my opinion, so I went about configuring xterm as my default terminal. The configuration goes in ~/.Xresources and you need to run xrdb ~/.Xresources after every change, or make vim do it.

Basic Configuration

Here are some “modern” sensible defaults I ended up landing on:

! Sensible defaults
XTerm.vt100.locale: false
XTerm.vt100.utf8: true
XTerm.vt100.scrollTtyOutput: false
XTerm.vt100.scrollKey: true
XTerm.vt100.bellIsUrgent: true
XTerm.vt100.metaSendsEscape: true

And here are some visual styling options, not including colors:

! Styling
XTerm.vt100.faceName: DejaVu Sans Mono
XTerm.vt100.boldMode: false
XTerm.vt100.faceSize: 11
XTerm.vt100.internalBorder: 16
XTerm.borderWidth: 0

XTerm supports key binding, but the syntax is non-obvious:

XTerm.vt100.translations: #override \n\
    Ctrl Shift <Key>N: scroll-back(1, halfpage) \n\
    Ctrl Shift <Key>T: scroll-forw(1, halfpage) \n\
    Ctrl Shift <Key>C: copy-selection(CLIPBOARD) \n\
    Ctrl Shift <Key>V: insert-selection(CLIPBOARD)

This allows copying and pasting to the clipboard (not just the X selection) with shift-ctrl-C and V. It also allows scrolling up and down with shift-ctrl-N and T (you can switch this to K and J to match vim keys in Qwerty).

URL Handling

So now we have a pretty usable setup, but there’s one more incredibly useful feature that was hard to figure out: opening URLs in the browser. We could of course select the URL and copy-paste, but there’s a better way.

XTerm has a configuration option called printerCommand which is a command that is piped all the text currently visible in the terminal. As the name suggests, it’s meant to be used to implement printing to physical paper, but we can save the trees and hijack it to instead scan the screen for URLs and open the browser:

#!/bin/sh -e

grep -Eo '\bhttps?://\S+\b' |
    uniq |
    ifne rofi -dmenu -i -p "Open URL" -auto-select |
    xargs xdg-open

This greps for URLs, removes consecutive duplicates with uniq, and displays a rofi menu to choose between them if there were multiple URLs. ifne is included in moreutils. Put this script in an executable file called select-url in your $PATH and then add this to .Xresources:

XTerm.vt100.printerCommand: select-url

XTerm.vt100.translations: #override \n\
    ...
    Ctrl Shift <Key>W: print(noAttrs, noNewLine)

Now when you press shift-ctrl-W, any URL shown in the terminal will open in the browser. You don’t have to select anything or use your mouse at all, nice!

Someday it would be great to improve select-url to also scan for email addresses. Maybe during the next pandemic…

Peeking at the Alternate Screen

Sometimes you open a fullscreen application like vim or a man page and you need to refer back to some text on the shell. Use this keybind to toggle back and forth:

XTerm.vt100.translations: #override \n\
    ...
    Ctrl Shift <Key>H: set-altscreen(toggle)

You can even use it view a previously opened vim or man page after you close out of it!

Opening New Terminals at the Current Directory

There’s a keybind action called spawn-new-terminal() that can be used for this, but even better is using xcwd to get the working directory of any currently focused window. Then you can put this in your i3 config for example:

bindsym $mod+Return exec --no-startup-id cd "`xcwd`" && xterm

Wish List

XTerm is missing a few small features:

  • Text reflow when the terminal is resized.
  • Fallback fonts don’t seem to always work. Maybe I’m missing a config option?
  • Transparency not natively supported. I don’t care about transparency but maybe it’s important to some people.
  • Occasionally strange flickering with picom, possibly a bug with picom?

In the end this wasn’t enough to stop me from using xterm, but the lack of text reflow still irks me from time to time. Overall, I’ve been pleasantly surprised with xterm after taking the time to configure it.