#005

Editor-agnostic plain text table formatter

Last updated:

A while back I wrote a plugin for the vis editor to format plain text tables interactively รก la Emacs Org Mode. No formulas or any fancy spreadsheet editing functions, just formatting. The plugin worked well, but I have to admit, the code was terrible. Editing plain text tables interactively is a hack in itself, but what I wrote was hacky^10. Anyway, after a while, I stopped using vis and went back to using vim. This left me with an unpleasant dilemma: should I maintain the spaghetti code that I no longer used, or let it rot? Even worse, I wanted to use the plugin with vim, but I wasn’t going to write yet another plugin1 that I would eventually abandon. This gave me the idea to rewrite the plugin as an editor-agnostic tool2: ptt.

TL;DR

Usage

ptt(1) can be used from the command line to quickly format a file with delimiter-separated values into a plain text table. However, it can also manipulate its cells, rows and columns by using a unique character called the cursor (a tilde by default) to keep track of the row and column of the table that is currently being manipulated. This is what allows ptt to interact with scriptable editors. Essentially, for an editor to interact with ptt, it needs to do the following:

  1. Insert cursor character at current location in table.
  2. Pipe table into ptt to perform an operation.
  3. Read ptt’s output.
  4. Search for cursor character, move to it, and delete it.

Depending on the operation that is performed on the table, ptt will position the cursor character such that when the editor reads its output, it can know where to move the actual editor cursor.

For example, assume that the following is the content of a file that is open in vim and vim’s cursor is at the ‘X’:

| Item    |XPrice [$] | Qty. |
|---------+-----------+------|
| Lemons  |      3.00 | 2.00 |
| Apples  |      2.00 | 4.00 |
| Chicken |     10.00 | 1.00 |

The ‘Price’ column can be moved to the right by running the following in vim:

:execute "normal i~\<Esc>vap:!ptt column right -\<CR>/\\~\<CR>r "

This results in the following table, where the second column is now the third and vim’s cursor followed the motion.

| Item    | Qty. |XPrice [$] |
|---------+------+-----------|
| Lemons  | 2.00 |      3.00 |
| Apples  | 4.00 |      2.00 |
| Chicken | 1.00 |     10.00 |

All the macro did is to perform the four steps mentioned above. However, instead of writing these confusing macros manually, one would ideally write bindings for their editor of choice to interact with ptt. At the time of writing I have implemented bindings for the vim and vis editors. These can be used as examples by anyone wishing to write bindings for another editor.

I’m aware that calling an external tool for every operation performed on a table is not very efficient. However, I believe it is a worthy trade-off to enable different editors to benefit from ptt. Furthermore, ptt is written in POSIX awk(1), which makes it very fast, portable, and free of dependencies.


  1. I knew of vim-table-mode, which is a powerful plain text table editor plugin for vim. However, I wanted something simpler that everyone could use, not just vim or vis users. 

  2. Vis users can still use the old plugin by cloning it from the ‘vis-tables’ branch. However, this plugin will no longer be maintained.