A simple shell status bar for OpenBSD and cwm(1)

       810 words, 4 minutes

These days, I try to use simple and stock software as much as possible on my OpenBSD laptop. I’ve been playing with cwm(1) for weeks and I was missing a status bar. After trying things like Tint2, Polybar etc, I discovered @gonzalo’s termbar . Thanks a lot!
As I love scripting, I decided to build my own.

The idea behind termbar is to launch an terminal that will loop printing the information you want ; via a shell script. It’s a bit like using xsetroot with dwm(1). That terminal will be ignored by cwm(1) and stay in some reserved placed.

The termbar resources

Using an Xresources file, start defining a dedicated resource class and a set of properties:

# vim ~/.Xresources
! ~/scripts/termbar inside xterm(1) 
termbar*faceName: CodeNewRoman Nerd Font:style=Bold:size=13 
termbar*geometry: 191x1+0+0 
termbar*internalBorder: 6 
termbar*saveLines: 0 
termbar*scrollBar: false 
termbar*title: termbar 
termbar*foreground: qogir_white 
termbar*background: qogir_black 
termbar*color1: qogir_red 
termbar*color3: qogir_orange

You can add those in a .Xdefaults if you prefer.

The termbar script

I’m using ksh(1) as a default shell. And I write all my scripts with it trying to stay as compatible as possible with sh(1). If you’re using bash, you may have to tweak a few things in my following script.

The script uses native OpenBSD commands (like apm, sysctl, …) to extract and format informations via functions. Then it loops into calling those functions, printing the whole result and pausing for a second.

# cat ~/scripts/termbar

trap 'exec $0' HUP # Restart itself 
trap 'tput cnorm; exit 1' INT QUIT TERM 


set -A _bat "${_norm}" "${_warn}" "${_alrt}" 
set -A _pwr "${_norm}" 
set -A _net "" "直" 
set -A _nic "em0" "iwm0" 
set -A _vol "奄" "奔" "墳" 

function bat { 
  [[ $(apm -a) -eq 1 ]] \ 
    && echo -n "${_pwr[0]} " \ 
    || echo -n "${_bat[$(apm -b)]} " 
  echo -n "$(apm -l)%${_norm}" 

function cal { 
  [[ $(date "+%H") -ge 6 && $(date "+%H") -le 22 ]] \ 
    && echo -n "${_norm}" \ 
    || echo -n "${_warn}" 
  echo -n $(date '+%a %d %b %H:%M')${_norm} 

function cpu { 
  echo -n "龍$(sysctl -n hw.setperf)% " 
  echo -n " $(sysctl -n hw.sensors.cpu0.temp0 | cut -d '.' -f 1)°C" 

function grp { 
  echo -n "${_hide}[ " 
  echo -n "$(xprop -root 32c '\t$0' _NET_CURRENT_DESKTOP | cut -f 2)" 
  echo -n " ]${_rset}" 

function net { 
  [[ -z "$(ifconfig ${_nic[0]} | grep 'status: no carrier')" ]] \ 
    && (echo -n ${_net[0]} ; return) 
  echo -n $(ifconfig ${_nic[1]} | \ 
    awk '/ieee80211:/ { print "直" $3 "(" $8 ")" }') 

function vol { 
  _v=$(sndioctl -n output.level | awk '{ print int($0*100) '}) 
  [[ $(sndioctl -n input.mute) -eq 1 ]] \ 
    && echo -n "${_norm}${_norm} " \ 
    || echo -n "${_warn}${_norm} " 
  [[ $(sndioctl -n output.mute) -eq 1 ]] \ 
    && echo -n "婢" \ 
    || echo -n "${_vol[$(($_v*3/101))]}" 
  echo -n "$_v%" 

function win { 
  _wid=$(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) 
  _win=$(xprop -id $_wid '\t$0' _NET_WM_NAME | awk -F '"' '{ print $2 }') 
  echo -n " ${_win}" 

tput civis # Hide cursor 

while true; do 
  _l="$(grp) $(win)" 
  _r="$(cpu) $(bat) $(net) $(vol) $(cal)" 

  #tput clear cup 1 0 
  tput cup 1 0 
  printf "%-120.120s\r" "$_l" 
  tput cup 1 120 
  printf "%110.110s" "$_r" 
  sleep 1 

tput cnorm # Show cursor 


I use a few colors to show current cwm group and alert me when battery is low or when it is time to go to bed… printf is used to format the strings and tput helps placing the text where it should be. Using shell colors can mess all the display without it. This seem to be because printf will count those non-printable characters when aligning but xterm will obviously not display them.

The alignment has to be calculated depending on your screen resolution and font size.

Let cwm(1) know about termbar

The .cwmrc file should contain the following lines:

# cat ~/.cwmrc
ignore termbar 
autogroup 0 termbar 
gap 30 0 0 0

This will allow termbar to be displayed and managed as a statusbar or dock. And the gap value depends on the font you use.

Launch termbar automatically

As I’m using xenodm(1), I added termbar to the .xsession file so that it starts automatically when I log in.

# cat ~/.xsession
xterm -name termbar -class termbar -e /home/jdoe/scripts/termbar &
exec /usr/local/bin/ck-launch-session /usr/X11R6/bin/cwm

The xterm command is configured to use the “termbar” class and run the “termbar” script. You’ll need a Nerd Font if you want fancy icons in your bar. Or you can use plain text and the default DejaVu font.

The script doesn’t appear in top, since I update only every seconds. So I don’t need to write it in C for better performance. I tried using lower delays to update and it worked well. But I don’t really need it.

That’s all folks!