In
LocationLocationLocation patch I actualised the Dispatcher pattern that already existed in nascent form in
TWikiDotPm. The changes to do this are inextricably enmeshed with the rest of the
LocationLocationLocation patch, but
PeterThoeny wanted a separate topic to document this change so here it is.
TWiki variables are those things in % signs e.g. %MAINWEB% and %SEARCH{}%
What has been wrought
In the past TWiki has always had a problem with expanding variables. Because perl regular expressions were used to extract variable invocations from topics, the expansion would easily get confused when variables were used in the parameters to other variables. The evaluation was perfectly deterministic, but the rules were opaque and frustrating.
To overcome this problem I implemented a simple (nay, moronic) parser that allows a guaranteed inside-out evaluation order. This parser always expands tags that are in the parameters to other tags before the tags the are parameters to. This is a fully deterministic and intuitive approach.
What won't work
Some things that used to work will not work any more. Specifically,
- Construction of new variables by combining the values returned from other tags. For example:
* Set MainLine = Turkey
%%MAINWEB%Line%
would in the past have expanded to "Turkey". It will now expand to "%MainLine%". This is a deliberate choice; to fully expand, the parser would have to stop after every variable expansion and re-parse the text from the start. The current approach allows a single pass over the text. For simple text this gives little performance advantage, but for complex topics involving many tags it can significantly accelerate expansion.
Precedence order of variables
For the parser to work, I had to abstract out the old
s/%XYZ%/&_handleXYZ()/
statements into precedence-ordered groups. These groups are (in order):
- user preferences
- preferences defined in TWiki topics e.g. EDITBOXWIDTH
- session internal variables
- these are variables that change according to the session e.g. USERNAME
- static internal variables
- these are variables whose value is set by the installation e.g. MAINWEB
- dynamic internal variables
- These are variables that have permanently-assigned handlers in the code e.g. SEARCH
Any tag defined higher up the order will override any lower definition. So, if a user defines a preference tag SEARCH, they will override the built-in SEARCH.
The groups are defined in appropriately named hashes in
TWikiDotPm. The hashes map the first three groups to strings, and the third group to function calls.
Normalised variable parameter syntax
Another affect of this change is to nomalise the syntax used in variables. All variables are expected to follow the "TWiki standard" syntax specification. Interesting this now means that %MAINWEB{}% is synonymous with %MAINWEB%, and %SEARCH% is a search for nothing. Obviously parameters to variables are also parsed in one place, meaning that variable parameter syntax is now normalised. This both guarantees consistent syntax and allows the possibility of "relaxing" the syntax definition as per the
AttrsContrib at some point in the future.
Note that there are still a number of variables that have escaped the net. Notably, many variables are processed when expanding templates. It would be nice to use the same parser to do this expansion, but that is for the future.
Opportunites opened up
Because dynamic internal variables are mapped to handlers, it would be trivial for a plugin to register a handler for a nominated variable. This would significantly simplify plugins that process embedded variables, such as %ACTION%. However it can only work for context-free variables, so it doesn't help with tags that are sensitive to their context, such as %CALC%.
--
CrawfordCurrie - 08 Nov 2004