Moldable Emacs
Moldable Emacs is about molding data into information. You can represent data in many ways. The context you work with defines if a representation is more useful than another.
Moldable Emacs introduces a new concept: Mold. Think of a mold as a function that, given a precondition, transforms some data into the representation you need. This enhances your understanding of things but also allows you to solve specific problems you have by solving general problems with molds
Typically a mold takes as input an Emacs buffer and produce a new buffer. I designed Moldable Emacs so you can easily compose molds, so that one mold can fulfill a precondition for another mold.
Presentation at EmacsConf21 here.
For example, given a source code file, I want to find how complex its functions are. Then I want to know the aggregate complexity of all the functions. This is what I would do.
I have a Python file.
I use M-x me-mold
to choose the “FunctionsComplexity” mold.
I use M-x me-mold
again to choose the “Playground” mold (and write
some code to calculate the total complexity).
I composed two molds for this: “FunctionsComplexity” (show complexity
of functions as an Org Mode table) and “Playground” (similar to Emacs
scratch buffer). The composition preserves (part of) the context
through the local variables self
and mold-data
. An inspector
buffer always shows you their current contents.
Installation
The suggested way to install this package is via use-package. This is my installation configuration:
(use-package moldable-emacs
:init (if (f-directory-p "~/.emacs.d/lisp/moldable-emacs")
(shell-command "cd ~/.emacs.d/lisp/moldable-emacs; git pull;")
(shell-command "cd ~/.emacs.d/lisp/; git clone [email protected]:ag91/moldable-emacs.git"))
:load-path "~/.emacs.d/lisp/moldable-emacs/"
:bind (("C-c m m" . me-mold)
("C-c m f" . me-go-forward)
("C-c m b" . me-go-back)
("C-c m o" . me-open-at-point)
("C-c m d" . me-mold-docs)
("C-c m g" . me-goto-mold-source)
("C-c m e a" . me-mold-add-last-example)
)
:config
(require 'moldable-emacs)
(add-to-list 'me-files-with-molds (concat (file-name-directory (symbol-file 'me-mold)) "molds/experiments.el")) ;; TODO this is relevant only if you have private molds
(me-setup-molds))
If you are using Doom Emacs
slightly modify this:
(use-package! moldable-emacs
...
(me-setup-molds))
(add-load-path! "~/.emacs.d/lisp/moldable-emacs/molds")
I am working on making moldable-emacs
itself explain which optional
and external dependencies you may need for what, but it is still work
in progress. For now an incomplete list from the top of my mind.
Emacs Dependencies
This package requires:
- dash.el
- s.el
- async.el
- thunk.el
Optionally:
- emacs-tree-sitter.el
you can get more functionality if you install tree-sitter’s grammars as well.
- esxml.el
- code-compass.el
- org-ql
- … (check these via the mold “WhatMoldsCanIUse?”)
(Optional) External Dependencies
- graph-cli
- graphviz
- imgclip
- ???
Testing
Install the Elisp Development Tool (Eldev) and run
eldev test
Getting Started
You can start with a fun exercise: access tutorials via the “Show Tutorials” mold. Or you can look in tutorials/.
Similar Packages
This extension attempts to implement Moldable Development for Emacs users. If you speak SmallTalk, try GlamorousToolkit because it is much more advanced.
Why I spend time developing this package
I find Moldable Development interesting because attempts to fill a gap of expression. The context we live everyday often becomes a comfortable prison for ourselves. When I work as a software engineer, I cultivate a vocabulary and a toolkit that elevates me and so separates me from others. I mean if my grandpa asks me about what I am doing at the computer, I typically don’t feel comfortable in replying: “I am baking a higher-order function to make this bit of code easier to test”.
Unluckily, this is an universal issue. Listen to a chef masterclass and you may likely hear things like “mise-en-place”, which may not ring a bell.
For software users this is a notable and critical issue because technology changes fast and the knowledge of yesterday is outdated today (for instance, checkout the number of versions of JS frameworks). This is pretty unsustainable. Moldable Development tries to start small and provide views for small data. This way you can understand small things. Then recur until we deal with big problems.
My hope is that we get to a point where I can tell my grandpa “I am baking a higher-order function to make this bit of code easier to test”, but in the way he can understand. And I want my computer to help me into doing that. This is not too bigger of an effort than translating that legacy COBOL codebase to something a beginner Python developer can understand.
I believe the secret is in molding the data into information accessible to people. This for me is telling a story. A story is a sequence of facts that carries some meaning to the listener. It is a fundamental tool to exchange meaning. The meaning I want to convey to my grandpa is about the smart technique he can apply in his daily life, not necessarily about how that works in the programming language I am working with. Similarly, a company with a legacy COBOL codebase cares about the functionality and not the technology: if they could translate that to a newer language/technology without losing functionality, they would not mind. (I guess, they would like it even if they could just extract the functionality as a set of requirements and test a new implementation against those: often even that is hard).
At this point this package is not mature enough for all of the above (yet!). But let me give you some examples of stories I tell myself through molds.
- “Given a code buffer, I want to see duplicated code because I copy-pasted a lot and I want to cleanup.”
- “Given my blog, I would like to change its theme by inverting colors (in one swoop)”
Here the context to mold is the CSS file of my blog + the feedback I received from my readers and the output is a CSS file with colors inverted. I focus only on my story by relying on existing molds that divide the CSS files in elements I can query.
- “When I am tired, given a long list of steps, I would like to see it as a succinct diagram.”
- “Given a Python file, I want the most complex function because I want something to refactor”
- “Given my personal notes and their history, I want to see what I have been most interested in lately so I can move forward.”
- “Given some code, I want to highlight the syntax constructs to teach myself what they mean and how I should use them.”
Further info
Vision
https://ag91.github.io/blog/2021/06/18/moldable-emacs-vision-basic-concepts-and-design
View code duplication as an Org buffer
https://ag91.github.io/blog/2021/05/26/moldable-emacs-make-everything-moldable-through-lisp
Exploring JSON via Elisp
https://ag91.github.io/blog/2021/06/18/moldable-emacs-how-to-explore-json-via-elisp
[Setup] Clojure tree-sitter grammar installation
OCR mold
Grabbing hyperlinks from HTML with Playground
https://ag91.github.io/blog/2021/07/19/moldable-emacs-capture-links-from-html-with-playground/
Showing examples for a Clojure function at point
Code transformation: edit your CSS files with a Playground!
Prototype: integrating Nyxt and Vega-Lite
Taking notes with molds
https://ag91.github.io/blog/2021/09/05/moldable-emacs-taking-lispy-notes-that-are-easier-to-search
Howto: Migrating to a terser format for molds
https://ag91.github.io/blog/2021/09/19/moldable-emacs-making-molds-a-little-easier-to-write/
Extend molds via hooks
Check which molds you can use and demo them!
https://ag91.github.io/blog/2021/10/02/moldable-emacs-molds-need-examples-too/
Moldable tutorials
https://ag91.github.io/blog/2021/10/15/moldable-emacs-moldable-tutorials/