Retry after REJECT: edit bad input instead of aborting

This commit is contained in:
Juerd Waalboer 2019-11-03 00:13:43 +01:00
parent e00fc00664
commit d8dfc2cde2
3 changed files with 41 additions and 7 deletions

View file

@ -8,7 +8,7 @@ sub command :Tab(adduser) {
$command eq 'adduser' or return NEXT; $command eq 'adduser' or return NEXT;
if ($cart->size) { if ($cart->size) {
return REJECT, "Create the account *before* scanning things."; return ABORT, "Create the account *before* scanning things.";
} }
return "Name for the new account", \&username; return "Name for the new account", \&username;

View file

@ -29,6 +29,11 @@ sub hook_reject {
_log("REJECT [$plugin] $reason"); _log("REJECT [$plugin] $reason");
} }
sub hook_retry {
my ($class, $plugin, $reason, $abort) = @_;
_log("RETRY [$plugin] $reason");
}
sub hook_user_created { sub hook_user_created {
my ($class, $username) = @_; my ($class, $username) = @_;
_log("NEWUSER $username"); _log("NEWUSER $username");

41
revbank
View file

@ -20,6 +20,9 @@ our %HELP = (
); );
my @words; my @words;
my $retry;
my @retry;
my $one_off = 0; my $one_off = 0;
if (@ARGV) { if (@ARGV) {
@ -44,7 +47,7 @@ $select->add(\*STDIN);
my $cart = RevBank::Cart->new; my $cart = RevBank::Cart->new;
sub prompt { sub prompt {
my ($prompt, $plugins, @completions) = @_; my ($prompt, $plugins, $completions) = @_;
$prompt =~ s/$/: /; $prompt =~ s/$/: /;
$prompt =~ s/\?: $/? /; $prompt =~ s/\?: $/? /;
@ -52,19 +55,31 @@ sub prompt {
my @matches; my @matches;
$readline->Attribs->{completion_entry_function} = sub { $readline->Attribs->{completion_entry_function} = sub {
my ($word, $state) = @_; my ($word, $state) = @_;
@matches = grep /^\Q$word\E/i, @completions if $state == 0; @matches = grep /^\Q$word\E/i, @$completions if $state == 0;
return shift @matches; return shift @matches;
}; };
my $done; my $done;
my $input; my $input;
print "$retry\n" if $retry;
$readline->callback_handler_install($prompt, sub { $readline->callback_handler_install($prompt, sub {
$done = 1; $done = 1;
$input = shift; $input = shift;
$readline->callback_handler_remove; $readline->callback_handler_remove;
}); });
if ($retry) {
my $preset = join " ", @retry[0 .. $#retry - 1];
my $cursor = length $preset;
$preset .= " " . join " ", @{ $retry[-1] };
$readline->insert_text($preset);
$readline->Attribs->{point} = $cursor;
@retry = ();
$retry = 0;
}
$readline->redisplay();
my $begin = my $time = time; my $begin = my $time = time;
while (not $done) { while (not $done) {
if ($::ABORT_HACK) { if ($::ABORT_HACK) {
@ -119,6 +134,7 @@ OUTER: for (;;) {
sub abort { sub abort {
print @_, " " if @_; print @_, " " if @_;
@words = (); @words = ();
@retry = ();
call_hooks "abort", $cart; call_hooks "abort", $cart;
$cart->empty; $cart->empty;
{ no warnings; redo OUTER; } { no warnings; redo OUTER; }
@ -157,7 +173,7 @@ OUTER: for (;;) {
delete $completions{abort}; delete $completions{abort};
} }
my $input = prompt $prompt, \@plugins, keys %completions; my $input = prompt $prompt, \@plugins, [ keys %completions ];
call_hooks "input", $cart, $input, $split_input; call_hooks "input", $cart, $input, $split_input;
@ -172,6 +188,7 @@ OUTER: for (;;) {
abort if grep $_ eq 'abort', @words; abort if grep $_ eq 'abort', @words;
my $word = shift @words; my $word = shift @words;
push @retry, $word;
PLUGIN: for my $plugin (@plugins) { PLUGIN: for my $plugin (@plugins) {
my ($rv, @rvargs) = eval { $plugin->$method($cart, $word) }; my ($rv, @rvargs) = eval { $plugin->$method($cart, $word) };
@ -198,11 +215,22 @@ OUTER: for (;;) {
} }
if ($rv == REJECT) { if ($rv == REJECT) {
my ($reason) = @rvargs; my ($reason) = @rvargs;
call_hooks "reject", $plugin->id, $reason, @words ? 1 : 0; #abort if @words;
abort if @words;
redo PROMPT; if (@words) {
call_hooks "retry", $plugin->id, $reason, @words ? 1 : 0;
push @retry, [@words];
@words = ();
$retry = $reason;
redo OUTER;
} else {
call_hooks "reject", $plugin->id, $reason, @words ? 1 : 0;
@retry = ();
redo PROMPT;
}
} }
if ($rv == ACCEPT) { if ($rv == ACCEPT) {
@retry = ();
next OUTER; next OUTER;
} }
if ($rv == NEXT) { if ($rv == NEXT) {
@ -215,6 +243,7 @@ OUTER: for (;;) {
abort; abort;
} }
call_hooks "invalid_input", $cart, $word; call_hooks "invalid_input", $cart, $word;
@retry = ();
abort if @words; abort if @words;
redo OUTER; redo OUTER;
} }