My First Vim Plugin: bufkill

misc

https://github.com/bit101/bufkill

Background

I’ve been using vim full time for about 5 years now, and was semi-comfortable with it for a while before that. It’s one of those technologies that you can go really deep on. And once you get used to the vim way of doing things, it’s hard to do things any other way.

For the record, I actually use neovim, a fork of vim. But I couldn’t give a thorough list of the difference between the two of them to be honest. For the most part they are functionally equivalent… I think. So I’m just going to continue to refer to both editors as vim, unless I’m talking about something that is actually different between them.

One of the fun things about vim is configuring it. It’s very easy to go down a very deep rabbit hole and spend hours (days) tweaking your configuration – trying out new plugins, creating mappings and functions that automate things. Then going back months later and realizing you never use half the stuff you added and removing it.

These tweaks usually go in your vim config – a file known as .vimrc in vim and init.vim for neovim. This config file is generally written in a language that is usually called VimScript, but also referred to as VimL, which I guess means “vim language”. Neovim also has a Lua api, which I will probably talk about in another post.

So your config usually is a bunch of statements that set up plugins, set options, perform key mappings for different actions. As you evolve more complex actions, you might start adding functions to your config to build up that logic. Eventually you might want to move those functions out of your config and package them in a distributable way. That’s basically all a plugin is.

The Problem

In vim, like most editors, you can open multiple files at once. These are represented by buffers. But buffers are more than just representations of file content. You can create a new buffer and use it to display information that has nothing to do with a file, like maybe a list of search results. There are also terminal buffers, which are just full-featured terminal emulators. Or buffers that represent a view of your file system. Anything, really.

You can view buffers one at a time, or in horizontal or vertical splits, or in tabs. You can have many, many buffers open at any one time, even if you only see one or a handful at a time. You can switch between buffers and you can close any buffer, which is known, somewhat unfortunately imo, as deleting a buffer. Deleting a buffer does not delete the file it represents on the file system. It just deletes that buffer from memory.

So here’s where the problem starts. Deleting a buffer is simple. You type :bd for “delete buffer” and it goes away.

But… if the buffer is modified, i.e. you’ve added, removed or changed some text and haven’t saved it back to the file it represents, you can’t delete it like that. You either need to save it first by calling :w for “write”, and then deleting it. Or you can discard the changes by calling :bd! to override the default behavior.

Calling :bd on a modified buffer.

But some buffers are read only. And it doesn’t make sense to save buffers that don’t represent files, like search results or terminal buffers. And some buffers are meant to represent files but haven’t been saved as an actual file yet, so saving them means providing a path and file name for them.

The Solution

So all of that complexity is the first big part of what bufkill solves. The plugin provides a command that you can map to a key shortcut (I use ,d) which will delete buffers intelligently.

If the buffer is readonly, or a terminal, or doesn’t have any changes that needs to be saved, it just deletes the buffer directly.

If the buffer has been modified, it prompts you for an action – Save, Discard changes, or Cancel.

Isn’t this a lot more helpful than that message above?

If you press S, the plugin attempts to save the file (more on that in a second). Pressing D calls :bd! to override the delete, discarding the changes. And pressing C gives you a way to back out and think about what you want to do.

Saving

As described earlier, a buffer may represent an existing file on the system, in which case it’s easy to just write the changes back to that file. And that’s exactly what the plugin does. And after saving, it deletes the buffer.

But a buffer may not have been saved yet, so it’s going to need you to tell it where to save it. bufkill has you covered here. It prompts you for a path and file name to save as:

But you’re not left to your own devices on trying to remember your file structure and typing in some long path by hand. Vim is an editor and knows about file systems. Once you start typing a path, completion is available, so you can tab your way down the the location you want and give your file a final name.

(not a paid advertisement for any of these products)

Defaults

Me, I like being able to decide what to do with each buffer I’m deleting. So I like the Save/Discard/Cancel prompts. But maybe you like feeling lucky and always going for the save. Or always going for the discard. I got your back. You can set up a default action in your config, so that every time you run the KillBuffer command, it automatically attempts to save without prompting you. Or you can make it always discard changes and immediately delete the buffer if that suits your workflow. Just add one of the following to your vim config file:

