| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- #!/usr/bin/env perl
- # vim:fenc=utf-8:ft=perl:et:sw=4:ts=4:sts=4
- use 5.008;
- use strict;
- use warnings qw(all);
- use List::Util qw(max sum);
- use Storable qw(lock_retrieve lock_store);
- ## no critic (ProhibitBacktickOperators ProhibitComplexRegexes ProhibitInteractiveTest)
- our $VERSION = q(1.4);
- my %rgb = (
- black => [qw[0 0 0]],
- red => [qw[1 0 0]],
- green => [qw[0 1 0]],
- yellow => [qw[1 1 0]],
- blue => [qw[0 0 1]],
- magenta => [qw[1 0 1]],
- cyan => [qw[0 1 1]],
- white => [qw[1 1 1]],
- );
- my @ticks = map { chr 0x2580 + $_ } 1 .. 8;
- binmode \*STDOUT => q(encoding(utf8));
- my $order = '';
- my $screen = 0;
- my $tmux = not -t \*STDOUT;
- my $rgb = 0;
- my $skip = 0;
- my ($help, $show_battery, $remaining, $bolt, $chart_bg, $chart_fg,
- $bright, $loadavg, $swap, $threshold, $width, $history);
- # parse the options file
- parse_config();
- if (@ARGV) {
- require Getopt::Long;
- Getopt::Long::GetOptions(
- q(help) => \$help,
- q(battery!) => \$show_battery,
- q(remaining!) => \$remaining,
- q(bolt!) => \$bolt,
- q(bg=s) => \$chart_bg,
- q(fg=s) => \$chart_fg,
- q(bright!) => \$bright,
- q(loadavg!) => \$loadavg,
- q(swap!) => \$swap,
- q(max=i) => \$threshold,
- q(order=s) => \$order,
- q(screen) => \$screen,
- q(tmux!) => \$tmux,
- q(rgb!) => \$rgb,
- q(width=i) => \$width,
- q(datfile=s) => \$history,
- q(skip=i) => \$skip,
- ) or help(-verbose => 1);
- }
- defaults();
- my $chart = eval { lock_retrieve $history };
- $chart = [ (0) x $width ] unless defined $chart;
- my %top;
- my $cpu = $loadavg ? load() : usage();
- push @$chart => $cpu;
- splice @$chart => 0, @$chart - $width if @$chart > $width;
- lock_store $chart => $history
- if time - ((stat $history)[9] || 0) >= $skip;
- unshift @$chart => (0) x ($width - @$chart);
- # Ordering from Activity Monitor.app
- my %colors = (
- f => [ green => 1 ], # free
- w => [ red => 2 ], # wired
- a => [ yellow => 3 ], # active
- i => [ blue => 4 ], # inactive
- c => [ cyan => 5 ], # cached
- b => [ cyan => 5 ], # buf (FreeBSD)
- x => [ magenta=> 6 ], # swap
- );
- # Custom ordering
- my @order = split //x => lc $order;
- for my $i (0 .. $#order) {
- my $color = $order[$i];
- $colors{$color}->[1] = $i + 1
- if exists $colors{$color};
- }
- my %memory = memory();
- delete $memory{x} unless $swap;
- my $scale = @$chart / sum values %memory;
- my $norm = $#ticks / max @$chart => $threshold;
- my $c = 0;
- for my $type (sort { $colors{$a}->[1] <=> $colors{$b}->[1] } keys %memory) {
- print my_color(
- map { defined $_ ? $_ : $colors{$type}->[0] }
- $chart_fg => $chart_bg
- );
- for (1 .. max(1 => sprintf q(%.0f) => $scale * $memory{$type})) {
- last if $c++ >= $width;
- print $ticks[$norm * shift @$chart];
- }
- }
- print $ticks[$norm * $cpu] if $c < $width;
- battery() if $show_battery or $remaining;
- my_reset(1);
- # For dependencies linting
- #printf qq(%-20s\t%s\n), $_ => $INC{$_} for sort keys %INC;
- sub parse_config {
- my $rcname = exists($ENV{RAINBARF})
- ? $ENV{RAINBARF}
- : qq($ENV{HOME}/.rainbarf.conf);
- if (open(my $rcfile, q(<), $rcname)) {
- while (<$rcfile>) {
- s/\#.*$//x;
- s/^\s+|\s+$//gx;
- if (my ($k, $v) = /^(?:\-{2})?(\w+)\s*(?:=\s*(.*))?$/x) {
- my $p = '--' . $k;
- if ($v) {
- $v =~ s/\$(\w+)/$ENV{$1}/gx;
- $p .= '=' . $v;
- }
- unshift @ARGV => $p;
- }
- }
- close $rcfile;
- }
- return;
- }
- sub help {
- my (@args) = @_;
- require Pod::Usage;
- return Pod::Usage::pod2usage(-noperldoc => 1, @args);
- }
- sub defaults {
- help(-verbose => 99) if $help;
- $show_battery = 1 unless defined $show_battery;
- $loadavg = 0 unless defined $loadavg;
- $swap = 0 unless defined $swap;
- $threshold = 1 unless defined $threshold;
- $width = 38 unless defined $width;
- $bright = 0 unless defined $bright;
- $remaining = 0 unless defined $remaining;
- $bolt = (defined $bolt and $bolt) ? chr 0x26a1 : q(|);
- require Term::ANSIColor if not $tmux and not $screen;
- $history = qq($ENV{HOME}/.rainbarf.dat)
- unless defined $history;
- return;
- }
- sub color_idx {
- my ($color, $brightness) = @_;
- return unless defined $color;
- my ($r, $g, $b) = map { $_ * $brightness } @{$rgb{$color}};
- return q(colour) . (16 + (6 * 6 * $r) + (6 * $g) + $b);
- }
- sub color_rgb {
- my ($color, $brightness) = @_;
- return unless defined $color;
- return q(rgb) . join '' => map { $_ * $brightness } @{$rgb{$color}};
- }
- sub my_color {
- my ($fg, $bg) = @_;
- my $out;
- if ($screen) {
- $out = qq(\5{);
- $out .= defined($bg)
- ? chr ord $bg
- : q(.);
- $out .= $bright
- ? uc chr ord $fg
- : chr ord $fg;
- $out .= q(});
- } elsif ($tmux) {
- if ($rgb) {
- $fg = color_idx($fg => 5);
- $bg = color_idx($bg => 2);
- } else {
- $fg .= q(,bright) if $bright;
- }
- $out = defined($bg) ? qq(#[fg=$fg,bg=$bg]) : qq(#[fg=$fg]);
- } else {
- my ($old_fg, $old_bg) = ($fg, $bg);
- if ($rgb) {
- $fg = color_rgb($fg => 5);
- $bg = color_rgb($bg => 2);
- } else {
- $fg = qq(bright_$fg) if $bright;
- }
- my $color = defined($bg) ? qq($fg on_$bg) : $fg;
- $out = eval { Term::ANSIColor::color($color) };
- if (not defined $out or $@) {
- if ($@ =~ /bright/x) {
- $bright = 0;
- print STDERR qq(Term::ANSIColor < 3.00 does not support the "bright" attribute!\n);
- $color =~ s/,?bright_?//x;
- } elsif ($@ =~ /\brgb\d+\b/x) {
- $rgb = 0;
- print STDERR qq(Term::ANSIColor < 4.00 does not support the 256-color palette!\n);
- $color = qq($old_fg on_$old_bg);
- } else {
- die qq(Unknown error: $@\n);
- }
- $out = Term::ANSIColor::color($color);
- }
- }
- return $out;
- }
- sub my_reset {
- my ($eof) = @_;
- if ($screen) {
- print qq(\5{= dd});
- } elsif ($tmux) {
- print q(#[fg=default,bg=default]);
- } else {
- print Term::ANSIColor::color(q(reset));
- }
- print qq(\n) if defined $eof;
- return;
- }
- sub top {
- if (not %top and -x q{/usr/bin/top}) {
- my @top;
- if ($^O eq q(darwin)) {
- @top = qx{/usr/bin/top -R -F -l1 -n0 -s0 -S};
- } elsif ($^O eq q(freebsd)) {
- @top = qx{/usr/bin/top -b -d2 -I -s1 -z};
- }
- for (@top) {
- my ($key, $value) = /^([\w\s]+)\s*:\s*(.+)/x;
- next unless defined $key;
- $key =~ y/A-Z /a-z_/;
- $top{$key} = $value;
- }
- $top{cpu_usage} = delete $top{cpu} unless exists $top{cpu_usage};
- $top{physmem} = delete $top{mem} unless exists $top{physmem};
- }
- return scalar keys %top;
- }
- sub load {
- my @l = qw(0 0 0);
- if (open my $loadavg, q{<}, q{/proc/loadavg}) {
- @l = (split /\s+/x, <$loadavg>)[0 .. 2];
- close $loadavg;
- } elsif (top() and exists $top{load_avg}) {
- @l = split /\s*,\s*/x, $top{load_avg};
- } elsif (-x q{/usr/bin/uptime}) {
- # fallback
- @l = (split /\s+/x, qx{/usr/bin/uptime})[-3 .. -1];
- }
- return $l[0];
- }
- sub usage {
- if (-e q{/proc/stat}) {
- my ($diff_usage, $prev_idle, $prev_total) = qw(-1 0 0);
- for my $i (reverse 0 .. 1) {
- my $fh;
- unless (open $fh, q{<}, q{/proc/stat}) {
- close $fh;
- return 0;
- }
- while (<$fh>) {
- next unless /^cpu\s+\d+/x;
- my @cpu = split /\s+/x;
- shift @cpu;
- my $idle = $cpu[3];
- my $total = sum(@cpu);
- my $diff_idle = $idle - $prev_idle;
- my $diff_total = $total - $prev_total;
- $diff_usage = ($diff_total - $diff_idle) / $diff_total;
- $prev_idle = $idle;
- $prev_total = $total;
- last;
- }
- close $fh;
- ## no critic (ProhibitSleepViaSelect)
- select(undef, undef, undef, $i / 10);
- }
- return $diff_usage;
- } elsif (top()) {
- my %usage =
- map { (/([\d\.]+)%\s+(\w+)/x) [1, 0] }
- split /\s*,\s*/x, $top{cpu_usage};
- return 1 - $usage{idle} / 100;
- }
- }
- sub memory {
- my %m;
- my %n = (K => 1/2**10, M => 1, G => 2**10);
- if (exists $top{physmem} and $top{physmem} !~ /\bunused\b/ix) {
- %m =
- map { lc $_->[2] => $_->[0] * $n{$_->[1]} }
- map { [(/(\d+)([KMG])\s+(\w)/x)] }
- split /\s*,\s*/x, $top{physmem};
- delete $m{u};
- } elsif (open my $meminfo, q{<}, q{/proc/meminfo}) {
- %m = map {
- /\b(Mem|Swap)?(Free|Cached|Active|Inactive|Total):\s*(\d+)/ix
- ? (($1 and $1 eq q(Swap))
- ? (q(s) . lc chr ord $2 => $3)
- : ( lc chr ord $2 => $3)
- ) : ();
- } <$meminfo>;
- close $meminfo;
- $m{c} -= delete $m{sc} || 0;
- delete $m{c} if $m{c} < 0;
- my $x = delete($m{st}) - delete($m{sf});
- $m{w} = delete($m{t}) - sum values %m;
- $m{x} = $x;
- } elsif (-x q{/usr/bin/vm_stat}) {
- # fallback
- %m = map {
- /\bPages\s+(free|active|inactive|speculative|wired\s+down):\s*(\d+)/ix
- ? (chr ord $1 => $2 << 2)
- : ();
- } qx{/usr/bin/vm_stat};
- $m{f} += delete $m{s};
- }
- if ($top{swap} and $top{swap} =~ /(\d+)([KMG])\s+(?:\+|Used,?)/ix) {
- $m{x} = $1 * $n{$2};
- }
- return %m;
- }
- sub battery_osx {
- my %battery = map {
- /"(TimeRemaining|(?:Max|Current)Capacity|FullyCharged|ExternalConnected)"\s*=\s*(\d+|Yes|No)/ix
- ? (lc chr ord $1 => $2)
- : ()
- } qx{/usr/sbin/ioreg -n AppleSmartBattery -r};
- return () if 5 != keys %battery;
- my $time;
- if ($battery{f} eq q(No)
- || ($battery{f} eq q(No) && $battery{e} eq q(Yes))
- || ($battery{f} eq q(Yes) && $battery{e} eq q(No))) {
- $time = $battery{t};
- }
- my $charging = ($battery{e} =~ /^y/ix);
- my $battery = eval { $battery{c} / $battery{m} };
- return ($battery, $charging, $time);
- }
- sub battery_acpi {
- my ($acpi_info, $acpi_state, %battery) = ('') x 2;
- return () unless grep {
- -d $_
- and -e ($acpi_info ||= qq($_/info))
- and -e ($acpi_state ||= qq($_/state))
- } sort glob q(/proc/acpi/battery/{BAT,CMB}[0-9]);
- for my $file ($acpi_info, $acpi_state) {
- my $fh;
- if (open $fh, q(<), $file) {
- while (<$fh>) {
- my ($key, $value) = /^([\w\s]+)\s*:\s*(\w+)/x;
- next unless defined $key;
- $key =~ y/A-Z /a-z_/;
- $battery{$key} = $value;
- }
- }
- close $fh;
- }
- my $charging = $battery{charging_state} ne q(discharging);
- my $time;
- $time = eval { ($battery{remaining_capacity} / $battery{present_rate}) * 60 }
- if not $charging
- and defined $battery{present_rate}
- and $battery{present_rate} =~ /^\d+$/x;
- my $battery = eval { $battery{remaining_capacity} / $battery{last_full_capacity} };
- return ($battery, $charging, $time);
- }
- sub battery_sys {
- my ($uevent, %battery) = ('');
- return () unless grep {
- -d $_
- and ( ( -e qq($_/energy_full) and -e qq($_/energy_now) ) or
- ( -e qq($_/charge_now) and -e qq($_/current_now) ) )
- and -e ($uevent ||= qq($_/uevent))
- } sort glob q(/sys/class/power_supply/{BAT,CMB}[0-9]);
- my $fh;
- if (open $fh, q(<), $uevent) {
- while (<$fh>) {
- my ($key, $value) = /^POWER_SUPPLY_([^=]+)=(.*)$/x;
- next unless defined $key;
- $key =~ y/A-Z/a-z/;
- $battery{$key} = $value;
- }
- }
- close $fh;
- my $charging = $battery{status} ne q(Discharging);
- my $time;
- if (not $charging) {
- if (defined $battery{power_now} and $battery{power_now} =~ /^\d+$/x) {
- $time = eval { ($battery{energy_now} * 60 / $battery{power_now}) }
- } elsif (defined $battery{charge_now} and $battery{charge_now} =~ /^\d+$/x) {
- $time = eval { (60 * ($battery{charge_now} / 1000) / ($battery{current_now} / 1000)) }
- }
- }
- my $battery = $battery{capacity} / 100;
- return ($battery, $charging, $time);
- }
- sub battery_freebsd {
- my $battery = qx{/sbin/sysctl -n hw.acpi.battery.life 2>/dev/null} or return;
- my $charging = qx,/sbin/sysctl -n hw.acpi.battery.state,;
- my $time = qx,/sbin/sysctl -n hw.acpi.battery.time,;
- $battery /= 100;
- if ($charging == 2) {
- $charging = 1;
- } elsif ($charging == 7) { # Battery absent
- return;
- } else {
- $charging = 0;
- }
- return ($battery, $charging, $time);
- }
- sub battery {
- my @battery;
- if (-x q{/usr/sbin/ioreg}) {
- @battery = battery_osx();
- } elsif (-d q(/proc/acpi/battery)) {
- @battery = battery_acpi();
- } elsif (-d q(/sys/class/power_supply)) {
- @battery = battery_sys();
- } elsif ($^O eq q(freebsd)) {
- @battery = battery_freebsd();
- }
- battery_print(@battery);
- return;
- }
- sub battery_print {
- my ($battery, $charging, $time) = @_;
- if (defined $battery) {
- my_reset();
- print my_color(($charging ? q(green) : q(red)));
- if ($show_battery) {
- print $bolt;
- if ($rgb and not $screen) {
- my @color;
- if ($battery > 0.5) {
- # green => yellow
- @color = (int((1 - $battery) * 12), 5, 0);
- } else {
- # yellow => red
- @color = (5, int($battery * 12), 0);
- }
- if ($tmux) {
- print q(#[fg=colour) . (16 + (6 * 6 * $color[0]) + (6 * $color[1]) + $color[2]) . q(]);
- } else {
- print Term::ANSIColor::color(q(rgb) . join '' => @color);
- }
- } else {
- if ($battery < 0.333) {
- print my_color(q(red));
- } elsif ($battery < 0.666) {
- print my_color(q(yellow));
- } else {
- print my_color(q(green));
- }
- }
- print $ticks[$#ticks * $battery];
- }
- }
- if ($remaining and defined $time) {
- my $sec = $time * 60;
- print q( ) . (($sec / (60 * 60)) % 24) . q(h) . (($sec / 60) % 60) . q(m);
- }
- return;
- }
- __DATA__
- =pod
- =head1 NAME
- rainbarf - CPU/RAM/battery stats chart bar for tmux (and GNU screen)
- =head1 VERSION
- version 1.4
- =head1 SYNOPSIS
- rainbarf --tmux --width 40 --no-battery
- =head1 DESCRIPTION
- Fancy resource usage charts to put into the L<tmux|http://tmux.sourceforge.net/> status line.
- The CPU utilization history chart is tinted with the following colors to reflect the system memory allocation:
- =over 4
- =item * B<green>: free memory;
- =item * B<yellow>: active memory;
- =item * B<blue>: inactive memory;
- =item * B<red>: wired memory on I<Mac OS X> / I<FreeBSD>; "unaccounted" memory on I<Linux>;
- =item * B<cyan>: cached memory on I<Linux>, buf on I<FreeBSD>.
- =item * B<magenta>: used swap memory.
- =back
- If available, battery charge is displayed on the right.
- Just go to L<https://github.com/creaktive/rainbarf> to see some screenshots.
- =head1 USAGE
- =head2 Installation
- =over 4
- =item *
- Traditional way:
- perl Build.PL
- ./Build test
- ./Build install
- =item *
- L<Homebrew|http://brew.sh/> way:
- brew install rainbarf
- =item *
- L<MacPorts|http://www.macports.org/> way:
- port install rainbarf
- =item *
- CPAN way:
- cpan -i App::rainbarf
- =item *
- Modern Perl way:
- cpanm git://github.com/creaktive/rainbarf.git
- =back
- =head2 Configuration
- Add the following line to your F<~/.tmux.conf> file:
- set-option -g status-utf8 on
- set -g status-right '#(rainbarf)'
- Or, under I<GNOME Terminal>:
- set-option -g status-utf8 on
- set -g status-right '#(rainbarf --rgb)'
- Reload the tmux config by running C<tmux source-file ~/.tmux.conf>.
- =head1 CONFIGURATION FILE
- C<~/.rainbarf.conf> can be used to persistently store L</OPTIONS>:
- # example configuration file
- width=20 # widget width
- bolt # fancy charging character
- remaining # display remaining battery
- rgb # 256-colored palette
- L</OPTIONS> specified via command line override that values.
- Configuration file can be specified via C<RAINBARF> environment variable:
- RAINBARF=~/.rainbarf.conf rainbarf
- =head1 OPTIONS
- =over 4
- =item C<--help>
- This.
- =item C<--[no]battery>
- Display the battery charge indicator.
- Enabled by default.
- =item C<--[no]remaining>
- Display the time remaining until the battery is fully charged/empty. See L</CAVEAT>.
- Disabled by default.
- =item C<--[no]bolt>
- Display even fancier battery indicator.
- Disabled by default.
- =item C<--[no]bright>
- Tricky one. Disabled by default. See L</CAVEAT>.
- =item C<--[no]rgb>
- Use the B<RGB> palette instead of the system colors.
- Also disabled by default, for the same reasons as above.
- =item C<--fg COLOR_NAME>
- Force chart foreground color.
- =item C<--bg COLOR_NAME>
- Force chart background color.
- =item C<--[no]loadavg>
- Use L<load average|https://en.wikipedia.org/wiki/Load_(computing)> metric instead of CPU utilization.
- You might want to set the C<--max> threshold since this is an absolute value and has varying ranges on different systems.
- Disabled by default.
- =item C<--[no]swap>
- Display the swap usage.
- Used swap amount is added to the total amount, but the free swap amount is not!
- Disabled by default.
- =item C<--max NUMBER>
- Maximum C<loadavg> you expect before rescaling the chart. Default is 1.
- =item C<--order INDEXES>
- Specify the memory usage bar order.
- The default is C<fwaic> ( B<f>ree, B<w>ired, B<a>ctive, B<i>nactive & B<c>ached ).
- =item C<--[no]tmux>
- Force C<tmux> colors mode.
- By default, L<rainbarf> detects automatically if it is being called from C<tmux> or from the interactive shell.
- =item C<--screen>
- L<screen(1)|http://manpages.ubuntu.com/manpages/hardy/man1/screen.1.html> colors mode. B<Experimental>. See L</CAVEAT>.
- =item C<--width NUMBER>
- Chart width. Default is 38, so both the chart and the battery indicator fit the C<tmux> status line.
- Higher values may require disabling the battery indicator or raising the C<status-right-length> value in F<~/.tmux.conf>.
- =item C<--datfile FILENAME>
- Specify the file to log CPU stats to.
- Default: F<$HOME/.rainbarf.dat>
- =item C<--skip NUMBER>
- Do not write CPU stats if file already exists and is newer than this many seconds.
- Useful if you refresh C<tmux> status quite frequently.
- =back
- =head1 CAVEAT
- =head2 Time remaining
- If the C<--remaining> option is present but you do not see the time in your status bar, you may need to increase the value of C<status-right-length> to 48.
- =head2 Color scheme
- If you only see the memory usage bars but no CPU utilization chart, that's because your terminal's color scheme need an explicit distinction between foreground and background colors.
- For instance, "red on red background" will be displayed as a red block on such terminals.
- Thus, you may need the ANSI B<bright> attribute for greater contrast, or maybe consider switching to the 256-color palette.
- There are some issues with that, though:
- =over 4
- =item 1.
- Other color schemes (notably, L<solarized|http://ethanschoonover.com/solarized>) have different meaning for the ANSI B<bright> attribute.
- So using it will result in a quite psychedelic appearance.
- 256-color pallette, activated by the C<--rgb> flag, is unaffected by that.
- =item 2.
- The older versions of L<Term::ANSIColor> dependency do not recognize bright/RGB settings, falling back to the default behavior (plain 16 colors).
- However, the whole L<Term::ANSIColor> is optional, it is only required to preview the effects of the L</OPTIONS> via command line before actually editing the F<~/.tmux.conf>.
- That is, C<rainbarf --bright --tmux> B<is guaranteed to work> despite the outdated L<Term::ANSIColor>!
- =back
- Another option is skipping the system colors altogether and use the B<RGB> palette (C<rainbarf --rgb>).
- This fixes the I<issue 1>, but doesn't affect the I<issue 2>.
- It still looks better, though.
- =head2 Persistent storage
- CPU utilization stats are persistently stored in the F<~/.rainbarf.dat> file.
- Every L<rainbarf> execution will update and rotate that file.
- Since C<tmux> calls L<rainbarf> periodically (every 15 seconds, by default), the chart will display CPU utilization for the last ~9.5 minutes (15 * 38).
- Thus, several C<tmux> instances running simultaneously for the same user will result in a faster chart scrolling.
- =head2 screen
- Stable C<screen> version unfortunately has a broken UTF-8 handling specifically for the status bar.
- Thus, I have only tested the L<rainbarf> with the variant from L<git://git.savannah.gnu.org/screen.git>.
- My F<~/.screenrc> contents:
- backtick 1 15 15 rainbarf --bright --screen
- hardstatus string "%1`"
- hardstatus lastline
- =head1 REFERENCES
- =over 4
- =item *
- L<top(1)|http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/top.1.html> is used to get the CPU/RAM stats if no F</proc> filesystem is available.
- =item *
- L<ioreg(8)|http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/ioreg.8.html> is used to get the battery status on I<Mac OS X>.
- =item *
- L<ACPI|http://www.tldp.org/howto/acpi-howto/usingacpi.html> is used to get the battery status on I<Linux>.
- =item *
- L<Battery|https://github.com/Goles/Battery> was a source of inspiration.
- =item *
- L<Spark|http://zachholman.com/spark/> was another source of inspiration.
- =back
- =head1 AUTHOR
- Stanislaw Pusep <stas@sysd.org>
- =head1 CONTRIBUTORS
- =over 4
- =item *
- L<Chris Knadler|https://github.com/cknadler>
- =item *
- L<cinaeco|https://github.com/cinaeco>
- =item *
- L<Clemens Hammacher|https://github.com/hammacher>
- =item *
- L<H.Merijn Brand|https://github.com/Tux>
- =item *
- L<Henrik Hodne|https://github.com/henrikhodne>
- =item *
- L<Joe Hassick|https://github.com/jh3>
- =item *
- L<Josh Matthews|https://github.com/jmatth>
- =item *
- L<Lars Engels|https://github.com/larsengels>
- =item *
- L<Sergey Romanov|https://github.com/sergeyromanov>
- =item *
- L<Tom Cammann|https://github.com/takac>
- =item *
- L<Tuomas Jormola|https://github.com/tjormola>
- =back
- =head1 COPYRIGHT AND LICENSE
- This software is copyright (c) 2016 by Stanislaw Pusep <stas@sysd.org>.
- This is free software; you can redistribute it and/or modify it under
- the same terms as the Perl 5 programming language system itself.
- =cut
|