From 515a3c19dd58c0bd6ea8c5bfdcf1ec24fd2fad83 Mon Sep 17 00:00:00 2001 From: Gwenn Englebienne Date: Wed, 23 Nov 2022 22:59:37 +0100 Subject: [PATCH] Display CPU usage as a bar graph using Unicode characters Extend configuration keywords "%usage" with "%usagebar" and "%cpu" with "%cpubar", which display the corresponding statistics as a bar, one character wide, instead of a percentage. These keywords can be combined in a single configuration. The graph is relatively coarse, with a resolution of 11 percentage points per bar increment, but it compresses the width of the representation from (typically) four characters to one. This is particularly useful on machines with larger numbers of cores. --- man/i3status.man | 6 +++++- src/print_cpu_usage.c | 28 ++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/man/i3status.man b/man/i3status.man index 36e1a6e7..dbf4f02f 100644 --- a/man/i3status.man +++ b/man/i3status.man @@ -453,9 +453,13 @@ when above degraded threshold can be customized with For displaying the Nth CPU usage, you can use the %cpu format string, starting from %cpu0. This feature is currently not supported in FreeBSD. +CPU usage can also be represented graphically using %usagebar and %cpubar +instead of, respectively, %usage and %cpu. This feature requires the use +of a (preferrably, monospace) font implementing "Block Elements" + *Example order*: +cpu_usage+ -*Example format*: +all: %usage CPU_0: %cpu0 CPU_1: %cpu1+ +*Example format*: +all: %usage [%cpubar0%cpubar1]+ *Example max_threshold*: +75+ diff --git a/src/print_cpu_usage.c b/src/print_cpu_usage.c index a7ee2e46..9c7f467e 100644 --- a/src/print_cpu_usage.c +++ b/src/print_cpu_usage.c @@ -64,6 +64,8 @@ static struct cpu_usage prev_all = {0, 0, 0, 0, 0}; static struct cpu_usage *prev_cpus = NULL; static struct cpu_usage *curr_cpus = NULL; +static const char *bars[] = {" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"}; + /* * Reads the CPU utilization from /proc/stat and returns the usage as a * percentage. @@ -201,14 +203,27 @@ void print_cpu_usage(cpu_usage_ctx_t *ctx) { *(outwalk++) = *walk; } else if (BEGINS_WITH(walk + 1, "usage")) { - outwalk += sprintf(outwalk, "%02d%s", diff_usage, pct_mark); - walk += strlen("usage"); + if (BEGINS_WITH(walk + 1, "usagebar")) { + if (diff_usage > 98) + diff_usage = 98; + outwalk += sprintf(outwalk, "%s", bars[diff_usage / 11]); + walk += strlen("usagebar"); + } else { + outwalk += sprintf(outwalk, "%02d%s", diff_usage, pct_mark); + walk += strlen("usage"); + } } #if defined(__linux__) else if (BEGINS_WITH(walk + 1, "cpu")) { + bool bar = false; + if (BEGINS_WITH(walk + 1, "cpubar")) + bar = true; int number = -1; int length = strlen("cpu"); - sscanf(walk + 1, "cpu%d%n", &number, &length); + if (bar) + sscanf(walk + 1, "cpubar%d%n", &number, &length); + else + sscanf(walk + 1, "cpu%d%n", &number, &length); if (number == -1) { fprintf(stderr, "i3status: provided CPU number cannot be parsed\n"); } else if (number >= cpu_count) { @@ -217,7 +232,12 @@ void print_cpu_usage(cpu_usage_ctx_t *ctx) { int cpu_diff_idle = curr_cpus[number].idle - prev_cpus[number].idle; int cpu_diff_total = curr_cpus[number].total - prev_cpus[number].total; int cpu_diff_usage = (cpu_diff_total ? (1000 * (cpu_diff_total - cpu_diff_idle) / cpu_diff_total + 5) / 10 : 0); - outwalk += sprintf(outwalk, "%02d%s", cpu_diff_usage, pct_mark); + if (bar) { + if (cpu_diff_usage > 98) + cpu_diff_usage = 98; + outwalk += sprintf(outwalk, "%s", bars[cpu_diff_usage / 11]); + } else + outwalk += sprintf(outwalk, "%02d%s", cpu_diff_usage, pct_mark); } walk += length; }