Hybrid of GNOME Do and Emacs ido mode for a standard VT100 terminal.
While working on my dissertation--which involved a lot of
research-caliber rather than production-caliber C and C++--I went
through an earnest phase of using vim
rather than emacs
with the
goal of having fairly evaluated both. In the process, I began sorely
missing Emacs's ido mode
. At the same time, I was commonly
working on Ubuntu systems where the GNOME Do application launcher
was having a bit of a moment. This all led to my interest in creating
a extensible, terminal-based ido-mode
-like prompt.
term-do
was largely duct-taped together as a means of
procrastination in between doing other research tasks. I did, however,
have a few things in mind while working on it:
-
Show completions as each character is typed in an
ido-mode
-style -
Allow "rotating" through the completions with Ctrl+S and Ctrl+R.
-
Support completions from a variety of (pluggable) sources.
-
Fast startup time: Should be near-instantaneous to launch from a terminal; any delay would disincentivize use in favor of plain bash completion.
-
Portable with as few dependencies as possible.
These loose requirements spiraled into a series of elements that went into the (overengineered) design:
-
Plugin system implemented as dynamic libraries, providing a mechanism to yield custom completions.
-
Hand-rolled ternary search tree implementation for quickly identifying completions from a prefix.
-
Bash history file parser for weighting commands such that common completions can be sorted in use-order.
-
Optional client/server mode for even faster startup time on older hardware.
-
A persistent mode where the process does not exit after the completed command is run, essentially functioning as a lightweight shell.
Because completions are implemented solely as plugins, the default
plugins that are built and used are the launcher
and dir
plugins;
other plugins are not included by default. The full list for
reference:
-
dir
: Yields directory/file completions based on the current command. -
launcher
: Reads the launcher configuration file which defines commands + possible completions. This configuration format became richer as time progressed to be a crude half-reimplementation of bash completion. Supports hardcoded completions as well as "parse the man page for flags" and "run command that generates completions" modes, including aliases with the_
prefix. -
rnd
: adds random junk completions, for testing purposes. -
bash-comp
: experimentation to shell out to bash and scrape it for bash completions directly; never worked quite as it needed to so I abandoned it for thelauncher
plugin instead.
Though I do not get as much use out of term-do
these days, I've
consistently packaged it for whatever OS I'm using so it's
available. Notably, there is an AUR package and a NixOS derivation
included in the pkgs
folder of this repo. See this commit for
an example of how to overlay the Nix derivation.
I found that having to type the term-do
command to run it was
cumbersome enough to discourage using the tool. So instead, I've
mapped the command to the Emacs-esque M-x
shortcut. This is done in
bash
using .inputrc
with:
$if Bash
"\M-x": "term-do\C-M"
$endif
and for zsh
using .zshrc
with:
bindkey -s "^[x" 'term-do^M'
If you want term-do
's cd
functionality to bubble up to the current
terminal, then you can wrap it in a shell function:
term-do() {command term-do "$*" && builtin cd $(cat ~/.term-do.d/pwd)}
The rest of the keyboard shortcuts are likely familiar to users of Emacs:
C-s
: rotate completions forward
C-r
: rotate completions backward
tab
: add current completion
enter
: run commandC-f
: remove current token and rebuild completionsC-c
,C-d
,C-g
: quit
There are better completion options these days, particularly in zsh
,
and term-do
's code has bit-rotted significantly. But I still haven't
found a terminal completion that matches ido-mode
closely enough for
my tastes. Hopefully one day I can resurrect term-do
, possibly in
the form of a zsh
plugin or similar to fill this niche.