Skip to content

Instantly share code, notes, and snippets.

@projectgus
Created October 9, 2014 22:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save projectgus/5f8e1fab789edd138a5b to your computer and use it in GitHub Desktop.
Save projectgus/5f8e1fab789edd138a5b to your computer and use it in GitHub Desktop.
i3status/i3bar custom status fields using JSON formatting
#!/usr/bin/env python3
import os, json, sys, subprocess, re
"""
i3_status/i3bar output munger using JSON formatted status lines,
allows you to add custom fields to the i3 status line.
In this example I add a "Backup Running" warning message at the
beginning if a duplicity backup is running, and also put 2.4GHz or
5GHz in the existing wlan0 status line.
The previous incarnation of this script was a shell script, and was
very simple (just prepending each line of text with a custom string.)
This incarnation is for i3status where output_format="i3bar", meaning
the i3status command produces JSON lines instead of plaintext. This
allows for detailed colour formatting of each field, etc. This is nice
and powerful but it means you can no longer just use a 5 line shell
script to add custom fields.
To use this script with i3, save it somewhere and set up something
like this in your .i3/config:
bar {
status_command /path/to/my_i3status.py
}
A sample i3status JSON line:
[{"name":"disk_info","instance":"/","full_text":"45.9 GiB"},{"name":"wireless","instance":"wlan0","color":"#FFFFFF","full_text":"W: (071% at BorkNet) 192.168.0.2"},{"name":"ethernet","instance":"bnep0","color":"#999999","full_text":"BT: down"},{"name":"ethernet","instance":"eth0","color":"#999999","full_text":"E: down"},{"name":"ethernet","instance":"tap0","color":"#FFFFFF","full_text":"VPN: up"},{"name":"battery","instance":"/sys/class/power_supply/BAT0/uevent","full_text":"FULL 92.04%"},{"name":"load","full_text":"0.18"},{"name":"time","full_text":"2014-10-10 09:13:34"}]
No custom fields are added to the first status output (i3status
currently produces what is formatted as an infinitely recurring list
of lists, and we skip the first entry).
Used with i3status 2.8, JSON output format version 1.0.
"""
def amend_statusline(status_line):
""" Return an amended status line. The status line is represented as a list of dicts."""
return get_backupstatus() + add_wifi_freq("wlan0", status_line)
def get_backupstatus():
""" Check if duplicity is running """
duplicity = os.system("/bin/pidof duplicity")
return [ {"name":"backup", "full_text":"Backup Running"} ] if duplicity == 0 else []
def add_wifi_freq(interface, status_line):
""" Amend the specified wireless interface's entry with frequency band """
for field in status_line:
try:
if field["instance"] == interface:
# iw says not to screenscrape info output, so it could stop working at any time...
info = subprocess.check_output(["/sbin/iw", interface, "info"], universal_newlines=True)
match = re.search("(\d)\d+ MHz",info)
if match is not None:
field["full_text"] = field["full_text"].replace(")"," %sGHz)"%match.group(1))
except KeyError:
continue
except subprocess.CalledProcessError:
continue
return status_line
def main():
with os.popen("/usr/bin/i3status", mode='r', buffering=1) as status:
while True:
sys.stdout.flush()
line = status.readline()
if line == "":
break
if not line.startswith(","):
print(line.strip())
continue
parsed = json.loads(line[1:])
print(",%s" % (json.dumps(amend_statusline(parsed)),))
if __name__ == "__main__":
main()
@jmoggr
Copy link

jmoggr commented May 7, 2015

Hello! I'm trying to do something similar. I'm not using the i3status command and i just have an infinite loop with a sleep command. It barely works though, the timing is all wrong. In your code what controlls the timing? Is there a way of doing this without the i3status process?

Thanks!

@Flurrywinde
Copy link

Hi, @jmoggr, I know it's 4 years later, but seeing as how I've been wanting to do the same thing and found my way here too, I thought I'd post what I've found so far, which is that Michael Stapelberg himself says not to do it (https://github.com/i3/i3/blob/next/contrib/trivial-bar-script.sh), so I guess I will start experimenting with i3status like @projectgus .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment