prompt: support "quoted" terms and \-escapes
With fancy retry, of course :)
This commit is contained in:
parent
f4d3b7fd5c
commit
a1e5d310a9
1 changed files with 56 additions and 6 deletions
62
revbank
62
revbank
|
@ -48,6 +48,39 @@ $select->add(\*STDIN);
|
||||||
|
|
||||||
my $cart = RevBank::Cart->new;
|
my $cart = RevBank::Cart->new;
|
||||||
|
|
||||||
|
sub split_input($input) {
|
||||||
|
$input =~ s/\s+$//;
|
||||||
|
|
||||||
|
my @terms;
|
||||||
|
my $pos = 0;
|
||||||
|
|
||||||
|
while (
|
||||||
|
$input =~ m[
|
||||||
|
\G \s*
|
||||||
|
(?| ' ( (?: \\. | [^\\'] )* ) ' (?=\s|;|$)
|
||||||
|
| " ( (?: \\. | [^\\"] )* ) " (?=\s|;|$)
|
||||||
|
| ( (?: \\. | [^\\;'"\s] )+ ) (?=\s|;|$)
|
||||||
|
| (;)
|
||||||
|
)
|
||||||
|
]xg
|
||||||
|
) {
|
||||||
|
push @terms, $1;
|
||||||
|
$pos = pos($input) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# End of string not reached
|
||||||
|
return \$pos if $pos < length($input);
|
||||||
|
|
||||||
|
# End of string reached
|
||||||
|
for my $term (@terms) {
|
||||||
|
$term =
|
||||||
|
$term eq ';' ? "\0SEPARATOR"
|
||||||
|
: $term =~ s/\\(.)/$1/gr;
|
||||||
|
}
|
||||||
|
return @terms;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub prompt($prompt, $plugins, $completions) {
|
sub prompt($prompt, $plugins, $completions) {
|
||||||
if ($prompt) {
|
if ($prompt) {
|
||||||
$prompt =~ s/$/:/ if $prompt !~ /[?>](?:\x01[^\x02]*\x02)?$/;
|
$prompt =~ s/$/:/ if $prompt !~ /[?>](?:\x01[^\x02]*\x02)?$/;
|
||||||
|
@ -81,11 +114,16 @@ sub prompt($prompt, $plugins, $completions) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($retry) {
|
if ($retry) {
|
||||||
my @trailing = @{ pop @retry };
|
my $word_based = ref($retry[-1]);
|
||||||
|
my @trailing = $word_based ? @{ pop @retry } : ();
|
||||||
my @rejected = pop @retry;
|
my @rejected = pop @retry;
|
||||||
my @accepted = @retry;
|
my @accepted = @retry;
|
||||||
s/\0SEPARATOR/;/ for @accepted, @rejected, @trailing;
|
s/\0SEPARATOR/;/ for @accepted, @rejected, @trailing;
|
||||||
$readline->insert_text(join " ", @accepted, @rejected, @trailing);
|
$readline->insert_text(
|
||||||
|
$word_based
|
||||||
|
? join(" ", @accepted, @rejected, @trailing)
|
||||||
|
: join("", @accepted, @rejected)
|
||||||
|
);
|
||||||
$readline->Attribs->{point} = @accepted ? 1 + length "@accepted" : 0;
|
$readline->Attribs->{point} = @accepted ? 1 + length "@accepted" : 0;
|
||||||
@retry = ();
|
@retry = ();
|
||||||
$retry = 0;
|
$retry = 0;
|
||||||
|
@ -170,10 +208,22 @@ OUTER: for (;;) {
|
||||||
|
|
||||||
length $input or redo PROMPT;
|
length $input or redo PROMPT;
|
||||||
|
|
||||||
@words = ($split_input
|
if ($split_input) {
|
||||||
? map { $_ eq ';' ? "\0SEPARATOR" : $_ } grep length, split(/\s+|(;)/, $input)
|
@words = split_input($input);
|
||||||
: $input
|
if (ref $words[0]) {
|
||||||
);
|
my $pos = ${ $words[0] };
|
||||||
|
@retry = @words = ();
|
||||||
|
$retry = "Syntax error.";
|
||||||
|
if ($input =~ /['"]/) {
|
||||||
|
$retry .= " (Quotes must be at beginning and end of terms only.)";
|
||||||
|
}
|
||||||
|
push @retry, substr($input, 0, $pos) if $pos > 0;
|
||||||
|
push @retry, substr($input, $pos);
|
||||||
|
redo PROMPT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@words = $input;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WORD: for (;;) {
|
WORD: for (;;) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue