i^BFalIhquI_mVTnsOiTwhA-#Va^{HdEvm>Fm7HJm+~Fepvlj~~t{+DJ
za*?yr{pLZ=9*-NoS>|cG@o%&1*XsIRlmUF$GnBz*3@E=2gAU=od^~;yh*Q6Q-kBQj|RJS^pd5h&d=OOUoVp<@ja!X8)>{fm;K-UjJ9c
zhgr5-63-I$;l)9Izqeqt>!X3P@>Ruo;*`IPWPUjDStRqwiC<2VZ%(|LBu}0A6(srZ
z#IG#Q6DMBjck($T`QVhFTf7(I#OIN$GfsRy4V1}WA9g~y-{6$5rRB0vSqvXmSXs9$
z7|~xyvR*myMI^tsIq|D-k3%wLhU25F>9ARMW>Eh9WiiQmUm*QKE{o;FzX+Ya4oiFz&JEgdm
zucfuFd8hHxd>(+Ea`Dvibu{kE|9z_68C>?|L4{vKc_S~lv@5v8?U0c_W8~%i`2Zd`
zo>OJ*%rCxYi5+dfbbWY2*`L7&9r3KAF=JosJZt(TxcGC#;6HKs`8US@a|Zt+>Rf(g
z@Z}8}_=ed}{z>6=^oq;QDI>pcnU;w45E0&$;A3QT?hVH_qnD+3~74Eht(47XtTSU3IVXON_jG
zA8Ay0>3-B~?6~)Zod~#>Dy?Is`zF7CEI~gj0q>}Q@2!A;7kIh;
ze!qhJSOxrb;5B8&@!u-Qe*oM+)1BheXTWQ{rTbAe63+}(QI;RB1zt-t`@ZDo%}RbQ
zoiH1??Bi=H*txR;{zt}+tQ+dA1nu@3{5ZeZpq$c#=3#ux<->%EL+SfWzp+zg9Ncc~
zJZSKCgZCJGzrp2uLc-vKz{|CJ*x>H>y621?`JScDieT%g!i`ajoG|ip%=a>h=PMQD
ze^CMdRRug??2jA6Yfal{fpb2%{rBK|d%1kLssg?oxZmoJJT@!&x%4O>ZlOG{32m)l
z=iUl9?i$8dBvaW~AVSNcxbcU2C>!2Mja~imM6_`y-|}nBq$B!ig+?Qp{zi2xFp$d7
zvH^-G<5?JJ?9Zgt1?8QQNTa!%yrMt3E19}KX>Kgr7@Du#seve
zgcFI-{ju<_P1-z3-`x!lXD)h%vb`Z(kW9uh=yWs{+L=gog%hDDE^=l<
z;r;=NqIx{!b%oQoq{&aXs%f5DQpqfCg~uoz
z%l4;}JG8+JDt#RkOLVVLqmfMDk84y
zt4^6q-p=jHWQvz_RX_D*+6-Cuah*3_9me@)tqGF4G3#bVdJ&9RG@K2iJKR<*8AZT!
zBMxD8Ro8)(?OeQU090f{e7)9TLErUtLFq_1>xB4PuLD7@!ebp5=WS&7b>>hslM3~O
zlTloCR#%Rlb~fJyBhh#=)Srn(No6&t#Bhc9)!y80ocA(k?-rKO553*++&l;!H+4Qf$E#fN
zcLh0*|GL3NU(Q2?%I^peQ-xz~7ykDgd}c5Da&9VA-iO40krTQL`urP!)a86tsNXck
z{&U;z{`0>x;V}_?IfoV6VHncB=u7|i8U1EZF7msEQ28B%_4$a)t^XIm*e~<*MDcf^
zVRKFlOKePyy%%Keb=Qg=gC6l
zeOct){tp{{iNBmX3!UxqU*aeBj=1#Yd|K#pB50_){l9bR%Q?2t`@}J$?{0q#I3L~c
z+~6YT6vcm+r{UsX(HHs}IQ&&g^yOT<=6bCna$-R0LMOoB5Q)B=pVt}vK~XeR^aOqn
z4>GqIlk*q(cau{l{*s@fFM04Q=-BPcxyxZ(pyIM!lj2{|7y2qg^0fUyPEb+
z>#!`>T`8taO!*a|!)8A6I{poOqz>%
literal 0
HcmV?d00001
diff --git a/dwmblocks.c b/dwmblocks.c
new file mode 100644
index 0000000..ded717c
--- /dev/null
+++ b/dwmblocks.c
@@ -0,0 +1,213 @@
+#include
+#include
+#include
+#include
+#include
+#ifndef NO_X
+#include
+#endif
+#ifdef __OpenBSD__
+#define SIGPLUS SIGUSR1+1
+#define SIGMINUS SIGUSR1-1
+#else
+#define SIGPLUS SIGRTMIN
+#define SIGMINUS SIGRTMIN
+#endif
+#define LENGTH(X) (sizeof(X) / sizeof (X[0]))
+#define CMDLENGTH 50
+#define MIN( a, b ) ( ( a < b) ? a : b )
+#define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
+
+typedef struct {
+ char* icon;
+ char* command;
+ unsigned int interval;
+ unsigned int signal;
+} Block;
+#ifndef __OpenBSD__
+void dummysighandler(int num);
+#endif
+void sighandler(int num);
+void getcmds(int time);
+void getsigcmds(unsigned int signal);
+void setupsignals();
+void sighandler(int signum);
+int getstatus(char *str, char *last);
+void statusloop();
+void termhandler();
+void pstdout();
+#ifndef NO_X
+void setroot();
+static void (*writestatus) () = setroot;
+static int setupX();
+static Display *dpy;
+static int screen;
+static Window root;
+#else
+static void (*writestatus) () = pstdout;
+#endif
+
+
+#include "blocks.h"
+
+static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
+static char statusstr[2][STATUSLENGTH];
+static int statusContinue = 1;
+static int returnStatus = 0;
+
+//opens process *cmd and stores output in *output
+void getcmd(const Block *block, char *output)
+{
+ strcpy(output, block->icon);
+ FILE *cmdf = popen(block->command, "r");
+ if (!cmdf)
+ return;
+ int i = strlen(block->icon);
+ fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
+ i = strlen(output);
+ if (i == 0) {
+ //return if block and command output are both empty
+ pclose(cmdf);
+ return;
+ }
+ if (delim[0] != '\0') {
+ //only chop off newline if one is present at the end
+ i = output[i-1] == '\n' ? i-1 : i;
+ strncpy(output+i, delim, delimLen);
+ }
+ else
+ output[i++] = '\0';
+ pclose(cmdf);
+}
+
+void getcmds(int time)
+{
+ const Block* current;
+ for (unsigned int i = 0; i < LENGTH(blocks); i++) {
+ current = blocks + i;
+ if ((current->interval != 0 && time % current->interval == 0) || time == -1)
+ getcmd(current,statusbar[i]);
+ }
+}
+
+void getsigcmds(unsigned int signal)
+{
+ const Block *current;
+ for (unsigned int i = 0; i < LENGTH(blocks); i++) {
+ current = blocks + i;
+ if (current->signal == signal)
+ getcmd(current,statusbar[i]);
+ }
+}
+
+void setupsignals()
+{
+#ifndef __OpenBSD__
+ /* initialize all real time signals with dummy handler */
+ for (int i = SIGRTMIN; i <= SIGRTMAX; i++)
+ signal(i, dummysighandler);
+#endif
+
+ for (unsigned int i = 0; i < LENGTH(blocks); i++) {
+ if (blocks[i].signal > 0)
+ signal(SIGMINUS+blocks[i].signal, sighandler);
+ }
+
+}
+
+int getstatus(char *str, char *last)
+{
+ strcpy(last, str);
+ str[0] = '\0';
+ for (unsigned int i = 0; i < LENGTH(blocks); i++)
+ strcat(str, statusbar[i]);
+ str[strlen(str)-strlen(delim)] = '\0';
+ return strcmp(str, last);//0 if they are the same
+}
+
+#ifndef NO_X
+void setroot()
+{
+ if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed.
+ return;
+ XStoreName(dpy, root, statusstr[0]);
+ XFlush(dpy);
+}
+
+int setupX()
+{
+ dpy = XOpenDisplay(NULL);
+ if (!dpy) {
+ fprintf(stderr, "dwmblocks: Failed to open display\n");
+ return 0;
+ }
+ screen = DefaultScreen(dpy);
+ root = RootWindow(dpy, screen);
+ return 1;
+}
+#endif
+
+void pstdout()
+{
+ if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed.
+ return;
+ printf("%s\n",statusstr[0]);
+ fflush(stdout);
+}
+
+
+void statusloop()
+{
+ setupsignals();
+ int i = 0;
+ getcmds(-1);
+ while (1) {
+ getcmds(i++);
+ writestatus();
+ if (!statusContinue)
+ break;
+ sleep(1.0);
+ }
+}
+
+#ifndef __OpenBSD__
+/* this signal handler should do nothing */
+void dummysighandler(int signum)
+{
+ return;
+}
+#endif
+
+void sighandler(int signum)
+{
+ getsigcmds(signum-SIGPLUS);
+ writestatus();
+}
+
+void termhandler()
+{
+ statusContinue = 0;
+}
+
+int main(int argc, char** argv)
+{
+ for (int i = 0; i < argc; i++) {//Handle command line arguments
+ if (!strcmp("-d",argv[i]))
+ strncpy(delim, argv[++i], delimLen);
+ else if (!strcmp("-p",argv[i]))
+ writestatus = pstdout;
+ }
+#ifndef NO_X
+ if (!setupX())
+ return 1;
+#endif
+ delimLen = MIN(delimLen, strlen(delim));
+ delim[delimLen++] = '\0';
+ signal(SIGTERM, termhandler);
+ signal(SIGINT, termhandler);
+ statusloop();
+#ifndef NO_X
+ XCloseDisplay(dpy);
+#endif
+ return 0;
+}
diff --git a/scripts/sb-clock b/scripts/sb-clock
new file mode 100644
index 0000000..ac5965d
--- /dev/null
+++ b/scripts/sb-clock
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+clock=$(date '+%I')
+
+case "$clock" in
+ "00") icon="🕛" ;;
+ "01") icon="🕐" ;;
+ "02") icon="🕑" ;;
+ "03") icon="🕒" ;;
+ "04") icon="🕓" ;;
+ "05") icon="🕔" ;;
+ "06") icon="🕕" ;;
+ "07") icon="🕖" ;;
+ "08") icon="🕗" ;;
+ "09") icon="🕘" ;;
+ "10") icon="🕙" ;;
+ "11") icon="🕚" ;;
+ "12") icon="🕛" ;;
+esac
+
+case $BLOCK_BUTTON in
+ 1) notify-send "This Month" "$(cal --color=always | sed "s/..7m//;s/..27m/<\/span><\/b>/")" && notify-send "Appointments" "$(calcurse -d3)" ;;
+ 2) setsid -f "$TERMINAL" -e calcurse ;;
+ 3) notify-send "📅 Time/date module" "\- Left click to show upcoming appointments for the next three days via \`calcurse -d3\` and show the month via \`cal\`
+- Middle click opens calcurse if installed" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+date "+📅%a %d %b %Y $icon%I:%M%p"
diff --git a/scripts/sb-cpu b/scripts/sb-cpu
new file mode 100644
index 0000000..a20a378
--- /dev/null
+++ b/scripts/sb-cpu
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "🖥 CPU hogs" "$(ps axch -o cmd:15,%cpu --sort=-%cpu | head)\\n(100% per core)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🖥 CPU module " "\- Shows CPU temperature.
+- Click to show intensive processes.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+sensors | awk '/temp1/ {print "🌡" $2}'
diff --git a/scripts/sb-disk b/scripts/sb-disk
new file mode 100644
index 0000000..b3d9469
--- /dev/null
+++ b/scripts/sb-disk
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Status bar module for disk space
+# $1 should be drive mountpoint, otherwise assumed /.
+
+location=${1:-/}
+
+[ -d "$location" ] || exit
+
+case $BLOCK_BUTTON in
+ 1) notify-send "💽 Disk space" "$(df -h --output=target,used,size)" ;;
+ 3) notify-send "💽 Disk module" "\- Shows used hard drive space.
+- Click to show all disk info." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+case "$location" in
+ "/mnt"* ) icon="💾" ;;
+ *) icon="🖥";;
+esac
+
+printf "$icon""$(df -h "$location" | awk ' /[0-9]/ {print $3 "/" $2}')"
+
diff --git a/scripts/sb-forecast b/scripts/sb-forecast
new file mode 100644
index 0000000..685be80
--- /dev/null
+++ b/scripts/sb-forecast
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Displays todays precipication chance (☔) and daily low (🥶) and high (🌞).
+# Usually intended for the statusbar.
+
+# If we have internet, get a weather report from wttr.in and store it locally.
+# You could set up a shell alias to view the full file in a pager in the
+# terminal if desired. This function will only be run once a day when needed.
+weatherreport="${XDG_DATA_HOME:-$HOME/.local/share}/weatherreport"
+getforecast() { curl -sf "wttr.in/$LOCATION" > "$weatherreport" || exit 1 ;}
+
+# Some very particular and terse stream manipulation. We get the maximum
+# precipitation chance and the daily high and low from the downloaded file and
+# display them with coresponding emojis.
+showweather() { printf "%s" "$(sed '16q;d' "$weatherreport" |
+ grep -wo "[0-9]*%" | sort -rn | sed "s/^/☔/g;1q" | tr -d '\n')"
+sed '13q;d' "$weatherreport" | grep -o "m\\([-+]\\)*[0-9]\\+" | sed 's/+//g' | sort -n -t 'm' -k 2n | sed -e 1b -e '$!d' | tr '\n|m' ' ' | awk '{print " 🥶" $1 "°","🌞" $2 "°"}' ;}
+
+case BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e less -Srf "$weatherreport" ;;
+ 2) getforecast && showweather ;;
+ 3) notify-send "🌈 Weather module" "\- Left click for full forecast.
+- Middle click to update forecast.
+☔: Chance of rain/snow
+🥶: Daily low
+🌞: Daily high" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# The test if our forcecast is updated to the day. If it isn't download a new
+# weather report from wttr.in with the above function.
+[ "$(stat -c %y "$weatherreport" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
+ getforecast
+
+showweather
diff --git a/scripts/sb-memory b/scripts/sb-memory
new file mode 100644
index 0000000..f5f83ef
--- /dev/null
+++ b/scripts/sb-memory
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "🧠 Memory hogs" "$(ps axch -o cmd:15,%mem --sort=-%mem | head)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🧠 Memory module" "\- Shows Memory Used/Total.
+- Click to show memory hogs.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+free --mebi | sed -n '2{p;q}' | awk '{printf ("💾%2.1f/%2.1fGB\n", ( $3 / 1024), ($2 / 1024))}'
diff --git a/scripts/sb-volume b/scripts/sb-volume
new file mode 100644
index 0000000..61588c3
--- /dev/null
+++ b/scripts/sb-volume
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Prints the current volume or 🔇 if muted.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e pulsemixer ;;
+ 2) pamixer -t ;;
+ 4) pamixer --allow-boost -i 1 ;;
+ 5) pamixer --allow-boost -d 1 ;;
+ 3) notify-send "📢 Volume module" "\- Shows volume 🔊, 🔇 if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+[ $(pamixer --get-mute) = true ] && echo 🔇 && exit
+
+vol="$(pamixer --get-volume)"
+
+if [ "$vol" -gt "70" ]; then
+ icon="🔊"
+elif [ "$vol" -lt "30" ]; then
+ icon="🔈"
+else
+ icon="🔉"
+fi
+
+echo "$icon$vol%"