App-vaporcalc
view release on metacpan or search on metacpan
bin/vaporcalc view on Meta::CPAN
use Defaults::Modern;
use App::vaporcalc::CmdEngine;
use App::vaporcalc::FormatString;
use App::vaporcalc::Recipe;
use App::vaporcalc::RecipeResultSet;
use App::vaporcalc::Types -all;
use Getopt::Long;
my $Opts = +{
help => sub {
say $_ for (
"vaporcalc - App::vaporcalc\n",
" --recipe=PATH Load specified recipe",
" --nocolor Disable ANSI colors",
"",
" --help",
" --version",
);
exit 0
},
version => sub {
my $vers = $App::vaporcalc::Recipe::VERSION || '[git]';
say "vaporcalc (App::vaporcalc $vers)";
exit 0
},
nocolor => 0,
recipe => '',
};
GetOptions( $Opts,
'help',
'version',
'nocolor',
'recipe=s',
);
fun getopts { state $argv = hash(%$Opts)->inflate }
use Term::ANSIColor ();
fun colorify (Str $color, Str $text) {
getopts->nocolor ? $text : Term::ANSIColor::colored($text, $color)
}
fun format_error ($err) {
# Colorify first line only:
return '' unless $err;
my @lines = split "\n", "$err";
$lines[0] = colorify red => $lines[0];
join "\n", @lines
}
fun flavor_strings (RecipeResultSet $rset) {
my $recipe = $rset->recipe;
my $result = $rset->result;
my $flav_recipe_str = '';
for my $flav ($recipe->flavor_array->all) {
my $pcnt = colorify 'bold red' => $flav->percentage;
my $tag = $flav->tag;
my $type = $flav->type;
$flav_recipe_str .= " $tag -> $pcnt % ($type)\n";
}
my $flav_result_str = '';
for my $flav ($result->flavors->kv->all) {
my ($tag, $ml) = @$flav;
$ml = colorify 'bold yellow' => $ml;
$flav_result_str .= " $tag => [$ml ml]\n";
}
hash(
recipe_flavor_string => $flav_recipe_str,
result_flavor_string => $flav_result_str
)->inflate
}
fun format_resultset (RecipeResultSet $rset) {
state $tmpl = <<'EOT';
--> target amount: %target_quantity ml
pg: %target_pg % vg: %target_vg %
nic base: %base_nic_per_ml mg/ml nic type: %base_nic_type%
nic target: %target_nic_per_ml mg/ml
flavor targets:
%flavor_recipe
notes: %notes
=>
vg: [%vg ml] pg: [%pg ml] nic base: [%nic ml]
(max vg total: %max_vg_total ml)
flavors:
%flavor_result
total: %total ml
EOT
my $recipe = $rset->recipe;
my $result = $rset->result;
my $flav_recipe_str = flavor_strings($rset)->recipe_flavor_string;
my $flav_result_str = flavor_strings($rset)->result_flavor_string;
format_str( $tmpl =>
notes => sub {
$recipe->notes->has_any ?
"\n" . $recipe->notes
->map(sub { colorify('bold yellow', ' - '.$_) })
->join("\n")
: 'none'
},
flavor_recipe => $flav_recipe_str,
flavor_result => $flav_result_str,
(map {; $_ => colorify('bold red', $recipe->$_) } qw/
target_quantity target_nic_per_ml
base_nic_per_ml base_nic_type
target_pg target_vg
/),
(map {; $_ => colorify('bold yellow', $result->$_) } qw/
vg pg nic total
/),
max_vg_total => sub {
colorify('bold yellow', $result->pg + $result->vg)
},
)
}
use Term::UI;
use Term::ReadLine;
my $termpkg =
$ENV{PERL_RL}
|| try { use_module('Term::ReadLine::Perl5') }
|| try { use_module('Term::ReadLine::Perl') }
|| 'Term::ReadLine';
my $term = $termpkg->new('vcalc');
my $outfh = $term->OUT || \*STDOUT;
$outfh->autoflush(1);
$outfh->say('Welcome to App::vaporcalc!');
$outfh->say("Try '@{[ colorify yellow => 'help' ]}' for usage details.");
my $cmdeng = App::vaporcalc::CmdEngine->new;
my $recipe = App::vaporcalc::Recipe->new(
target_quantity => 10,
base_nic_per_ml => 100,
target_nic_per_ml => 12,
target_pg => 45,
target_vg => 55,
flavor_percentage => 10,
);
my $initial_input = getopts->recipe ? 'recipe load '.getopts->recipe : undef;
my $orig_prompt = colorify green => 'vcalc> ';
my $prompt;
PROMPT: while (1) {
$prompt //= $orig_prompt;
my $input = $initial_input // $term->get_reply(
prompt => $prompt,
default => 'calc'
);
undef $initial_input;
next PROMPT unless $input;
$term->addhistory($input);
$input = 'show recipe' if $input eq 'calc';
last PROMPT if $input =~ /^(?:exit|quit)/i;
my $parsed = try {
$cmdeng->parse_cmd($input)
} catch {
$outfh->say( format_error(">> Parser err: $_") );
undef
} or next PROMPT;
my $cmd_result = try {
$cmdeng->prepare_cmd(
subject => $parsed->subject,
verb => $parsed->verb,
params => $parsed->params,
( run in 1.753 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )