The Igneous Linearizer is currently fantasy software.
If I wrote it right now the below would be its README.
Folder Full of Wikilinks-Markdown (FFWM):
Wikilinks are double bracket links like
[[this]]
, popularized by
🌐 Roam Research. With this knowledge the rest of FFWM is self-describing.
💾 Obsidian
is a popular program built on this data format.
Igneous Linearizer is a transpiler from FFWM to a single text file.
The intended use case is to:
a) write programs inside 💾 Obsidian or other similar systems using granular definitions and explicit links
b) turn them into a text file
c) run them with a normal interpreter/compiler
The advantage of this is that code can be mixed with other writing and documentation in Obsidian while still knowing it's correct. This includes linking to definitions, having names auto-update when changed, transcluding definitions, etc.
The result is like literate programming, but with a graph structure instead of a tree of modules. Have a type declaration that's essential to more than one component of the code? No problem, transclude it into both.
The disadvantage is that you lose your IDE features. Thus it's only intended for snippets, examples, and other small programs.
$ ./igneous-linearizer /home/me/my-obsidian-vault/hello-world.md > hello-world.scm
Then run it as normal:
$ guile hello-world.scm
Hello, world!
The primary function of the Linearizer to is to:
a) build the reachable set of the starting page
b) serialize the starting page plus that set, topologically sorted and double newline separated, into the output file.
For example, the contents of the
hello-world.md
page from above might be:
(display [[hello-world-string]])
Along with a sibling page called
hello-world-string.md
with the contents:
(define hello-world-string
"Hello-world!")
This would output:
(define hello-world-string
"Hello-world!")
(display hello-world-string)
If a transclusion link is used via
![[foo]]
syntax, the contents of that link will be inserted into the linking
file instead of the name.
For example, to get the following output:
(define-record-type <person>
(make-person name age)
person?
(name person-name)
(age person-age))
You could use these markdown files:
(name person-name)
(age person-age)
(define-record-type <person>
(make-person name age)
person?
![[name]]
![[age]])
This has the advantage that now the references to
name
and
age
can be explicit, meaning they show up in backlinks for those pages,
you get renaming for free, etc.
An important drawback: Obsidian at least will put every transclusion on its own line, even if there's inline content before and after it. So you're limited in how you use the above style unless you control the rendering.
Modules in many languages start with a distinguished section. For instance Haskell modules will start with something like this:
{-# LANGUAGE ScopedTypeVariables #-}
module Main (main) where
import Commonmark
import Commonmark.Pandoc
If you'd like to insert a fixed preable before the rest of the output you can do that yourself, separately from the Linearizer.
However, if you'd like use a page from your FFWM as the preamble there's a flag for this, eg:
$ ./igneous-linearizer --preamble imports.md /home/me/my-obsidian-vault/hello-world.md > hello-world.hs
The argument passed to
--preable
must be a file in the same FFWM as the starting file.
Links and transclusions will be inlined the same as above. This way you can factor out imports or pragmas and use them in multiple projects. However, no reachable set of these will be built and inserted into the middle of the document, since they're not intended to be referenced by the code itself.
The Linearizer doesn't try to generate idiomatically organized code.
The only structure traditional source code provides for organization is a tree of modules. Collapsing the FFWM digraph down to this in a nice way isn't something I wanted to deal with. So Igneous Arborizer is left unclaimed.