From 0f81584d8fd4cd68f5dea31fac19af202f9834bb Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Sun, 9 Jun 2019 13:57:08 -0700 Subject: [PATCH] Interpreter: split_line() now takes an options hash; now accepts "strip_quotes" and "keep_spaces" --- PBot/FactoidCommands.pm | 2 +- PBot/Interpreter.pm | 42 +++++++++++++++++++++++--------------- PBot/Plugins/Quotegrabs.pm | 2 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/PBot/FactoidCommands.pm b/PBot/FactoidCommands.pm index fad3a26c..5a169eca 100644 --- a/PBot/FactoidCommands.pm +++ b/PBot/FactoidCommands.pm @@ -614,7 +614,7 @@ sub factunset { my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factunset', $usage, 1); return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message - my ($key) = $self->{pbot}->{interpreter}->split_line($arguments, 1); + my ($key) = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1); return $usage if not length $key; diff --git a/PBot/Interpreter.pm b/PBot/Interpreter.pm index 1711acb0..f1cfd1dc 100644 --- a/PBot/Interpreter.pm +++ b/PBot/Interpreter.pm @@ -546,9 +546,7 @@ sub extract_bracketed { # unbalanced quotes gracefully by treating them as part of the argument # they were found within. sub split_line { - my ($self, $line, $strip_quotes) = @_; - - $strip_quotes = 0 if not defined $strip_quotes; + my ($self, $line, %opts) = @_; my @chars = split //, $line; @@ -561,6 +559,7 @@ sub split_line { my $i = 0; my $pos; my $ignore_quote = 0; + my $spaces = 0; while (1) { $last_ch = $ch; @@ -582,6 +581,8 @@ sub split_line { $ch = $chars[$i++]; + $spaces = 0 if $ch ne ' '; + if ($escaped) { $token .= "\\$ch"; $escaped = 0; @@ -596,7 +597,7 @@ sub split_line { if (defined $quote) { if ($ch eq $quote) { # closing quote - $token .= $ch unless $strip_quotes; + $token .= $ch unless $opts{strip_quotes}; push @args, $token; $quote = undef; $token = ''; @@ -616,15 +617,20 @@ sub split_line { # begin potential quoted argument $pos = $i - 1; $quote = $ch; - $token .= $ch unless $strip_quotes; + $token .= $ch unless $opts{strip_quotes}; } next; } if ($ch eq ' ') { - push @args, $token if length $token; - $token = ''; - next; + if (++$spaces > 1 and $opts{keep_spaces}) { + $token .= $ch; + next; + } else { + push @args, $token if length $token; + $token = ''; + next; + } } $token .= $ch; @@ -637,16 +643,16 @@ sub split_line { sub make_args { my ($self, $string) = @_; - my @args = $self->split_line($string); + my @args = $self->split_line($string, keep_spaces => 1); my @arglist; - my @arglist_quotes; + my @arglist_unstripped; while (@args) { my $arg = shift @args; - # add argument with quotes preserved - push @arglist_quotes, $arg; + # add argument with quotes and spaces preserved + push @arglist_unstripped, $arg; # strip quotes from argument if ($arg =~ m/^'.*'$/) { @@ -657,12 +663,15 @@ sub make_args { $arg =~ s/"$//; } - # add unquoted argument + # strip leading spaces from argument + $arg =~ s/^\s+//; + + # add stripped argument push @arglist, $arg; } - # copy quoted arguments to end of arglist - push @arglist, @arglist_quotes; + # copy unstripped arguments to end of arglist + push @arglist, @arglist_unstripped; return \@arglist; } @@ -675,6 +684,7 @@ sub arglist_size { # shifts first argument off array of arguments sub shift_arg { my ($self, $args) = @_; + return undef if not @$args; splice @$args, @$args / 2, 1; # remove original quoted argument return shift @$args; } @@ -695,7 +705,7 @@ sub split_args { } while (--$count > 1 and $i < $max); } - # get rest from 2nd half of arglist, which contains original quotes + # get rest from 2nd half of arglist, which contains original quotes and spaces my $rest = join ' ', @$args[@$args / 2 + $i .. @$args - 1]; push @result, $rest if length $rest; return @result; diff --git a/PBot/Plugins/Quotegrabs.pm b/PBot/Plugins/Quotegrabs.pm index 6c4640fe..df59fb2d 100644 --- a/PBot/Plugins/Quotegrabs.pm +++ b/PBot/Plugins/Quotegrabs.pm @@ -169,7 +169,7 @@ sub grab_quotegrab { my ($grab_nick, $grab_history, $channel, $grab_nicks, $grab_text); foreach my $grab (@grabs) { - ($grab_nick, $grab_history, $channel) = $self->{pbot}->{interpreter}->split_line($grab, 1); + ($grab_nick, $grab_history, $channel) = $self->{pbot}->{interpreter}->split_line($grab, strip_quotes => 1); $grab_history = $nick eq $grab_nick ? 2 : 1 if not defined $grab_history; # skip grab command if grabbing self without arguments $channel = $from if not defined $channel;