perl6 Colored match, some regex interpolation works and some don't; color code inconsistent

Viewed 151

I have some long lines and I want to highlight the matches with colors that I want. One function uses substitution, and the other function uses recursion. Some works and some don't; I am looking for a consistent way to interpolating into regex. Thank you very much !!!

sub colorMatch ($aStr, $aRegex, $aColor) {
    my $colorOff = '\e[0m';
    my $a =$aStr.subst(/(<{$aRegex}>)/, $aColor ~ "# $/ #" ~ $colorOff, :g);
    # not working, $/ not interpolating corresponding matches, all Nil
    say $a;
}

colorMatch("a-12-b-3-c-4-def-567", '\d+', '\e[1;31m');
colorMatch("a-12-b-3-c-4-def-567", '<alpha>+', '\e[1;31m');
say "\e[1;31m" ~ " color1 " ~ "\e[0m" ~ 
    "\e[1;36m" ~ " color2 " ~ "\e[0m";

sub colorMatch2 ($aStr, $aRegex, $colorNumber) {
    my $colorOff = "\e[0m";
    if $aStr.chars > 0 {
    my $x1 = ($aStr ~~ m/<{$aRegex}>/);
    my $x2 = $x1.prematch;
    my $x3 = $x1.Str;
    my $x4 = $x1.postmatch;
    return ($x2 ~ "\e[1;{$colorNumber}m" ~ $x3 ~ $colorOff)
        ~ colorMatch2($x4, $aRegex, $colorNumber);
    }
}

say colorMatch2("a-12-b-3-c-4-def-567", '\d+', 31); # works, red color
say colorMatch2("a-12-b-3-c-4-def-567", '567', 36); # works, green color
say colorMatch2("a-12-b-3-c-4-def-567", '\w+', 31); # works, red color
say colorMatch2("a-12-b-3-c-4-def-567", '[a..z]+', 31); # fails with [] and ..
say colorMatch2("a-12-b-3-c-4-def-567", "<alpha>+", 31); # fails with <>


Use of Nil in string context
  in sub colorMatch at colorMatch.pl line 4
a-\e[1;31m#  #\e[0m-b-\e[1;31m#  #\e[0m-c-\e[1;31m#  #\e[0m-def-\e[1;31m#  #\e[0m

# seems to do substitution, but $/ is empty and color not shown;

Use of Nil in string context
  in sub colorMatch at colorMatch.pl line 4
\e[1;31m#  #\e[0m-12-\e[1;31m#  #\e[0m-3-\e[1;31m#  #\e[0m-4-\e[1;31m#  #\e[0m-567

# seems to do substitution, but $/ is empty and color not shown;

 color1  color2 # both colors work and shown as expected, 
 # color1 red and color 2 green; why inconsistent with above???

a-12-b-3-c-4-def-567 # works, red color
a-12-b-3-c-4-def-567 # works, green color
a-12-b-3-c-4-def-567 # works, red color
No such method 'prematch' for invocant of type 'Bool'
  in sub colorMatch2 at colorMatch.pl line 17
  in block <unit> at colorMatch.pl line 28
3 Answers

It's not an interpolation problem. The syntax for character classes and ranges is a little different. You need:

'text' ~~ / <[a..z]>+ /

As for your other error about calling prematch() on a bool, the result is False because in the final recursion level, it doesn't match anymore. You need to check the result before assuming it matched.

Finally, for "Use of Nil in string context", it's because you're using Str.subst, and like most function calls in most languages, the arguments are evaluated before the function begins. You're using $/ in an argument, but it's not yet set because the function's body hasn't even started to execute. The s/match/replacement/ operator does not suffer this difficulty, so I suggest you change your code to:

$aStr ~~ s:g/(<$aRegex>)/$aColor# $/ #$colorOff/;

(Or for better readability:)

$aStr ~~ s:g {(<$aRegex>)} = "$aColor# $/ #$colorOff";

This assumes you've made $aRegex into a regex rather than a string. Also, since the new code modifies $aStr, you need to change $aStr to $aStr is copy in the function signature.

Thank you all for your help. Here is my revised version. The only problem is that, for some reason I cannot figure out, the substitution function is not interpreting color code, but the same color code works with plain "say" routine. Thanks !

Note: defining 'my $x = rx/$aRegex/' and then using '/< $x >/' works unpredictably; so I end up using /<{$aRegex}>/;

sub colorMatch ($aStr, $aRegex, $aColor) {
    my $colorOff = '\e[0m';
    my $x = rx/$aRegex/;
    my $bStr = $aStr;
    $_ = $aStr;
    # my $a =$aStr.subst(/(<$x>)/, $aColor ~ "# $/ #" ~ $colorOff, :g);
    # $bStr ~~ s:g/(<$x>)/$aColor ~ "# $/ #" ~ $colorOff/;
    # s:g/(<{$aRegex}>)/($aColor $/ $colorOff)/;
    s:g/(<{$aRegex}>)/($aColor $/ $colorOff)/;
    say $_; # for some reason, color codes are not interpreted;
}

colorMatch("a-12-b-3-c-4-def-567", '\d+', '\e[1;31m');
colorMatch("a-12-b-3-c-4-def-567", '<alpha>+', '\e[1;36m');
say "\e[1;31m" ~ " color1 " ~ "\e[0m" ~ "\e[1;36m" ~ " color2 " ~ "\e[0m";
say "a-\e[1;31m 12 \e[0m-b-\e[1;31m 3 \e[0m-c-\e[1;31m 4 \e[0m-def-\e[1;31m 567 \e[0m"; # this works; 
say "\e[1;31m a \e[0m-12-\e[1;31m b \e[0m-3-\e[1;31m c \e[0m-4-\e[1;31m def \e[0m-567"; # this works
say "(\e[1;36m a \e[0m)-12-(\e[1;36m b \e[0m)-3-(\e[1;36m c \e[0m)-4-(\e[1;36m def \e[0m)-567"; # works

sub colorMatch2 ($aStr, $aRegex, $colorNumber) {
    my $colorOff = "\e[0m";
    # my $x = rx/$aRegex/;
    # say $x; # /$x/ or /<$x>/ do not all work; prints out "rx/$aRegex/"
    if $aStr.chars > 0 {
    my $x1 = ($aStr ~~ m/<{$aRegex}>/); # <{$aRegex}> works
    my $x2 = $x1 ?? $x1.prematch !! $aStr;
    my $x3 = $x1 ?? $x1.Str !! "";
    my $x4 = $x1 ?? $x1.postmatch !! "";
    return ($x2 ~ "\e[1;{$colorNumber}m" ~ $x3 ~ $colorOff)
        ~ colorMatch2($x4, $aRegex, $colorNumber);
    } else {
    return "";
    }
}

# colorMatch2 all works now:

say colorMatch2("a-12-b-3-c-4-def-567", '\d+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", '567', 36);
say colorMatch2("a-12-b-3-c-4-def-567", '\w+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", '<[a..z]>+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", "<alpha>+", 31);

And the results:

a-(\e[1;31m 12 \e[0m)-b-(\e[1;31m 3 \e[0m)-c-(\e[1;31m 4 \e[0m)-def-(\e[1;31m 567 \e[0m)
(\e[1;36m a \e[0m)-12-(\e[1;36m b \e[0m)-3-(\e[1;36m c \e[0m)-4-(\e[1;36m def \e[0m)-567
 color1  color2 
a- 12 -b- 3 -c- 4 -def- 567 
a -12- b -3- c -4- def -567
( a )-12-( b )-3-( c )-4-( def )-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
Related