Support +1 and -1

This commit is contained in:
Juerd Waalboer 2021-08-10 21:53:24 +02:00
parent 83caf2c183
commit 2f182b34ed

View file

@ -5,6 +5,7 @@ HELP "*<N>, x<N>, <N>x, <N>*" => "Repeat previous/next product N times";
my $err_stacked = "Stacked repetition is not supported.";
my $err_pfand = "Plugins 'pfand' and 'repeat' cannot be combined.";
my $err_nope = "Entry does not support repetition.";
my $err_postfix = "Addition/substraction is only supported the other way around.";
my $limit = 200;
my $err_limit = "Repetition is limited at $limit items.";
@ -14,42 +15,69 @@ sub command {
return ABORT, $err_pfand if $cart->entries('is_pfand');
my ($pre, $post) = $command =~ /^(\d+)?[x*](\d+)?$/
my ($lhs, $op, $rhs) = $command =~ /^(\d+)?([x*+-])(\d+)?$/
or return NEXT;
my $last = ($cart->entries)[-1];
return NEXT if $pre and $post; # 123x123 -> invalid syntax
return NEXT if $lhs and $rhs; # 123x123 -> invalid syntax
if ($post) {
return REJECT, $err_limit if $post > $limit;
if ($rhs) {
return ABORT, "Can't modify an empty transaction." if not $cart->size;
return REJECT, $err_stacked if $last->multiplied;
return REJECT, $err_nope if $last->attribute('no_repeat');
return REJECT, $err_limit if $rhs > $limit;
$last->quantity($post);
if ($op eq '+') {
my $new = $last->quantity + $rhs;
return REJECT, $err_limit if $new > $limit;
$last->quantity($new);
return ACCEPT;
}
if ($op eq '-') {
my $new = $last->quantity - $rhs;
if ($new > 0) {
$last->quantity($new);
} else {
$cart->delete($last);
print "Deleted.\n";
}
return ACCEPT;
}
# $op is not + or -, so it must be * (or x).
return REJECT, $err_stacked if $last->multiplied;
$last->quantity($rhs);
return ACCEPT;
}
if (not $pre and not $post) {
if (not $lhs and not $rhs) {
# Lone operator. Convert withdrawal into repetition.
return ABORT, "Can't modify an empty transaction." if not $cart->size;
if ($op eq '+' or $op eq '-') {
$self->{op} = $op;
return "$op how many?", \&plusminus;
}
if ($last->has_attribute('is_withdrawal')) {
$pre = abs $last->{amount};
$pre == int $pre or return REJECT, "Repeat only works on integers.";
$lhs = abs $last->{amount};
$lhs == int $lhs or return REJECT, "Repeat only works on integers.";
$cart->delete($last);
}
}
if ($pre) {
$pre = abs $pre; # withdrawal is negative
if ($lhs) {
return REJECT, $err_postfix if $op eq '+' or $op eq '-';
return REJECT, $err_limit if $pre > $limit;
$lhs = abs $lhs; # withdrawal is negative
return REJECT, $err_limit if $lhs > $limit;
$cart
->add(0, "? (The next thing you add will be multiplied.)", { _repeat => 1, refuse_checkout => 1 })
->quantity($pre);
->quantity($lhs);
return ACCEPT;
}
@ -70,6 +98,27 @@ sub repeat {
return ACCEPT;
}
sub plusminus {
my ($self, $cart, $arg) = @_;
$arg =~ /^\d+$/ and $arg > 0
or return REJECT, "Invalid value.";
my $last = ($cart->entries)[-1];
my $new = $last->quantity;
$new += $arg if $self->{op} eq '+';
$new -= $arg if $self->{op} eq '-';
return REJECT, $err_limit if $new > $limit;
if ($new < 0) {
$cart->delete($last);
print "Deleted.\n";
} else {
($cart->entries)[-1]->quantity($new);
}
return ACCEPT;
}
sub hook_added_entry {
my ($self, $cart, $entry) = @_;
$cart->size >= 2 or return;