#!/usr/bin/perl use v5.14; use strict; use warnings; use JSON; use Clone 'clone'; use IO::Handle; # Send the header so that i3bar knows we want to use JSON: printf "%s", '{"version":1}'; # Begin the endless array. printf "%s", '['; # We send an empty first array of blocks to make the loop simpler: printf "%s",'[],'; open my $conky, "-|:encoding(utf8)", "conky -c $ENV{HOME}/.i3/conkyrc-perl"; STDOUT->autoflush(); my @data; my %in_progress; my $json = JSON->new; $json->ascii([1]); my %simple_mappings = ( "SHORTTEXT" => "shorttext", ); my %commands = ( battery => \&get_bat_stats, ); LINE: while (<$conky>) { chomp($_); next if m/^\s*$/; if (m/^END_BLOCK$/) { STDOUT->printf("%s,\n", $json->encode(\@data)); undef @data; next; } if (m/^COLOR: (#[a-zA-Z0-9]+)$/) { $in_progress{color} = $1; next; } for my $key (keys %simple_mappings) { if (m/^$key: (.*)$/) { $in_progress{$simple_mappings{$key}} = $1; next LINE; } } if (m/^FULLTEXT: (.*)$/) { my $fulltext = $1; $in_progress{full_text} = $fulltext; push @data, clone \%in_progress; undef %in_progress; next; } if (m/^COMMAND: ([^\s]*)(?: (.*)?)$/) { my $command = $1; my @args = split / /, $2; die "Unknown command requested: $command" unless defined $commands{$command}; my $command_ret = $commands{$command}->(@args); for my $text (@$command_ret) { $in_progress{full_text} = $text; push @data, clone \%in_progress; } undef %in_progress; next; } printf STDERR "Got unexpected data: %s\n", $_; } sub get_bat_stats { my $bats = [@_] // ["BAT0"]; my $ret = []; for my $bat (@$bats) { next unless -e "/sys/class/power_supply/$bat"; open my $fh, "<", "/sys/class/power_supply/$bat/uevent"; my %values; while (my $line = <$fh>) { my ($key, $value) = split /=/, $line; $key =~ s/^POWER_SUPPLY_//; chomp $value; $values{$key} = $value; } close $fh; my $time_remaining_hours = 0; $time_remaining_hours = $values{ENERGY_NOW} / $values{POWER_NOW} unless $values{POWER_NOW} == 0; push @$ret, sprintf("%s %s%%, %.2fW, %.2fh", $bat, $values{CAPACITY}, $values{POWER_NOW} / 1e6, $time_remaining_hours); } return $ret; }