The sky above the port was the color of television, turned to a dead channel.

— Opening paragraph from William Gibson’s Neuromancer.

So I thought to myself, why not write a screensaver for Emacs? Enter snowcrash.el. It’s not on MELPA or anything, but it does live on GitHub within my Emacs configuration repository.

M-x snowcrash RET looks like this:

It’s fun to look at or leave running as a screensaver!

Background

Figure 1: TV Noise, a.k.a. Snowcrash. Public Domain

Figure 1: TV Noise, a.k.a. Snowcrash. Public Domain

This is Snowcrash. The TV turns to random noise and if you have sound, the speakers produce a sharp hiss. Some people find it soothing. Some find it a bit much and upsetting.

Figure 2: Classic 10PRINT. scrus, CC-BY-SA-4.0

Figure 2: Classic 10PRINT. scrus, CC-BY-SA-4.0

10 PRINT CHR$(205.5+RND(1)); : GOTO 10

Now, This is 10PRINT. a simple toy program from Commodore 64 days (circa mid 80’s) that draws a textual labyrinthine pattern across the screen. Bonus, there’s a fun, free book about 10PRINT. Don’t miss out on the refreshing take of 10PRINT’s cultural impact.

The catch? Not everyone has a C64 emulator set up, however, probably everyone has Perl installed. Here is a 10PRINT version for Perl using ASCII characters:

Why? How?

Alright, with knowledge of 10print and snowcrash/TV noise, let’s talk more about snowcrash.el!

I wanted to see how difficult it might be to create a simple Snowcrash-y screensaver mode in Emacs. My initial attempt “snowcrash-ified” a normal buffer instead of creating a new major mode. This worked, but didn’t have an easy way to stop the timer (responsible for redrawing) on the buffer’s deletion. Plus, the modeline looked real confusing with the major mode indicated as “Fundamental mode” (the least specialized text editing mode).

Unlike “10print”, what I call “snowcrash” does not involve scrolling text. Instead, snowcrash.el rewrites the buffer every second. “10print” randomly selects forward slash (/) or backwards slash (\) for each character; snowcrash.el randomly selects a standard space (ASCII 0x20) or full block (Unicode 0x2588 ), creating a satisfying noise effect like an old television.

I discovered the full block character using Emacs’s Unicode search functionality nestled within C-x 8 <RET> (insert-char). I typed *block in the minibuffer then perused through the match candidates. To prove how easy it is to enter unicode characters in Emacs, I’ll insert umbrella, brain, snowman emojis real quick here in a couple seconds: ☂🧠☃. Viola!

Other Emacs screensavers

By the way there are other cool Emacs goodies that can serve as screensavers. Here’s a short list. It is not exhaustive.

  1. M-x dark-souls - spam “You died” in the buffer (MELPA)
  2. M-x gameoflife-animate - Conway’s game of life (MELPA)
  3. M-x fireplace - cozy fire vibes (MELPA)

Possible iterations

Here are some ideas for further improvement generated while writing this major mode. Sorted from fun to boring.

  1. Add color!
  2. Ensure the snowcrash-mode works correctly with multiple snowcrash-mode buffers.
  3. Ensure snowcrash-mode removes the timer and hooks when the feature is unloaded or the in the case of the buffer’s major mode changing prior to deleting the buffer.

Elisp Footgun: (random) vs (random LIMIT)

I’ll conclude this post with a elisp quirk—an elisp footgun. The Elisp (random) function has several distinct behaviors depending on how it’s used. This makes for a funny API replete with oodles of legacy vibes.

  • (random) returns an integer between most-negative-fixnum and most-positive-fixnum inclusive. (random 4) returns a random integer from 0 to 3 inclusive (0, 1, 2 or 3).

So good so far. Function named random generates random numbers.

  • (random t) reinitializes the seed to a random value. (random "something") reinitializes the seed derived from "something".

Yep, if you pass a STRING or t to (random), the seed is changed. On the other hand, if you pass nothing (nil) or an INTEGER, (random) selects a random INTEGER. I’m sure there was well meaning intentions in overloading (random)’s behavior by dispatching on the argument’s type and value. It’s confusing as hell.

Compare with Python’s random module possessing a random.seed() and a random.randrange() separating out the APIs for easy access.

API Design Matters!

And a final quote reminding us that careful API design matters!

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. Code for readability.

John Woods

Figure 1: sudo plus emacs

Figure 1: sudo plus emacs

Emacs offers TRAMP as a way to edit files over ssh or as a different user. Combine with sudo-edit for easy superuser edits. VSCode has a feature reminiscent of TRAMP called Remote Development using SSH.

