#!perl HELP "*, x, x, *" => "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 $limit = 24; my $err_limit = "Repetition is limited at $limit items."; sub command { my ($self, $cart, $command) = @_; return ABORT, $err_pfand if $cart->entries('is_pfand'); my ($pre, $post) = $command =~ /^(\d+)?[x*](\d+)?$/ or return NEXT; my $last = ($cart->entries)[-1]; return NEXT if $pre and $post; # 123x123 -> invalid syntax if ($post) { return REJECT, $err_limit if $post > $limit; return ABORT, "Can't repeat an empty transaction." if not $cart->size; return REJECT, $err_stacked if $last->multiplied; $last->quantity($post); return ACCEPT; } if (not $pre and not $post) { # Lone operator. Convert withdrawal into repetition. if ($last->has_attribute('is_withdrawal')) { $pre = abs $last->{amount}; $pre == int $pre or return REJECT, "Repeat only works on integers."; $cart->delete($last); } elsif (not $cart->size) { return ABORT, "Can't repeat an empty transaction."; } } if ($pre) { $pre = abs $pre; # withdrawal is negative return REJECT, $err_limit if $pre > $limit; $cart ->add(0, "? (The next thing you add will be multiplied.)", { _repeat => 1 }) ->quantity($pre); return ACCEPT; } return REJECT, $err_stacked if $last->multiplied; return "Multiply previous product by", \&repeat; } sub repeat { my ($self, $cart, $arg) = @_; $arg =~ /^\d+$/ and $arg > 0 or return REJECT, "Invalid value."; return REJECT, $err_limit if $arg > $limit; ($cart->entries)[-1]->quantity($arg); return ACCEPT; } sub hook_added_entry { my ($self, $cart, $entry) = @_; $cart->size >= 2 or return; my @entries = $cart->entries; my @planned = $cart->entries('_repeat'); return if not @planned; return ABORT, "Multiple repeats queued; I'm confused." if @planned > 1; return ABORT, $err_pfand if $cart->entries('is_pfand'); return if $planned[0] == $entries[-1]; return ABORT, "Queued repeat is not the penultimate item; I'm confused" if $entries[-2] != $planned[0]; my $num = $planned[0]->quantity; $cart->delete($planned[0]); $entries[-1]->quantity($num); }