lemonbar
a minimalistic (windowmanager) panel
Table of Contents
1. Lemonbar
I really like to configure everything to my own personal needs… That's why I'm using lemonbar
(https://github.com/LemonBoy/bar)
as my window manager panel.
lemonbar (formerly known as bar) is a lightweight bar entirely based on XCB. Provides full UTF-8 support, basic formatting, RandR and Xinerama support and EWMH compliance without wasting your precious memory
Because I am a bspwm
user (a great minimalist window manager https://github.com/baskerville/bspwm),
I had to think about which panel I'd actually wanted to use, since bspwm
doesn't have one out of the box.
I first used pypanel a lot, but… nowadays running an older python2 panel seemed inappropriate.
That's when I took a look at lemonbar
. It's a little C
program, which puts a black (or any color you want)
bar at the top or bottom of your window manager's desktop.
You can pipe text into it, which it will display.
That way you are able to build your very own panel by simply writing a shell script
and piping it to lemonbar
.
1.1. Usage
You can simply clone the repository from github and build it right away like this:
git clone https://github.com/LemonBoy/bar.git lemonbar cd lemonbar make # (or maybe even make install)
After building it, you should have a binary called lemonbar
. If you run it without any arguments,
you should see a black bar appearing on the top of your screen.
Now you're ready to write a simple shell script, - conataining a loop - and pipe it's output to
lemonbar
, to see the results in your panel.
1.1.1. First script
You should probably start with something elementary like:
#!/bin/bash while true; do echo "%{c}%{B#770}%{F#000}Hello world" sleep 1 done
This example is using some format strings like %{c}
to display the text at the center of the panel
(as you can probably guess, it's l
for left and r
for right) or %{B#770}
to set the background
color or %{F#000}
to set the font color.
Colors can be set in hex values like #rrggbb
(or even with an alpha value at he beginning #aarrggbb
)
or just #rgb
.
Let's say we save this test file as test.sh
. Now you can pipe the output into lemonbar
like this:
./test.sh | lemonbar
This way you can easily display things like date, time, day of the week, battery status or even the CPU load. But as you can guess that simple while true loop will get confusing when we add too much stuff to display. That's when more advanced scripts come into play :D
1.1.2. More advanced scripts
I like putting the stuff to display in simple functions. So I can turn them on and off, like this:
clock() { DATETIME=$(date "+%a %d.%b %T") echo -n "$DATETIME" } while true; do buf="%{l}%{B#000}%{F#FFF} $(clock) " # a commented out centered clock # buf="%{c}%{B#000}%{F#FFF} $(clock) " buf="${buf} %{c}Hello World!" echo $buf sleep 1 done;
This function simply runs date "+%a %d.%b %T"
wich gives you an output like this: Mi 23.Nov 22:55:04
.
The loop below defines a variable called buf
and concatinates the output of the functions
(in this case only one function and a Hello World!
string).
As I said, I like it that way, because I can comment things out bery easy :)
Then it echos the buffer.
When we pipe this script into lemonbar, we get a black bar with the date output on the left and
a Hello World!
at the center.
- Battery Status
A simple function to diplay the battey percentage might look like this:
Battery() { BATPERC=$(acpi --battery | cut -d, -f2) echo "$BATPERC" }
Which outputs the percentage like
96%
. I like to have it on the right side of my panel, so I'd go like this:buf="${buf}%{r}$(Battery)"
But then, I thought I'd like to see if the battery charges or looses power, or if the powersupply is plugged in. That's when I came up with something like:
battery() { BATC=/sys/class/power_supply/BAT0/capacity BATS=/sys/class/power_supply/BAT0/status AC=$(acpi --ac-adapter | cut -d: -f2) if [[ $AC == *"on-line"* ]]; then test "`cat $BATS`" = "Charging" && echo -n '+' || echo -n '~'; else test "`cat $BATS`" = "Charging" && echo -n '+' || echo -n '-'; fi sed -n p $BATC }
…and added it to the buffer (
$buf
) like that:buf="${buf} %{F#02C}BAT: %{F#FFF}$(battery)"
- Windows and Desktops
Since using bspwm and sxhkd most of my windows are displayed fullscreen, I use multiple dektops and switch alot between them. That's why knowing the dektops I am on and displaying the name is important to me. For this reason I have two little funtions to help me out:
# get and echo the current dektop name desktopname() { cur=`xprop -root _NET_CURRENT_DESKTOP | awk '{print $3}'` desktop_names=`xprop -root _NET_DESKTOP_NAMES` cur_name_id=`bc <<< $cur+2+$cur` cur_name=`echo ${desktop_names} | awk -v var="$cur_name_id" -F "\"" '{print $var}'` echo $cur_name }
Let's go through step by step:
xprop -root _NET_CURRENT_DESKTOP | awk '{print $3}'
prints out the current dektop number.xprop -root _NET_DESKTOP_NAMES
returns a list of desktop names like this:_NET_DESKTOP_NAMES(UTF8_STRING) = "bash", "mail", "firefox", "zeug", "stuff", "jack", "gimp", "morestuff", "Desktop"
Then these infos given the next line calculates the id for awk (next line) then outputs the current Desktop name in the end :) I use it like this inside the panel:
buf="${buf} «« $(desktopname) »»"
The next one is an dynamic and graphic way to display the current dektop number:
# get all dektops and display them while highlighting the current one groups() { cur=`xprop -root _NET_CURRENT_DESKTOP | awk '{print $3}'` tot=`xprop -root _NET_NUMBER_OF_DESKTOPS | awk '{print $3}'` window=`bc <<< $cur+1` desktop_names=`xprop -root _NET_DESKTOP_NAMES` cur_name_id=`bc <<< $cur+2+$cur` cur_name=`echo ${desktop_names} | awk -v var="$cur_name_id" -F "\"" '{print $var}'` for w in `seq 0 $((cur - 1))`;do line="${line}%{B#000}%{F#888}="; done line="${line}%{B#FFF}%{F#000} $window %{F#000}" for w in `seq $((cur + 2)) $tot`; do line="${line}%{B#000}%{F#888}="; done echo $line }
Based on the two infos
_NET_CURRENT_DESKTOP
and_NET_NUMBER_OF_DEKTOPS
we create a little loop to highlight the current dektop and display the other ones as=
and unhighlighted. We add it to our buffer:buf="${buf} %{c}»»[$(groups)%{B#000}%{F#FFF}]««"
And it should finally look like this (if you're on dektop 4):
Figure 1: A screenshot from my lemonbar
- Volume, CPU, RAM
To show my CPU usage or my used RAM I use the following two functions:
cpuload() { LINE=`ps -eo pcpu |grep -vE '^\s*(0.0|%CPU)' |sed -n '1h;$!H;$g;s/\n/ +/gp'` X=`bc <<< $LINE` bc <<< $X/4 } memused() { t=`grep -E 'Mem(Total)' /proc/meminfo |awk '{print $2}'` f=`grep -E 'Mem(Free)' /proc/meminfo |awk '{print $2}'` bc <<< "scale=2; 100 - $f / $t * 100" | cut -d. -f1 }
The first one grabbing the CPU percentage with
ps -eo pcpu
, then adding the values and dividing the result by 8 (because of my eight cores). This gives me the aproximate load in percentage :) I add it to the buffer like this:buf="${buf} %{F#C20}CPU: %{F#FFF}$(cpuload)" buf="${buf} %{F#C20}RAM: %{F#FFF}$(memused)"
I need to adjust the colors to the load.. something like from green (low load) to yellow, then red (heavy load). But that's still in progress :D
To display the current volume I use
amixer
like that:volume() { amixer get Master | sed -n 's/^.*\[\([0-9]\+\)%.*$/\1/p'| uniq }
…and fill the buffer like this:
buf="${buf} %{F#090}VOL: %{F#FFF}$(volume)"
- Network stuff
To display my network status, like "is my device connected to any WLAN?" and "what external IP do we have here?". In order to get the network connection state I use this function:
network() { wifi='wlo1' # I once used it to detect ethernet connections with: # eth0='enp0s31f6' ip link show $wifi | grep 'state UP' >/dev/null && int=$wifi # in case of ethernet this last thing would be: ... && int=eth0 ping -c 1 bios-blog.com >/dev/null 2>&1 && echo "$int connected" || echo "$int disconnected" }
This simply shows the connection state of my wireless network device. To display my external IP I have a simple webservice running which responses with the IP calling the site. So I can go with curl like that:
get_ip() { curl -s my.webservice.com | grep '<p></p>' | awk -F "<p></p>" '{print $1}' | awk -F " " '{print $1}' }
I kinda like sort the IP out from the stuff written on the website with the
grep
andawk
commands. :) In the end I append this to mybuf
variable like that:buf="${buf} %{r}%{F#990}NET: %{F#FFF}$(network)"
The
%{r}
is only to display this on the right side of my bar…
1.2. Conclusion
Well that's not all about lemonbar and piping a script to it, but I think that's enough for this post. I guess I'll do another part in the future because I didn't mention how you make stuff happen when clicking on lemonbar with your mouse, or how I solved the color changing from green, to yellow, to red if my memory gets low or my CPU is too busy.
So let's say: to be continued…