Nishanth Shanmugham

Read this first

Start tmux automatically

I wanted to start tmux—the terminal multiplexer—automatically when I opened a new terminal window.

I had some specific requirements however. For instance, I wanted to have a “main” tmux session that new windows should try to attach to. And if I was already attached to the main tmux session, then I wanted any subsequent new terminal windows to create new unnamed sessions (this way each window has its own independent session).

The requirements

  1. If the “main” session doesn’t exist, create a new session named “main”.
  2. If the “main” session exists and there are zero clients attached to it, attach to it ourselves.
  3. If the “main” session exists and there is already a client attached to it, create a new unnamed session.

I wrote a script to do this, since it seems like tmux’s built-in subcommands and flags can’t account for these requirements on their own. The command tmux new -A -s main...

Continue reading →

Hibernate in Fedora

I spent time yesterday making HybridSleep and Hibernate work in Fedora 32 on a ThinkPad X1 Carbon with an encrypted disk.

I don’t ever plan to manually use hybrid sleep or hibernate; I’d instead just lock my screen or close the laptop lid. So why even bother to have them work?

It’s because hybrid sleep and hibernate are useful to have when battery power runs out. You’ll find in /etc/UPower/UPower.conf that the computer attempts hybrid sleep, hibernate, and a full shutdown, in this order, when the battery runs out. If you don’t want a full shutdown and to lose working state when this happens, you should want a working hibernate or hybrid sleep.

$ cat /etc/UPower/UPower.conf | tail -n 3
 If HybridSleep isn't available, Hibernate will be used
 If Hibernate isn't available, PowerOff will be used

How to use this guide

There are 5-6 issues that users...

Continue reading →

Vim-like cursor keys on a 60% keyboard


I’m using a 60% keyboard, which has 61 keys—the WASD VP3. It doesn’t have dedicated cursor keys, so I set up Fn + hjkl to act as cursor keys.

The default mappings use Fn + ijkl as cursor keys.

Fn + i: up
Fn + k: down
Fn + j: left
Fn + l: right

Compare this to the vim-like movements, which I prefer:

Fn + k: up
Fn + j: down
Fn + h: left
Fn + l: right

Thankfully, the VP3 has 3 user-programmable layers—accessed by Fn + {<,>,?}. So I programmed the first of these layers to use the vim movement bindings. (I also then reprogrammed Fn + i to represent Home, which previously represented by Fn + h, would be lost in the new bindings otherwise.)


Here’s a link to the keyboard manuals and, as an example, the steps I followed to program Fn + j to represent the down cursor key instead of the original left cursor key.

  1. Optionally reset all your previous programming by pressing Right...

Continue reading →

Kindle font

I’m liking reading on Kindle.

I really like the feel of electronic paper technology: the screen lighting, the slow turning of pages, and the black & white colors. I’m also thankful for the ability to quickly get samples of books to see if I would be interested in the full books.

I recently learned that you can add custom fonts to Kindle. Palatino is my favorite of the built-in fonts, but custom ones have made reading more enjoyable. I’m really liking the free font Linux Libertine O at size 6, bold level 2, tightest line spacing, and medium margins. This is what it looks like.


Continue reading →

Properly typed omit function in TypeScript

Writing a properly typed omit function requires a few type casts. I think this is the cleanest possible way (I’d be thrilled to learn of a cleaner way), and it doesn’t include an allocation for an Object.keys(obj) array.

function omit<T, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {
    const ret = {} as Omit<T, K>
    const omitKeys = new Set(keys)

    for (const k in obj) {
        const key = k as unknown as K
        if (omitKeys.has(key)) {
        const presentKey = key as unknown as Exclude<keyof T, K>
        ret[presentKey] = obj[presentKey]

    return ret

Let’s look at the necessity and the safety of each type cast.

const ret = {} as Omit<T, K>

This is necessary at some point before returning. Typing it early (instead of casting later in the return statement) also assists in typing at other portions of the function. This...

Continue reading →

Accidental removal of side-effect imports

This particular issue is something I’ve come across in Go code shipped to staging/a semi-stable environment, and it’s unfortunately one that is difficult to catch in code review if you’re not looking out for it. I’ll cover how the issue happens and show a couple of ways I’ve learned to prevent the issue from happening.

First, the overview. Go has the ability to import a package purely for the package’s side-effects (i.e. you don’t actually use a symbol from the package in your code, just the side-effects).

As an example let’s look at the expvar package in std lib. Importing the package, as a side-effect, registers a HTTP handler at “/debug/vars” that prints the state of published vars. In addition, it publishes by default a couple of exported vars named memstats and cmdline.

How the issue arises

I’ll stick to the std lib in this example, so the example may be a bit simple, but I...

Continue reading →

A stricter Omit type

In TypeScript you’ll find globally available utility types that are useful to manipulate and transform types in common ways. One of the types, Omit, can be used to remove specified properties from a type. For the uninitiated it works like this:

type SongProps = {
  album: string
  artist: string
  title: string
  loved: boolean

type X = Omit<SongProps, "title" | "loved">
// {
//   album: string
//   artist: string
// }

But a thing I’ve disliked about the built-in Omit type is that specifying a non-existent property in an Omit call doesn’t result in an error.

As an example, if we renamed the title property to name in the SongProps type, the Omit line still compiles successfully. (You can imagine how this issue would be exacerbated if the SongProps and Omit lines were far away.)

type SongProps = {
  album: string
  artist: string
  name: string // renamed
  loved: boolean

Continue reading →

A guide to using built-in TLS in Redis

Redis version 6 added TLS as a built-in feature. This makes me super happy, because I’m now able to use Redis as a store with my applications running on App Engine considering that the traffic is encrypted, without additional tools or a paid Redis Cloud plan.

Keep in mind that you will have to build Redis with TLS support at compile time. See

I couldn’t find an end-to-end example for setting up TLS (not very surprising considering that the feature was released April 30 this year), which would have really helped a novice like me. So here we are in case it helps someone else.

Generate cert files

To use TLS with Redis, you’ll have to generate:

  1. a certificate-key pair for the server (redis.crt, redis.key), and
  2. a root CA certificate (ca.crt)

The TL;DR is that you run

FQDN=<redis-server-ip> make generate

with this Makefile.


Continue reading →

Parallel tests in Go

Go surprises me with how simple it makes things. Today, it was parallel testing. In other languages I’ve used, it may require third-party packages, require complicated syntax, or may just not be possible. In Go, it’s as simple as:

import "testing"

func TestMeow(t *testing.T) {
    // test logic here

func TestRoar(t *testing.T) {
    // test logic here

func TestBark(t *testing.T) {
    // test logic here

Tests marked with t.Parallel() will execute in parallel with other tests also marked with t.Parallel(). So the tests TestMeow() and TestRoar() will run in parallel, but TestBark() will not.

In case you want to run tests serially despite marking them parallel, you can set the test.parallel flag instead of commenting out each t.Parallel() call.

$ go test -test.parallel 1

Continue reading →