let g:bufkill_default_action = 'save'
let g:bufkill_default_action = 'discard'
let g:bufkill_default_action = 'prompt'

Actually prompt is the default so you don’t really need to add that, but if you want to be explicit about it, go for it.

There are a few other options you can set, but that’s the most important one.

Splits

This is the other big chunk of functionality and one of the main reasons I started working on this plugin. Going to assume you have the concept of a split in vim – you split your screen horizontally or vertically and show a different buffer in each one. You might be comparing two files, or you might have a header file in one part of the split and the implementation in another. Or some non-file buffer like a file system tree plugin or search results in one split.

My personal workflow while working on a project is to have a vertical split, with my code buffers in the left panel, and a narrow panel on the right with a terminal buffer. A key mapping will run the build process in that terminal whenever I want.

Now, say I have a bunch of code buffers open, with one of them visible in that left pane. I’ve just opened this file to check something and I’m done with it so I want to delete that buffer and go back to the other files I was working on. When I delete that buffer, I get this:

Not really what I wanted…

All my other open buffers are still there in the background, but I’ve lost my split and now the terminal buffer has taken over. That’s not what I wanted. I wanted the split to remain and the most recent buffer to replace the one in the left pane. Like this:

That’s better.

So, that’s basically what bufkill does. If you have a split open and you delete a buffer from one pane, it will keep that split there and pull up the previous buffer in the pane you were working in. It will continue doing that until the buffer in the other pane is the last open buffer – at that point it will kill the split and just show that buffer.

Though the example shows a terminal buffer being pinned in a vertical split on the right, and that was exactly my original use case, none of that matters. Whatever pane you delete a buffer from will be replaced with the next buffer, and whatever pane is not active will remain pinned. You can delete buffers in the left pane and the right pane will remain pinned. Then you can jump to the right pane and delete buffers there and whatever is in the left pane will remain pinned. Same if you do a horizontal split with top and bottom panes.

Caveats

This split functionality of this plugin was really only designed with splits in mind. Vim “tabs” are another way of representing multiple open buffers on your screen. I don’t use vim tabs, so I haven’t done much testing in this area, but it very well might break the functionality.

Also, the plugin was designed to work best when you just have a single split open. In vim it is possible to have multiple splits and even nested splits. The plugin is certainly going to have issues with those kinds of layouts, but it should just mean that it won’t delete a buffer that you to delete because it thinks it should keep it open in another split. Fortunately, you can just revert to the built in :bd or :bd! in that case.

I have no idea what’s going to happen here.

Ignore Splits

Also, if you just aren’t interested in the split handling stuff, or it’s causing problems for you, you can disable that part of the plugin with the ignore splits option. Just add this to your config:

let g:bufkill_ignore_splits = 1

You’ll still have all the Save/Discard/Cancel and file naming functionality, but it won’t get fancy about trying to preserve splits.

Side note…

For those analyzing the screenshots, yes, I did start writing this post around 6:00 am on a Sunday. That’s how I roll.

Letting Go of Random

tutorial

In a recent post I shared some thoughts about art and included a few, somewhat tongue-in-cheek comments about the use of random number generation. Specifically,

Random is evil. Random is lazy. Random is OK when you’re starting a new piece. It’s OK when you have a formula and you’re searching for an interesting range of input parameters. But once you find something interesting, lock in those parameters and start focusing.

Interestingly, this was the part of the post that generated the most comments – only a few, but it was definitely the thing that several people latched onto. So I thought I’d expand my thoughts on it.

Now of course I don’t actually think random is evil. But it can be lazy, and it can definitely be boring. But yes, I use random all the time. In my blgo library I have a random module with all kinds of useful functionality that derives from Golang’s built-in pseudo random number generator (PRNG). In my bljs library, I had to build my own PRNG because one doesn’t exist in JavaScript. No, Math.random is not a useful PRNG since you cannot seed it.

So what, in my opinion, is a good use of random and what is not?

Random positions and sizes

