Five years ago when I moved to the i3 window manager, I started using its status bar, the i3bar. It is text based, and it's up to you what gets shown there. However it is not very modular: it's weird to combine different information to be shown since everything has to be joined in a single string manually.
About one year later I discovered a program to solve that issue: i3blocks. The way it works is that in its config you define the blocks that you want and what script will be run for each one. The text output for each script is what will be shown for that block in the status bar.
I currently have 9 blocks in my status bar: time, schedule, task, battery, keyboard, storage-root, storage-home, update and music.
Probably the most obvious block. I can't think of a status bar that doesn't show the current time...
This block shows the date (weekday, day, month and year) and time. Having the time showing in bold is a detail I really like, but don't recall where I got the idea from.
This block shows me the current schedule i.e. what I should be doing right now. As you can see I should be reading a book instead of writing this blog post right now... But I have to hurry if I want to post this! 😝
I have shown this block previously in the "Organization beyond Taskwarrior" post.
This block shows my current task context and the number of tasks I have currently in my inbox, the number of stuck projects, and the number of tasks with near due dates.
When all three are zero, this block is hidden, although that is very rare. As you can see, I haven't had enough time to sort the tasks in my inbox lately 😅.
I also showed this block already in the "Organization beyond Taskwarrior" post.
This block shows the battery charge percentage. The icon reflects the current charge (out of 4 possibilities), and when the battery is low the background becomes red to catch my attention.
When the battery is charging and at a high percentage, this block is hidden.
This block shows me the current keyboard layout. Since I only use two layouts, pt-br (ABNT2) and en-us, and most of the time I use the english one, this block only shows in red when I'm in the portuguese layout. When I'm in the english one, it stays hidden.
I introduced this block after too many times trying to use vim and having forgotten that I was in the portuguese layout.
These two blocks show the available and total storage spaces on my disks. The first (computer icon) shows for the root partition, while the second one (home icon) shows for the home partition. These blocks are almost always hidden, unless the free space gets low, in which case they show up with the red background.
Note: The free space shown in the pictures wouldn't normally be considered low, I just forced them to appear here.
This block shows the number of packages that can be updated. It only shows if the number is high enough, otherwise the block stays hidden.
I used to have this block turn the background red if the kernel package needed to be updated, since I noticed that in Arch Linux updating the kernel doesn't keep the modules for the previous version around. This means that updating the kernel should be followed by a system reboot, otherwise some weird bugs could happen due to the lack of required modules (e.g. USBs not working). However after I found out about the kernel-modules-hook package that solves this problem, I removed this check and update the kernel without worrying.
This block shows me the current playing music. It shows the artist followed by the track name, and the icon reflects the current state: playing or paused. When no music is playing the block stays hidden.
Since the artist or track name can get very long, when they get longer than a fixed length, I omit the rest using "...".
Old block: cardapio-unicamp
This is not a block that I currently use, but it was my favorite one so I want to mention it. Its purpose was to inform me of the meal that was being served at the university's restaurant, so I could decide if I wanted to eat there or somewhere else.
There were two iterations of it. In the beginning, it simply showed the meal
description for the next meal. After some time I changed it to instead show the
quality of the meals for the whole week. I did this by matching the meal
description with words I considered either good or bad. The end result was ten
squares, each day separated by a
| and with the first square for lunch and
the second for dinner. The square colors showed the quality: white for normal,
green for good and red (or magenta in this old color scheme) for bad.
The meal descriptions were queried using a short python program of my own,
called cardapio-unicamp. The script to get the meal quality for the whole week
is also available in that repository. The conversion from the
- to the colored squares I don't have published, but it was a couple of
simple (yet ugly) lines of bash, so I'm sure you can do something better if you
want to have that 🙂.
I really like my current status bar setup but it took time and improvements to get here.
For instance I find the consistency is key for each block to be easily identifiable: each block has its own color above and some empty space around it, and its icon is always the first thing on the left followed by the text.
I also take advantage of colors to reduce the amount of text needed on the blocks. For example, the task block has three different numbers, but no label for each, since each color already gives away their meaning.
Reducing the amount of stuff in the status bar helped me focus in what is really relevant at the moment. To achieve that I started questioning myself which information really was important. I don't really care about which WiFi network I'm connected to most of the time, and I used to have a block for that (and it's a very common one), so I just ditched it. And there's information that is only relevant sometimes, which is why I now have my blocks stay hidden unless their current information is relevant.
I also reduced the number of useless updates of the blocks by changing them to update based on a signal instead of a timeout whenever possible. So for example the keyboard block only updates when I press the binding to toggle the keyboard, which sends a signal to this block.
Hooking each block to a signal also makes the blocks update faster to asynchronous events. For example, I update the packages in my computer using an alias, which in addition to updating through pacman, sends a signal to the update block at the end. So as soon as I have updated the packages, that block disappears, and not after some timeout.
Over time I've also written some code to make the block definition easier. As
with other parts of my system, I started my blocks in bash, but eventually
migrated them to python. As part of this I wrote a
in python that receives the icon, text and color for the block, and outputs it
in the JSON format required by i3blocks.
I also have a
update_i3blocks command that receives the name of the block
and sends the appropriate signal, so I can update specific blocks from other
commands in the system.
The one annoying bug
When I migrated the block scripts to python I started having issues with the blocks disappearing randomly. It took me almost a year to really dive into the i3blocks code and find and fix this issue. Although it was hard to find, it was also interesting to understand the issue. It didn't have anything to do with python, it's just that since python code runs slower than bash, it became more apparent.
Unfortunately, since the i3blocks repository is no longer actively maintained, if you're facing this same issue and want to fix it, you'll need to apply the patch and compile it yourself (though that is is pretty simple). Nevertheless I can't overstate how happy I am to finally get rid of this annoying bug. Now I can just relax and enjoy my status bar showing all, and only, information that is relevant to me 🙂.