commit 9727c60f174f960a211cf665939df08c631d2995 Author: eleksir Date: Sun Sep 23 14:52:52 2018 +0300 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..66c6b86 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +## WM helper scripts + +Some unfinished scripts mostly for i3 wm. + +Properly working is only acpid.pl. \ No newline at end of file diff --git a/acpid.pl b/acpid.pl new file mode 100644 index 0000000..e1bf09f --- /dev/null +++ b/acpid.pl @@ -0,0 +1,170 @@ +#!/usr/bin/perl +# +# Hibernates system if battery charge drops under $MIN_CHARGE and battery discharging + + +use strict; +use warnings "all"; +use Fcntl; + +sub logger($); # logs messages if $debug != 0 +# maybe one time i'll use it +sub i3wmstate; # returns 1 if i3wm running, else - 0 + + +$0 = 'acpid.pl'; +my $debug = 0; +my $MIN_CHARGE = 10; + +my $base = '/sys/class/power_supply/BAT0'; + +unless(-f "$base/present") { + logger("Battery info at /sys/class/BAT0/present not found, quitting.\n"); + exit 0; +} + +my $battery_present = 2; +my $battery_check = 2; +my $charging = 2; + +while ( sleep(180) ) { +# check that battery is in place + open(ACPI, "$base/present") or next; + my $buf = ''; + + if (read(ACPI, $buf, 1)) { + if ($battery_check == 0) { + logger("Ability to read from /sys/class/BAT0/present restored\n"); + $battery_check = 1; + } + + if ($buf == '0') { + if ($battery_present != 0) { + logger("We have no battery, skipping charge level polling until it appears\n"); + $battery_present = 0; + } + + close ACPI; + next; + } + } else { + if ($battery_check != 0) { + logger("Unable to read from /sys/class/BAT0/present\n"); + $battery_check = 0; + } + + close ACPI; + next; + } + + close ACPI; + $battery_present = 1; + +# check status, we have no need to poll battery if it charging/charged + unless (-f "$base/status") { + logger("Something broken in /sys, unable to find $base/status, quitting\n"); + exit 1; + } + +# TODO: file access save state and print on change + open(STATUS, "$base/status") or do { + logger("Unable to open $base/status\n"); + next; + }; + + $buf = ; + close STATUS; + + chomp($buf); + + if ($buf ne 'Discharging') { + if ($charging != 1) { + logger("Battery charging.\n"); + $charging = 1; + } + } else { + if ($charging != 0) { + logger("Battery discharging.\n"); + $charging = 0; + } + } + +# read charge state + unless (-f "$base/capacity") { + logger("Something broken in /sys, unable to find $base/capacity, quitting\n"); + exit 1; + } + +# TODO: file access save state and print on change + open(CHARGE, "$base/capacity") or do { + logger("Unable to open $base/capacity\n"); + next; + }; + + read(CHARGE, $buf, 3) or do { + logger("Unable to read $base/capacity, but file is in place\n"); + next; + }; + + chomp($buf); # just in case + + if ($buf < $MIN_CHARGE) { + logger("Battery charge is less than 10%, hibernating\n"); + `dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate`; + } else { + if ($buf < ($MIN_CHARGE + 5)) { + `notify-send --urgency=critical --expire-time=10000 --icon=battery-caution "Low battery charge: $buf%"`; + } + + if ( ($charging == 1) and ( $buf > 100) ) { + `notify-send --urgency=normal --expire-time=3000 "Battery overcharging"`; + } + + logger("Charge is $buf%\n"); + } +} + + +sub logger ($) { + if ($debug != 0) { + my $msg = shift; + $msg = localtime() . ' ' . $msg; + syswrite STDOUT, $msg; + } +} + +sub i3wmstate { + my $flag = 0; + opendir(P, '/proc') || die 'no /proc found!'; + + while (readdir(P)) { + my $pid = $_; + next unless(defined($pid)); + next if ($pid eq ''); + + if (-d "/proc/$pid") { + # dir UID == APCID.pl process user owner + if ((stat("/proc/$pid"))[4] == int(getpwnam($ENV{'LOGNAME'}))) { + next unless(-r "/proc/$pid/cmdline"); + open(CMDLINE, "/proc/$pid/cmdline") || die "unable to open /proc/$pid/cmdline"; + my $cl = ; + close(CMDLINE); + + if(defined($cl)) { + if ((substr($cl, 0, 2) eq 'i3') and (length($cl) <= 4)) { + $flag = 1; + undef $cl; + undef $pid; + last; + } + } + + undef $cl; + } + } + + undef $pid; + } + + return $flag; +} diff --git a/hdmi_toggle.sh b/hdmi_toggle.sh new file mode 100644 index 0000000..7f69f1d --- /dev/null +++ b/hdmi_toggle.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# ugly udev hook to toggle display configuration + + +# grab the display and xauthority cookie +export DISPLAY=$(w -h -s | grep ":[0-9]\W" | head -1 | awk '{print $2}') +X_USER=$(w -h -s | grep ":[0-9]\W" | head -1 | awk '{print $1}') +export XAUTHORITY=/home/$X_USER/.Xauthority + +# get the status of the external display +status=$(< /sys/class/drm/card0-HDMI-A-1/status) +case $status in + disconnected) + su $X_USER -c 'xrandr --output HDMI-1 --off' + logger "disabled hdmi output for $X_USER" + ;; + connected) + while [[ $(< /sys/class/drm/card0-HDMI-A-1/enabled) -ne 'enabled' ]]; do + su $X_USER -c 'xrandr --output HDMI-1 --auto' + sleep 1; + done + + su $X_USER -c 'xrandr --output HDMI-1 --auto --right-of eDP-1' + logger "enabled hdmi output for $X_USER" + ;; +esac diff --git a/i3status-mt b/i3status-mt new file mode 100644 index 0000000..f13b363 --- /dev/null +++ b/i3status-mt @@ -0,0 +1,230 @@ +#!/usr/bin/perl +# vim: set ai et ts=8 sw=8 sts=8 : + +# set username +# set uptime +# set time +# set xtitle of focused window +# set list of windows for current tag +# set list of windows for all tags +# set la +# set current language +# set battery charge + +# main loop impl. : +# save cur. str and compare it with prev. if it differs - update + +# proposed: 3 types of loop: +# slow loop for batt charge, la +# 1 second loop for time, uptime +# main (fast) loop for window name, language + +use Fcntl; +use Encode qw(decode encode); +use threads; +use threads::shared; + +sub gettimestr(); +sub getfocusedwidowtitlestr(); +sub getlangstr(); +sub getuptimestr(); +sub getlastr(); +sub getbatterychargestr1(); +sub getbatterychargestr2(); + +sub slow_thread(); +sub onesec_thread(); + +my $pstr = ''; + +my $charge :shared; +my $la :shared; +my $uptime :shared; +my $time :shared; + +threads->create('slow_thread'); +threads->create('onesec_thread'); + +sleep 1; + +while(1){ + $str = ''; + $str .= getfocusedwidowtitlestr(); + $str .= "$ENV{'USER'}"; + $str .= getlangstr(); + $str .= $uptime; + $str .= $la; + $str .= $charge; + $str .= $time; + + if($pstr ne $str){ + syswrite STDOUT, "$str\n"; + $pstr = $str; + } + +# sleep for 0.333 second; + select(undef, undef, undef, 0.333); +} + + +sub slow_thread(){ + threads->detach(); + + while(1){ + $charge = getbatterychargestr2(); + $la = getlastr(); + sleep 300; + } +} + + +sub onesec_thread(){ + threads->detach(); + + while(1){ + $uptime = getuptimestr(); + $time = gettimestr(); +# as we report time with precision of 1 minute, update 1/60 seconds + sleep 60; + } +} + + +sub gettimestr(){ + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; + my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); + my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); + $year = $year + 1900; + + my $str .= sprintf(" | %s, %s %s %s %02s:%02s ", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min); + + undef $sec; undef $min; undef $hour; undef $mday; undef $mon; undef $year; undef $wday; + @months = -1; undef @months; + @wdays = -1; undef @wdays; + + return $str; +} + + +sub getfocusedwidowtitlestr() { +# making some utf-8 mumbo-jumbo :( + my $str; + utf8::upgrade($str); + + if (-x '/usr/bin/xdotool'){ + $str = `xdotool getactivewindow getwindowname`; + }elsif (-x '/usr/bin/xprop'){ + $str = (split( /=/, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; + chop $str; chop $str; $str = reverse $str; chop $str; chop $str; $str = reverse $str; + } + + chomp($str); + + $str = encode('UTF-8', decode('UTF-8', $str)); + + if (length($str) != 0) { + my $stripped = undef; + + if (length($str) > 40){ + $str = substr($str, -38, 38); + $str = encode('UTF-8', decode('UTF-8', $str)); + $str = ' ... ' . $str; + } + + $str = '['. $str .'] | '; + }else{ + $str = '| '; + } + + return $str; +} + + +sub getuptimestr(){ + if(tell(UPTIME) == -1){ open UPTIME, "/proc/uptime"; }; + + $u = ; + seek UPTIME, SEEK_SET, 0; + $u = (split(/ /, $u, 2))[0]; + $days = int($u / 86400); # 86400 = 1 day + $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour + $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); + $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); + my $str = sprintf(" | up:[%sd,%02sh,%02sm]", $days, $hours, $minutes); + + undef $u; undef $days; undef $hours; undef $minutes; undef $seconds; + + return $str; +} + + +sub getlastr(){ + if(tell(LA) == -1){ open LA, "/proc/loadavg"; }; + + my $la = ; + seek LA, SEEK_SET, 0; + $la = (split(/ /, $la, 2))[0]; + + return (" | LA:[$la]"); +} + + +sub getbatterychargestr1(){ + my $str = ''; + + if (-f "/sys/class/power_supply/BAT0/present"){ + open A, "/sys/class/power_supply/BAT0/present"; + $P = ; + close A; + chomp($P); + + if($P eq '1'){ + open A, "/sys/class/power_supply/BAT0/charge_full"; + my $full_charge = ; chomp($full_charge); close A; + open A, "/sys/class/power_supply/BAT0/charge_now"; + my $current_charge = ; chomp($current_charge); close A; + $str .= sprintf(" | Bat:[%03d%%]", int(($current_charge / $full_charge) * 100) ); + undef $current_charge; undef $full_charge; + } + } + + return $str; +} + + +sub getbatterychargestr2(){ + my $str .= " | Power:["; + open AC,"/sys/class/power_supply/ADP1/online"; + + if( == 1){ + $str .= "AC"; + }else{ + $str .= "DC"; + } + + close AC; # display % charge only if possible + if (open DC,"/sys/class/power_supply/BAT0/capacity"){ + $str .= ' '. ; + close DC; + chomp $str; + $str .= '%'; + } + $str .= "]"; + + return $str; +} + + +sub getlangstr(){ + my $str .= " | Lang:["; + + if(`xset -q` =~ /Group 2: on /o){ + $str .= "RU]"; + }else{ + $str .= "EN]"; + } + + return $str; +} + + diff --git a/i3status-mt-json b/i3status-mt-json new file mode 100644 index 0000000..b2e5d3f --- /dev/null +++ b/i3status-mt-json @@ -0,0 +1,291 @@ +#!/usr/bin/perl +# vim: set ai et ts=8 sw=8 sts=8 ft=perl : + +# set username +# set uptime +# set time +# set xtitle of focused window +# set list of windows for current tag +# set list of windows for all tags +# set la +# set current language +# set battery charge + +# main loop impl. : +# save cur. str and compare it with prev. if it differs - update + +# proposed: 3 types of loop: +# slow loop for batt charge, la +# 1 second loop for time, uptime +# main (fast) loop for window name, language + +use Fcntl; +use threads; +use threads::shared; + +sub gettimestr(); +sub getfocusedwidowtitlestr(); +sub getlangstr(); +sub getuptimestr(); +sub getlastr(); +sub getbatterychargestr1(); +sub getbatterychargestr2(); +sub getinboxstat(); +sub getproblemsstat(); + +sub slow_thread(); +sub onesec_thread(); + +my $pstr = ''; + +my $charge :shared; +my $la :shared; +my $uptime :shared; +my $time :shared; +my $inbox :shared; +my $problems :shared; + +my $default_color = '#3e78fd'; + +threads->create('slow_thread'); +threads->create('onesec_thread'); + +sleep 1; + +syswrite STDOUT, "{\"version\":1, \"click_events\": true}\n"; +syswrite STDOUT, "[\n[],\n"; +while(1){ + $str = "[ "; +# $str .= getfocusedwidowtitlestr() . ","; + $str .= getfocusedwidowtitlestr() . ", "; + $str .= sprintf("{ \"name\" : \"username\", \"full_text\" : \"%s\", \"color\" : \"%s\" }", $ENV{'USER'}, $default_color) . ", "; + $str .= getlangstr() . ", "; + $str .= $uptime . ", "; + $str .= $la . ", "; + $str .= $charge . ", "; + $str .= $time; + $str .= " ],\n"; + if($pstr ne $str){ + syswrite STDOUT, "$str\n"; + $pstr = $str; + } + +# sleep for 0.333 second; + select(undef, undef, undef, 0.333); +} + +sub slow_thread(){ + threads->detach(); + + while(1){ + $charge = getbatterychargestr2(); + $la = getlastr(); + sleep 300; + } +} + +sub onesec_thread(){ + threads->detach(); + + while(1){ + $uptime = getuptimestr(); + $time = gettimestr(); + $inbox = getinboxstat(); + $problems = getproblemsstat(); +# as we report time with precision of 1 minute, update 1/60 seconds + sleep 60; + } + +} + + +sub gettimestr(){ + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; + my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); + my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); + $year = $year + 1900; + + my $str .= sprintf("{ \"name\" : \"time\", \"full_text\" : \"%s, %s %s %s %02s:%02s\", \"color\" : \"%s\" }", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min, $default_color); + + undef $sec; undef $min; undef $hour; undef $mday; undef $mon; undef $year; undef $wday; + @months = -1; undef @months; + @wdays = -1; undef @wdays; + + return $str; +} + +sub getfocusedwidowtitlestr(){ + my $str; + + if (-x '/usr/bin/xdotool'){ + $str = `xdotool getactivewindow getwindowname`; + }elsif (-x '/usr/bin/xprop'){ + $str = (split( /=/, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; + chop $str; chop $str; $str = reverse $str; chop $str; chop $str; $str = reverse $str; + } + + chomp($str); + $string =~ s/[\"|\{|\}|\'|,]/_/g; + + if (length($string) > 64){ + $string = substr($string, 0, 64); + } + + $str = sprintf ("{ \"name\" : \"title\", \"full_text\" : \"%s\", \"color\" : \"%s\" }", $str, $default_color); + + return $str; +} + +sub getuptimestr(){ + if(tell(UPTIME) == -1){ open UPTIME, "/proc/uptime"; }; + + $u = ; + seek UPTIME, SEEK_SET, 0; + $u = (split(/ /, $u, 2))[0]; + $days = int($u / 86400); # 86400 = 1 day + $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour + $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); + $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); + my $str = sprintf("{ \"name\" : \"uptime\", \"full_text\" : \"UP: %sd,%02sh,%02sm\", \"color\" : \"%s\" }", $days, $hours, $minutes, $default_color); + + undef $u; undef $days; undef $hours; undef $minutes; undef $seconds; + + return $str; +} + +sub getlastr(){ + if(tell(LA) == -1){ open LA, "/proc/loadavg"; }; + + my $la = ; + seek LA, SEEK_SET, 0; + $la = (split(/ /, $la, 2))[0]; + $la = sprintf("{ \"name\" : \"la\", \"full_text\" : \"LA: %s\", \"color\" : \"%s\" }", $la, $default_color); + + return $la; +} + +sub getbatterychargestr1(){ + my $str = ''; + + if (-f "/sys/class/power_supply/BAT0/present"){ + open A, "/sys/class/power_supply/BAT0/present"; + $P = ; + close A; + chomp($P); + + if($P eq '1'){ + open A, "/sys/class/power_supply/BAT0/energy_full"; + my $full_charge = ; chomp($full_charge); close A; + open A, "/sys/class/power_supply/BAT0/energy_now"; + my $current_charge = ; chomp($current_charge); close A; + $str .= sprintf("Bat:%03d%%", int(($current_charge / $full_charge) * 100) ); + undef $current_charge; undef $full_charge; + } + } + + $str = sprintf("{ \"name\" : \"powersource\", \"full_text\" : \"%s\", \"color\" : \"#555555\" }", $str); + + return $str; +} + +sub getbatterychargestr2(){ + my $str = ''; + my $color = $default_color; + open AC,"/sys/class/power_supply/ADP1/online"; + + if( == 1){ + $str .= "AC"; + }else{ + $str .= "DC"; + } + + close AC; # display % charge only if possible + if (open DC,"/sys/class/power_supply/BAT0/capacity"){ + my $charge = ; + close DC; + chomp($charge); + + if ($charge < 10){ + $color = '#800000'; + } elsif (($charge >= 10) and ($charge < 25)){ + $color = '#ffa500'; + } elsif (($charge >= 25) and ($charge < 80)){ + $color = '#008000'; + } else { + $color = '#0000a0'; + } + + $str .= " $charge"; + } + + $str = sprintf("{ \"name\" : \"powersource\", \"full_text\" : \"Power: %s%%\", \"color\" : \"%s\" }", $str, $color); + + return $str; +} + +sub getlangstr(){ + my $str .= "Lang: "; + + if(`xset -q` =~ /Group 2: on /o){ + $str .= "RU"; + }else{ + $str .= "EN"; + } + + $str = sprintf("{ \"name\":\"lang\", \"full_text\" : \"%s\", \"color\" : \"%s\" }", $str, $default_color); + + return $str; +} + +sub getinboxstat(){ + if((-d "$ENV{'HOME'}/Maildir/INBOX/cur") and (-d "$ENV{'HOME'}/Maildir/INBOX/new")){ + my $inboxtotal = 0; + my $inboxunread = 0; + my $inboxunseen = 0; + opendir DIR, "$ENV{'HOME'}/Maildir/INBOX/cur"; + foreach (readdir(DIR)){ + next if ($_ eq '.'); + next if ($_ eq '..'); + unless ($_ =~ /,F?R?S$/){ $inboxunread++; } + $inboxtotal++; + } + closedir DIR; + opendir DIR, "$ENV{'HOME'}/Maildir/INBOX/new"; + foreach (readdir(DIR)){ + next if ($_ eq '.'); + next if ($_ eq '..'); + unless ($_ =~ /,F?R?S$/){ $inboxunread++; $inboxunseen++; } + $inboxtotal++; + } + closedir DIR; + return (sprintf("i %d/%d/%d", $inboxunseen, $inboxunread, $inboxtotal)); + } + return(''); +} + +sub getproblemsstat(){ + if((-d "$ENV{'HOME'}/Maildir/Problems/cur") and (-d "$ENV{'HOME'}/Maildir/Problems/new")){ + my $inboxtotal = 0; + my $inboxunread = 0; + my $inboxunseen = 0; + opendir DIR, "$ENV{'HOME'}/Maildir/Problems/cur"; + foreach (readdir(DIR)){ + next if ($_ eq '.'); + next if ($_ eq '..'); + unless ($_ =~ /,F?R?S$/){ $inboxunread++; } + $inboxtotal++; + } + closedir DIR; + opendir DIR, "$ENV{'HOME'}/Maildir/Problems/new"; + foreach (readdir(DIR)){ + next if ($_ eq '.'); + next if ($_ eq '..'); + unless ($_ =~ /,F?R?S$/){ $inboxunread++; $inboxunseen++; } + $inboxtotal++; + } + closedir DIR; + return (sprintf("p %d/%d/%d", $inboxunseen, $inboxunread, $inboxtotal)); + } + return(''); +} + diff --git a/i3status-mt-json-a-optimized b/i3status-mt-json-a-optimized new file mode 100644 index 0000000..e855519 --- /dev/null +++ b/i3status-mt-json-a-optimized @@ -0,0 +1,340 @@ +#!/usr/bin/perl + +use Fcntl; +use POSIX; + +use JSON::PP; +use utf8; +use Encode; +use open qw(:std :utf8); + +use threads; +use threads::shared; + +sub gettimestr(); +sub getfocusedwidowtitlestr(); +sub getuptimestr(); +sub getlastr(); +sub getbatterychargestr1(); +sub getbatterychargestr2(); + +sub slow_thread(); +sub onesec_thread(); +sub reader(); +sub launcher($); + +my @charge :shared; +my $la :shared; +my $uptime :shared; +my $time :shared; +my $shoot :shared = 1; + +my $default_color = '#5c5b5a'; +my $blue_color = '#3e78fd'; + +my @name = qw / + ff vv ch con tel pid hc mp db kee + title username uptime la powersource time /; + +my @align = qw / + left left left left left left left left left left + center right right right right right /; + +my $a; +my %name_index; + +for (my $i = 0; $i < @name; $i++) { + $name_index{$name[$i]} = $i; + $a->[$i]->{'name'} = $name[$i]; + + if ($name[$i] eq 'username') { + $a->[$i]->{'full_text'} = $ENV{'USER'}; + } elsif ($name[$i] eq 'title') { + $a->[$i]->{'min_width'} = ' '; + } else { + $a->[$i]->{'full_text'} = $name[$i]; + } + + $a->[$i]->{'color'} = $blue_color; + + if ($align[$i] eq 'left') { + $align[$i] = "center"; + $a->[$i]->{'color'} = $default_color; + $a->[$i]->{'separator_block_width'} = 1; + $a->[$i]->{'separator'} = JSON::PP::false; + $a->[$i]->{'border'} = '#3dbaf4'; + $a->[$i]->{'min_width'} = sprintf(' %s ', $name[$i]); + } + + $a->[$i]->{'align'} = $align[$i]; +} + +my $title; +my $prev_title = ''; + +threads->create('slow_thread'); +threads->create('onesec_thread'); +threads->create('reader'); + +sleep 1; + +syswrite STDOUT, "{\"version\":1, \"click_events\": true}\n"; +syswrite STDOUT, "[\n[],\n"; + +while (1) { + my $in = ''; + + $title = getfocusedwidowtitlestr(); + + if ($title ne $prev_title) { + $shoot = 1; + $prev_title = $title; + } + + if ($shoot == 1) { + $a->[$name_index{'title'}]->{'full_text'} = $title; + $a->[$name_index{'uptime'}]->{'full_text'} = $uptime; + $a->[$name_index{'la'}]->{'full_text'} = $la; + $a->[$name_index{'powersource'}]->{'full_text'} = $charge[0]; + $a->[$name_index{'powersource'}]->{'color'} = $charge[1]; + $a->[$name_index{'time'}]->{'full_text'} = $time; + my $json = JSON::PP->new; + $json = $json->ascii(0); + $json = $json->utf8(0); + $json = $json->allow_unknown (0); + $json = $json->canonical(1); + $json = $json->space_before(0); + $json = $json->space_after(0); + $json = $json->indent(0); + my $str = $json->encode($a); + undef $json; + syswrite STDOUT, $str . ",\n"; + undef $str; + $shoot = 0; + } + +# sleep for 0.333 second; + select(undef, undef, undef, 0.333); +} + +sub slow_thread() { + threads->detach(); + my @prev_charge = ('',''); + my @current_charge; + my $prev_la = ''; + my $current_la; + + while (1) { + @current_charge = getbatterychargestr2(); + + if ($current_charge[0] ne $prev_charge[0]) { + $shoot = 1; + @prev_charge = @current_charge; + @charge = @current_charge; + } + + $current_la = getlastr(); + + if ($current_la ne $prev_la) { + $shoot = 1; + $prev_la = $current_la; + $la = $current_la; + } + + sleep 300; + } +} + +sub onesec_thread() { + threads->detach(); + + while (1) { + $uptime = getuptimestr(); + $time = gettimestr(); +# as we report time with precision of 1 minute, update 1/60 seconds + $shoot = 1; + sleep 60; + } +} + + +sub gettimestr() { + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; + my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); + my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); + $year = $year + 1900; + + my $z = sprintf("%s, %s %s %s %02s:%02s", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min), + + undef $sec; undef $min; undef $hour; undef $mday; undef $mon; undef $year; undef $wday; + @months = -1; undef @months; + @wdays = -1; undef @wdays; + + return $z; +} + +sub getfocusedwidowtitlestr() { + my $str; + + if (-x '/usr/bin/xdotool') { + $str = `xdotool getactivewindow getwindowname`; + } elsif (-x '/usr/bin/xprop') { + $str = (split( /=/, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; + chop $str; chop $str; $str = reverse $str; chop $str; chop $str; $str = reverse $str; + } + + chomp($str); + $str =~ s/[\"|\{|\}|\'|,|\(|\)|\[|\]]/ /g; + + if (int(length($str)) > 24) { + $str = substr($str, 0, 25); + } elsif (int(length($str)) < 1) { + $str = ' '; + } + + # not sure about utf-8-ness of this chunk, so try to check it + $str = eval { decode('UTF-8', $str, Encode::FB_CROAK) } // ' '; + + return $str; +} + +sub getuptimestr() { + if(tell(UPTIME) == -1){ open UPTIME, "/proc/uptime"; }; + + my $u = ; + seek UPTIME, SEEK_SET, 0; + $u = (split(/ /, $u, 2))[0]; + my $days = int($u / 86400); # 86400 = 1 day + my $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour + my $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); + my $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); + + $u = sprintf("UP: %sd,%02sh,%02sm", $days, $hours, $minutes); + + undef $days; undef $hours; undef $minutes; undef $seconds; + + return $u; +} + +sub getlastr() { + if(tell(LA) == -1){ open LA, "/proc/loadavg"; }; + + my $la = ; + seek LA, SEEK_SET, 0; + $la = (split(/ /, $la, 2))[0]; + + return $la; +} + +sub getbatterychargestr1() { + my $str = ''; + + if (-f "/sys/class/power_supply/BAT0/present"){ + open A, "/sys/class/power_supply/BAT0/present"; + my $P = ; + close A; + chomp($P); + + if($P eq '1') { + open A, "/sys/class/power_supply/BAT0/energy_full"; + my $full_charge = ; chomp($full_charge); close A; + open A, "/sys/class/power_supply/BAT0/energy_now"; + my $current_charge = ; chomp($current_charge); close A; + $str .= sprintf("Bat:%03d%%", int(($current_charge / $full_charge) * 100) ); + undef $current_charge; undef $full_charge; + } + + undef $P; + } + + my @z = ($str, '#555555'); + + return @z; +} + +sub getbatterychargestr2() { + my $str = ''; + my $color = $default_color; + my $file; + + if (-f "/sys/class/power_supply/ADP1/online") { + $file = "/sys/class/power_supply/ADP1/online"; + } elsif ("/sys/class/power_supply/AC/online") { + $file = "/sys/class/power_supply/AC/online"; + } else { + return ('??', '??%'); + } + + open AC, $file or return ('??', '??%'); + + if ( == 1) { + $str .= "AC"; + } else { + $str .= "DC"; + } + + close AC; # display % charge only if possible + if (open DC,"/sys/class/power_supply/BAT0/capacity") { + my $charge = ; + close DC; + chomp($charge); + + if ($charge < 10){ + $color = '#800000'; + } elsif (($charge >= 10) and ($charge < 25)) { + $color = '#ffa500'; + } elsif (($charge >= 25) and ($charge < 80)) { + $color = '#008000'; + } else { + $color = '#0000a0'; + } + + $str .= " $charge"; + } + + my @z = (sprintf("Power: %s%%", $str), $color); + + return @z; +} + +sub reader() { + threads->detach(); + my $str = ''; + my $j; + + while () { + $str = $_; + + if (substr($str, 0, 1) ne '{') { + $str = substr($str, 1); + } + + chomp($str); + next if ((length($str) < 2) or (substr($str, -1, 1) ne '}')); + + $j = decode_json($str); + if ($j->{'button'} eq '1') { + if ($j->{'name'} eq 'ff') { threads->create('launcher', '/usr/bin/firefox'); } + if ($j->{'name'} eq 'vv') { threads->create('launcher', '/usr/local/bin/vivaldi'); } + if ($j->{'name'} eq 'ch') { threads->create('launcher', '/usr/bin/chromium'); } + if ($j->{'name'} eq 'con') { threads->create('launcher', '/usr/bin/urxvt'); } + if ($j->{'name'} eq 'tel') { threads->create('launcher', '/home/eleksir/.local/bin/Telegram'); } + if ($j->{'name'} eq 'pid') { threads->create('launcher', '/usr/bin/pidgin'); } + if ($j->{'name'} eq 'hc') { threads->create('launcher', '/usr/bin/hexchat'); } + if ($j->{'name'} eq 'mp') { threads->create('launcher', '/usr/bin/mousepad'); } + if ($j->{'name'} eq 'db') { threads->create('launcher', '/usr/bin/deadbeef'); } + if ($j->{'name'} eq 'kee') { threads->create('launcher', '/home/eleksir/.local/bin/kee'); } + } + } +} + +sub launcher($) { + my $prog = shift; + threads->detach(); + + if (fork() == 0) { + exec ($prog); + } +} + +# vim: set ai tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab ft=perl : # diff --git a/i3status-st b/i3status-st new file mode 100644 index 0000000..44282ff --- /dev/null +++ b/i3status-st @@ -0,0 +1,168 @@ +#!/usr/bin/perl +# set username +# set uptime +# set time +# set xtitle of focused window +# set list of windows for current tag +# set list of windows for all tags +# set la +# set current language +# set battery charge + +# main loop impl. : +# save cur. str and compare it with prev. if it differs - update + +# proposed: 3 types of loop: +# slow loop for batt charge, la +# 1 second loop for time, uptime +# main (fast) loop for window name, language + +use Fcntl; + +sub gettimestr(); +sub getfocusedwidowtitlestr(); +sub getlangstr(); +sub getuptimestr(); +sub getlastr(); +sub getbatterychargestr1(); +sub getbatterychargestr2(); + +my $pstr = ''; +while(1){ + $str = ''; + $str .= getfocusedwidowtitlestr(); + $str .= "$ENV{'USER'}"; + $str .= getlangstr(); + $str .= getuptimestr(); + $str .= getlastr(); + $str .= getbatterychargestr2(); + $str .= gettimestr(); + + if($pstr ne $str){ + syswrite STDOUT, "$str\n"; + $pstr = $str; + } + +# sleep for 0.25 second; + select(undef, undef, undef, 0.25); +} + + +sub gettimestr(){ + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; + my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); + my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); + $year = $year + 1900; + + my $str .= sprintf(" | %s, %s %s %s %02s:%02s ", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min); + + undef $sec; undef $min; undef $hour; undef $mday; undef $mon; undef $year; undef $wday; + @months = -1; undef @months; + @wdays = -1; undef @wdays; + + return $str; +} + +sub getfocusedwidowtitlestr(){ + my $str; + + if (-x '/usr/bin/xdotool'){ + $str = `xdotool getactivewindow getwindowname`; + }elsif (-x '/usr/bin/xprop'){ + $str = (split( /=/, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; + chop $str; chop $str; $str = reverse $str; chop $str; chop $str; $str = reverse $str; + } + + chomp($str); + + if (length($str) != 0){ + $str = '['. $str .'] | '; + }else{ + $str = '| '; + } + + return $str; +} + +sub getuptimestr(){ + if(tell(UPTIME) == -1){ open UPTIME, "/proc/uptime"; }; + + $u = ; + seek UPTIME, SEEK_SET, 0; + $u = (split(/ /, $u, 2))[0]; + $days = int($u / 86400); # 86400 = 1 day + $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour + $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); + $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); + my $str = sprintf(" | up:[%sd,%02sh,%02sm]", $days, $hours, $minutes); + + undef $u; undef $days; undef $hours; undef $minutes; undef $seconds; + + return $str; +} + +sub getlastr(){ + if(tell(LA) == -1){ open LA, "/proc/loadavg"; }; + + my $la = ; + seek LA, SEEK_SET, 0; + $la = (split(/ /, $la, 2))[0]; + + return (" | LA:[$la]"); +} + +sub getbatterychargestr1(){ + my $str = ''; + + if (-f "/sys/class/power_supply/BAT0/present"){ + open A, "/sys/class/power_supply/BAT0/present"; + $P = ; + close A; + chomp($P); + + if($P eq '1'){ + open A, "/sys/class/power_supply/BAT0/energy_full"; + my $full_charge = ; chomp($full_charge); close A; + open A, "/sys/class/power_supply/BAT0/energy_now"; + my $current_charge = ; chomp($current_charge); close A; + $str .= sprintf(" | Bat:[%03d%%]", int(($current_charge / $full_charge) * 100) ); + undef $current_charge; undef $full_charge; + } + } + + return $str; +} + +sub getbatterychargestr2(){ + my $str .= " | Power:["; + open AC,"/sys/class/power_supply/ADP1/online"; + + if( == 1){ + $str .= "AC"; + }else{ + $str .= "DC"; + } + + close AC; # display % charge only if possible + if (open DC,"/sys/class/power_supply/BAT0/capacity"){ + $str .= ' '. ; + close DC; + chomp $str; + $str .= '%'; + } + $str .= "]"; + + return $str; +} + +sub getlangstr(){ + my $str .= " | Lang:["; + + if(`xset -q` =~ /Group 2: on /o){ + $str .= "RU]"; + }else{ + $str .= "EN]"; + } + + return $str; +} diff --git a/xbacklight b/xbacklight new file mode 100644 index 0000000..bee80f7 --- /dev/null +++ b/xbacklight @@ -0,0 +1,53 @@ +#!/usr/bin/perl + +my $arg = $ARGV[0]; +my $step = 10; # measured in percents + +sub fsread($); # read 1-st line from file +sub fswrite(@); # write string to file + +my $brightnessfile = "/sys/class/backlight/acpi_video0/brightness"; +my $maxbrightness = fsread("/sys/class/backlight/acpi_video0/max_brightness"); +my $currbrightness = fsread($brightnessfile); + +my $a = $maxbrightness / 100; +$step = int($step * $a); + +if ( $arg eq "up" ) { + if ($currbrightness != $maxbrightness) { + my $projectedbrightness = $currbrightness + $step; + + if ($projectedbrightness > $maxbrightness) { + $projectedbrightness = $maxbrightness; + } + + fswrite($projectedbrightness, $brightnessfile); + } +} elsif ( $arg eq "down" ) { + if ($currbrightness != 0) { + my $projectedbrightness = $currbrightness - $step; + + if ($projectedbrightness < 0) { + $projectedbrightness = 0; + } + + fswrite($projectedbrightness, $brightnessfile); + } +} + + +sub fsread($) { + my $fname = shift; + open (F, $fname) || die; + my $str = ; + close F; + return $str; +} + +sub fswrite (@) { + my $str = shift; + my $fname = shift; + open(OF, ">", $fname) || die; + print OF $str; + close OF; +}