Not a great use of random. One of the most boring. I once said something like, “If you can draw a shape, you’re an artist. Randomly draw 10,000 of the same shape, you’re a generative artist.” But honestly I think that’s the ultimate in boring, lazy generative art. Here’s 10,000 random points:

And 500 random squares with random sizes:

And 500 random lines:

I could go on. And I could generate 10,000 individual “art works” like any one of these with a few lines of code. Each would be different. But I wouldn’t call it art. Maybe in my very, very early days of experimenting with graphic code I thought this looked kind of cool. But seriously, I hope your skills and self-expectation rise above this level really quickly.

A Different Random?

So what might be better? Taking it slowly, let’s just try a different random. If you’re using Math.random or something similar that generates a random number, you’re probably getting a uniform distribution. This means that there is an equal probability that you’ll hit any given number in a given range. So it’s all pretty flat and boring. You could try a normal distribution. This favors numbers in the center of your given range, giving you something like this:

For this, you’ll either need a PRNG that has a normal distribution function, or you’ll need to come up with one yourself. Here’s a JavaScript example I found on StackOverflow that seems to do the trick:

// Standard Normal variate using Box-Muller transform.
function randn_bm() {
    var u = 0, v = 0;
    while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
    while(v === 0) v = Math.random();
    return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}

Unlike a uniform distribution generators however, normal distribution generators will usually give you a range of numbers both negative and positive. Most of the generated numbers (around 99.7%) should fall into the range of -3.0 to +3.0. So you’ll have to do some transformations to get them into the range you actually want them.

Here’s an example that places 100 squares in a normally distributed random position, and uses a normal distribution for their sizes as well:

In this case, I took the absolute value of a generated number (which would generally wind up in the range of 0 to 3, weighted heavily towards 0) and multiplied it by 40 to get the size of each square. This skews the square sizes toward the smaller range. Of course, you could do different math to skew it to larger squares, or even towards medium sized squares, with smaller and larger ones occurring less frequently.

And some random lines with normal distribution:

If you find normal distribution interesting, you might want to look at one of the many other probability distributions.

We’re still in the realm of random, but even so, I think the results are much more interesting.

Noise

Another strategy that is more interesting than uniform random distribution is using noise. This usually means Perlin or Simplex noise (which I’ve discussed here in depth). Here, I chose 10,000 random points, but only accepted them if the noise value at that location was above 0 (in a range of -1 to +1):

Things get more interesting when you throw size into the mix. This one does the same thing, but draws squares. The size of each square is in proportion to the value of the noise at that point.

Other

Other things to try are various types of attractor formulas, chaos games, iterated function systems (IFS) and other fractal-related formulas. These can often be just as chaotic and unpredictable as PRNGs, but at the same time give some kind of underlying structure that is much more interesting than uniformly distributed random numbers.

Random Colors

I know next to nothing about color theory, and tend to do things in black and white as long as I can get away with it. Big fan of monochrome. But now and then I’m forced to use color under extreme duress. My first naive attempts to fly under the radar with color usually go along with a function I created called randomRGB, which does what you would guess.

Here’s the above normally distributed squares (a few more of them this time) with random RGB color values.

Well, it IS colorful. But it evokes absolutely nothing. From there, I usually move over to HSV colors, which at least sends me in the right direction. Here, I’m using a random hue from 0 to 60 and a saturation and value of 1.0:

At least this has something going for it. A kind of pixelated, MineCraftian fire maybe. Or, we could keep a single hue and vary the saturation:

Or a random value:

These at least have something going for them. If you want to go all out, you can start creating color palettes. Adobe Color Wheel is a great resource. Here’s a split complementary palette I generated:

To be fair, I’m still just picking one of the five values from the palette randomly, so it’s still pretty lame. I refer back to my first statement of this section. I think it would probably be better to use the reds in one area and the blues in another and the green as a highlight… or something.

Random is Not Evil

As you can see, in just about all of my “non-random” examples, I’m still using random to some degree. But I’m using it secondarily, piping it through something else, which gives it some structure. Once you have some kind of predictable structure, then you start tweaking values to move that structure a bit this way or that way and start adding some of your own taste and judgement into what you are creating. Then it starts to become more of your work, not just the work of a PRNG.

