Where parallels cross

Interesting bits of life

Moldable Emacs: molds need examples too!

Too long; didn't read

Molds can be challenging to use. Let's use tests to document them then! Let me show you how moldable-emacs is self documenting. And that one can generate useful documentation from source code.

The problem

The best systems are self documenting. Creators of things like these are super cool. I came to understand that the best of the best are those that design a tool in such a way that you can use the tool to learn/understand it. Pretty convoluted, right? An example helps: in Common Lisp I can use an inspector to see what a thing is.

(inspect 'inspect)
The object is a SYMBOL.
0. Name: "INSPECT"
1. Package: #<PACKAGE "COMMON-LISP">
2. Value: "unbound"
3. Function: #<FUNCTION INSPECT>
4. Plist: NIL

I find this cool because the inspector works on itself. Similarly on how you can edit Emacs source in Emacs.

An amazing way I have seen this done is in GlamorousToolkit. GT is a Pharo/SmallTalk system. So everything is an object. These objects may be complex. The user can do more if she has examples to work from. Now GT made sure to extract as much value as possible from tests. So unit tests check objects. But also produce examples for how the object works.

For example, notice how the object behind GT's Wardley Maps defines examples.

/assets/blog/2021/10/02/moldable-emacs-molds-need-examples-too/screen-2021-09-24-22-11-04.jpg

The green icons mean that I ran those examples as tests. But I can also inspect them to learn how to use that object. So I can both validate the object and learn about it from them. And GT let me view this information in the shape I need: view the example, visualize the graphic it creates, open the source code or run tests. These are just views of the same thing.

Then self documentation becomes more about your tool recognizing a pattern and make that accessible for you too. It is about inclusivity.

Then the question: how does moldable-emacs learn from these majestic examples?

It is a problem indeed

I like the idea behind self documentation because it inspires me of doing the best I can with the little I have got. As we have seen, if I put effort in writing an unit test, I should also use it for documentation. And the extra benefit is that the docs are finally alive: users may keep updating examples to fit to their needs. By doing so they also update tests. A healthy feedback loop!

Lisp comes with macros. The idea here is that if functions are powerful, why not to apply that idea to the source code itself? So we can edit code with code. Again we do a lot with the little we got.

While I was developing code-compass, I ended up creating a doctor function because somebody was struggling at finding the dependencies they needed to use my tool. A doctor function shows you what dependencies you miss. I think a doctor function is a patch. Somewhere in code-compass's source there is an import. Or even a statement that invokes a software that is not available by default. By this I mean that the information is there. It is just well hidden. This inaccessibility forces me to spend more time (both in writing and maintaining more software) while the computer could as well do that for me.

Again the lazy me wants the machine to do the boring tasks. Can moldable-emacs improve over code-compass?

And there is a solution

The secret is: patterns. GT uses special syntax to mark examples. Macros use defmacro to mark a special function that acts on source. We can call names other people because we associate a name to a pattern (a face). Ops, I went off track!

Ahem, let me show a pattern in moldable-emacs.

:given (:fn (and
             (executable-find "graph")
              (me/require 'esxml)
              report))

Actually there is more than one here. First we have the :given which tells there is a precondition. Then we have :fn that I have recently introduced. And finally we have (executable-find "graph") and (me/require 'esxml)!

This last ones are the stars of the show today. I have been evolving a pattern: any time I use an external Emacs package or an external software, I use these functions. We need to get the most from the little we got, remember? Indeed, I find these functions useful as precondition of a mold. If these return false, the mold is unusable. So the first benefit is mold selection. And you can see that this pattern hints that we can collect dependencies easily. Do you see where I am going?

Now moldable-emacs is about molds that help you understand software in the way you need it. In this case, I would like to know what molds I can use and what I can't. And if I can't, what am I missing.

This is how it works.

You can see that the mold "WhatMoldsCanIUse" shows two sets of molds: the ones I can and the ones I could use. This mold behaves according to the context, so I run it on something looking like an IP address to trigger the "Decode IP address" mold. We can see that I am missing a dependency there. The cool thing is that I get a link that brings me to find the dependency. It would be trivial (any PR welcome!) to improve the mold to let Emacs install that package for me!

Moreover, I showed that I can open a "Demo" link for that mold. That is how moldable-emacs learn from GT. Molds can provide examples. You can demo these to preview a mold, if you are unsure of how it works. These examples can also work as tests. This story has rough edges (for example, in handling images), but you can already run things like the following.

(me/test-mold-examples (me/find-mold "Playground"))

The plan is to create a mold to do just that. So that when you are on a mold you can unit test it. (At some point, that will also become a condition for the mold to be usable.)

Again, you can see that now we are applying molds on molds. It reminds me of the previous Common Lisp snippet (inspect 'inspect).

Documentation, testing, listing dependencies and demos all rely on the structure of molds. That data format creates a pattern our Emacs can use to give valuable information to us.

And we can also mix things! Look for example how we can get detailed information about the "Query" mold.

(me/mold-doc "Query")

Here me/mold-doc mixes the :docs and :examples of a mold to produce detailed documentation. You can access these easily using the me/mold-docs command. Please note that I needed to write examples for demo and testing needs, but documentation comes out for free!

All in all, this feels a good start to make moldable-emacs self documenting. There are still huge issues for molds with side-effects: for instance, I could not write examples yet for the molds that show notes. Testing those would fail because different users have different notes. Still I am sure I can overcome those issues somehow later. The point is that making documentation a first class citizen and easy to keep up-to-date is possible (and cheap)!

Conclusion

When you write your first mold add some docs! And even an example if you are courageous! I will explain later the facilities to make easy to add an example. In the meanwhile explore the documentation that is generated for you with me-mold-docs.

Happy exploring!

Comments