2

Well, I've been searching the internet for the last 10+ hours with no luck or success regarding this..

I am attempting to convert irc control codes(colors, etc) into html, the input text plucked from an eggdrop tcl bound event. The bold/underline works fine.. haven't tested the italics yet, but that's not what is at issue.

.. The issue is, that my regex appears to be matching the wrong character(s). I set up my regex -- I assumed to have knowledge of from previous experience in coding(php/js mainly) -- to match against \003(\d+)[,]?(\d*)(.*?), as I want the numbers after the control character, to then use as an index in a list, to pull the requisite html hex color. However, the number that gets pulled does not appear to even be a number, not showing up correctly in the terminal, and instead appears to be a control character(from my experience using gedit).

The code for my process is below, it is part of a larger script, which logs text to a file. Everything else works, but this process.

To the question.. What exactly have I done wrong here? The only error message I've been receiving is something akin to '(control character) invalid index'.

proc logger:control {text} {

    set val {
        {FFF}
        {000}
        {00007F}
        {009000}
        {FF0000}
        {7F0000}
        {9F009F}
        {FF7F00}
        {FFFF00}
        {00F800}
        {00908F}
        {00FFFF}
        {0000FF}
        {FF00FF}
        {7F7F7F}
        {CFD0CF}
    }

    while {[regsub {\002(.*?)\002} $text {<b>\1</b>} text]} {}
    while {[regsub {\037(.*?)\037} $text {<u>\1</u>} text]} {}
    while {[regsub {\035(.*?)\035} $text {<i>\1</i>} text]} {}
    while {[regsub {\003([0-9]+)[,]?(\d*)(.*?)} $text "</span><span style='color: [lindex $val \1] ;'>\3" text]} {}
    # ^ the line that throws the error
    while {[regsub {\003[^\d]} $text {$text</span>} text]} {}

    return $text
}
Daedalus
  • 7,518
  • 3
  • 29
  • 56
  • It seems that tcl is not substituting `\1` which causes the error. Maybe you could assign the first catch a variable (say catch) and then call it in another regsub `lindex $val $catch`? – Jerry Feb 16 '13 at 11:49
  • @Jerry: No, it's that Tcl is substituting the `\1` too early. – Donal Fellows Feb 16 '13 at 17:35
  • The RE matches seem like they could be done more efficiently. Check out what the `-all` option to `regsub` does… – Donal Fellows Feb 16 '13 at 17:37

1 Answers1

2

As you say, the problem is this line:

while {[regsub {\003([0-9]+)[,]?(\d*)(.*?)} $text "</span><span style='color: [lindex $val \1] ;'>\3" text]} {}

The first problem with that is that Tcl is interpreting \digit in the replacement immediately, as you have quoted it with "double-quotes". The fix? Use braces:

while {[regsub {\003([0-9]+)[,]?(\d*)(.*?)} $text {</span><span style='color: [lindex $val \1] ;'>\3} text]} {}

The second problem is that then you'll get literal Tcl command fragments in the text after that. Probably not what you want! Alas, there's nothing like the /e flag in Perl here; you need a totally different approach:

# First, defang any Tcl metacharacters
set text [string map {\\ \\\\ [ \\[ ] \\] $ \\$} $text]
# Second, do the replacements, inserting Tcl fragments
while {[regsub {\003([0-9]+)[,]?(\d*)(.*?)} $text {</span><span style='color: [lindex $val \1] ;'>\3} text]} {}
# Third, do the substitutions we just inserted
set text [subst $text]

Note, you have to be careful to make sure your RE takes into account the extra backslashes when using this trick. Thankfully, in your case it makes no difference as your pattern doesn't match backslashes.

Donal Fellows
  • 120,022
  • 18
  • 134
  • 199
  • Thank you for this, I was wracking my brains for hours trying to figure out why it wasn't working.. seems tcl is a bit more complex than I imagined. – Daedalus Feb 16 '13 at 20:01
  • @Daedalus: I've been meaning to implement some sort of command substitution for `regsub` for ages, but nailing down exactly what it should do is tricky… – Donal Fellows Feb 16 '13 at 22:42
  • And yes, this is one of the few genuinely tricky bits; the `string map`/`regsub`/`subst` sequence isn't one that you're likely to invent on your own. (I got it originally from Brent Welch, except we didn't have `string map` back then…) – Donal Fellows Feb 16 '13 at 22:44
  • Well then, am I thankful that this site exists, and that you're a member of it, heh. – Daedalus Feb 16 '13 at 22:45