Often, I will have some formula that generates some kind of fractal or attractor. It can produces quite different images depending on what parameters you give it. But that means there can be millions or even billions of different potential images (infinite really, but many of them will be very similar). So I’ll create a loop that just makes a bunch of thumbnails with random parameters and generate a grid of images. On each thumbnail, I’ll print the parameters that created that image.Here’s a sample from last year:

click to see full size.

When I see one I like, I’ll hard code those parameters into the code and generate a larger version. Then I’ll tweak them one way or the other to create something that I really, really like. This use of random allows me to explore way more possibilities in a much shorter time than manually trying to find a good set of parameters.

Summary

I could probably go on about this subject a lot longer, but hopefully I’ve clarified my thoughts a little bit and maybe given you some ideas to try out.

Circle Inversion

tutorial

Circle inversion is a mathematical technique that holds a lot of opportunities for the creative coder.

Circle inversion, or circular inversion, or geometric inversion is a method of transforming a point within a circle to a new point outside the circle or vice-versa. By transforming multiple points, you can transform entire shapes, which become warped and curved in interesting ways, as if the original shape was reflected onto a curved surface. You can even do a circle inversion chaos game with multiple random circles to create interesting fractals. We’ll dive into that after we cover the basics.

The All Important Formula

So we start with a circle centered at x0, y0 with a radius of r. And a point x1, y1 within that circle. We want to invert that point to x2, y2, outside of the circle. That’s the point we need to find.

To describe it a different way, we can easily get the distance from the center of the circle to point x1, y1. We’ll call that dist0. We want to get the distance from the center to x2, y2, which we’ll call dist1.

The formula is simply r^2 / dist0. That’s if the first point is inside the circle. If you want to transform a point outside the circle to a point inside it … well, actually, it’s the exact same formula, which is nice and handy.

I’m not going to go deep into the geometry and math that you use to work out that formula, but it’s a good idea to work it out if you’re into that kind of stuff. There are plenty of pages that will show you exactly what’s going on here.

And the code that will make it happen:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const dist0 = Math.sqrt(dx * dx + dy * dy);
  const dist1 = r * r / dist0;
  const angle = Math.atan2(y1 - cy, x1 - cx);

  return {
    x: cx + Math.cos(angle) * dist1,
    y: cy + Math.sin(angle) * dist1,
  }
}

This takes the center x, y and radius of a circle and the x, y of another point. It calculates the distance from the point to the center using standard Pythagorean theorem, and finds dist1 using the formula I just described. It then finds the angle from the circle center to the point and uses some trig to find the new point. And here it is in action:

You can move the circle’s center, change its radius, and move point p0. Point p1 will then move in accordance. Things to note:

  • As p0 gets close to the edge of the circle, p1 also moves in close to the edge of the circle.
  • As p0 gets close to the center of the circle, p1 moves out to infinity.
  • When p0 goes outside of the circle, p1 crosses over to the inside.

There’s a bit of an optimization you can make to this code to remove all the trig. I’ll just put it here and leave it to you to figure out how it’s working:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const dist0 = Math.sqrt(dx * dx + dy * dy);
  const dist1 = r * r / dist0;
  const ratio = dist1 / dist0;

  return {
    x: cx + dx * ratio,
    y: cy + dy * ratio,
  };
}

In fact, you can go even one step further. Since we’re dividing by dist0 twice, we’re actually dividing by the square of dist0. So we can use that to get rid of the square root and both distances:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const ratio = (r * r ) / (dx * dx + dy * dy);

  return {
    x: cx + dx * ratio,
    y: cy + dy * ratio,
  };
}

Shapes

Once you can invert a single point, you can start inverting entire paths of points, meaning you can invert shapes. To give you a feel for this, here’s a little app that lets you draw on the canvas with your mouse. It will draw both the exact path you are drawing, as well as the inverted path.

There’s no clear button, so you’ll have to refresh the whole page if you want to restart a drawing. If you want to spend some more time with it, you can open up the app in a fresh page.

