Ara
Table of Contents
Ara is a simple cli program that prints Covid-19 stats. Currently it only prints India's Covid stats.
Documentation
ara
by default will first look for the file in $XDG_CACHE_HOME
, if that
is not set then HOME/.cache
is used, the file name is assumed to be
ara.json
, there is currently no option to override this or the full
path.
If you run ara
on OpenBSD then it should use OpenBSD::Unveil
.
Default logic is to check if the file is available locally & if it's not
older than 8 minutes, in any other case it fetches the latest data. This
can be controlled with local
& latest
option.
The file is downloaded over a secure connection & the server's identity is verified.
Options
local
This option forces ara
to use the data available locally, it will only
override this option when the file doesn't exist on disk.
latest
This will force ara
to fetch the latest data.
Note: local
& latest
option cannot be used together, ara
will print a
warning & latest option will be ignored.
notes
Only state notes will be printed if this option is passed.
rows
rows
option takes an integer as argument which can be passed as --rows
n
, where n
is an integer.
ara
will only print maximum these many number of rows, if you pass 0 or
a negative number then ara
will ignore it & print all the rows.
showdelta
This will show delta values for every row, default is to show delta only on rows that were updated "Today".
Note: This can be disabled by autohide
option.
nodelta
This will remove delta values from every column.
nototal
This will remove the "Total" or "India" row from the table.
hide
option should be used for this purpose, this option is only kept
for backwards compatibility.
nowords
"Confirmed", "Recovered" & "Deaths" column format numbers in words. For example, "1.6 lakhs" instead of "1,60,000" which makes it easier to read. This option will disable this behaviour.
"Active" column doesn't format numbers in words because it's alignment is set as "right" & formatting it this way doesn't look good. There is currently no option to change this behaviour.
autohide
This will automatically hide some columns if the term size is smaller than expected, it's just a bunch of `if' blocks.
push @to_hide, "updated" if $t_columns < 110; push @to_hide, "active" if $t_columns < 100; undef $show_delta if $t_columns < 80; $no_delta = 0 if $t_columns < 80;
Currently (2020-08-03) it's just these lines pasted above but that might change so look at the source for latest rules.
hide
hide
is able to hide states & columns from the table, the values should
be space seperated like --hide active "last updated" recovered
. These
are case sensitive & should be lowercase.
Arguments can be passed as they're printed, for example --hide "jammu
and kashmir"
is equivalent to --hide jk
because "JK" is what's printed
on the table.
Only "States" & "Notes" column cannot be hidden, ara
will print a
warning if you try to do so.
Note: "updated" is aliased to "last updated", so you can pass --hide
updated
& it would hide the "last updated" column.
Note: The feature to get space seperated values is marked as
experimental in Getopt::Long
so the behaviour can change in future,
worse even get removed. To guarantee backwards compatibility pass each
value by itself like --hide jk --hide active
, this is equivalent to
--hide jk active
.
- Implementation
%hide
hash is created from@to_hide
which was created from user arguments byGetopt::Long
.undef @hide{ @to_hide } if scalar @to_hide;
%hide
contains values of@to_hide
as keys & the value to those keys is not defined, henceundef
. This one line says Perl to "undef these keys from the hash%hide
" where these refers to the values of@to_hide
. This will fail if@to_hide
is empty so we have to check for that.Alternatively we can do
@hide { @to_hide } = ()
which works even if@to_hide
is empty & does the same thing otherwise, this looks more cryptic so I use the first way.To check if a specific column is to be hidden or not we use
exists
likeexists $hide{something}
.There are other ways of doing this & maybe those would be better, I didn't test which one was the best.
- Columns
To make
hide
work we put create@columns
& push columns to it unless the user has asked to hide it.my @columns; push @columns, 'Confirmed' unless exists $hide{confirmed}; push @columns, 'Active' unless exists $hide{active};
- States
The whole block is skipped if the user has asked to hide the state. As said above, statecode is also check if that's what is printed in the table which is true only if
length $state > 16
. There is no good reason for not checking statecode for everything.next if exists $hide{lc $state} # User sees the statecode if length $state > 16 so we also match # against that. or ( length $state > 16 and exists $hide{lc $statewise->[$i]{statecode}});
- Columns
show
show
also accepts space seperated values & just like in hide
's case it's
experimental & can change in future.
show
will only show states that are passed. For example, --show jk
will
only print data for Jammu & Kashmir. If both show
& hide
is used for
states then hide
is ignored. show
for states can be used with hide
for
columns.
- Implementation
show
's implementation is similar tohide
's.%show
hash is created from@to_show
.undef @show{ @to_show } if scalar @to_show;
If user has used
show
thenhide
is ignored, this is achieved by an if-else block. This also means that invalid values in state would causehide
to be ignored, for example passing--show invalid
wouldn't match anything buthide
will still be ignored. This is intentional.if ( scalar @to_show ) { next unless exists $show{lc $state} or ( length $state > 16 and exists $show{lc $statewise->[$i]{statecode}}); } else { ... }
help
help
will print help for ara
which will have little information about
all these options listed above.
nototal
was removed fromhelp
becausehide
option does the same thing & is recommended.
Cross-platform compatibility
Previously ara
had OpenBSD specific code & would simply fail to run on
other OSes, now it runs on all platforms. There is still OpenBSD
specific code but it's used only when ara
detects to be running on
OpenBSD.
use constant is_OpenBSD => $^O eq "openbsd"; require OpenBSD::Unveil if is_OpenBSD; sub unveil { if (is_OpenBSD) { return OpenBSD::Unveil::unveil(@_); } else { return 1; } }
is_OpenBSD
is a constant so the if-else block is optimized at compile
time. Another way would be to define the sub inside the if-else block
which is what I did initially but that is not the same thing as this.
You cannot define sub like that in Perl because this step happens at compile time & so the if-else block is ignored, which means the code will be equivalent to else block being true all the time because that's what comes later.
if (is_OpenBSD) { require OpenBSD::Unveil; OpenBSD::Unveil->import; } else { sub unveil { return 1; } }
Above code block will override the unveil sub to be return 1;
everytime,
this was fixed in commit 245aebe3da915afc0feafc7257f025e2e66a987f
.
This will still fail on OpenBSD if users don't have OpenBSD::Unveil
in
@INC
, this shouldn't be an issue with Perl in base but if user runs
custom Perl then it might not be in @INC
, in that case user is expected
to fix this by adding the path to OpenBSD::
in @INC
.
Demo Videos
- Ara 2020-06-14 (new options)
- Ara 2020-06-06