If you define a tag with
registerTagHandler
, if this tag returns a string that looks like a tag, then the leading and trailing percent character is chopped off after
TWiki::_processTags
.
Tag handlers are really designed for applications where the content of the tag is fully evaluated before return. The parser would be horrendously inefficient otherwise (not that it's exactly super fast already....) --
CC
Say you have
sub myTag {
return '%YOURTAG{value="Have a nice day"}%';
}
From a user perspective, it appears that the two following constructs should behave the same way:
sub commonTagsHandler {
$_[0] =~ s/%MYTAG({.*)}?%/&myTag()/geo;
}
and
TWiki::Func::registerTagsHandler( 'MYTAG', \&myTag );
but they are not:
- The first variant returns
%YOURTAG{value="Have a nice day"}%
- The second variant returns
YOURTAG{value="Have a nice day"}
I don't quite understand why there would be a problem. Obviously,
myTag
would have to be careful not to return a tag that would get recursively evaluated over and over again. But certainly, that is the responsibility of the plugin writer, not the system.
Can you give an example where we could get into an infinite loop that would not be due to carelessness of the plugin writer. And if you want to protect against that, why do we allow this in
commonTagsHandler
? Or the other handlers?
I think this is a needless inconsistency and forces people to use
commonTagsHandler
where they could use registered tags (which I believe are more efficient). --
TW
It's not a question of an infinite loop, so much as a question of parser efficiency. At the moment the parser is sort-of recursive descent - at least evaluation is inside-out-left-right. It is assumed that an inner tag will be fully expanded before the final text is placed in context of the outer tag. If you don't make this assumption, you end up with the situation where an inner tag can return a result which constructs a new tag that didn't exist before the inner tag was expanded (as is the case in your example). Of course you can cope with this if you are prepared to always go back to the start of the text and reparse the whole thing every time an inner tag is evaluated, but that is rather inefficient (that's basically how
commonTagsHandler
works, and this is the reason why tag handler registration is more efficient). --
CC
I know I have asked this before, but are you sure that it wouldn't be better to move to a table-driven parser in the long run?
Anyway, the enhancement suggestion is to remove these (from a user perspective) gratuitous differences. --
TW
I really doubt it. The existing parser tokenises the input stream, and minimises string operations wherever possible, so I doubt a table driven parser would be any faster.
Documenting the "gratuitous differences" (as described in
Item3192 is the appropriate course of action. You can't stop plugin authors from performing arbitrary text replacements, but importing this arbitrariness into the core is not, IMHO, a good idea, so I'm discarding this.
CC