I’m going to stop here for now. The core takeaway is that invert function. Play around with it and see what happens when you draw different shapes. I’ll come back later with that circle inversion chaos game concept I mentioned earlier. That’s where things get really fun.

Note on diagrams.

The drawings above were done on my Onyx Boox Note Air eInk tablet. I had talked about sketching in eInk in an earlier post. I was about to code up some graphics to show the principles, or maybe break out some kind of drawing application, then decided to give it a go just sketching on the tablet. I then exported the drawings and added them to the post. It’s also the first time I used color in sketching on eInk. Although the Note Air is not a color tablet, you can choose different colors to draw with. They render in black and white on the eInk screen, but when exported, they are indeed color drawings. Not super important to the post. It was just a fun little workflow that worked out pretty well from my viewpoint

Controls: MiniComps

Graphics: BLJS

Support this work

Source for the final piece.

BIT-101 in 2021

misc

I don’t always to a year in review post, but I like to do them when I remember to do so. Looking back over 2021, I’m surprised by how much I did and how much I posted here. Things really got quiet during the last few months, so I forgot how much stuff I cranked out earlier.

Some highlights:

  • 75 blog posts this year! Whoa. Most in a LONG time. And more views on this blog than in well over ten years (thanks HackerNews!)
  • I did a fair number of tutorials on math, graphics and creative coding techniques.
  • I finally created a solid version of MinimalComps for the web! Renamed Minicomps (https://minicomps.org/).
  • I did a bunch of general visual, interactive experiments, even some interactive audio generation stuff.
  • I participated in 7 days of code in July.
  • I created an animated gif every day in August for #awegif2021
  • I bought a Mac. And liked it. But Linux is still my personal daily driver.
  • I did a deep dive into Perlin, Simplex, and Curl noise, which was pretty interesting for me and spurred a lot of conversation elsewhere. https://www.bit-101.com/blog/2021/07/the-noise-series/.
  • I broke down and experimented with NFTs.
  • I did a deep dive into gif and video making tools, several posts worth of tips and tricks.
  • I started a mailing list.
  • I celebrated 20 years of BIT-101!

Sometimes I get a bit down on myself, thinking I’m not doing anything interesting. But when I list it all out, it looks pretty impressive. There was quite a bit going on in my personal and work life the last few months, so things toned down recently. Nothing particularly bad, just stuff pulling my attention away and leaving me with not much energy for writing either code or much else at the end of the day.

I’m hoping to get back into the swing of things in the coming year though. I think I’ve inspired myself to write more after taking a look at the above.

One thing I definitely feel the need to follow up on is the whole subject of NFTs. I’m still very conflicted over them. I created more than a handful and was surprised how much money I was able to earn from the ones I created. Then I took a little break from it for a few weeks and came back and did some more. Then took a more permanent break. I still don’t feel very good about the whole thing right now. I still don’t understand what people are paying for and what they think they are getting. There’s a whole lot of people cranking out a whole lot of low quality, low cost NFTs. And there are established, well known artists making fewer pieces and getting very high prices for them. And there is everything in between. The system as it stands seems like a fad right now and it feels like it will all come crashing down before very long. On the other hand, I believe there is something there that could evolve into a very stable and useful system of rewarding artists for their work. I’ll keep watching the space. I expect a lot of change in it in the coming year. I’m intrigued where it might go, but I’m not 100% comfortable participating in it as things stand. Which sucks, because I like money as much as the next person, and it’s a relatively easy way to make money doing what I like to do. I’m not drawing a line in the sand, but for now I’d rather just code cool pieces and let people look at them without “collecting” them.

Thoughts on Art

misc

I’ve been thinking a lot about “art” recently. Specifically, what people call “generative art”, “algorithmic art”, “code art”, “math art”, etc. Here are some random thoughts.

Message

I’ve never been one to try to communicate some message through the things I create. I really only try to create things that are visually interesting. I can get very excited about the way a piece looks and I just want to show others and hope that they get a taste of that excitement too. Sometimes things I create can evoke various emotions – they can look ominous, dark, scary, energetic, fun, etc. I often find that when I feel a certain way about a piece, others tend to experience that same feeling. I guess you could call that a message if you want. But I don’t know that I’ve ever sat down to create some digital art with the thought, “I feel like creating something dark and ominous today,” or intentionally tried to create any emotion before I started.

Discovery

For me, creating art with code is way more about discovery. I play around with some technique, or combine one technique with another dis-related technique just to see what happens. Then I see something interesting and I zoom in on it. Sometimes this means literally zooming into some detail in an image. More often it means focusing on some combination of parameters that have created a particular result. There’s a promise of something even more interesting there. I start tweaking numbers to see if I can bring out more of that something. I increment a parameter a few times and that thing I saw goes away. So I decrement it and maybe that thing becomes bigger, or more clear, or more detailed. It’s more like mining than creating.

Math

I love math, or “maths” if that’s how you think of it. I love finding some new interesting formula. I subscribe to recreational math blogs, YouTube channels, Twitter feeds. I go to the math section of bookstores and libraries. I scroll through Wolfram and Wikipedia looking for new ideas. Old copies of Scientific American, Omni, Quantum and other math and science magazines. I get sucked in by anything that has a graph or an interesting diagram. It’s got to be visual. For me, math is the ultimate creative tool. It’s the canvas, it’s the paint, it’s the brush. Really, it’s the artist. All the images are already there. I’m just carefully extracting a few of them out of the sea of numbers. If I have to have a message in my art it’s “Look how amazing math is.”

Random

Random is evil. Random is lazy. Random is OK when you’re starting a new piece. It’s OK when you have a formula and you’re searching for an interesting range of input parameters. But once you find something interesting, lock in those parameters and start focusing. My code framework is set up to allow me to easily create animations by changing parameters over each of many frames. Sometimes I’ll generate several hundred frames all with random parameters. I’ll print the parameters right on the piece. Then I’ll sift through the frames one by one and find those that have something I like. I’ll grab those parameters and hard code them and start tweaking them as described above. But random should come at the start, not at the end. I never continue to use random parameters to generate a finished piece. I’m totally lying. I do it often enough. But I feel lazy when I do it.

Technology

People often ask me what technology I used to create my images. I think they expect that I’m using some app or framework that has all these kinds of image generation tools built into it. I don’t. I write mostly in Go (Golang). I have some custom Go bindings for the C library, cairographics. Cairo is a pretty powerful drawing API, but that’s all it is – it draws lines and arcs curves and rectangles, sets colors, etc. Nearly identical in most important ways to the HTML Canvas drawing API. That’s all I need – those 2D drawing primitives. I have a framework of my own that I’ve built up over many years that does all the complex fancy stuff. But it’s all based on those 2d primitive drawing actions.

Color

I love monochrome. Black and white. I love to be able to bring out form and emotion just by the relative brightness of black and white pixels. Sometimes I’ll experiment with color. I have a random RGB function that makes me feel guilty when I use it. I like using HSV colors better. You can create nice gradients. You can keep one hue and vary the saturation or value. You can create a range of colors with a similar hue. I’d like to take a deep dive into learning color theory some time. But I’m very comfortable with black and white.

Combination

One of my best techniques is a meta-technique. I mentioned it above. Every time I learn some new technique or formula, I do a mash up with that and some other technique I already know. I know I’ve talked about that in other posts in more detail. It’s the best way to discover something that has a chance of the elusive “nobody has done this before”.

Dislikes

  • AI/ML/GAN stuff. It just does nothing for me. To me it just looks like Photoshop filters on steroids. I know there’s a lot of impressive stuff going on behind the scenes, but the result is not interesting to me.
  • Glitch art. I think this is due to the fact that I grew up in the 60s and 70s and 80s. Everything was glitchy. I didn’t like it then and I don’t like it now. I like that things are not glitchy now. I like that I turn on the TV and see a clear picture without bending the coat hanger stuck in the back into some new shape.
  • 3D. By this I mean slick, realistic 3D stuff done in professional 3D rendering packages. I like occasionally hand-coding lofi 3D stuff.
  • Shaders. In either 2D or 3D. I probably should like shaders. You can do some impressive math-based stuff with them. I’ve used them. I even written about them and touched on them in some videos, but they never stuck as something I wanted to continue working with.

OK, now here’s where you’re going to say, “You should check out _____ (AI/Glitch/3D/Shader thing).” And I’ll say, “Thanks, that looks cool. Maybe I’ll check it out.” But I never will. But really, thanks! I appreciate your enthusiasm. I’m not saying any of these things are inherently bad. Just sharing my tastes.

My Music Appreciation Project

misc

Not a big fan of music streaming.

I have a good size, custom curated, very well organized library of music on my hard drive. It’s taken me years to create, it’s all backed up. I have a subsonic server behind Wireguard so I can listen to it from my phone or other devices, and it’s all also synced to my Sony Walkman NW-A55 hi-res digital audio player that I use with my Ikko OH1 IEMs.

I’m really very satisfied with this setup.

But still, I find myself not being able to decide what to listen to way too often. The paradox of choice. Fairly often I’ll just throw the whole thing, or maybe some specific genre on shuffle, and that’s pretty good. But I also like listening to albums. When I’m just choosing an album myself, I’ll gravitate to the same few dozen or so artists. Other stuff might go months or years without being listened to.

I think my devices and software let me shuffle albums, but I wanted to create a long range plan to get to all of it over time. Here’s what I did:

  1. Printed out a list of all artists. Literally just went to the terminal and did an ls in my music folder, directing it to a file.
  2. Pulled that file into a Google spreadsheet, one artist per line.
  3. Shuffled them.

Now I’m just working down the list. I just grab the next artist in the list and choose an album and start playing.

If I’m not feeling the vibe with that particular artist or album, I just move on. But I try to listen to at least one or two songs anyway.

When I move on to the next artist, I mark the previous one as done.

Here’s what’s on my playlist for today:

  • Ministry
  • Van Morrison
  • Harry Nillson
  • The White Stripes
  • John Lee Hooker

I’ve really been enjoying this strategy. Been listening to music that I haven’t in a long time, not just the same albums over and over. And it’s all content that I’ve chosen to put in my library, so it’s all artists I generally like to some degree. And sometimes get totally different genres up against each other, which is fun.

This is going to take months to go through, but it’s been keeping things fresh.

Strange Attractor Flow Fields

tutorial

One of my tricks when coming up with new generative ideas is to take two (or three) completely unrelated techniques and combine them. I even created an app once where I had a long list of concepts and it would randomly combine them and come up with things like, “circle packing with diffuse limited aggregation”. (I just made that up and I’m not sure how it would work, but it’s intriguing, isn’t it?) I can’t say that the app ever sparked any projects that I ended up using, but I’ll probably go back to it some time and see if I can make it better.

This post was one of those successful combinations that evolved on its own and produced something that I have never seen anyone explore before. It produces a visualization of the forces behind a strange attractor that I find fascinating and beautiful. It feels like putting on special glasses that let you see the invisible workings of the universe.

Sketching in eInk

misc

In my last post I talked about my newest eInk tablets from Onyx Boox. Beyond reading ebooks and saving articles, the Note Air is a fantastic sketching tool. The Wacom layer and stylus is one of the big features that led me to look beyond Kindle devices. It was nice on the 7.8″ Nova Pro, but on the 10.3″ Note Air, I’ve really fallen in love with the drawing feature.

Preliminary Pen Points

The Note Air comes with a stylus that attaches to the side of the device via a magnet. All I can say is that it makes a good backup stylus.

Issues with the stylus:

  1. The magnet is not strong enough to trust, so you wind up having to figure out your own way to keeping track of the stylus. Because it WILL fall off and get lost.
  2. The stylus does not have an eraser feature. some styluses put an eraser function in the top of the stylus, where you’d find an eraser on a regular pencil. Others add a button that switches the stylus into erase mode. The default Note Air stylus does neither. So when you want to erase something, you have to choose the eraser tool from the tool bar, erase, then re-choose the drawing tool you were drawing with.

I wound up getting a Wacom One stylus.

It looks nice, feels nice, has an eraser button, and doesn’t break the bank.

I read a lot of reviews about the Remarkable 2 Marker stylus that is made for the Remarkable 2 eInk tablet. It’s apparently really good, but pretty pricey. It does work on the Boox devices. Maybe I’ll spring for one some day, but I’m happy with the Wacom One for now. One of the pros of the Remarkable stylus is that the tips are made of a different substance than a lot of other styluses, which gives it a good amount of drag and makes it feel like a regular pen, rather than sliding a piece of plastic across glass. Remarkable sells replacement tips, which fit the Wacom One, so I got a set of them, and I can attest it does add to the experience.

To hold the pen when I’m not using it, I got some of these Ringke pen holders.

These just stick to the cover and have an elastic loop. Been working out perfectly.

Seriously Sketching Stuff

Now onto the sketching functionality of the device. The built-in notes app is where you do the sketching and it’s one of the main apps on the Note Air. This is what it looks like:

You can name your notes, organize them in folders, rename them, view them as a list or thumbnails, etc.

Notes can have multiple pages. You can see above the Notepad1(1) has a little “6” in the corner. This means that this note has 6 pages. While in the note, you can choose to see an overview of all of the pages.

You can delete, add, rearrange, export, and share pages here.

There are multiple sketch tools you can use:

I most often just use the default pen tool. All of the tools allow you to adjust their width. All but the ballpoint pen and marker are also pressure sensitive. You can change colors – various shades of gray mostly, but also a few real colors. Though you won’t be able to see these on a black and white eInk device until you export the note.

There’s all the usual other tooling, if all a bit basic. A few basic shapes, several different kinds of erasers, lasso tool for selecting and moving parts of your sketch, zoom, text, handwriting recognition.

It even has layers, which is pretty damn cool.

You can add layers, rearrange them, hide them, delete them. The bottom layer is a background template. It can be blank, our you can set it to just about anything. Above you can see a basic grid template. There are a bunch built in:

Three pages worth, for drawing, writing, penmanship, accounting, whatever. There are also ones you can download from the Boox cloud:

And you can add your own, just by putting the into the right folder on the device. Just do an internet search for PDF graph paper or pdf templates and you’ll find all kinds of useful stuff. Or you can just create any PDF you want and put it in there. Here are some I added:

You can turn the template’s visibility on and off from the layers tool, which is really quite nice.

On for drawing:

And then off:

I’m constantly using this to figure out stuff that I want to code. I have pages and pages of sketches like this. Most are just brainstorming or figuring out the math about something.

The touch layer of the device is totally separate from the Wacom drawing layer, so there’s no need to worry about putting your hand on the device as you’re drawing. When you want a new page in a particular sketch, just swipe with your finger, right to left, and you’re on a new page. Go back and forth to existing pages by swiping right or left.

You can set up notes to automatically sync to the cloud, using Onyx’s own cloud sync, Youdao (a Chinese service), Evernote, Dropbox and/or OneNote. Synced notes are available in the cloud as PDFs, but you can also export them as PNGs.

I always have the Note Air nearby when I’m doing some creative coding, so it’s easy to just grab it and work out some idea. I just create note after note, page after page. Space is no worry. They’re backed up and easily available on Dropbox, not floating around on pieced of dead tree pulp.

While the sketch/notes app is probably not something you’re going to create amazing art with, it’s super useful for sketching and notes. I also use it to take notes in meetings and interviews. Very nice for that.

I have to give a warning though. While the built-in notes app is super responsive and a joy to use, the Wacom layer is not optimized for third party drawing, sketching or note-taking applications on the web or Android apps. It will be a bad experience using apps like that. It would be nice if that got fixed, but not holding my breath. I did see where someone has put together their own libraries that make the experience much better in third party apps, but I have not tried it myself.

[Update 01/01/22]

The latest firmware for the Boox tablets has apparently improved the third party app sketching functionality. At least for popular apps like Evernote. I’ve not tried it out myself. Pretty happy with the internal note app.