Text Lens UI Paradigm
There is a UI paradigm that I love, and I’ve decided to give it a name: the Text Lens.
Off the top of my head, I can think of 4 existing instances of the Text Lens paradigm. I didn’t write any of them, and I can’t take any credit for the idea. But I would like to see more of them, and maybe I’ll write some in the future.
So let me lay out the examples that I know of, and suggest some more places I would like to see them used.
The idea of the Text Lens is to give a (possibly minimized) view of some kind of data or structure as text, and allowing you to edit the text and save it to reflect those changes back to the original. The four examples I can think of right now:
wdired
in Emacs
Emacs has dired
mode, which lets you view directory listings as text. wdired
lets you also edit the text, then save the changes back to the directory. So, for example, you can use your editor to perform a series of regex replacement renamings, delete lines, etc, then commit those changes to be executed on the actual files, renaming them, deleting them, or modifying attributes like file permissions or timestamp.
wgrep
in Emacs
This is my favorite one by far. wgrep
turns a grep
(or Ripgrep rg
or similar tools) result page into writeable text, which it can then flush out to all of the relevant files. So you can use grep
or rg
to search for instances of identifiers throughout your code base and documentation, and perform search-and-replace on all files at once. You can use context flags for grep
to get more lines before or after matches to operate on surrounding context. It’s such a retrospectively obvious idea, I wonder why nobody wrote it much earlier. It has become one of my favorite Emacs packages.
vidir
But text lenses don’t have to be tied to Emacs. In fact, it’s probably best if they are built as separate tools that can be used with any text editor.
The vidir
command is like wdired
— you get a text view of a directory listing and edit it. It is both better and worse than wdired
— better because you can use any editor (it’s not limited to Emacs), and because rather than doing it on a single directory, you can also pipe any file list to it, eg. with find . | vidir -
and edit full path names. Slightly worse because you can’t edit other file metadata, just the paths. Like wdired
, changes to file paths, or deleting lines, results in moving or deleting files.
Rebase buffer in Git
When you perform an interactive rebase with git
, IE git rebase -i
, it produces a file listing commits, where each line says pick HASH COMMIT_MESSAGE
. You can reorder the lines to reorder the commits, or delete lines to drop commits, and you can change the word pick
to several alternatives that affect how the commit is treated (eg. merging it with the previous commit, stopping at the commit to manually edit or perform other actions before continuing, editing the commit message, etc).
Ideas
The main trend is that they take some data that is not itself text, or that forms a window into pieces of text from multiple places, and they provide a text file that you can edit, using the editing power tools that you (maybe) know to quickly make broad changes and flush them out. wdired
, vidir
, and wgrep
all make the process much faster, easier, and more centralized than doing the same operations with alternative methods. The git rebase
UI doesn’t even have any great alternatives, as far as I’m aware. (Magit provides an alternative rebase UI that is, in my opinion, strictly worse. I go out of my way to disable Magit’s rebase UI from ruining the rebase buffer UI.)
Let’s brainstorm some other places where this paradigm would be useful:
Audio File Metadata
I would love to have a command to collect the metadata of all audio files (maybe recursively) in a directory as a single temporary file, then let me edit the file and write the changes back out to the individual files. I find music tagging somewhat cumbersome. I have many albums with slight variations in spelling for artist names and such. Occasionally I go through and fix some, but there are always more. This would make consistent tagging a lot easier.
Also I often want to be more audatious in my tagging. It is my music collection. In addition to complete tagging of artists, titles, etc. that are usually there, and metadata that is typically missing but that I want such as a full list of individual artists, recording studio and personel, etc, I want to write custom metadata for my own tagging, ranking, and sorting. I would be much more likely to do that if I had a good interface for it. Though also I would need a music player that handles more metadata fields… Another item on my infinite to-do list that I’ll probably never get around to.
Calendar Events
I want to be able to eg. query for events in a given week and get a text list of them in some simple, editable format. Then be able to edit them and write the changes back out.
wjq
The jq
tool is nice for digging in to JSON trees to access sub fields, including mapping over lists, etc. It would be nice to have a way to write out the minimal result of jq
to a buffer, edit it, and then get out the full original JSON tree with the modifications reflected in it.
This could also exist for other tree data formats like XML or s-expressions.
sqlite buffer edit
I would like to be able to select fields from a sqlite database to a buffer, edit the buffer, then flush the data back to the database. I don’t want to fuss with all of the writing commands or use a GUI tool.
For all of my Emacs nerdery, it may surprise some people that I don’t use any of the in-emacs mail clients. It is likely that one of them already provides a text lens UI for your mail inbox. Anyway, a mail text lens could show one line for each mail with the common metadata, and let you delete lines to delete mail (or preferable move it to a trash or archive or some other configured folder), it could have user-defined tags that you can edit, and it could list the folder and let you edit to move it.
zip / archive listing edit
A text lens UI for creating and editing zip files or other archives would be nice. Different archive formats allow different kinds of top-level and per-file metadata and configuration. A text lens could let you not only change, remove, add, or reorder included files, but also change metadata, the kind of compression used per-file, etc.
Multi-file with file name view
How about a buffer that concatenates multiple files together, with their file names in some kind of special syntax. Then you can do edits on files and their file names together. Eg. you can bulk find/replace names that are included in the file name. Changing file names to fit file contents, eg. when you decide on a name for your skunkwork software prototype, is always a mildly tedious affair. Or this could be an extended feature of wgrep.
What’s in a name?
The name “text lens” seemed very natural to me, a way of viewing and editing data as text. And tt maybe hearkens to the functional programming concept of lenses. But lenses in functional programming are composable, while text lenses are all bespoke tools that don’t have any obvious ways of composing them. Hmm. Tell me if you think of a better name.
A general kind of tool
I love that text lenses let you use a general tool, a text editor, to edit new kinds of data. It lets you use (or hone) existing skills to do new things. It’s a kind of power multiplier, where you can make one tool more powerful, rather than learning more weak tools.
Text lenses give me a similar vibe to programatic file systems, a la Plan 9 or Fuse. I constantly wish that Fuse were better supported and more robust (and that other ideas migrating from Plan 9 to Linux and Unixes generally, like per-process filesystem views, were fleshed out to be more practically useful), and that more things had file system interfaces. Maybe I should write another blog post about programmatic file systems that I want to exist…
That said, you really need a text lens to be easy to learn. If the text lens has some complicated or difficult syntax, then it will be too cumbersome to use. wgrep
, wdired
, and vidir
are very easy and intuitive to use. The git rebase UI is more complicated, but still fairly simple, and it comes with instructions in comments about how to use the different keywords. Some of the suggested text lenses here might end up being too complicated. Eg. some fields for a calendar event can be very complicated while needing to adhere to some rigid specification, for example repetition. But I think you could usefully allow some kinds of writes in simplified syntax, and treating complicated elements in existing events as black boxes.
Anyway, I’m probably not going to write any of these in the immediate future. But please let me know if you write any text lens UIs!