[pmwiki-devel] Markup rule evaluation sequence

Patrick R. Michaud pmichaud at pobox.com
Fri May 23 00:24:59 CDT 2008


On Fri, May 23, 2008 at 08:40:45AM +1200, john.rankin at affinity.co.nz wrote:
> >> In the latest case, I had rule1 set to evaluate '>links'
> >> and rule2 set to evaluate '<block'. PmWiki evaluates
> >> 'block' '>links'. In my case, I needed rule2 to evaluate
> >> after rule1, but it didn't and it took me several tries
> >> to get the behaviour I wanted, as it involved a chain of
> >> related rules.
>
> > Did you try setting rule1 to '>links' and rule2 to '>rule1'?
>
> The wrinkle in this case is that rule1 is optional and can be disabled.
> In which case, who knows what rule2 will do. 

Even if a rule is disabled, it still participates in setting the
rule sequencing.  In other words, if you do:

    Markup('rule1', '>links', ... );
    Markup('rule2', '>rule1', ... );

and later

    DisableMarkup('rule1');

then rule2 is still enabled, and will still occur in the same
sequence as it would if rule1 is enabled.  You can use 
?action=ruleset to verify that this is the case.

So, I would just define rule2 to always come after rule1.

But if you're in a situation where it's possible that rule1
doesn't even exist (as opposed to being "disabled"), then
we can still handle it.  The code for defining rule2 looks like:

    Markup('rule1', '>links');
    Markup('rule2', '>rule1', "pattern2", "replacement2");

If rule1 already exists, then the first call to Markup() here won't
really impact.  If rule1 doesn't exist, then a "dummy rule" is
created for rule1 to simply hold its place in the sequence and
then rule2 is created relative to that.

In fact, the above will work even if rule1 is defined *after* rule2:

    Markup('rule1', '>links');
    Markup('rule2', '>rule1', "pattern2", "replacement2");
    ...
    Markup('rule1', '>links', "pattern1", "replacement1");

A call to Markup without a pattern simply creates a "placeholder"
entry for the rule in PmWiki's rule sequence, and other rules can
be set relative to that placeholder.  In fact, this is how PmWiki
creates most of the standard sequence placeholders in the first
place (pmwiki.php, line 254):

    Markup('fulltext','>_begin');
    Markup('split','>fulltext',"\n",
      '$RedoMarkupLine=1; return explode("\n",$x);');
    Markup('directives','>split');
    Markup('inline','>directives');
    Markup('links','>inline');
    Markup('block','>links');
    Markup('style','>block');

And, a recipe can always define its own inter-rule markers that
can serve as sequence anchors for other rules:

    Markup('rulemarker', '>links');
    Markup('rule1', '<rulemarker', "pattern1", "replacement1");
    Markup('rule2', '>rulemarker', "pattern2", "replacement2");

Here we're guaranteed that rule2 will always come after the 'links'
marker, and after rule1 if it happens to exist.

> What I'd like to do is
> have some permanent foundations on which to pin possibly
> temporary markup rules. 

The existing rule sequence markers are intended to be the "permanent
foundations", and recipes are intended to be able to build from
those.  They can always add their own placeholders, or supply
their idea of what a rule's sequence would be if it doesn't
already exist.

A recipe can also check to see if a rule exists by using
things like $MarkupTable['rule1'].

> I also find that things break when a
> rule changes its location in the evaluation order, affecting any
> rules on which it depends. For example, this happened to me
> when one of the core PmWiki rules moved between 2.1 and 2.2.

...and that's probably why it happened as part of a beta and
not as part of 2.1.  :-)

Hope this helps!

Pm



More information about the pmwiki-devel mailing list