Devlog

Introduction

Small blurbs about what I’ve been working on, learning, and thinking about. There’s a good chance that at least some this contains incorrect information.

Bitten by complicated FP once again

October 10, 2024

Before falling asleep I had some ideas for this website. I want to add a dark mode, use the colors from my Neovim theme and also make some layout changes. I thought using the colors from my theme would be straight forward, since I can just generate some CSS variables as an additional output. There’s a new-ish light-dark CSS function that I can use and generate CSS like this:

--color-yellow-fg: light-dark(#000, #fff);

Except that I can’t. The way my theme works is that it all starts with a configuration table that has two entries, for the light and the dark colors. Each variant is then passed to a make_themes function, which is a mini pipeline that outputs the different light or dark themes (Alacritty, Fish, …). The key realization here is that the pipeline only ever has access to light or dark colors, but never both. Now go back and look at the light-dark function. Yes, it needs both.

This is yet another case of making a system unnecessarily constrained. I’m so often reminded of Rich Hickey these days. If I had just dumped all colors into a map that has the complete “theme context”, and passed that around, it would be much simpler to make modifications now. What makes matters worse is that I wrote all of this in a style that resembles functional programming more than idiomatic Lua. There’s lots of mapkv(fn, merge(tableA, tableB)). This also makes it hard to modify my own code, which I wrote mere months ago.

I guess I’ll start by solving the immediate problem and somehow make the full theme context available everywhere. Next, I’ll untangle the FP stuff.


I stepped away from the computer for a bit which brought me some much needed mental clarity. In the end it wasn’t as difficult as I thought. In fact, a pretty sizeable Lua refactor worked on first try, which is really rare for me, when programming in a dynamic language like Lua. I created a context table that has both light and dark and passed this to the theme functions, which now return a table that has a light and a dark key. I tried relying less on FP constructs but the code is still a bit of a mess. At least I managed to always keep the code in a working state. The last hurdle is that the string producting template functions are all called with a huge table that has the key/value color pairs from all themes in it. The idea behind this is that one theme can reference colors from another. This is actually one of the two key ideas behind this theme. Why is this annoying now? I want to create one CSS variable for every base color value my theme has (light.sucess.fg, dark.success.fg, …). The way this works in all themes so far is that you create a template string:

--color-light-success-fg: light-dark(${light-success-fg}, ${dark-success-fg})

This feels tedious though. Can’t I just generate those lines automatically based on the variable names? The problem here is that I have this huge blob of stuff and there’s currently no way to differentiate which slice of keys comes from which theme. It would be nice, in retrospect, if that big table worked like this

local colors = {
  nvim = {
    Normal = {},
  },
  css = {
    LightSuccess = {}
  }
}

instead of

local colors = {
  Normal = {},
  LightSuccess = {},
}

The pragmatic thing for now is to stick with the repetitive string templating.

Dark mode for terminal users

October 9, 2024

I firmly believe that you should use light mode when the ambient lighting is bright. As far as I know, science agrees with that, since dark text on a white background is easier to read than the opposite.

But after the sun has set and you’ve dimmed all the lights, staring at a bright screen seems wrong and it looks out of place when the rest of your system switches to dark mode.

For the longest time I’ve therefore wanted to have the automatic dark/light mode switching in my terminal environment, which consists of Alacritty, tmux, Fish and Neovim (tmux doesn’t define any color values of its own, so we can ignore it).

I finally got around to spending some time on this not so tricky problem and I’d say I’m 85% there. I use my own color theme which exports config files for, among other things, all three programs listed above. And all config files are available in a dark and a light mode. Meaning, in Neovim I can simply switch to the dark version with :color yui_dark. Since Neovim has a nice client/server architecture I can also do this remotely:

:let g:lightline.colorscheme = "yui_dark" | colorscheme yui_dark | call lightline#init() | call lightline#colorscheme() | call lightline#update()<CR>

Alacritty also has a nice API for changing config values from the shell. You can read more about it under man alacritty-msg (and man 5 alacritty for the config values) but the gist is alacritty msg config -w -1 'colors.cursor.background="#CCCCCC"'.

Lastly, for configuring the Fish shell syntax colors you use shell commands anyway, so the exported “config” is a Fish file that I can call whenever I want. The file has commands like this:

set fish_color_match eae9e9
set fish_color_selection --background=474355
set fish_color_search_match --background=4f4b5f
...

In other words: I now have shell commands for remotely changing Alacritty, Fish and Neovim from light to dark mode and vice versa. The “only” thing left to do is to find a way of running either of the two variants when the system switches themes.

Why is `O(log n) + O(log n) = O(log n)`

October 9, 2024

I was thinking about this recently while doing some Leetcode binary search problems. For this particular problem I split it up into two sub problems, each of which used binary search.

This Stack Overflow answer explains it nicely. Constant, multiplicative factors don’t matter much for Big O notation. So the sub problems can also be thought of as O(2 * log n), where the constant factor of 2 doesn’t matter.

During this exercise I also came across a cool graphing tool called Desmos which could be very handy for visualizing and intuitively understanding some of these concepts.