At the time, I didn’t know of M-x sudo-edit so I wrote my own implementation. It sucked, didn’t work on chained TRAMP connections (e.g. ssh then edit as root on the remote host). Also, it turned out non-standard file buffers (such as dired) require dedicated code paths that I’d have to troubleshoot and diagnose. It wasn’t easy to figure out how to write this interactive lisp function. And indeed, it’s not what I want at all.

Figure 2: sudo-edit in action

Figure 2: sudo-edit in action

No, what I actually want is sudo-edit with its quality, time-tested defuns. Besides, it’s easy to use:

  1. M-x package-install sudo-edit RET. (See sudo-edit on MELPA.)
  2. Next visit the file then run M-x sudo-edit RET.
  3. Finally, type in your sudo password and viola! You can now edit and save the buffer as root!

Read more about sudo-edit in C-h f sudo-edit RET or see the source code — embedded with commentary and documentation — here on GitHub.


sudo make me a sandwhich.

…By the way I had to figure out how to make decent gifs from a webm. Generate a color pallet then perform the transcode using that color data to ensure decent contrast. See this StackExchange answer.

My 2024 in Review

Updated Monday, Feb 24, 2025

Figure 1: Biked &amp; camped 100 miles (160 km) from Milwaukee to Manitowoc in 36 hours

Figure 1: Biked & camped 100 miles (160 km) from Milwaukee to Manitowoc in 36 hours

It’s been a tumultuous year. It took a multitude of drafts to complete this short piece. I felt demoralized when authoring this post. Then I reviewed my 2023 in review post and it put my frustration in perspective: Life is pain and joy. It’s an undulation of anguish one day, blissful peace the next. Keep pushing through and learning. That’s all I should expect for myself. The rest is gravy.

Things I achieved this year

Figure 2: The physical journals of 2024 (digital not included!)

Figure 2: The physical journals of 2024 (digital not included!)

  1. I sold my car and lived car free in Milwaukee. Bikes and busses!
  2. Became an avid cyclist cruising around Milwaukee. I also went on multi-day a bike tour along Eastern Wisconsin. Stay tuned for bike content.
  3. Developed my exercise into an at-home calisthenics program (using the body for weight). I was exerting reps of 60 sit ups, 15 pull ups. While I cannot achieve these metrics today, soon I’ll restore to my peak performance then exceed it. Life had gotten in the way, and I need this for myself.
  4. Began going to therapy and working on my mental well being, big time. Wrote 70,000 words in journal.
  5. Tutored dozens of students. Computer literacy, Programmable Logic Controllers, Haskell, Python, Java, Perl, Computer Science things. I’ve learned a lot about teaching and my students seem to enjoy working with me.
  6. Migrated most of my computers off NixOS and towards Debian Stable/Testing. Life is too short to dink around with self-inflicted NixOS snafus and community invalidating all but the savants’ opinion on UX/DX. Will NixOS look the same in five years, hard to say. I do know Debian will, though!
  7. Bought a van to try vanliving in. Sold or donated 90% of my possessions. The less ownership, the better I felt. Turns out freedom (to me) means possessing what I need and enjoy, not what others say that I need to own.
  8. Moved out of Milwaukee and visiting with family and missed connections over the winter. Facing one’s demons is the ultimate therapy. Van travel begins sometime in early 2025.
  9. Joined two book clubs and read a LOT of books for the clubs and for myself.
Figure 3: The van for the vanlife experiment

Figure 3: The van for the vanlife experiment

Goals for 2025

  1. Continue with my fitness goals. Pain free is the name of the game. And a stronger core.
  2. Supplant my irrational desire for a tech job (solely for income) with a healthier way to earn money. 9-to-5 tech work isn’t for me. Search for serenity in the work. Eyes on the flow states. Because tech doesn’t have flow anymore… it’s mostly meetings and jumping up and down whenever boss asks you to.
  3. Continue with the navel gazing. Build up the creative muscle throughout. Express myself in more fun ways like art and writing.
  4. Continue reading lots. Continue writing lots. Monetize the writing. Poetry is really cool too; I’ll wordsmith them verses.
  5. Try vanliving and if it doesn’t work out, consider moving country where car ownership isn’t romanticized despite traffic violence manifesting as a fairly understood, tractable problem, yet we won’t solve it here in this country.
Figure 4: My main transportation for 2024. &lt;$500 for everything in frame. DIY saves money big time.

Figure 4: My main transportation for 2024. <$500 for everything in frame. DIY saves money big time.

Thanks

Thanks to all my friends. Thanks to all that listened to me hem and haw about stuff. Thanks to all that were willing enough to take a chance and be vulnerable with me. Thanks to my parents for letting me stay around for a little while as I move on to vanliving. Thanks to my parents dog for being such a sweetie.

Figure 5: Scout is a good doggo

Figure 5: Scout is a good doggo

Don’t put up with bullshit. Most Americans live for about 2.44 gigaseconds. Make each second count.