Hacky Custom Tag Woes


Okay, I figured it out by myself. I don’t know why I’m so reluctant to step through code in TADS, but I should probably do it more often. The issue is the line:

start = match[1] + match[2];

Which sets the point at which the next iteration searches for the next tag. When the string that’s substituted is shorter than the original string, the next iteration starts off too far ahead, which in the case of ‘<.k cat>, <.k mouse>’ means it starts in the middle of the second tag and can’t recognise it.

Although I’m sure it’s inefficient, I’m going to comment out this line of code altogether. Subtracting numbers from it just sounds like a recipe for array out of bounds exceptions…

-------------------------------------Original Problem-------------------------------------------------

So my WIP is using special formatting for certain words - formatting that is initially set based on the interpreter’s capabilities and which the user can then also change. I have a little function which takes a string and adds html formatting to it as necessary, or returns the string in all caps, or just returns the string unchanged.

Because I wanted to make using this function extra easy, I decided to create my own special tag. After a cursory glance through the docs and library, I basically just ripped off the conversationManager outputFilter like so:

[code]keywordManager: OutputFilter
filterText(ostr, txt)
local start;

    /* scan for our keyword tags */
    for (start = 1 ; ; )
        local match;
        local tag;
        local arg;
        /* scan for the next tag */
        match = rexSearch(tagPat, txt, start);

        /* if we didn't find it, we're done */
        if (match == nil)

        /* get the argument (the third group from the match) */
        arg = rexGroup(3);
        if (arg != nil)
            arg = arg[3];

        /* pick out the tag */
        tag = rexGroup(1)[3].toLower();

        /* check which tag we have */
            //replace it with k function string
            txt = rexReplace(tagPat, txt, k(arg), 0);

        /* continue the search after this match */
        start = match[1] + match[2];

    return txt;
tagPat = static new RexPattern(
    + '(k'
    + ')'
    + '(<space>+(<^rangle>+))?'
    + '<rangle>')

In the showIntro method I add this outputFilter with the following line:


The idea is that this allows me to output strings like so:

"Some text to be output, this <.k word> is highlighted.
I was under the impressions that all this was working fine, but apparently there’s a certain condition in which it goes peculiar. If the ‘k’ function returns a string that doesn’t contain HTML tags, and there are two of these tags in a row with no letters between them, like so:

"Here is a list of a <.k cat>, <.k dog> and <.k mouse>."

What is actually output is something like this:

And the debug view in the workbench complains of ‘Error: Unknown tag’ for the ‘<.k mouse>’ tag.

So… I’ve managed to blag it this far, but I think I need help now. If I hard code the ‘k’ function to return 'hello, everything works, if I hard code it to just ‘hello’ then I get the error for a list as above. I’m wondering if there’s something wrong with my regular expression in tagPat? I just copied the one being used in the conversationManager, so maybe I need to tweak it a little more? Alternatively, could the problem be a conflict with an existing outputFilter?

I could just switch to using my k function directly, but at this late juncture I’m not keen to do such a massive find/replace job on my code…