+sub extend_match_regex_left {
+ my ($line, $match, $regex) = @_;
+
+ my $s = reverse substr $line, 0, $match->{x};
+ if ($s =~ /^($regex)/) {
+ $match->{string} = reverse($1) . $match->{string};
+ $match->{x} -= length $1;
+ $match->{offset} -= length $1;
+ }
+ return;
+}
+sub extend_match_regex_right {
+ my ($line, $match, $regex) = @_;
+
+ my $s = substr $line, $match->{x} + length $match->{string};
+ if ($s =~ /^($regex)/) {
+ $match->{string} .= $1;
+ }
+ return;
+}
+sub extend_match {
+ my ($screen, $config, $input, $match) = @_;
+
+ $screen->debug('extend_match', 'started');
+
+ return if not defined $match;
+
+ $screen->prompt(name => 'extend', value => undef);
+ $screen->draw_prompt($config);
+
+ delete $match->{id}; # don't draw any match ids
+ $screen->draw_matches($config, [], [$match]);
+ $screen->refresh;
+
+ my $line = $input->{lines}[$match->{y}];
+
+ while (1) {
+ my $match_old = \%{$match};
+
+ my $char = $screen->getch;
+ if ($char eq "\n"
+ or $char eq $config->{setting}{alternative_return}) {
+ last; # accept match
+
+ } elsif ($char eq 'w') { # select current word (both directions)
+ extend_match_regex_left($line, $match, qr/\w+/);
+ extend_match_regex_right($line, $match, qr/\w+/);
+ } elsif ($char eq 'b') { # select current word (only left)
+ extend_match_regex_left($line, $match, qr/\w+/);
+ } elsif ($char eq 'e') { # select current word (only right)
+ extend_match_regex_right($line, $match, qr/\w+/);
+
+ } elsif ($char eq 'W') { # select current WORD (both directions)
+ extend_match_regex_left($line, $match, qr/\S+/);
+ extend_match_regex_right($line, $match, qr/\S+/);
+ } elsif ($char eq 'B') { # select current WORD (only left)
+ extend_match_regex_left($line, $match, qr/\S+/);
+ } elsif ($char eq 'E') { # select current WORD (only right)
+ extend_match_regex_right($line, $match, qr/\S+/);
+
+ } elsif ($char eq '0') { # select to beginning of line
+ extend_match_regex_left($line, $match, qr/.+/);
+ } elsif ($char eq '$') { # select to end of line
+ extend_match_regex_right($line, $match, qr/.+/);
+
+ # Allow mode changes if not overwritten by local mappings.
+ } elsif (defined $config->{mapping}{mode}{$char}) {
+ $screen->draw_matches($config, [$match_old], []); # clear match
+ return { key => $char };
+
+ } else {
+ next; # ignore unknown mappings
+ }
+
+ $screen->draw_matches($config, [$match_old], [$match]);
+ $screen->refresh;
+ }
+
+ $screen->debug('extend_match', 'done');
+
+ return { match => $match };
+}
+