twtw5/twtw9
There was a telephone call this week, that started out planning a trip together and ended maybe weβll never talk to each other again. Well, whatβs going on with my gals and in some cases boys? Do you ever lie to yourself? The biggest lie I tell myself is βIβll remember thisβ. Or maybe itβs βi donβt careβ. Remember that time a dog got into the school? Damn. Iβd love a day like that again. The word βastroblemeβ still makes my heart skip a beat. Jennifer imagined me beside her on the porch while she back and forth in a rocking chair. I spent the weekend, and I spent some of the evenings too. There was one of the evenings I went out to the bar near the Financial Times office to say hello to some people I used to work with at the Financial Times. It was nice to see them. I think I was annoying but Iβm really so very not used to socializing with people who arenβt the computer at the moment. There were a lot of times this week when I wanted to drink tequila but none of them were the time I was at the bar. During the evenings I have been working on Littlebook 3.0. Or, 1, as the case may be. Iβve tried a few different systems for Littlebook3 so far. The first one I tried, (the pic last week), was very much a proof of concept. It was nice, but very rough and I need it to work in a web browser too. The second thing I tried was esoteric and fun, everything in pure js with no build step. Runtime reflection by parsing function.toString() with acorn. Grabbing the place lb.defineCommand() was called from by inspecting (new Error).stack. Doc strings inside the function, like lisp and python, by including a template string as the first line in the function. That was converted on the fly to markdown, and displayed together helpfully (βxyz is an interactive command defined at xyz.js:10:2β then the doc string) just like emacs. Once i started writing with it, i learned that it would feel as though i were operating the computer through a big pool of honey. All heavy, all sticky, all weighed down and slow. The third attempt seems very promising. Itβs kind of crazy, you should see my whiteboard. But I think it will be very cool. It took me all weekend to get it working, but I was able to edit the text editor using itself tonight before bed and thatβs how you know youβre living. The part I was building this weekend is the bootstrapping system (which i call bookstrap, or littlebootstraps). You see itβs an important design goal that you should be able to completely change the editor if you want, you need access to the code that powers it and the power to change it. Thatβs in addition to making an explorable system that teaches you while you learn it and change it. Some more rewrites are needed there, and more prototyping (building more custom code in it so i can see how it feels, and improving how it feels over time). Hereβs how the bootstrapping works:
- You load up Littlebook (in the browser, or the one on your computer)
- bookstrap kicks in and detects your βnative file systemβ β thatβs opfs:// on the web version and file:// when youβre using Littlebook Desktop
- bookstrap creates a library for each of the local filesystem protocols you have available
- The install phase grabs all the source code and puts it somewhere you can change it β on the web it puts it in opfs:///littlebook/system/, and on desktop it puts it in ~/.local/share/littlebook/
- The install phase makes you a user directory (opfs:///littlebook/user, ~/.config/littlebook/)
- The User/early-init.js script is executed (as a non-esm script)
- The install phase passes off to the bundleworker, which creates an esbuild worker
- The bundleworker is set up to be able to resolve imports in your opfs:/// or file:/// system, using the fs api that bookstraps prepared. As well as importmaps.
- The bundleworker loads System/entrypoint.ts, compiles it, bundles it, evals it.
- The runtime system initializes the core editor things: events, surfaces, surface layers, views, protocol handlers and their defaults
- The system then dynamically imports your User/init.ts file where you can add new events, surfaces, surface layers, protocol handlers and views
I believe that this is a powerful enough system to build an even more powerful system with. All the steps before bundleworker (including early-init.js) are executed as regular scripts, so they can even help build the importmap. Everything about the system (apart from bookstrap and bundleworker) is replaceable, itβs all in the hands of the user.
The βgrabs all the source codeβ from step 4 is entertaining. On desktop mode itβs pretty normal, the source code is embedded in the .app and itβs extracted out to your local share dir. On the web, itβs slightly sillier. The opfs worker fetches a file called /system.json which contains a virtual file tree of the entire system, and it creates a file in opfs for each entry. Surprisingly that takes only about 100ms to do. My plan for the reflection is to analyze the sourcemaps generated by esbuild (theyβre made available to the user too), and combine that with some of the error parsing code i threw away from attempt 2 (wednesday). The settings & commands system is important for being able to build UIs and electric help. Iβll be reading my emacs manual.
I have to go.