Skip to content

ag91/moldable-emacs

Repository files navigation

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.

resources/pythonFile.jpg

I use M-x me-mold to choose the “FunctionsComplexity” mold.

resources/pythonFunctionComplexity.jpg

I use M-x me-mold again to choose the “Playground” mold (and write some code to calculate the total complexity).

resources/playgroundMold.jpg

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 git@github.com: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.el
  • pcsv.el
  • … (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.”

    images/duplicatedCodeMold.gif

  • “Given my blog, I would like to change its theme by inverting colors (in one swoop)”

    images/invertBlogThemeWithMolds.gif

    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.”

    images/listToPicture.gif

  • “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

https://ag91.github.io/blog/2021/06/22/how-(simple-is)-to-install-a-clojure-tree-sitter-grammar-and-use-it-from-emacs/

OCR mold

https://ag91.github.io/blog/2021/07/16/moldable-emacs-capturing-text-from-open-images-with-an-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

https://ag91.github.io/blog/2021/07/27/moldable-emacs-finding-examples-of-clojure-functions-(with-tests)/

Code transformation: edit your CSS files with a Playground!

https://ag91.github.io/blog/2021/08/11/moldable-emacs-editing-your-file-via-treesitter-(or-how-i-fixed-my-css-with-a-playground)/

Prototype: integrating Nyxt and Vega-Lite

https://ag91.github.io/blog/2021/08/22/moldable-emacs-vega-lite-nyxt-and-emacs-towards-sustainable-development

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

https://ag91.github.io/blog/2021/09/23/moldable-emacs-extending-the-playground-powers-via-hooks-to-include-dired

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/

Stats mold

https://ag91.github.io/blog/2021/10/22/moldable-emacs-how-to-get-useful-info-about-a-buffer-without-reading-it/

JavaScript and Parenscript Mold with Nyxt

https://ag91.github.io/blog/2021/10/29/emacs-with-nyxt-capturing-youtube-links-at-time-and-molding-nyxt-with-js/

Mold examples as tests

https://ag91.github.io/blog/2021/12/23/moldable-emacs-examples-for-docs-demos-and-ert-tests

Async molds

https://ag91.github.io/blog/2021/12/31/moldable-emacs-make-your-molds-async-with-ease

Learn syntax

https://ag91.github.io/blog/2022/02/11/moldable-emacs-learning-syntax-from-your-editor/

About

Adapting Emacs for moldable development

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published