I'm very dissatisfied with the current state of the world in two regards:
𝐀. Computer owners can't easily understand or modify programs they run.
𝐁. Computer vendors compete to limit permissions for modifying programs.
I'm very dissatisfied with the current state of the world in two regards:
𝐀. Computer owners can't easily understand or modify programs they run.
𝐁. Computer vendors compete to limit permissions for modifying programs.
The whole program is arranged on a 2D surface within a series of nested boxes. You can hit ‘run’, and it extracts the code from the surface and runs it and you get to play a game of Snake. (Only on a computer; even though the app runs on a phone, you can't play this particular game of Snake without arrow keys.) So it can be viewed as a sort of Literate Program, even though the representation I'm tangling from has a richer UI than is typical, a surface you can pan and zoom around with a mouse wheel or touchscreen. (It doesn't support editing yet. This is a purely reading experience for now.)
I wasn't trying to build yet another Literate Programming experience, though. What was on my mind was Christopher Alexander. Read more →
Try it out. You'll need to first install LÖVE for your platform. It's tiny, completely open source, and live editable on a computer.
Here's a test build of my hypertext browser where every "page load" picks a random background. The foreground and link colors adapt to preserve a minimum contrast (WCAG AAA level).
Colors in my markup language are no longer rgb. Background colors are strings of the form 'hue:intensity:lightness', e.g. 'red:5:4' (following the perceptually uniform Oklch space). Foreground colors can contain just 'hue' or 'hue:intensity'. Missing fields get filled in to maintain contrast.
Intensity and lightness can take 8 levels (0 to 7). Hue can take one of 8 values: red, orange, yellow, green, cyan, blue, purple, magenta. Hue can also be grey, in which case it can't have an intensity. Just 'grey:lightness'.
Here's the key code, 200 lines of Lua.
Now, like all the best chess variants, this one uses all the rules of chess, just with one crucial, minimal tweak. So to implement Monster chess I had to first implement chess. Which I did (and not for the first time). But by the time I'd implemented all the legal moves, castling, en passant, pawn promotion, forbidden moving into check -- I was at 500+ lines of code. At that scale of program, Carousel's janky scrollbars get too thin for my fat fingers to acquire on the phone. Carousel's only nice up to 100-150 lines.
So I switched to my template repository for standalone apps using the Carousel UI. I've done this before, most notably with my Sokoban client which you can edit the source code for right on your phone. Indeed, editing the source code is the expected way to skip 10 or 60 levels. On some level everything I do stems from the desire to believe that editing source code can be a nice user experience.
I soon had a second chessboard app. But it felt like spaghetti. The Carousel template lets me split up a large program into multiple files, but with all the problems of text-based program navigation, and all my bespoke janky tools to boot. You're looking for a specific function. Which file is it in? It's hard to read code you didn't write, and on some level everything I do is an attempt to make it easier. You know, literacy. Computational literacy. The ability to read a novel of code or write an email of code. But we're not at the promised land yet, and meanwhile I have spaghetti nobody should bother with.
So I ripped out all my Carousel stuff and made it just a plain LÖVE app. File size dropped from 128KB to 8KB. So clean! But now it's not easy to modify, particularly on a phone. You have to unpack the zip file, find a text editor, etc. And on some level everything I do is an attempt to keep things easy to modify. Read more →
There's 3 tools that you can use independently:
All 3 tools use a common data source of a) files with some `---
` metadata up top and a small number of VARIABLES
that get substituted in, and b) index files containing a list of files that constitute a site.
All 3 tools are single-file and so self-contained and easy to move wherever you want, mix and match. For example, my site has two distinct blogs (main site and devlog). I run the first tool once and the others twice each.
I can't quite cut my site over to this, though. Open questions I ran into with my site:
<title>
tag, but show no title in the <body>
(because I already show the date and it would be redundant). It's unclear how to do that without a whole templating language.
I'm sure there are others. SSGs seem to be one of those things that everyone a unique-snowflake version of. But check it out if you're willing to leave Markdown behind. Using HTML is more accessible than Markdown. For example, it lets you distinguish a couple of key categories of <code>
: keyboard shortcuts with <kbd>
, references to names in other snippets with <var>
and computer output with <samp>
. Markdown's backticks can't do that. It doesn't matter if you never share your posts, and it's natural to not want to look at HTML given how monstrous it can get. But HTML also has a lovely core that a lot of civilizational effort went into, and it's sad that layers above don't use all of it. A little more manual labor can provide a nicer reading experience for others.
Thanks Cristóbal Sciutto, m15o, Eli Mellen, Tom Larkworthy and others in the Future of Coding community for inspiration.
Transcript
For a while now I've been trying to improve the way I program. I've made some progress. I can edit my programs live, and the tooling that enables it is not much code.
Here is the template I create new apps from. It starts out with something silly: every time I click with my mouse it draws a random rectangle.
Here is the code for this app.
There's not much right now, but it grows from here and in principle the app continues running as it evolves.
But debugging is still hard. It takes a long time to streamline my thinking about each new problem. I often print information to the terminal, and then struggle to visualize the text my program is printing. And if I draw debug information on the canvas, it competes for space with the app.
So I think I need new infrastructure. There are probably tools I could use that are too hard to build while deep in something else. One such tool is a windowing system. As my app runs it can dump things to other windows, and I can show them separately from my app. Read more →
Anyways, here's a little program I made to try to stretch Decker to more of the sort of procedural graphics I tend to gravitate towards on LÖVE:
This is dancing letters, a fixed piece of text except we're constantly switching the case of each letter at random.
Here's the code, to give you a flavor for what Decker's quite elegant mix of Lua and APL looks like:
local s: "abcdef" # put in whatever text you want
on view do
if ! 5%sys.frame
me.clear[]
local y:each c in s random["%u","%l"] format c end
local margin:15
me.text[y margin,margin,me.size-margin*2]
end
end
And here's that code along with the surrounding card (you need a canvas widget to be present just so) in a less readable form that you can copy and paste into a deck of your own:
%%CRD0{"c":{"name":"home","script":"on view do\n \nend","widgets":{"canvas":{"type":"canvas","size":[300,200],"pos":[48,51],"animated":1,"volatile":1,"script":"local s: \"Call me Ishmael. Some years ago--never mind how long precisely--having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off--then, I account it high time to get to sea as soon as I can.\"\n\non view do\n if ! 5%sys.frame\n me.clear[]\n local y:each c in s random[\"%u\",\"%l\"] format c end\n local margin:15\n me.text[y (margin,margin,me.size-margin*2)]\n end\nend","border":1,"scale":1}}},"d":{}}
An environment for visualizing programs
(Not to be confused with visual programs, or visualization more generally.)
Examples of coordinate spaces:
Some examples of messages, to show the sorts of use cases this framework might unlock:
print
statements as a message from the "code" coordinate space to a different, 0-D (append-only so there's no notion of coordinate) space.
The major question for me now is: how do you configure a buffer? You need some concise way to specify the space (perhaps just by naming from a small menu of options), handlers that listen for messages (e.g. keypress or mousepress), handlers for sending messages (e.g. widgets on the space that perform tasks when you interact with them), and generic handlers for sending messages to other buffers (e.g. print
; here I'm imagining it to send a message from some arbitrary process, through say a socket, back into the environment, with enough information to route it to the appropriate buffer accompanied by a reasonable coordinate)