dwmsss

DWM System Status String.

There are number of ways to write status monitor in dwm. The most straightforward being a shell script but after learning C you always see scripts as quick prototype no matter how well written. But shell script was what I have been using all that time. Finally at the July 25 of 2023 after using dwm for more than 2 years the time has came to redeem myself and rewrite that script in proper language.

All I wanted in status monitor was:

When looking at Status Monitors Submitted By Others I was unsatisfied with how complicated they are. But only because they tried to be generic, apply to more cases and appeal to bigger crowd. Also they really tried to accomplish everything with C. I decided to give myself some slack to reduce complexity. I found it amazing that changing requirements slightly can simplify implementation by a lot.

Audio was the biggest pain point. Therefore I decided to call amixer program directly with system() function. Call me a cheater but you will quickly find that there is no victory in programming audio on Linux. Anyway, with audio out of the way everything else was easy. I love the use of "static" for strings in each status function. And I like how introduction of single utility function word() made everything dead simple.

This is how it looks like: up@ 45v -56b | 11-04 05:21 and it says that WiFi is connected, volume level is 45%, battery level is 56% and not charging, then month, day, hours and minutes.

Because implementation is very short I'm posting it here.

#include       /* DWM System Status String v2.4   sss  / / */
#include      /* From irek.gabr.pl/dwmsss.html     __/ /  */
#include        /* Public domain (unlicense.org)  >~('__/   */

/* Read first word from file under PATH into BUF of SIZ as string.
 * ASCII characters smaller than 48 ('0') are consider delimiters. */
void word(char *buf, int siz, const char *path) {
	FILE *fp = fopen(path, "r");
	if (!fp) return;
	for (; --siz; buf += 1) if ((*buf = getc(fp)) < 48) break;
	*buf = 0;
	fclose(fp);
}

static char *wifi(void) {
	static char buf[8];
	word(buf, 8, "/sys/class/net/wlp3s0/operstate");
	return buf;
}

static char *volume(void) {
	static char buf[8];
	system("amixer get Master | grep -om1 '[0-9]\\+%' > /tmp/dwmsss");
	word(buf, 8, "/tmp/dwmsss");
	return buf;
}

static char *battery(void) {
	static char buf[8];
	word(buf,   2, "/sys/class/power_supply/BAT0/status");
	word(buf+1, 6, "/sys/class/power_supply/BAT0/capacity");
	*buf = *buf == 'C' ? '+' : '-'; /* Convert status to + or - */
	return buf;
}

static char *date(void) {
	static char buf[16];
	time_t now = time(0);
	strftime(buf, 16, "%m-%d %H:%M", localtime(&now));
	return buf;
}

int main(void) {
	return printf(" %s@ %sv %sb | %s",
		wifi(), volume(), battery(), date()) < 0;
}

Setup

# ~/.xinitrc
while true; do
	xsetroot -name "$(dwmsss)"
	sleep 2
done

Epilogue

At this point (November 2023) I don't run dwm anymore. I'm on Debian GNU/Linux 12 (bookworm) with Xfce 4.18. I was using dwm window manager exclusively for 2 years therefore I decided to try desktop manager for a change to see if there is something that I'm missing out but I no longer remember. It's probable that I will switch back to dwm after being frustrated with lack of control or usage of resources.

Written: 2023-08-22

Updated: April 2024