21 juin 2020 · 5 min read
i3 is a tiling window manager on Linux. It supports tiling, stacking, and tabbing layouts, which it handles dynamically. The advantage is that you no longer waste time organizing your windows with the mouse. With i3
the layout is automatic. The windows open by occupying the available space. Using customizable keyboard shortcuts, you can move them around, display them full screen, arrange them horizontally or vertically. This is much more convenient and faster than using the mouse.
Another advantage is that the status bar is a single line of fully configurable text. No need for extensions like on Gnome or KDE that don’t always meet your needs.
You want a status bar that displays the current price of some crypto-currencies ? a button to enable/disable VPN ? display the weather ? display your public IP address ? it is simple to do with some bash and python. Here is how to do it.
At the bottom of this article, you will find the link to a Github repository with the source code of all the widgets shown in the bar below.
Here is a situation :
i3 on GitHub is a relatively old but still active project. The system is light and powerful. i3-gaps is a “fork” that creates a gap between windows for a visual effect. There is also Sway which works with Wayland (the successor of the X11 graphics server). But it does not support NVIDIA graphics cards.
The scripts presented here will work on all those window managers.
The default status bar is i3status. A simple configuration file displays the date and time, memory usage, free disk space, battery level and other useful informations.
More advanced alternatives exist : i3pystatus, goi3bar, i3status-rust… but why to use a heavy and complicated framework when you can do it yourself ?
The i3bar protocol is well documented. You just have to produce a JSON file in standard output and read the events in standard input (click events from the bar elements).
In the /home/your-name/.config/i3/config
file, modify the status_command
line to run your bash script :
bar {
status_command exec /home/your-name/.config/i3status/mybar.sh
}
A basic example of this bash script is given at https://github.com/i3/i3/blob/next/contrib/trivial-bar-script.sh. Let’s use this template to create the file /home/your-name/.config/i3status/mybar.sh
:
# Send the header so that i3bar knows we want to use JSON:
echo '{ "version": 1 }'
# Begin the endless array.
echo '['
# We send an empty first array of blocks to make the loop simpler:
echo '[]'
# Now send blocks with information forever:
while :;
do
echo ",[{\"name\":\"id_time\",\"full_text\":\"$(date)\"}]"
sleep 1
done
The infinite while
loop will call every second the system command date
to display the date and time. You can change the sleep
value to refresh every 10 seconds, for example. Reload the i3
configuration with the WIN+SHIFT+R
keyboard keys. Your status bar now looks like this :
First, let’s create a small bash script named /home/your-name/.config/i3status/click_time.sh
. It will be called when you click on the date/time field in the status bar :
#!/bin/sh
cal -y # displays the year calendar
read -n 1 -r -s # wait for a touch key to exit the terminal
Don’t forget to make this script executable with the command chmod +x click_time.sh
.
Modify the previous mybar.sh
script as follows :
echo '{ "version": 1, "click_events":true }'
echo '['
echo '[]'
# launched in a background process
(while :;
do
echo ",[{\"name\":\"id_time\",\"full_text\":\"$(date)\"}]"
sleep 1
done) &
# Listening for STDIN events
while read line;
do
# echo $line > /tmp/tmp.txt
# on click, we get from STDIN :
# {"name":"id_time","button":1,"modifiers":["Mod2"],"x":2982,"y":9,"relative_x":67,"relative_y":9,"width":95,"height":22}
# DATE click
if [[ $line == *"name"*"id_time"* ]]; then
alacritty -e /home/your-name/.config/i3status/click_time.sh &
fi
done
Some explanations :
"click_events":true
indicates to the i3
protocol that we are going to handle mouse events.id_time
, the click_time.sh
script is executed. It displays the current year’s calendar in a terminal. alacritty
can be replaced with the terminal of your choice.Demonstration ! Clicking on the date displays the annual calendar :
Let’s create the python file /home/your-name/.config/i3status/cpu.py
:
#!/usr/bin/env python3
# install the package "psutil" with the command "pip3 install psutil --user"
import psutil
print(psutil.cpu_percent(interval=1), end='')
This script displays for example 1.2
if the CPU is busy at 1.2%.
Let’s modify the mybar.sh
script :
echo '{ "version": 1, "click_events":true }'
echo '['
echo '[]'
# launched in a background process
(while :;
do
echo -n ",["
echo -n "{\"name\":\"id_cpu\",\"background\":\"#283593\",\"full_text\":\"$(/home/your-name/.config/i3status/cpu.py)%\"},"
echo -n "{\"name\":\"id_time\",\"background\":\"#546E7A\",\"full_text\":\"$(date)\"}"
echo -n "]"
sleep 1
done) &
# Listening for STDIN events
while read line;
do
# echo $line > /tmp/tmp.txt
# on click, we get from STDIN :
# {"name":"id_time","button":1,"modifiers":["Mod2"],"x":2982,"y":9,"relative_x":67,"relative_y":9,"width":95,"height":22}
# DATE click
if [[ $line == *"name"*"id_time"* ]]; then
alacritty -e /home/your-name/.config/i3status/click_time.sh &
# CPU click
elif [[ $line == *"name"*"id_cpu"* ]]; then
alacritty -e htop &
fi
done
The bar now looks like this:
You may have noticed that a background color is added with the key background
. When you click on the CPU usage, the htop
utility is launched in a terminal.
So, this is a simple way to create an i3 status bar. If you have other ideas don’t hesitate to share them.
Icons can be displayed using the Font Awesome.
Here is a full i3 status configuration on Github where you will also find the widgets to start/stop a VPN, display the weather, public IP address, local IP address, memory usage, battery level, volume and the number of available system packages to update.