A Jacket, Microcontrollers, and Clojure
》I ♡ Cyberpunk
If the look of this blog is not a clue already, let me just go ahead and say I love cyberpunk. And maybe plain old punk just a little bit, too.
I love going to Alchemy, or To The Moon. I’m frequently at the Atlanta Eagle. Sometimes you can even spot me at a goth night event. I already have cyberpunk-adjacent clothing and boots. OK, that’s a lie, the boots are straight-up cyberpunk.
So why not have more lovely cyberpunk gear? In leather, of course. I just happen to have an old leather jacket that needs some love.
But if this jacket is going to be cyberpunk it needs some glow. It needs some radios. Maybe input devices. Definitely LEDs.
Here’s the story of building the first component for the jacket.
Going places I shouldn't with JNA
》Why C when you can CLJ?
Someone close to me says when looking at dangerous animals: "if not friend, then why friend shaped?" I feel like that about C. While C isn’t exactly dangerous, the slow write-compile-test cycle when when working on visual projects is a real drag.
Which is a shame because I’ve done a number of visual projects in Clojure over the years and have always wanted to incorporate them into XScreenSaver. I even wrote a hack for XScreenSaver once in C. Though it worked in the end, getting there was a slog. And in the end, JWZ wouldn’t accept it because it didn’t compile on his Mac.
[exasperated emoji here]
The workings of an XScreenSaver hack aren’t complicated - the main
xscreensaver
daemon creates an empty window and then launches another process
(the "hack") to draw remotely on the window. That’s easy to do in X11
by
passing along the window id from the daemon to the hack.
Surely that can be done with Java/Clojure, right?
Well read on and see exactly how wrong I was.
More for the ClojureScript SVG Toolbox
》New Goals
The fool that I am decided to fork the startpage project from the previous post into two projects: one that’s static content suitable for sharing with the rest of the world, and one that’s more dynamic and relies on sources of data that are only available on my home network.
That meant really pinning down the features required for the simplified page before moving on to the fully-featured one.
The main features were limited by what could be served off of a local filesystem. That narrowed the options down to:
A calendar widget
Sets of page links
Configurable color
Building A ClojureScript SVG Toolbox
》Laments and Goals
Why do I do this to myself? The idea, so easy. The implementation, such pain.
I wanted to build a custom startpage (aka "new tab page") in my usual cyberpunk style. There are dozens and dozens of startpages out there to choose from, many of which were very stylish. But none were the phosphor green-drenched (retro?) future-styled UI my heart desired.
Well, I’ve been on this ClojureScript journey, so why not continue it?
There were a few must-haves:
An "ambient calendar" showing a year progression
A per-Firefox-instance set of URLs
Current temperature and daily high/low forecast
Today’s allergen levels
Style that would make a movie studio jealous
No ongoing animation after the page loads
Then some stretch goals:
Weather radar
Disk usage of certain systems that I need to keep an eye on
Traffic conditions and alerts
Calendar entries
And two not-haves: a search bar and a clock. CTRL-k
to search is a habit. And I
friggin' hate clocks on my desktop. Long ago I learned they distract me.
Oh, this is going to be painful.
Stumbling Through Interop
》Surely I can just cargo cult this
After making so much process building a
progressive web app, I decided to take a detour into making some "simpler"
pages, without re-frame
. To pull in some EDN data to work with, I quickly
needed to figure out how to use fetch
. JavaScript interop looks like Java
interop, right? Objects, members, methods. What works in one place should
work in the other. Right?
》Enter promises and consternation
I started playing around just by seeing what fetch
returns:
(js/fetch edn-url ) ; => #object[Promise [object Promise]]
Getting a promise
object in return was not a surprise. Previous work taught
me that JS uses async code and promises heavily. Which makes sense — any
blocking of a page’s JS thread leads to a frozen page. Treating the promise
like a magic bottlecap, I reach for the handy old tools realized?
and deref
:
(realized? (js/fetch edn-url )); => :repl/exception!
(deref (js/fetch edn-url )); => :repl/exception!
Oh, no! This isn’t the same at all.