I am currently working on an application in Emacs, which will (in particular) display some tabular data – very much like Dired or list-processes
. Since I expected that the problem of displaying such tables is already solved and there’s no need to reinvent the wheel, I asked on the Emacs mailing list about such a utility. It turned out that there are two of them built in Emacs.
The first one is called Tabulated List Mode. It is used for listing packages in package.el
, for listing processes and for the buffer list. The other one is EWOC, which is used by Emacs’ Version Control module and for ERT (which, I have to admit, I know nothing about – I’ll try to fix that some day).
So, which one is better?
As is often the case for programming questions, it depends. I first decided to use EWOC for my application, then switched to Tabulated List Mode (which I’ll call TLM for short from now on)… only to get back to EWOC next. Why did I do that? Read on.
The main features of both tools are quite similar. Both can be given a set of data (records with some fields, so to speak), display them in a given buffer, and – when the point is somewhere in this table – determine which record the point is on (although TLM’s functions to do that are undocumented – I filed a bug report about that). The main differences are: data structures used to keep the records and the printing routines.
While TLM uses a plain old list (either kept in a variable, or generated dynamically by a function), EWOC uses an ad-hoc two-directional list, made from CL-like structs. This is a bit strange, especially that the set of atomic operations on that list implemented in EWOC is rather small. Basically, you can only enter a new element to the list and delete an element from the list. In particular, you can’t easily split the list into two – that you have to implement yourself – so one of the most natural sorting algorithms, MergeSort, is neither implemented nor trivial to add. You can, however, collect all entries satisfying some predicate into a (usual) list and remove entries satisfying some predicate from the list. This way, you can implement a (probably not the most effective) sort by copying the EWOC into a list, emptying it, sorting the list (using the built-in sort
) and generating the EWOC again. Since in my use the number of entries is at most two-digit, I didn’t care for any attempts at faster sorting.
On the other hand, TLM shines at sorting: sorting by any column (field) is already implemented, using string<
by default, but allowing for custom predicates (or disabling sorting by any particular column altogether).
This leads to another difference: the display. TLM displays a fixed header with column titles and an arrow showing which column is used for sorting (and in which direction). EWOC has a more free-form look-and-feel: it is the programmer who is responsible for setting up the header (and footer), displayed above and below the table. They are also not confined to one line. (In fact, this was one of the main reasons I switched to EWOC: I completely don’t care about sorting by different columns, I only have two fields which are really useful for sorting, and one of them need not be displayed anyway.)
The next main difference is in fact the scope of both packages. While TLM (as the name suggests) is a complete major mode (derived from Special Mode), EWOC deals only with displaying the table – the user is completely responsible for setting up the mode, defining the keymap etc.
Last but not least, EWOC has a tiny but complete example in the docs; for an example of using TLM, I read portions of simple.el
, where the functions responsible for process lists are implemented.
So which should you choose for your application? If you want something simpler to set up, and not necessarily extremely customizable, TLM may be the way to go. If, on the other hand, you want more control over the display (in particular, the header and footer), and you don’t expect having to sort long lists of entries (like, say, maybe several hundred), and you don’t mind coding a bit more things yourself, EWOC might be better.
Happy hacking!