blog/content/sundries/shit-code/index.md

313 lines
16 KiB
Markdown
Raw Permalink Normal View History

2023-02-07 01:29:44 +00:00
+++
title = "Shit-code and Other Performance Arts"
slug = "shit-code-and-performance-art"
date = "2023-02-08"
2023-02-09 18:38:02 +00:00
updated = "2023-02-09"
2023-02-07 01:29:44 +00:00
[taxonomies]
tags = ["software", "art", "sundry", "proclamation", "chaos"]
[extra]
toc = false
+++
# A sundry collection of intellectual property, some less intellectual than other
2023-02-09 19:30:57 +00:00
Something I firmly believe is that it's important to make jokes in any medium. Here at NebCorp Heavy
2023-02-07 01:29:44 +00:00
Industries & Sundries, despite occasional dabbling with the
[physical](@/sundries/a-thoroughly-digital-artifact/index.md), we work primarily with software, and
2023-02-09 01:32:29 +00:00
software is one of our primary corporate humor channels. Below is just some of our work there,
2023-02-07 01:29:44 +00:00
from least to most useless.
## *katabastird, a graphical countdown timer*
[katabastird](https://crates.io/crates/katabastird) is, in its own words, "a simple countdown timer
that is configured and launched from the commandline." It looks like this when it's running:
![katabastird running normally][katabastird_normal]
It was created for a couple reasons:
- I wanted to make a GUI program to learn how to use a [particular library called
"egui"](https://github.com/emilk/egui);
- I had signed up to give a five-minute talk to demonstrate the latest release of a [commandline
argument parsing library called "clap"](https://docs.rs/clap/4.0.0/clap/), which I had titled,
"Clap for Clap Four", and I needed a program to showcase it.
Obviously the best way to showcase a commandline-parsing library is to incorporate it into a
graphical program. Other commandline-mission-critical features included changing the color of the
background to get more and more red as less time remained
![katabastird almost done counting down][katabastird_ending]
and using the font used by the alien in *Predator*
![get to the choppah][katabastird_predator]
But by far its greatest feature is an undocumented option, `-A`, that will play an [airhorn
salvo](https://gitlab.com/nebkor/katabastird/-/blob/4ccc2e4738df3f9d3af520e2d3875200534f4f6f/resources/airhorn_alarm.mp3)
when it's done. This option is visible in the program's help text, but it's not described.
2023-02-07 06:03:51 +00:00
Truly honestly, this is not a great program. Once it's launched, it only understands two keyboard
inputs, `ESC` and `q`, both of which simply cause it to exit. Using the mouse, you can pause,
restart, and reset. And that's it, that's all the interaction you get.
2023-02-07 01:29:44 +00:00
In spite of this, I find myself using it all the time. It's easy to launch with different times (the
commandline parsing understands things like `-h` for hours, `-m` for minutes, etc.), and its last
invocation is just an up-arrow in my terminal away. The airhorn cracks me up every time.
At some point, I plan on changing it to something that uses the GPU to run a fire simulation on the
numbers, and have the flame intensity get higher as the time remaining gets lower. I'll save that
2023-02-07 06:03:51 +00:00
for when I want to get slightly more serious about graphics and shaders, though; it would basically
be a total re-write.
As for the name, it's just a perversion of "katabasis", which means, "descent to the Underworld". I
guess a bastardized "bastard" is in there, too. Listen, I'm gonna level with you: I'm not wild about the name, but
what's done is done.
2023-02-07 01:29:44 +00:00
## *randical, a commandline program for generating random values*
2023-02-07 06:03:51 +00:00
Some time ago, I was [trying to work out some ways to pick random points in a
sphere](https://blog.joeardent.net/2018/07/right-and-wrong-ways-to-pick-random-points-inside-a-sphere/),
and during that exploration, I found myself wanting to just be able to generate random values
2023-02-09 18:38:02 +00:00
outside of any program in particular. So, I wrapped a primitive interface around [the random value
2023-02-07 06:03:51 +00:00
generation library](https://docs.rs/rand/0.8.0/rand/index.html) I was using. I wound up using it
selfishly and in a limited fashion for that project, but afterward, decided to expand it a bit and
release it, as my first [real Rust crate](https://crates.io/crates/randical).
I'll reproduce the help text here, since it's fairly comprehensive:
``` text
$ randical -h
Radical Random Value Generator 1.618033
Generates arbitrary numbers of uniformly distributed random values.
USAGE:
randical [FLAGS] [OPTIONS]
FLAGS:
--buel Prints either 'Here.' or 'Um, he's sick. My best friend's sister's boyfriend's brother's girlfriend
heard from this guy who knows this kid who's going with the girl who saw Ferris pass out at 31
Flavors last night. I guess it's pretty serious.', with equal probability. Not compatible with `-t`
or `--bule`.
--bule Prints either 'true' or 'false', with equal probability. Not compatible with `-t` or `--buel`.
-e, --exit With equal probability, exit with either status 0, like /bin/true, or status 1, like /bin/false.
Technically compatible with all other options, but exit status will have no relation to any
generated output. Sets default number of values to print to 0.
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-n, --num-vals <NUM_VALS> Number of random values to print out. Defaults to 1.
-t, --type <TYPE> Type of random value to print. Defaults to 'bool'.
Possible values are 'b'ool, 'f'loat64, 'U'UIDv4, 'u'nsigned64, 's'igned64, and 'k'suid
with millisecond precision.
```
2023-02-07 01:29:44 +00:00
2023-02-07 06:03:51 +00:00
The [README](https://github.com/nebkor/randical/blob/main/README.md) contains some examples of using
it to do various things, like simulate a fair coin toss, or an *unfair* coin toss, or "a *Sliding
Doors*-style garden of forking paths alternate timeline for Ferris Bueller's presence or absence on
that fateful day."
2023-02-07 01:29:44 +00:00
2023-02-07 06:03:51 +00:00
I have one actual non-shithead usecase for this program: in my [.emacs file, I use it to
generate](https://gitlab.com/nebkor/dotfiles/-/blob/3aaf06fc66cdb541b76dfd44d25c369c4762301f/.emacs#L113-116)
[ksuids](https://segment.com/blog/a-brief-history-of-the-uuid/). But I don't *really* use it.
I include it mostly because, by most measurable metrics, this is my most popular program with end
users that I can specifically identify:
![randical's popularity is baffling][randical_downloads]
2023-02-09 01:32:29 +00:00
Who is downloading my software, and why? I don't know, and more importantly, I don't care or need to
know. It's truly better for everyone that way.
## *freedom-dates, a library neither wanted nor needed*
When I started writing this post, "freedom-dates" existed strictly as a shit-head idea of mine about
the dumbest possible way to represent dates as a string. In fact, I had had it about a month before,
while chatting with some friends on Discord.
![the birth of the birth of freedom][freedomdates-discord]
*<center><sup><sub>actually i did ask if i should</sub></sup></center>*
As usual, I thought tossing a small crate together to realize this joke would take, at most, one
hour, and be maybe ten lines long. At least this time, it only took five or six times as long as I
thought it would. In its own words, `freedom-dates`
> provides a convenient suite of affordances for working with dates in *freedom format*. That is, it
> takes representations of dates in Communinst formats like "2023-02-08", and liberates them into a
> Freedom format like "2/8/23".
For something like this, where I would not want to actually be accused of punching down or being a
jingoistic moron, it's important to be as multidimensionally absurd as possible; I really needed to
commit to the bit and provide maximum, richly-textured incongruity.
Luckily, using the [Rust language](https://www.rust-lang.org/) helps with that in a lot of
ways. After I [published it to the official package
repository](https://crates.io/crates/freedom-dates), the official documentation site built and
published the [autogenerated documentation](https://docs.rs/freedom-dates/latest/freedom_dates/) for
it. This leads to the creation of content that looks like this:
![this is history][freedoms-birthday]
The slick-looking defaults and basically frictionless process for participating in the Rust
ecosystem make it easy for culture-jamming like this. All I had to do was diligently comment, test,
and document my code[^just-do-lots-of-work], and the larger systems took care of the rest.
Rust also provides a lot of different fancy programming tools, like
[`Traits`](https://docs.rs/freedom-dates/latest/freedom_dates/trait.FreedomTime.html), that allow
you to dress up deeply unserious content in deeply serious costume.
In all real seriousness, though, I hope that seeing how easy it is to get something this silly
published in the official channels inspires you to overcome any trepidation about doing that
yourself, if you have something you want to share!
## *bad_print, a silly program*
A few years ago, someone at the [Recurse Center](https://recurse.com/)[^rc-link] started a chat
thread titled "bad print", and opened it with,
> you probably didn't know that you needed a bad print function, one that spawns a thread for each
> character in your string and prints the single character before quitting... well, now that you
> know that you needed this, i've written one for you
and then pasted a 3-line program in Haskell, and asked for other implementations of "bad print", in
any language. I whipped one up using [Rayon](https://github.com/rayon-rs/rayon), a library for doing
some things in parallel really easily, but eventually settled on the following, which uses a much
smaller and more focused external library called
[threadpool](https://github.com/rust-threadpool/rust-threadpool):
``` rust
use std::io::Write;
use std::{env, io};
use threadpool::ThreadPool;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
panic!("Please supply a phrase to be badly printed.")
}
let string = args[1..].join(" ");
let num_threads = string.len();
println!(--------);
let pool = ThreadPool::new(num_threads);
for c in string.chars() {
pool.execute(move || {
print!("{}", c);
let _ = io::stdout().flush();
});
}
pool.join();
println!();
}
```
2023-02-07 06:03:51 +00:00
2023-02-09 01:32:29 +00:00
I noted about it, relative to earlier versions,
2023-02-07 06:03:51 +00:00
2023-02-09 01:32:29 +00:00
> It appears to output strings with an even larger edit distance from the arguments given to it,
> presumably due to the chaos inherent to harnessing the power of one full tpc (thread per char).
2023-02-07 06:03:51 +00:00
2023-02-09 01:32:29 +00:00
Indeed, witness it for yourself:
``` text
$ bad_print Behold the awesome power of one full Thread Per Character.
--------
Bwoesmd elpoh or onh eu Thread earPCh ceearfofelwtter la.
```
By far the most impressive was a bash script that did *Matrix*-style cascading text in your
terminal, called, appropriately enough, `bad_matrix`; that particular one was by someone [who's a
bit of a shell
wizard](https://www.evalapply.org/posts/shell-aint-a-bad-place-to-fp-part-2-functions-as-unix-tools/index.html#main).
2023-02-07 01:29:44 +00:00
# Other peformance arts
2023-02-09 01:32:29 +00:00
An artist's medium is all of reality and all of time, so every piece of the work is eligible for
expression; the frame is also part of the work. Software in my culture is still embedded in a
context that is a bit stuffy, a bit up its ass about things like "copyright" and "semantic
versioning"[^smegver], and so they're things I enjoy playing with, too.
At the bottom of the [readme for
freedom-dates](https://github.com/nebkor/misfit_toys/blob/master/freedom-dates/README.md), I have
the following about the version:
> Freedom *STARTS* at number 1, baby! And every release is ten times the last, so second release is
> 10, then 100, etc. FREEDOM!
and indeed it is at version 1.0.0; the two `.0`s after the `1` are there to satisfy Cargo's
requirements about semver[^smegver].
2023-02-07 01:29:44 +00:00
## goldver
2023-02-09 01:32:29 +00:00
When I version software for public consumption, I tend to use a scheme I call
"[goldver](https://gitlab.com/nebkor/katabastird/-/blob/main/VERSIONING.md)", short for "Golden
Versioning". It works like this:
> When projects are versioned with goldver, the first version is "1". Note that it is not "1.0", or,
> "1.0-prealpha-release-preview", or anything nonsensical like that. As new versions are released,
> decimals from *phi*, the [Golden Ratio](https://en.wikipedia.org/wiki/Golden_ratio), are appended
> after an initial decimal point. So the second released version will be "1.6", the third would be
> "1.61", etc., and on until perfection is asymptotically approached as the number of released
> versions goes to infinity.
In order to be compliant with the semver version structure, the following rule is applied to
projects published to the official Rust package repository:
> Once there have been at least three releases, the version string in the Cargo.toml file will
> always be of the form "1.6.x", where x is at least one digit long, starting with "1". Each
> subsequent release will append the next digit of phi to x. The number of releases can be
> calculated by counting the number of digits in x and adding 2 to that.
I sincerely believe that this is *better than [semver](https://semver.org/)* for plenty of non-library
software. It was Windows 95 and then Windows 2000; obviously there was a lot of change. I don't care
about arguing about the whether or not this is a "patch release" or a "minor release" or a "major
change". There are no downstream dependents who need to make sure they don't accidentally upgrade to
the latest release. If someone wants to update it, they know what they're getting into, and they do
it in an inherently manual way.
2023-02-07 01:29:44 +00:00
## chaos license
2023-02-09 01:32:29 +00:00
Anything that I can[^chaos-software], I license under the Chaos License, which states,
> This software is released under the terms of the Chaos License. In cases where the terms of the
license are unclear, refer to the [Fuck Around and Find Out
License](https://git.sr.ht/~boringcactus/fafol/tree/master/LICENSE-v0.2.md).
This is about as
[business-hostile](https://blog.joeardent.net/2017/01/say-no-to-corporate-friendly-licenses/) as I
can imagine, far worse even than the strong copyleft licenses that terrified the lawyers at ILM when
I was there. It oozes uncertainty and risk; you'd have to be deranged to seriously engage with
it. But if you're just a person? Dive right in, it doesn't really matter!
---
That's about all I have for now, my droogs. Go take what you know and do something weird with it; it
may amuse you! You might learn something! You might make someone laugh!
---
2023-02-07 01:29:44 +00:00
[katabastird_normal]: ./katabastird_normal.png "counting down with one hour, twenty-nine minutes, and forty-three seconds remaining"
[katabastird_ending]: ./katabastird_almost_done.png "counting down with one second remaining"
[katabastird_predator]: ./katabastird_predator.png "get to the choppah"
2023-02-07 06:03:51 +00:00
[randical_downloads]: ./randical_installs.png "who the hell are these people?"
2023-02-09 01:32:29 +00:00
[freedomdates-discord]: ./birth_of_freedomdates.png "a screencap of a conversation where I suggest 'freedom-formatted' dates are 'seconds since july 4 1776'"
[freedoms-birthday]: ./freedoms_birthday.png "Freedom was born at noon on the Fourth of July, '76, Eastern Time. This is History."
[^just-do-lots-of-work]: I did more test-writing and documenting for that useless joke project
than for most other software I ever write.
[^rc-link]: See also the link at the bottom of the page here.
[^smegver]: "semantic versioning" sounds like it could be a good idea: "the versions should be
meaningful, and when they change, they should be changed in a way that means something
consistent". As usual with these things, it's turned into a prescriptivist cult whose adherents
insist that all software be released according to its terms. This is annoying.
[^chaos-software]: This is basically anything I write by me, for me, as opposed to contributing to
someone else's project.