Help talk:ParserFunctions/Archive 1

From Meta, a Wikimedia project coordination wiki

Happy days[edit]

Yippee! Yay! 'Oh frabjous day! Callooh! Callay!'

Ahem. Ok, so this looks wonderful. Just a couple of comments;

{{if: <condition> | <then text> | <else text> }}

Using pipes (|) as the argument separator is problematic when the <text> sections include wiki table markup (i.e. |-, |, ||) and sometimes even wiki links (i.e. [[Page name|Text to display]]). Would it be possible to use some other character to separate the arguments?

Also, does the expr function take commas into consideration? For example;

{{expr: 1,440 / 60}}

Would this evaluate to '24' or choke on the comma and need '1440' to be used instead? --CBDunkerson 16:09, 5 April 2006 (UTC)[reply]

1) Pipes are used as the argument separator for templates too, that's why it's used here. Every ASCII punctuation character has its uses in plain text. What's needed is an escaping method, or a way to change the separator. 2) It would choke on the comma. Is this a problem? Are you sure the answer should be 24, not 0.024? Commas are used in some locales as a decimal point. -- Tim Starling 17:30, 5 April 2006 (UTC)[reply]
  1. Plain text isn't so much the problem. In the cases where a specific character is needed you can just use the equivalent ascii code... it'll be converted for display purposes, but won't otherwise impact the markup. The problem with '|' is that we want it to be considered in the markup, just as 'table markup' rather than 'next argument' markup. As such, most characters other than '|' would be fairly safe and something like '\' or ':' could probably be used. Obviously, making the separator definable would work also... though I must warn you that I (or someone else) would immediately expand that into a method of performing string splitting operations.
  2. No, comma handling is not vital. I just had a thought of using things like {{expr: {{NUMBEROFARTICLES}} mod 10}} to generate a 'random' number between 0 and 9 to simplify how w:Wikipedia:Featured content picks the date of materials to display. And yes... I know I am evil. --CBDunkerson 21:34, 5 April 2006 (UTC)[reply]
We could always request a {{rand:min|max}}. =) Looking at the code in ParserFunctions.php, it looks like this would be easy to do. —Locke Coletc 04:39, 6 April 2006 (UTC)[reply]
Actually writing it yourself is even easier: User:Locke Cole/Rand/Rand.php. =) See talk page there for caveats. —Locke Coletc 05:39, 6 April 2006 (UTC)[reply]
Agree with CBD, {{if:...}} would need to allow table markup to be handled correctly to be really useful (an if: would still be useful on it's own, but it'd be more useful (a lot more) if it allowed table markup. BTW: Thank you Tim, you're awesome. =) —Locke Coletc 22:15, 5 April 2006 (UTC)[reply]
Check out template:! (edittalklinkshistory) for cases where you need a literal "|" (in wiki tables), see also Qif conditionals and its talk page. -- Omniplex (w:t) 04:09, 6 April 2006 (UTC)[reply]
There you can read: "For obvious reasons this is a high risk template, and it cannot be substituted."
MediaZilla:02777 / bugzilla:02777 – "Request for a {{substall:bar}} beside {{subst:bar}}"
One should offer a "clean" implementation from the beginning. Best regards Gangleri · Th · T 09:13, 6 April 2006 (UTC)[reply]
Yes, somebody went to the trouble to protect it on Wikipedia, probably a good idea, a template generating one character can't be improved. Conditional templates can't be substituted, and {{!}} is only relevant for conditional templates within Wiki tables. No additional problem with your substall idea, you'd get a working "!" minus the condition, so far (only templates) it 'is clean.
For the ParserFunctions/Archive 1 mixing this with {{!}} is dubious. We'd need something on the same level as {{if: x | y | z }}, and if we don't want to waste other special characters maybe {{|}} could be hardwired to generate a vertical bar everywhere. -- Omniplex (w:t) 14:30, 6 April 2006 (UTC)[reply]

I guess it replaces the templates and magicwords first isn't? So for example {{if: {{expr: {{tomorrow}} / 7}} | {{expr: {{tomorrow}} / 7}} | 7}} where TemplateTomorrow is {{expr: {{CURRENTDAY}} + 1}} would give the week day number of tomorrow and not any ugly error. Note that this template-into-template wouldn't work with current templates.

BTW. How are unrecognized expressions handled? What error message is shown?

Platonides 19:50, 5 April 2006 (UTC)[reply]

It interacts quite well with other templates, in the tests I've done. I guess we'll have a demo running soon so you can test it yourself. At present, only a generic "Invalid expression" error message is displayed on error, but this could easily change. There's already some extra information available for debugging. -- Tim Starling 04:21, 6 April 2006 (UTC)[reply]

is this running anywhere?[edit]

so we can play with it and try to port some of the current qif using templates? 130.88.171.52 00:34, 6 April 2006 (UTC) Plugwash 00:45, 6 April 2006 (UTC)[reply]

Maybe in a day or two. -- Tim Starling 04:21, 6 April 2006 (UTC)[reply]
This is now "a day or two" plus three. I say Tim go ahead and apply this parser functions now. Borgx 13:40, 9 April 2006 (UTC)[reply]
Is the code running properly already? Using MW 1.6.1 with the code and it will not really work for me. Using this in a template:
{{if:title|Title: {{{title}}}|notitle}}
 {{if:developer|Developer: {{{developer}}}|nodeveloper}}
If i leave one of the two paramaters away, it simply prints {{{title}}} as an example. My intention is to use this instead of a qif template in my own wiki. --Simon Moon 01:37, 7 April 2006 (UTC)[reply]
You should be using this I believe:
{{if:{{{title|}}}|Title: {{{title}}}|notitle}}
 {{if:{{{developer|}}}|Developer: {{{developer}}}|nodeveloper}}
Also, and Tim will know for certain, but I think this might require MW 1.7 (in other words, you might have to use something from SVN (which is what I'm using)). —Locke Coletc 01:53, 7 April 2006 (UTC)[reply]
When you think you did something wrong, you did. Thanks, tested and works fine with your example now. This works just great now. Currently i am trying some more advanced things, with calling templates inside those constructs, but this really works just great as a replacement for qif.--Simon Moon 02:11, 7 April 2006 (UTC)[reply]

Tested it, with the code above, and failed. The code works, no problem there, as well as the example above works as intended. The problems start when you try to use wiki pipe (not working because of the delimiter), html (does also not work, it converts everything inside the construct from the real tags to their html_etinities values) and templtes with variables (seem to brake also because of the delimiter). If somebody can get it to work like qif does currently work (in any possible way) please leave a note here with what you did. --Simon Moon 03:03, 7 April 2006 (UTC)[reply]

Yeah, I'd already hit upon the HTML limitation, but I hadn't tried calling a template from within it (and if what you say is true, that's bad). Without some kind of escaping, table markup will likely never work (not a major issue if HTML works, but it'd still be nice). —Locke Coletc 04:13, 7 April 2006 (UTC)[reply]
Messed around more with it, so it really is impossible to use html in templates, even if referenced, as long as its inside one of these constructs. It would be sadly, very useless if there is no possiblity to either use anything advanced (including a pipe) directly, or for that matter html (direct or in an included template). The basic goal i am trying to accomplish is to get it to write a row in a table only, if it really is needed (the field is filled with something). This basic technique is used in a ton of templates (see the qif template). I think finding a way to do this is very important, as this could lead to the removal of many of meta templates, that as far as i can read up, would be pretty big relief on the system once they are gone. --Simon Moon 05:40, 7 April 2006 (UTC) Just found an interesting discussion with a comment from Brion. There is no impact on server performance, at least none that is known of. Still, a direct parser approach is imho the better way and i will stick to this one here. --Simon Moon 05:56, 7 April 2006 (UTC)[reply]
I suspect (or really hope) that HTML at least will be allowed. BTW, I successfully called a template from within {{if:...}}, was that a problem for you still? —Locke Coletc 10:28, 7 April 2006 (UTC)[reply]
You can use a template, but HTML within that template break. To show you the exact meanings of this.

This is a Box template as i test it (calling it Box Game):

<table class="wikitable" style="width:200px; height:200px" align=right>
 <tr><td colspan="2">'''{{{title|Please fill in a Title!}}}'''</td></tr>
 {{if:{{{developer|}}}|{{Box Row|Developer:|{{{developer}}}}}}}</table>

Within that we have the template Box Row, that contains this:

<tr><td>{{{1}}}</td></td>{{{2}}}</td></tr>

Now i call the template like this:

{{Box Game
 | title = Sandbox Game
 | developer = The best Developer Ever
 }}

Which results with this as output in the pages sourcecode:

<table class="wikitable" style="width:200px; height:200px" align="right">
 <tr><td colspan="2"><b>Sandbox Game</b></td></tr>
 &lt;tr&gt;&lt;td&gt;Developer:&lt;/td&gt;&lt;/td&gt;The best Developer Ever&lt;/td&gt;&lt;/tr&gt;</table>

Of course the above html code for the developer line shows as "normal" html code on the page, like you would write it in the code to be displayed correctly, but that does not help at all really. I messed with wiki pipe for tables, but that did not work at all inside template calls. What really gets me is how simple the implementation is. Its only 7 lines of code plus a few for registering into the software. There must be a simple solution to this problem, but i have not found it yet. --Simon Moon 20:24, 7 April 2006 (UTC)[reply]

Working example of if, to replace qif, using wiki pipe[edit]

I got it to work with wiki pipe now. It is very picky about how its written. Here the working examples. Be sure to not include any spaces or empty lines, this can break it.

Template:Box Game

{| class="wikitable" style="width:400" align=right
| colspan="2"|'''{{{title|Please fill in a Title!}}}'''
{{if:{{{developer|}}}|{{Box Row|[[Developer|Developer:]]|{{{developer}}}}}}}
{{if:{{{publisher|}}}|{{Box Row|Publisher:|{{{publisher}}}}}}}
|}

Template:Bow Row

|-
| {{{1}}} || {{{2}}}

Example of how to apply it in a page:

{{Box Game
| title = Sandbox Game
| developer = Some Coders
| publisher = New Publisher
}}

Title needs always to be filled out or it prints that nice warning about filling in a title. If you leave away developer or publisher, the whole table row is left out of the loop. I also added the example of pipe link for developer. Its safe to use them there, but also directly inside the construct like this:

{{if:{{{publisher|}}}|[[Publisher|Publisher:]]{{{publisher}}}}}

The whole construct works this way as a sound replacement for qif, as long as this extension is installed.

There is a big drawback in this, when you have a lot of lines. In the above example, if you add like 10 lines with the if constructs and they are all empty, the result will be a lot of

<br>

and

<p>

tags. This can only be gotten around by putting them together on basically the same line. So right after the closing brackets of one if, the next opening brackets of the other. This looks ugly as hell in the template code, but will make the template work exactly as planed.

Double colons?[edit]

A suggestion has been made on the mailing list to require double colons for extension functions, e.g. {{if:: condition | then | else }} and {{expr:: 1 + 1}}. Vote for the syntax below:

Single colon[edit]

Double colon[edit]

Hash/Number sign[edit]

I previously suggested using {{#if…}} which would AFAICT conflict with nothing existing. It is currently rejected by the parser, would it be very difficult to make it valid? HTH HAND —Phil | Talk 11:59, 6 April 2006 (UTC)[reply]

It's not rejected by the parser when I try it. -- Tim Starling 00:19, 7 April 2006 (UTC)[reply]

Discussion[edit]

Is this necessary? I mean, I don't see the conflict between {{if:...}} and the interwiki links (which use [[xx:...]]).. or is there something I'm missing here? =) FTR, I'd prefer a single colon, but if there's some technical reason why double colons would be better, I'm open to voting for double colons. —Locke Coletc 04:28, 6 April 2006 (UTC)[reply]

You can have interwiki transclusion in MediaWiki, it's just that the feature isn't enabled. Note that there might ultimately be quite a lot of these parser functions, I suppose that's an argument for keeping the namespace separate. -- Tim Starling 05:56, 6 April 2006 (UTC)[reply]

Might there not be another approach as well, instead of the mentioned above? A pseudo namespace as with Special, containing those functions? It would be standarized in every wiki, not interfereing with any interwiki operability. Example would be to use Parse:if or Parse:expr for this. --Simon Moon 00:13, 7 April 2006 (UTC)[reply]

Division operator[edit]

Is there any objection to using div instead of / (forward slash) as the division operator? I think it would make it a bit more readable (especially when nested within template code for example). —Locke Coletc 06:09, 6 April 2006 (UTC)[reply]

I'm quite happy with forward slash. div can be a synonym if you really want. -- Tim Starling 08:23, 6 April 2006 (UTC)[reply]
That'd work I guess. =) —Locke Coletc 08:47, 6 April 2006 (UTC)[reply]

using "e" as syntax delimiter[edit]

  • What about this:
{{if: <condition> e <th&#x65;n t&#x65;xt> e <&#x65;ls&#x65; t&#x65;xt> }}<br />
example: {{if: {{satisfied}} e gr&#x65;at! e sorry! }}<br />
Yeah, very funny. If you've got any sensible suggestions for how to solve this, please speak up. We can't just change the delimiter to some other punctuation character, that would break backwards compatibility. As I keep saying, we need a delimiter declaration tag or an escaping system. -- Tim Starling 10:15, 6 April 2006 (UTC)[reply]
How would {{if: <condition> | <then text> | <else text> }} support
  1. definition of two / three table lines
  2. inclusion of templates
    1. bidirectional code like
      {{if: {{PAGENAME}}=ערשטע זײַט | הײַנט | {{א||b= demo only}}{{{mode|פּרוּװ}}} }} א
Writing everything in one line and using one delimiter reminds me about Lisp. I never got involved and my superficial knowledge dates back nearly 20 years.
Sincerly traying to find another soution Gangleri · Th · T 11:48, 6 April 2006 (UTC)[reply]
Who says it would have to be in one line? I assumed it would be possible to do;

<tr>{{if: {{{Param|}}} |<th>Header 1<td>{{{Param}}} |<th>Header 2<td>{{Template}}

}}</tr>

Note that {{NS:4}} works just fine if a line break is inserted between the ':' and '4'... so this ought to as well given that it uses the same method. Of course, that's where the issue with '|' specifically comes in since multi-line entries would allow wiki table markup... but the '|' characters used in table markup get interpreted as argument delimeters for the 'if'. Hence my suggestion of some other character... in less common use than 'e'. I'm ok using HTML, but as noted some prefer wiki table markup. Being able to define 'these pipes' as argument separators but 'these other pipes' as table markup and 'these yet other pipes' as straight text would work... but frankly seems likely to be insanely convoluted in both implementation and execution. Definable argument separators (e.g. something like {{if:\: <test>\<then text>\<else text>}}) would be great, but add a level of complexity. --CBDunkerson 16:10, 6 April 2006 (UTC)[reply]
Hang on, why are you all complaining about the use of | in table syntax? Why not just use HTML tables? -- Tim Starling 10:19, 6 April 2006 (UTC)[reply]
Certain editors think using HTML is "yucky" and "gross"... FWIW, I don't care and I think HTML is better (table syntax is evil), but if there were a way to make table syntax work with this it'd curb the complaints people sometimes make. =) To be absolutely clear, some people dislike HTML on the principle that HTML is inferior to wiki-markup table syntax. Still others dislike mixing wiki-markup table syntax with HTML (as is often done to try and make non-dynamic portions of templates simpler to read). —Locke Coletc 10:33, 6 April 2006 (UTC)[reply]
I would recommend that anyone who needs to write complex conditionals push their arguments down a level into other templates, in the best traditions of structured programming.  :-) --baylink@en.wp
I do neither complain about the usage of "|" in table syntax nor in templates, optional parameters, pipes. I would be happy to have another delimter/keywords for {{if:}}.
"We can't just change the delimiter to some other punctuation character, that would break backwards compatibility." I know Tim how painfull "migration" can be and how difficult it is not to break a live site. With Special:Whatlinkshere/template:if one can identify where this particular template is used.
For a transition time we could use two delimiters, clean the code from the pages where "|" are used and switch to the final syntax at day "Z". This might not be the "smartest" way. If you know other alternatives just let us all know about them.
Regards Gangleri · Th · T 12:02, 6 April 2006 (UTC)[reply]

reducing the costs of {{rand:}}[edit]

  • In a similar manner one could solve issues related to caching:
{{rand: <number> | <number> }}
Yeah that'd be good. Let's do that. :]
Or maybe we could implement random number logic, but restrict it to just a few pages like w:Wikipedia:Featured content (where pseudo 'randomly' selected 'featured' items are displayed currently) where it'd serve some useful purpose. No, those pages wouldn't get cached but a few 'showcase' pages which update constantly would not be a terrible strain on the servers. --CBDunkerson 16:29, 6 April 2006 (UTC)[reply]
I have no intention of making the rand function reduce the parser cache effectiveness. You can use it if you want but you'll have to run action=purge to make it change. -- Tim Starling 23:40, 6 April 2006 (UTC)[reply]
Having it generate a new number every time the page is loaded would indeed be bad. But having it generate a new random number every 15/30 minutes (or every few hours) wouldn't be so bad, would it? I found the method for disabling caching entirely, but is there a way to set an expiry period? (e.g. - use the cached results for XX minutes, after which, call me again and reset the timer, using the cached results for XX minutes, repeat). —Locke Coletc 23:49, 6 April 2006 (UTC)[reply]

hall of shame[edit]

hey sorry everybody i didn't mean to open a can of worms with the en:category:date math templates. it just kinda got out of hand. all i really wanted was to do a few timezone calculations. --Ed Poor 00:26, 7 April 2006 (UTC)[reply]

Documentation[edit]

I am pretty new to extensions here, and i would say many others are as well. So if i get this right, all this needs is to put those two files in your medawiki (in extensions clearly to make it nice) and then inclode it in the localsettings (ParserFunctions.php file of course). Right? If so, this little piece of info added would be good for the content page imho. --Simon Moon 00:29, 7 April 2006 (UTC)[reply]

Yes, that's it (and to be clear (I think you hint at this above), you only add ParserFunctions.php to LocalSettings.php, not Expr.php (but both files must be in /extensions for it to work)). I don't know if instructions would be appropriate or not and will defer to Tim on that (my gut feeling is we shouldn't include instructions; there's probably a page explaining extension installation elsewhere). —Locke Coletc 00:49, 7 April 2006 (UTC)[reply]
Changed, my Tim forgive an unexpierenced user :) --Simon Moon 01:03, 7 April 2006 (UTC)[reply]

Leap Year[edit]

Here's a slightly more advanced example of {{expr:...}}-

{{expr:((({{CURRENTYEAR}} mod 4) = 0) and (({{CURRENTYEAR}} mod 100) <> 0)) or ((({{CURRENTYEAR}} mod 100) = 0) and (({{CURRENTYEAR}}} mod 400) = 0))}}

*or*, more readable-

{{expr:
(
  (
    ({{CURRENTYEAR}} mod 4) = 0
  ) and (
    ({{CURRENTYEAR}} mod 100) <> 0
  ) 
) or (
  (
    ({{CURRENTYEAR}} mod 100) = 0
  ) and (
    ({{CURRENTYEAR}} mod 400) = 0
  )
)
}}

Locke Coletc 10:33, 7 April 2006 (UTC)[reply]

2nd part: when ({{CURRENTYEAR}} mod 400) = 0, also ({{CURRENTYEAR}} mod 100) = 0 :-) WebBoy 13:25, 7 April 2006 (UTC)[reply]

ifeq[edit]

Is ifeq case-sensitive or case-insensitive? WebBoy 13:27, 7 April 2006 (UTC)[reply]

Looks like it's case sensetive. I imagine a case-insensetive version would be possible though (similar to stricmp() in C) by using strcasecmp(). —Locke Coletc 18:08, 9 April 2006 (UTC)[reply]


Condition checks[edit]

Is that these functions have the pre-condition checks, like something didive by zero? And also, I think if possible, maybe can include some functions like log functions. Some logs maybe useful like log (base on 10), ln (base on e) and lg (base on 2), or maybe can customised buy putting a base into the function. :) --Shinjiman 00:51, 9 April 2006 (UTC)[reply]

Yup, division by zero does cause an error to be displayed (a PHP error I mean). This was fixed by changing the code in Expr.php, in function doOperation for case EXPR_DIVIDE to:
                        case EXPR_DIVIDE:
                                if ( count( $stack ) < 2 ) return false;
                                $right = array_pop( $stack );
                                $left = array_pop( $stack );
                                if ($right == 0) {
                                        $stack[] = 0;
                                } else {
                                        $stack[] = $left / $right;
                                }
                                break;
This causes it to return zero on a division by zero (and no longer displays the error message of course). It would probably be better if an error were displayed though (not a PHP error). —Locke Coletc 01:45, 10 April 2006 (UTC)[reply]

Can this be substed?[edit]

Just a side question: can templates that use these new functions be substed? I'm asking this because the templates that use en:template:qif today cannot be substed, because qif cannot be substed. Not that I am a special fan of substing - rather the opposite. Just asking... --Ligulem 22:32, 10 April 2006 (UTC)[reply]

Fairly certain the answer is yes. Though subst'ing templates (with a few exceptions anyways) is just plain silly. —Locke Coletc 00:51, 11 April 2006 (UTC)[reply]

will it go live?[edit]

Is this assumed to go live on the wikis in the next time? --::Slomox:: >< 23:38, 10 April 2006 (UTC)[reply]

<sarc>I hope so, hmm was just thinking with enough nested funtions, and logic gates, anything is possible :) </sarc> xaosflux Talk 01:51, 11 April 2006 (UTC)[reply]

It's live now. -- Tim Starling 10:01, 12 April 2006 (UTC)[reply]

Can we use white space like in template calls?[edit]

Can we use white space (space, newlines) as in template call? For example like this:

{{if:: {{{title|}}}
  | title is: {{{title}}}
  | no title was specified
}}

It would be good if the white space handling were the same as for template call, I mean please ignore white space:

  • before and after the "|"
  • before the closing "}}"
  • after the "if::"

--Ligulem 10:05, 11 April 2006 (UTC)[reply]

It seems to (currently) ignore whitespace (including line feeds) as you describe. If you haven't, you should setup a local copy of MediaWiki to play with it. (Apache is free, MySQL is (mostly?) free, MediaWiki is free; give it a try, heh). =) —Locke Coletc 10:52, 11 April 2006 (UTC)[reply]
Probably will do so, if this here has any chance to succeed. The problem is not to invent stuff like this here (Carl has already done that). Problem is to get it live :-). --Ligulem 11:13, 11 April 2006 (UTC)[reply]

note on usage of whitespace in templates[edit]

  • Please note that whitespace / new lines can breake templates:
template:vandal (below {{msgnw:template:vandal}})
<span class="plainlinks"><!--

-->{{noping|{{{1|128.0.0.1}}}}} <span style="font-size:90%;"><!-- -->([[User talk:{{{1|128.0.0.1}}}|talk]]&nbsp;• <!-- -->[[Special:Contributions/{{{1|128.0.0.1}}}|contribs]]&nbsp;• <!-- -->[[Special:DeletedContributions/{{{1|128.0.0.1}}}|deleted contribs]]&nbsp;• <!-- -->[{{fullurl:Special:Log|user={{urlencode:{{{1|128.0.0.1}}}}}}} logs]&nbsp;• <!-- -->[{{fullurl:Special:AbuseLog|wpSearchUser={{urlencode:{{{1|128.0.0.1}}}}}}} filter log]&nbsp;• <!-- -->[[Special:Block/{{{1|128.0.0.1}}}|block user]]&nbsp;• <!-- -->[{{fullurl:Special:Log/block|page=User:{{urlencode:{{{1|128.0.0.1}}}}}}} block log]&nbsp;• <!-- -->[[luxo:{{{1|128.0.0.1}}}|GUC]]&nbsp;• <!-- -->[[Special:CentralAuth/{{{1|128.0.0.1}}}|CA]])</span></span><noinclude>{{documentation}}</noinclude>

{{vandal|bar}}<br clear="all" />
----
{{vandal
|bar
}}<br clear="all" />
==== rendering ~~~~~ ====
{{subst:vandal
|bar
}}<br clear="all" />
----

generates:‎
bar (talk • contribs • deleted contribs • logs • filter log • block user • block log • GUC • CA)


[//meta.wikimedia.org/wiki/User:Bar bar ] ([[User talk:bar |talk]] • [[Special:Contributions/bar |contribs]] • [[Special:DeletedContributions/bar |deleted contribs]] • logs • filter log • [[Special:Block/bar |block user]] • block log • [[luxo:bar |GUC]] • [[Special:CentralAuth/bar |CA]])

rendering 09:14, 13 April 2006 (UTC)[edit]

[[User:bar |bar ]] ([[User talk:bar |talk]] • [[Special:Contributions/bar |contribs]] • page moves • [[Special:Blockip/bar |block]] • block log)


bugzilla:05121 – "Facilitate bidirectional editing / readability via a trailing escape character (as "\") at the end of line"

note: opened
bugzilla:05584 – "Ignore new lines inside [[ ... ]] and [ ... ]"
Gangleri · Th · T 17:33, 15 April 2006 (UTC)[reply]

Can we nest if-constructs?[edit]

For example like this:

{{if:: {{{title|}}}
  | {{if:: {{{author|}}}
      | {{{author}}}, {{{title}}}
      | {{{title}}}
    }}
  | no title was specified
}}

? --Ligulem 11:19, 11 April 2006 (UTC)[reply]

What about using ¦ instead of |?[edit]

Like this:

{{if:: <condition> ¦ <then text> ¦ <else text> }}

Could this help to prevent the parsing problems with table syntax? --Ligulem 11:24, 11 April 2006 (UTC)[reply]

I'd really prefer an US ASCII solution, typing raw UTF-8 on an OS and browser strongly believing in charsets with at most 256 characters would be a PITA. Or could I just say &brvbar; to get your UTF-8 proposal? -- Omniplex (w:t) 12:26, 11 April 2006 (UTC)[reply]
"&brvbar;" reminds me at escaping techniques. Please do not use "&brvbar;". Best regards Gangleri · Th · T 12:43, 11 April 2006 (UTC)[reply]
Well, it usually works on browsers supporting only Latin-1 or windows-1252. Actually it should work on any browser, it's a part of the HTML DTDs back to stoneage. Unfortunately that point is moot here, because the Mediawiki software destroys backwards compatibility by replacing UTF-8 for HTML 3.2 entities, except from &nbsp; or &#160; - otherwise I wouldn't be here, replacing nbsp entities would be too clueless. -- Omniplex (w:t) 18:46, 12 April 2006 (UTC)[reply]

Question[edit]

On the Wikipedia, why does this:

<u onmouseover="alert(document.cookie);">text</u>

Come out as:

Text (underlined)

But this:

 {{#if: 1=1|<|}}{{#if: 1=1|u onmouseover="alert(document.cookie);"|}}{{#if: 1=1|>|}}{{#if: 1=1|text|}}{{#if: 1=1|</u>|}}

Come out as:

 <u onmouseover="alert(document.cookie);">text  (not underlined, no "</u>")

?

All the best,
Nick.

A bit above, you can see my tries of implementing a replacement for qif. i came across teh same problem you do have now. As soon as you use html inside the if statements, it breaks. It simply displays the html special codes instead. --Simon Moon 06:53, 12 April 2006 (UTC)[reply]
Actually HTML is fixed now and seems to work. However, it appears the person above was wondering why he couldn't get an exploit to work? My guess would be that the lone < is translated into &lt;, so the HTML never properly forms. The </u> is likely removed by HTML Tidy (or MW's internal sanitizer) because of the lack of an opening <u>. This is a good thing. —Locke Coletc 06:57, 12 April 2006 (UTC)[reply]
FYI, I wanted to confirm that the exploit did not work. Also, I don't think HTML is fixed now - see below - because if it were fixed, then both should give the same output, because they are logically equivalent, whereas currently they do not. -- All the best, Nick.

text

text


Wrong result?[edit]

result of {{#if: 3+9-10|3+9 is 10|3+9 is not 10}}: 3+9 is 10

According to documentation, if the condition is 0 then it is considered false, and the else text is returned. But the according to expression above, the result returned is the then section although the condition is not 0. Borgx 08:37, 12 April 2006 (UTC)[reply]

You're using it wrong. =) Try {{#if: {{#expr:((3 + 9) = 10)}}|3+9 is 10|3+9 is not 10}}. Also, read the documentation for #if more closely. —Locke Coletc 08:42, 12 April 2006 (UTC)[reply]
) sorry, forgot the {{#expr}}. Borgx 08:44, 12 April 2006 (UTC)[reply]
That's not the #expr! A {{#if:}} is not evaluating the expression, it is just comparing the text of the first parameter value with the empty text. If it is empty, then it returns the else-string. So if you write {{#if: {{#expr: sometest}} | true-text | false-text }}, it will always return the true-text, because the result of the {{#expr}} will be a non-empty text represeting the numeric evaluation of sometest. fr:user:verdy_p

Or do:

{{#ifeq:{{#expr:3+9}}|10|3+9 is 10|3+9 is not 10}}

which gives:

3+9 is not 10

...but ...

3+7 is 10

-- All the best, Nick.

You can also use {{#if: {{#expr:3+7=10}} | 3+7 is 10 | 3+7 is not 10}} -- Tim Starling 09:41, 12 April 2006 (UTC)[reply]

Server or client?[edit]

Sorry for asking stupid question: does the computation done by Wikimedia server or by the client computer (my computer, for example) ? 134.157.5.208 08:19, 12 April 2006 (UTC)[reply]

Server. 218.215.2.197 08:42, 12 April 2006 (UTC)[reply]
Thanks, so it come to the server-client philosophy. Why we pay more for the computation on our server, when we could give the user the work load? I notice that MediaWiki have been constantly/consistently applying the rule of server computation, there must be good reasons. But I guess for simple math calculation, client computer may do it well, saving us the load on server? 134.157.5.208 08:56, 12 April 2006 (UTC)[reply]
The server needs to know the targets of links so it can register them in the database. And some clients can't do even the simplest of mathematical calculations. -- Tim Starling 09:46, 12 April 2006 (UTC)[reply]

some functions[edit]

How to implement this simple pseudocode:

if the month is April then write This is April else write This is not April

Since we can not use:

{{#if: {{CURRENTMONTHNAME}}=April|This is April|This is not April}}

Because

{{#if: {{CURRENTMONTHNAME}}=Aprils|This is April|This is not April}}

also return This is April

The only way i can think of is:

{{#if: {{#ifeq: {{CURRENTMONTHNAME}}|April|somestring|}}|This is April|This is not April}}
{{#if: {{#ifeq: {{CURRENTMONTHNAME}}|Aprils|somestring|}}|This is April|This is not April}}

How about make simple function {{#is:}} with same function as {{#ifeq:}} but returns non-empty string (character 'a' for ex) for equal condition and returns empty string for not equal condition.

So:

{{#if: {{#is: {{CURRENTMONTHNAME}}|April}}|This is April|This is not April}} will return "This is April"
{{#if: {{#is: {{CURRENTMONTHNAME}}|Aprils}}|This is April|This is not April}} will return "This is not April"
{{#if: {{#isnot: {{CURRENTMONTHNAME}}|April}}|This is not April|This is April}} will return "This is April"
{{#if: {{#isnot: {{CURRENTMONTHNAME}}|Aprils}}|This is not April|This is April}} will return "This is not April"

Borgx 09:05, 12 April 2006 (UTC)[reply]

{{#if:{{#expr:({{CURRENTMONTH}} = 4)}}|This is April|This is not April}} which produces This is April. —Locke Coletc 09:18, 12 April 2006 (UTC)[reply]

Locke Cole, thanks for the answer, but I was refered to string comparison in general. Borgx 09:24, 12 April 2006 (UTC)[reply]

Okay, if you want to do the string compare, try {{#if:{{#ifeq:{{CURRENTMONTHNAME}}|April|1}}|This is April|This is not April}}
  • {{#if:{{#ifeq:{{CURRENTMONTHNAME}}|April|1}}|This is April|This is not April}} produces This is April
  • {{#if:{{#ifeq:{{CURRENTMONTHNAME}}|Aprils|1}}|This is April|This is not April}} produces This is not April
We return "1" on a match so #if will equate it to "true". —Locke Coletc 09:31, 12 April 2006 (UTC)[reply]
What's wrong with {{#ifeq: {{CURRENTMONTHNAME}}|April|This is April|This is not April}}? -- Tim Starling 09:33, 12 April 2006 (UTC)[reply]
Nothing actually, I assumed from the complexity of the examples that Borgx was looking for something.. complicated. :P I was probably wrong. =) —Locke Coletc 12:39, 12 April 2006 (UTC)[reply]

Trial implementations[edit]

I've been rewriting the hideously complex logic code behind the Vietnamese Wikipedia's front page to use this extension's syntax instead, wherever possible. You can clearly see the difference at some of the transcluded templates, and it's working like a charm. [1] [2] I've also started to port some of the more generic logic templates to the new syntax. [3]

Someday I'll try and tackle that notorious language infobox. *shakes head in utter amazement*

 – Minh Nguyễn (talk, contribs) 09:31, 12 April 2006 (UTC)[reply]

In [4], instead of {{#if: {{{1|{{CURRENTWEEK}}}}} + 52 - 1 > 52 |{{#expr: ({{{1|{{CURRENTWEEK}}}}} + 52 - 1) mod 52}}|{{#expr: {{{1|{{CURRENTWEEK}}}}} + 52 - 1 }}}}, can't you just use {{#expr: ({{{1|{{CURRENTWEEK}}}}} + 51) mod 52}}? -- Tim Starling 10:00, 12 April 2006 (UTC)[reply]
I don't think so, because this segment of the code is used to determine which week's featured article to link to. During Week 1, the template is supposed to link to the articles for Weeks 50, 51, and 52. Simply modding the week number will make it link to Week 0, which doesn't exist. Then again, I'm horrible at math, particularly with mods, so I probably did miss several ways to make it more efficient. – Minh Nguyễn (talk, contribs) 10:31, 12 April 2006 (UTC)[reply]
I think should work:
1 week before
{{#expr: ({{{1|{{CURRENTWEEK}}}}} + 50) mod 52 + 1}} (16)
2 weeks before
{{#expr: ({{{1|{{CURRENTWEEK}}}}} + 49) mod 52 + 1}} (15)
3 weeks before
{{#expr: ({{{1|{{CURRENTWEEK}}}}} + 48) mod 52 + 1}} (14)
-- Tim Starling 10:58, 12 April 2006 (UTC)[reply]
Alright, thanks a lot! – Minh Nguyễn (talk, contribs) 11:28, 12 April 2006 (UTC)[reply]

whitespace handling[edit]

User:Ligulem/if-test-1 contains:

{{#if: {{{a|}}}|param a has value {{{a}}}}}

User:Ligulem/if-test-2 contains:

{{#if: {{{a|}}}
  | param a has value {{{a}}}
}}

(1) *-{{User:Ligulem/if-test-1|a=val_a}}- produces:

  • -param a has value val_a-

which is fine, but

(2) *-{{User:Ligulem/if-test-2|a=val_a}}- produces:

  • -param a has value val_a-

this is different behaviour as in en:template:qif, which ignores whitespace (general template param behaviour). How can I achieve the same as with qif, without having to write the whole template code on a single line? Writing the the whole m:template:cite book on a single line is a bit tough. --Ligulem 12:45, 12 April 2006 (UTC)[reply]

Ok. I can use comments:
User:Ligulem/if-test-3 contains:
{{#if: {{{a|}}}
  |param a has value {{{a}}}<!--
-->}}
*-{{User:Ligulem/if-test-3|a=val_a}}- then produces
  • -param a has value val_a-
--Ligulem 12:51, 12 April 2006 (UTC)[reply]
I can have it trim whitespace, but are you sure that's what you want? It means you won't be able to use #if to insert spaces or line breaks. -- Tim Starling 12:58, 12 April 2006 (UTC)[reply]
For spaces, they could use &#32; (or if it's hex, I always mix it up, &#20;) couldn't they? Linespaces with BR? (not optimal, I agree). —Locke Coletc 13:00, 12 April 2006 (UTC)[reply]
Tim, you are right. Leave it as it is. It can well be that this is better than with qif. With qif we had to do &32; for example to insert a space (as Locke writes above). --Ligulem 13:08, 12 April 2006 (UTC)[reply]
Please trim the whitespace as offered. Substituting this new function for {{qif}} without having the whitespace trimmed in the same way as for template parameters will make it much more difficult to produce legible wikitext. Also there should be no real reason why anybody should need to use this function to introduce line-breaks: if a simple space using is not suffucient then use <br />. HTH HAND —Phil | Talk 13:34, 12 April 2006 (UTC)[reply]
There's also some interaction with "*" lists; see w:User:Phil Boswell/cite book regression tests where I have simply substituted {{qif|test=…|then=…|then=…}} with {{#if:…|…|…}} and the white-space suddenly introduced has thoroughly broken the template. HTH HAND —Phil | Talk 13:39, 12 April 2006 (UTC)[reply]
Tim has done the trimming [5]. Thanks to Tim! --Ligulem 14:31, 13 April 2006 (UTC)[reply]

#ifexpr[edit]

This was something I suggested on IRC, and just wanted to document here. #ifexpr is a proposal to wrap together a call to #if and #expr in one single call. So instead of--

{{#if: {{#expr:((10 + 1) = 11)}} | 10 + 1 is 11 | 10 + 1 is not 11}}

you'd do this

{{#ifexpr: ((10 + 1) = 11) | 10 + 1 is 11 | 10 + 1 is not 11}}

The syntax would be this--

{{#ifexpr: <expression to be tested> | <true text> | <false text>}}

Your expression in #ifexpr would need to result in zero (or blank) to be considered false, and result in non-zero to be considered true. This would help reduce the complexity (and nesting) of these calls.

Thoughts? —Locke Coletc 13:04, 12 April 2006 (UTC)[reply]

Yes, seems like a good idea to me. In fact, it's actually what I originally thought the new #if construct did, and it was only after reading the docs, because I was not able to get it to work that way, that I realised it was different. So yes, I'd support this. -- All the best, Nickj. 02:22, 13 April 2006 (UTC)[reply]
I'm not sure, folks would try expressions not always resulting in 1, 0, or void. -- Omniplex (w:t) 19:49, 13 April 2006 (UTC)[reply]
Anything non-zero would be true (just as the case is now with #if). —Locke Coletc 20:36, 13 April 2006 (UTC)[reply]
That would be neither zero nor void, not the same logic as {{qif}} and other Parameter default tricks, but no problem for me. Further down somebody's unhappy with a defined 0, our mixture of ideas adapted from LISP, C, and what else can be explosive. -- Omniplex (w:t) 22:09, 13 April 2006 (UTC)[reply]

#switch[edit]

The #if function seems to work a treat. Could we possibly also have #switch as per {{en:template:switch}}? Currently usage is as follows:

{{switch
 |VALUE-TO-BE-TESTED
 | case: bar=hello
 | case: bar=world
 | default=Neither ''bar'' nor ''bar''
}}

where VALUE-TO-BE-TESTED is a parameter or a variable

Constraints
  • The variable to switch have some constraints because the value must be able to be used as a parameter name.
    • Characters known not to work are: =|
    • There mustn't be any space between the pipe character and the first character.
  • There is no fall-through (if you look at the code, you know why).
  • If default is not defined, the result if no value matches will be blank.

The same constraints would apply with any luck, making it easy to convert. You might want to consider obviating the "case:" construct. HTH HAND —Phil | Talk 14:52, 12 April 2006 (UTC)[reply]

Suggested syntax[edit]

 {{#switch: ''VALUE-TO-BE-TESTED''
  | bar=hello
  | bar=world
  | Neither ''bar'' nor ''bar''
 }}

I'm having some difficulty deciding how to specify the default condition: any suggestions? HTH HAND —Phil | Talk 15:29, 12 April 2006 (UTC)[reply]

Personally I think we should keep the "case:" bit (which would also make it easier to come up with that "default" condition). Syntax would be:
 {{#switch: ''VALUE-TO-BE-TESTED''
  | case: bar=hello
  | case: bar=world
  | default: Neither ''bar'' nor ''bar''
 }}
Only the first colon would be significant as a delimeter/separator, so you'd still be able to use colons in the return value for example (same for the equal sign; only the first equal sign would be significant). For the default case, there would be no equal/test value. I do absolutely believe a switch construct is necessary though, otherwise we'll end up with nested #if's (assuming we want to ditch the switch template). —Locke Coletc 22:19, 12 April 2006 (UTC)[reply]
Actually, let's expand this a bit. One of the things that bugged me about the Switch template was that there was no way to do fall-through. So how about, if there's NO equal sign, it "falls through" until it finds a case with an equal sign? Here's an updated syntax:
 {{#switch: ''VALUE-TO-BE-TESTED''
  | case: bar
  | case: bar=hello
  | case: baz=world
  | default: Neither ''bar'' nor ''bar'' nor even ''baz''
 }}
Note here that if "foo" is a match to VALUE-TO-BE-TESTED, it falls through to "case: bar=hello". Note also that you should be able to fall-through to the "default:" case as well. —Locke Coletc 00:59, 13 April 2006 (UTC)[reply]
"Fallthrough" in an inherently functional (i.e. non-procedural) language seems counter-intuitive to me. What you're implementing here is a general function on a finite domain, not a procedure. I'm voting for Phil's original suggestion. -- Tim Starling 10:59, 13 April 2006 (UTC)[reply]
I wonder if what LC actually wants is to be able to specify the same outcome for two or more values without duplicating the result? So in the above, the desired result is "hello" when the input value is "foo" OR "bar", "world" if it is "baz" and the extended message otherwise. This interpretation is more appropriate to a functional language and would seem to be useful. HTH HAND —Phil | Talk 11:16, 13 April 2006 (UTC)[reply]
Exactly. —Locke Coletc 11:35, 13 April 2006 (UTC)[reply]
The two concepts are equivalent, yes. But the syntax Locke Cole suggested seems to be guided by the procedural concept, not the functional one. -- Tim Starling 03:59, 14 April 2006 (UTC)[reply]

Personally, I've never understood the purpose of the : after case; it seems superfluous. How about:

 {{#switch: ''VALUE-TO-BE-TESTED''
  | case bar=hello
  | case bar=world
  | default=Neither ''bar'' nor ''bar''
 }}

Using this syntax, fallthrough would be more intuitive to express:

 {{#switch: ''VALUE-TO-BE-TESTED''
  | case bar|case bar=hello
  | case baz=world
  | default=Neither ''bar'' nor ''bar'' nor even ''baz''
 }}

Or, simplified even more:

 {{#switch: ''VALUE-TO-BE-TESTED''
  | case bar|bar=hello
  | case baz=world
  | default=Neither ''bar'' nor ''bar'' nor even ''baz''
 }}

--Algorithm 23:13, 13 April 2006 (UTC)[reply]

Locke's proposed syntax[edit]

Actually, the more I think about it, the more I like Phil's proposal, but with two minor modifications--

 {{#switch: ''VALUE-TO-BE-TESTED''
  | bar
  | bar=hello
  | baz=world
  | =Neither ''bar'' nor ''bar'' nor even ''baz''
 }}

The modifications are: 1) Change to how the default case is reached (the "=" (equal sign) at the beginning of the line). 2) Fallthrough support (detected by the lack of an equal sign). This also has the advantage of being consistant with #if (which, unlike qif, doesn't have "test", "then", or "else"). Thoughts? —Locke Coletc 23:47, 13 April 2006 (UTC)[reply]

Only problem I can see is that you can't set "" as any value other than the default. Very clean, though. --Algorithm 01:07, 14 April 2006 (UTC)[reply]
Sounds quite reasonable to me, although I'll be maintaining that it's really a method for giving the same result for two different inputs rather than "fallthrough", formatting my #switch statements like this to make the point:
 {{#switch: ''VALUE-TO-BE-TESTED''
  | bar|bar = hello
  | baz = world
  | = Neither ''bar'' nor ''bar'' nor even ''baz''
 }}
I'm not sure about the default syntax but I guess if nobody can think of a better idea then I'll implement it. -- Tim Starling 04:35, 14 April 2006 (UTC)[reply]
from [Wikitech-l] ParserFunctions trial
{{#switch: VALUE-TO-BE-TESTED
 | bar|bar|bla|more = hello
 | baz = {{# world }}
 | = Neither ''bar'' nor ''bar'' nor ''bla'' nor ''more'' nor even ''baz''
}}
More details at section [[#{{# <wikisyntax> }}|{{# <wikisyntax> }}]]. Gangleri · Th · T 11:07, 14 April 2006 (UTC)[reply]

Default construct[edit]

Ok, we take Locke's syntax, and change it a bit:

{{#switch: VALUE-TO-BE-TESTED
 | bar|bar|bla|more = hello
 | baz = world
 | Neither ''bar'' nor ''bar'' nor ''bla'' nor ''more'' nor even ''baz''
}}

What I have done is that I removed the equal sign for the default construct. The idea is this: If the last section doesn't constain an equal sign, than that's a default construct. This I assume is totally disambigious, because the last section can not fall throught to a next section. This will enable for examples with a check for an empty parameter. AzaToth 22:47, 15 April 2006 (UTC)[reply]

Perhaps this would work as a switch hook (I havn't tested it, I just wrote it on the fly):

    function switchHook(&$parser){
        $args = array_slice(func_get_args(),1);
        $test = trim(array_shift($args));
        $default = "";
        $fallthrough = false;
        if(!strpos($args[-1],"="))
            $default = trim($args[-1]);
        while($arg = array_shift($args)){
            if(strpos($arg,"=")){
                list($key,$value) = explode($arg,"=",1);
                if($test == trim($key) || $fallthrough)
                    return trim($value);
            }
            elseif(trim($arg) == $test)
                $fallthrough = true;
        }
        return $default;
    }

AzaToth 16:00, 16 April 2006 (UTC)[reply]

A comment of the code to Tim, why is there a $&parser passed to the functions? no functions seems to used it. AzaToth 17:44, 16 April 2006 (UTC)[reply]
No functions use it yet. Experience has taught us that if we don't pass that parameter, extension writers will use globals instead of the current context object, thus breaking all sorts of things. -- Tim Starling 11:05, 17 April 2006 (UTC)[reply]
Question: could we make sure that we do not use newlines as a syntax element (as in the Manske tables)? So now: are the proposed syntaxes for switch such that switch constructs can theoretically be written on a single line (or all tokens on a separate line for the other extreme)? I think this would be good (I haven't checked that myself, I'm asking the inventors). --Ligulem 17:44, 16 April 2006 (UTC)[reply]

Personally, I think it's a bad idea in general to exclude any ASCII character that doesn't have to be. "|" is already lost, but there's no reason to exclude "=" or newlines. AzaToth, your example is very clean, but it requires that the default argment NEVER contain an "=", which rules out putting HTML in the default position. I think that we either need to go with Locke's idea, or keep the "case/default" structure we had earlier; e.g.:

 {{#switch: ''VALUE-TO-BE-TESTED''
  | case bar|bar=hello
  | case baz=world
  | default=Neither ''bar'' nor ''bar'' nor even ''baz''
 }}

--Algorithm 20:00, 17 April 2006 (UTC)[reply]

Yes, this is why I kept the = for the default case. Only the first equal sign is significant, others are ignored. While I dislike the problem with never being able to "switch" against an empty parameter, that can be handled easily enough with a #ifeq before the switch (and I suspect matching against empty will be fairly rare). —Locke Coletc 07:43, 18 April 2006 (UTC)[reply]

You know what, scratch that. AzaToth's code is the simplest and most efficient, PROVIDED THAT the {{#: ... }} construct is implemented. I've got some thoughts on how to implement it, which I'll put in the below section. --Algorithm 23:22, 18 April 2006 (UTC)[reply]

testing for string non-emptyness[edit]

I am trying to do something like:

{{#if: {{#expr: {{{a|}}} or {{{b|}}} }} |a or b is not empty}}

which I mean to be that the then-string ("a or b is not empty") should be emitted if a or b are not empty (of course it doesn't work like that). How can I achieve that? Do we need a new operator for #expr to achieve this? For example "nonempty"?

{{#if: {{#expr: nonempty({{{a|}}}) or nonempty({{{b|}}}) }} |a or b is not empty}}

please consider also the "and" example:

{{#if: {{#expr: nonempty({{{a|}}}) and nonempty({{{b|}}}) }} |a and b is not empty}}

Things like that are quite common. See for example en:template:booland of en:Category:Boolean templates. --Ligulem 16:51, 12 April 2006 (UTC)[reply]

You do it like this: {{#if: {{{a|}}}{{{b|}}} || a or b is not empty}} -- Tim Starling 18:42, 12 April 2006 (UTC)[reply]
Yes, I know this transformation (we have done this with the weeble) trick. This is for the "or" case. BTW, it must be like this: {{#if: {{{a|}}}{{{b|}}} |a or b is not empty}}. The 'and' case can be done by nesting. --Ligulem 21:15, 12 April 2006 (UTC)[reply]

But how would you do that: I need a template that has two parameters a and b. if a or b or both are empty, the template should emit the string "a and b must both be nonempty" and the empty string in all other cases. The pseudo-code would be:

if (not(nonempty(a) and nonempty(b))) {
  return "a and b must both be nonempty"
}

--Ligulem 21:15, 12 April 2006 (UTC)[reply]

I guess I found a solution. User:Ligulem/if-test-5 contains:
{{#if: {{#if: {{{a|}}} | {{#if: {{{b|}}} |1}}}} ||a and b must both be nonempty}}
*-{{User:Ligulem/if-test-5}}- gives
  • -a and b must both be nonempty-
*-{{User:Ligulem/if-test-5|a=xx}}- gives
  • -a and b must both be nonempty-
*-{{User:Ligulem/if-test-5|b=yy}}- gives
  • -a and b must both be nonempty-
*-{{User:Ligulem/if-test-5|a=xx|b=yy}}- gives
  • --
Anyone a better idea? --Ligulem 21:42, 12 April 2006 (UTC)[reply]
Not a better idea (currently anyways), but this might be a bit cleaner if #ifexpr were available:
{{#ifexpr:({{#if:{{{a|}}}|1|0}} and {{#if:{{{b|}}}|1|0}})||a and b must both be nonempty}}
Locke Coletc 22:26, 12 April 2006 (UTC)[reply]
Ah. Looks nicer yes. This strongly smells like another m**a-template {{nonempty|{{{a|}}}}} containing {{#if:{{{1|}}}|1|0}}. I can already hear the hooting...:-) --Ligulem 23:24, 12 April 2006 (UTC)[reply]
OH NOES, NOT META-TEMPLATES! ;) But yes, barring an extension function, it seems like a reasonable meta-template to me. —Locke Coletc 03:01, 13 April 2006 (UTC)[reply]

Notes on syntax[edit]

  • Why is the "trailer" "deprected" in the sixth example?
# "{{#if: always | yes is yes | no is no }}"
# "{{#if: always |  yes is yes  |  no is no  }}"
# "{{#if: | yes is yes | no is no }}"
# "{{#if: |  yes is yes  |  no is no  }}"
# "{{#if: ||  no is no  }}"
# "{{#if: ||  no is no  | trailer as table code}}"
# "{{#if: ||  no is no
multi line text<br />
...
}}"
# "[[{{#if: always | yes is yes | no is no }}]]"
# "[[talk:{{#if: always | yes is yes | no is no }}|{{#if: always | yes is yes | no is no }}]]"
# "[[{{#if:
always
| yes is yes
| no is no
}}]]"
# "[[user:{{#if:
always
| yes is yes
| no is no
}}|{{#if:
always
| yes is yes
| no is no
}}]]"

generates:‎

  1. "yes is yes"
  2. "yes is yes"
  3. "no is no"
  4. "no is no"
  5. "no is no"
  6. "no is no"
  7. "no is no

multi line text
..."

  1. "yes is yes"
  2. "yes is yes"
  3. "yes is yes"
  4. "yes is yes"


I would say the result of {{#if: || no is no | trailer as table code}} is not specified (erroneous use). As such the implementation may emit what it pleases. And what it does is fairly reasonable. But I fear I have not understood what you want to tell with that testcase. --Ligulem 22:04, 12 April 2006 (UTC)[reply]
The example is using an empty <then text>. If you look carefully at the syntax, the start, the expression, the delimiters and the fields inbetween and compare with the result you may see that you will not be able to generate "reasonable table code" with the <else text>. It is simply "blocked". Gangleri · Th · T 23:39, 12 April 2006 (UTC)[reply]
Yes. I believe I have understood that there is an empty "then-text" in {{#if: || no is no | trailer as table code}}, due to the "||". Because ParserFunctions uses "|" as a syntax element, ParserFunctions cannot be used for Manske tables (tables using the "|" as a syntax element). This is by design. This has already been said. --Ligulem 07:30, 13 April 2006 (UTC)[reply]
Here's a working example (I hope, actually a test):
	# "{{#if: always | yes is yes {{!}} no is no }}"
	# "{{ifdef | 0 | empty is empty {{!}} 0 is 0 }}"
	# "{{#if: || no is no }}"
	# "{{ifdef || isn't ifndef }}"
	# "{{#if: || no is no {{!}} trailer as table code }}"
  1. "yes is yes | no is no"
  2. " empty is empty | 0 is 0 "
  3. "no is no"
  4. ""
  5. "no is no | trailer as table code"
Not pretty, but does the trick. For an #if: without else {{ifdef|test|then}} is very similar (for a void test, not for 0), and probably not slower than #if:, so maybe check out ifdef for your purposes if you want to avoid the layer violation. -- Omniplex (w:t) 04:57, 13 April 2006 (UTC)[reply]
  • Thanks Omniplex for your suggestion! However I feel that a clean implementation should be implemented correctly and should not require "workarounds" of any kinds.
  • If you take a look at Parser.php?revision=13540 and search for "# Split template arguments" you will find
"function getTemplateArgs( $argsString )"
  • There you will see also the
"$args = explode( '|', substr( $argsString, 1 ) );"
  • However "$args" is smart enough to handle the "|" pipe character(s) if it is / they are inside "[[" and "]]". Remember that "|" is used also in image syntax.
  • What seems to be odd (compare with ParserFunctions.php) is that only a part of the code is transfered to
"function ifHook( &$parser, $test = '', $then = '', $else = '' )"
"function ifeq( &$parser, $left = '', $right = '', $then = '', $else = '' )"
  • Whatever code exists after the first "|" character in the <else> part is lost. With other words {{#if: ...}} and {{#ifeq: ...}} are processing only a part of the code. Best regards Gangleri · Th · T 08:57, 13 April 2006 (UTC)[reply]
We can probably quibble over this for ages, but the #if: as is with three arguments test + then + else behaves consistently with ordinary templates taking three parameters: A fourth or later parameter is ignored. Allowing extraneous vbar only in else but (of course) not in then would be confusing - this stuff is supposed to work for cluelesss users.
I'd support a kludge if we split it in a hypothetical #idef: and #ifndef:, both with two arguments test + then, the latter supporting extraneous vbars. Your proposal to support it in else and not then is against my basic design instincts. -- Omniplex (w:t) 19:34, 13 April 2006 (UTC)[reply]
re: "Allowing extraneous vbar only in else but (of course) not in then would be confusing - this stuff is supposed to work for cluelesss users."
I agree that it is not symmetrical. The proper solution would be a selfexplanatory then and a selfexplanatory else. Gangleri · Th · T 23:37, 13 April 2006 (UTC)[reply]
Your later (see below) proposal {{#: what|ever}} is better than anything we discussed here. -- Omniplex (w:t) 01:05, 16 April 2006 (UTC)[reply]

minimal multiline RTL compatibility test[edit]

  • looks OK
׳{{#if:
שטענדיק
| יאָ יז יאָ
| נײן יז נײן
}}׳
----
׳{{#if:
|| נײן יז נײן
}}׳

generates:‎
׳יאָ יז יאָ׳


׳נײן יז נײן׳

What means "RTL"? --Ligulem 22:08, 12 April 2006 (UTC)[reply]
"right to left" script see RTL: "Right-to-left writing, as applied in Arabic and Hebrew. See Bi-directional text and Writing system." Gangleri · Th · T 23:44, 12 April 2006 (UTC)[reply]

subst variant 19:48, 12 April 2006 (UTC)[edit]

  • looks OK
׳{{subst:#if:
שטענדיק
| יאָ יז יאָ
| נײן יז נײן
}}׳
----
׳{{subst:#if:
|| נײן יז נײן
}}׳

generates:‎
׳יאָ יז יאָ׳


׳נײן יז נײן׳

asymmetry between expression parts and result parts[edit]

  • If you look closer at the syntax you might discover the asymmetry between expression parts and the result parts. The expression parts may contain the "( )" "Grouping operators" but the result parts lack such "meta" constructs ("begin" / "end, "{" / "}" etc.). The "result parts" end at the "hardwired" pipe chacater; as shown above this aplies also for the "<else text>" without any need.
  • My objections are not theoretical. The actual syntax can not be used to generate conditional wikitable syntax as optional table lines, variable table subdivisions etc. Gangleri · Th · T 20:11, 12 April 2006 (UTC)[reply]

I'm wondering if it might be better to use the HTML syntax for tables in these cases, anyhow. As the wikitable syntax and the ParserFunctions syntax use a similar set of characters (not to mention the template syntax), the HTML table syntax might serve to create less confusion and make the templates easier to manage. Some of the code I've written at Wikipedia has an uncanny resemblance to Lisp, as it uses a very limited set of characters for everything under the Sun, except that it's all written on one line.

I know that using the HTML syntax isn't really an answer to the objections you've brought up, but it might be more useful, since it'd be a lot easier to spot the HTML syntax in en:Template:Infobox Language, for example.

 – Minh Nguyễn (talk, contribs) 03:09, 13 April 2006 (UTC)[reply]

FWIW, I prefer pure XHTML for the most part as well. It's, IMO, easier to pick out the conditionals (and other template calls) in XHTML than it is to pick it out in table syntax. —Locke Coletc 03:32, 13 April 2006 (UTC)[reply]

Plus, I've also seen a lot of infoboxes that use meta-templates just because no one thought to use XHTML. Since you can actually mix XHTML table syntax with wikitable syntax, it's just inexcusable in some of these cases. – Minh Nguyễn (talk, contribs) 07:08, 13 April 2006 (UTC)[reply]

Mediawiki is trying to promote its own table syntax. For myself I can tell that it took a while to get familiar with it. When working on an issues I would like to focus an that topic without taking care of all the "workarounds" required to implement what I was intended to do. This is why it should be still possible that anybody could use the table syntax of his / her choice. Gangleri · Th · T 10:54, 13 April 2006 (UTC)[reply]
  • It should be fair to say that "{{" ... "}}" can be used as "Grouping operators". However I feel that this complicates issues and "nesting" makes the syntax less legible as it could be. For every instance of "{{#if: ...}}" / "{{#ifeq: ...}}" one or two additional templates would be required 'template:.../then' and / or 'template:.../else'. Personaly I see no simplification using these. Gangleri · Th · T 10:54, 13 April 2006 (UTC)[reply]
I just remembered
bugzilla:02777 – "Request for a {{substall:bar}} beside {{subst:bar}}"
which would conflict with "{{" ... "}}" as substitute for "Grouping operators". Gangleri · Th · T 01:01, 14 April 2006 (UTC)[reply]

AND, OR, and XOR[edit]

Why are And and OR just logical ops instead of binary ops? Like "111 AND 101 == 101" in C++ or PHP, here they should be implemented in C++ standard. Furthermore, XOR is also a needed op for completeness sake. 67.15.34.251 05:26, 13 April 2006 (UTC)Upssdr 04:45, 15 April 2006 (UTC)[reply]

XOR is proposed further up on this page (and I suspect Tim will add it soon). Regarding binary ops, the way it's implemented, I don't even know if that'd be (easily) possible. It'd be (sort of) nice to have, but I don't know if it'd be worth the effort. —Locke Coletc 05:39, 13 April 2006 (UTC)[reply]
I mean those bit operators. It just take a few changes in expr.php. Like:
case EXPR_AND:
  if ( count( $stack ) < 2 ) return 'missing_operand';
  $right = array_pop( $stack );
  $left = array_pop( $stack );
  $stack[] = ( $left && $right ) ? 1 : 0;

Changing the "( $left && $right ) ? 1 : 0" into "$left & $right" is just okay. 67.15.34.251 05:26, 13 April 2006 (UTC)Upssdr 04:45, 15 April 2006 (UTC)[reply]

Why does everyone seem to think that adding XOR will make it complete? What about NAND and NOR? Logical XOR isn't implemented in C, probably because it's equivalent to conversion to boolean followed by inequality, i.e. A xor B := (A=0) != (B=0). So it's rather redundant. Bitwise operators are useful in programming, e.g. for manipulation of bitfields, but I fail to see any application in the context of writing articles. There are thousands of mathematical functions that I haven't implemented in this package, I don't understand why you would think the bitwise operators are the most significant omission. Why aren't you suggesting functions that actually have an application on Wikipedia, such as time and date functions? -- Tim Starling 10:41, 13 April 2006 (UTC)[reply]
IIRC you'd only need NAND, anything else can be built using it. XOR doesn't have this propoerty. We'd need BITXOR when we get bit operators. After some minor obstacles like Wikimedia world dominance... :-) -- Omniplex (w:t) 20:12, 13 April 2006 (UTC)[reply]

xor[edit]

I posted this on Wikipedia:Village pump, but wanted to mention it here as well. While I can't see any use for it right now, for completeness sake, it would be nice if xor were added to the logical operators. In keeping with and, or and not, I would also propose it use the word xor (as opposed to ^ if we were to use the C syntax). —Locke Coletc 09:15, 8 April 2006 (UTC)[reply]

Second that, it actually does have its uses. Shouldn't be to haard to add anyways, looking at the code. --Simon Moon 09:27, 8 April 2006 (UTC)[reply]
Logical xor is equivalent to inequality, see above. -- Tim Starling 04:38, 14 April 2006 (UTC)[reply]
No. With logical xor one condition may be true (one true, one false; one false, one true), but not both (false, false; true, true). See exclusive or (specifically, see the truth table under the TOC). And FWIW, PHP does have an "xor" operator you can use for this purpose. —Locke Coletc 05:24, 14 April 2006 (UTC)[reply]
Let me spell it out for you.
A B A equals B A xor B
0 0 1 0
0 1 0 1
1 0 0 1
1 1 1 0
Notice any similarities between the third and fourth columns? -- Tim Starling 09:20, 14 April 2006 (UTC)[reply]
You're right. Don't know why I didn't catch that the first time. —Locke Coletc 09:30, 14 April 2006 (UTC)[reply]
XOR is always useful and pre-defined operator in any programming language. Also NAND or NOR will not appear in any programming language. But I think Tim tells something fundamental to Wikipedia: any new features must help to Wikipedia. I'm just someone desiring Tim to develop a C++ compiler with PHP. :) Upssdr 04:45, 15 April 2006 (UTC)[reply]

Give a few more infomation in error message[edit]

I suppose if the position of error occurring is given, debugging will be much more conveniet especially in some long expressions, or it's better to return the source with error in bold. This is also easy to implement. Just add "$p" in expr.php after returning error message. Like:

case EXPR_AND:
  if ( count( $stack ) < 2 ) return 'missing_operand';

return 'missing_operand' to 'missing_operand "$p"' and add a few handling functions in ExprParser->error() or ExtParserFunctions->expr(). 67.15.34.251 05:59, 13 April 2006 (UTC)Upssdr 04:55, 15 April 2006 (UTC)[reply]

The position within the string isn't known at the time doOperation() is called because it isn't stored in the stack. In an expression like "2*2+3", $p points to the 3 when the multiplication is evaluated. -- Tim Starling 10:12, 13 April 2006 (UTC)[reply]
I made a terrible mistake. But the technical detail doesn't matter. It's just nice to reveal the error position for developer. You can add new lines after those 'Expression error': <br/>Error in bold: strtr( $expr, '$expr[$p]', '<b>$expr[$p]</b>') ). Upssdr 04:55, 15 April 2006 (UTC)[reply]

#nowiki:[edit]

I was thinking about something that would strip [[Wiki Markup]] out of a variable (resulting in Wiki Markup), so I decided to go ahead and try it: {{#nowiki:[[This is a random snippet]] of Wikimarkup.}} Results in: This is a random snippet of Wikimarkup.

It'll strip:

[[Links]] (as Links)
[[Piped|Links]] (as Piped)
{{Templates}} (as Templates)
{{Templates|With pipes}} (as Templates)
[www.external.com Links] (as Links)
__NOEDITSECTION__ (as null)
''Italic'' (as Italic)
'''Bold''' (as Bold)
'''''Bold italic''''' (as Bold italic)
<!-- Comments --> (as Comments)

This is the code. Thoughts? There's still an issue with table markup that I haven't sorted out. Jude(talk,contribs) 09:39, 13 April 2006 (UTC)[reply]

I can see how this might well be useful in several places. Just a couple of points:
  • should [[Link|Title]] be rendered as Link or as Title?
  • Should the comments be stripped out entirely, rather than simply removing the tags?
HTH HAND Phil | Talk 12:13, 13 April 2006 (UTC)[reply]
Hm. Both matters of personal preference, I think, though I agree that comments are likely not meant to be seen, it would probably be better to just strip them out entirely. I'll update the code. :-) Jude(talk,contribs) 12:25, 13 April 2006 (UTC)[reply]
Something like msgnw: skipping <noinclude> sections would be very interesting. Just in case if you're looking for new ideas, msgnw: is nice for a template docu, but not if the template has long parts which are never included. -- Omniplex (w:t) 22:21, 13 April 2006 (UTC)[reply]

usage restrictions because of other bugs[edit]

{{#ifeq: {{lc:{{{namespace}}}}} | || {{#ifeq: {{lc:{{{namespace}}}}} | image |:image: | {{#ifeq: {{lc:{{{namespace}}}}} | category |:category: | {{lc:{{{namespace}}}}}: }} }} }}
[[{{inline|namespace=category}}foo]]
----
[[{{subst:inline|namespace=category}}foo]]

generates:‎
[[

category:foo]]

[[

category:foo]]


bugzilla:05121[edit]

bugzilla:05121 – "Facilitate bidirectional editing / readability via a trailing escape character (as "\") at the end of line"

{{#ifeq: {{PAGENAME}} |ערשטע זײַט | הײַנט | {{א||b= demo only}}{{{mode|פּרוּװ}}} }} א

generates:‎
אפּרוּװ א

  • For better readybility it would be helpfull to write this as
{{#ifeq:\
{{PAGENAME}}\
|ערשטע זײַט\
|הײַנט\
|\
{{\
א\
|\
|b= demo only\
}}\
פּרוּװ\
}}\
 א
  • Note that the last line starts with a "heading" space which displays here at the right.
  • When you want to edit this go to the "end of lines" (trust your browser: position the cursor in a line and press the <end of line>-key; you will be at the the right position regardless where you will "see" the cursor) and delete both the "\" and the "end of lines". Then you get this:
{{#ifeq:{{PAGENAME}}|ערשטע זײַט|הײַנט|{{א||b= demo only}}פּרוּװ}} א

generating:‎
אפּרוּװ א

  • The examples are equivalent (the second is trimed); there is no practic use of this particular example; it is hard to trace hard to understand and silly. But keep in mind that "debugging" means dealing with objects "unknown" to you. Best regards Gangleri · Th · T 12:38, 13 April 2006 (UTC)[reply]
P.S. For a meaningfull example see template:inline/yi|diff=328827&oldid=328826. 12:52, 13 April 2006 (UTC)

Possible problem with value 0 for #if[edit]

Hmm. I suspect there might be a problem with #if when the condition string is "0".

Consider User:Ligulem/if-test-6 containing

{{#if: {{{a|}}} | a was specified and was set to "{{{a}}}" | a was not specified }}

And the following test cases:

*{{User:Ligulem/if-test-6}}

  • a was not specified

*{{User:Ligulem/if-test-6 | a=1 }}

  • a was specified and was set to "1"

*{{User:Ligulem/if-test-6 | a=0 }}

  • a was specified and was set to "0"

The last test case might be a bit a surprise (and possibly a problem).

I would say, the template User:Ligulem/if-test-6 does not work as I would (intuitively) expect it, if param a has the value "0".

In User:Ligulem/work/cite web 1 I wrote an attempt to rewrite en:template:cite web using the new #if:. But I believe as I wrote it, it doesn't work if one or more of the params are set to "0" when including. I admit this is a boundary case. But en:template:qif does not have this problem, I believe.

Any ideas? Am I wrong? Can this be "fixed" by another use pattern? --Ligulem 21:21, 13 April 2006 (UTC)[reply]

You should be able to do a test with #ifeq against blank and then use the "else" space as necessary. If #ifexpr is implemented, I think #if should be turned into a simple blank/non-blank test. —Locke Coletc 21:33, 13 April 2006 (UTC)[reply]
Or, as an alternative to "fixing" #if, we could add #ifdef and #ifndef which would check for the presence (or absence) of a value at all. —Locke Coletc 21:35, 13 April 2006 (UTC)[reply]
I'm still puzzleing. I fear the spec (and thus the implementation) of #if should be changed to:
"If the condition is 0 or an the empty string (ignoring leading and trailing space), then it is considered false, and the else text is returned. Otherwise, the then text is returned."
But then the spec of #expr should also be changed (or there is something missing). Hrmm...
--Ligulem 21:45, 13 April 2006 (UTC)[reply]
Why would #expr need to be changed? =) It would still return 0 or 1 for conditional results; and for math functions (conversions from kilometres to miles or vice versa) it would still return integer values. For conditionals, you'd just use #ifeq and compare against 0 or 1 (as desired). —Locke Coletc 22:29, 13 April 2006 (UTC)[reply]
Ok. This has nothing to do with #expr. You are right. #expr should not be changed. But #if should be changed as I wrote. Currently, it is not a handy replacement for qif. #if should be turned into a simple blank/non-blank test. --Ligulem 22:41, 13 April 2006 (UTC)[reply]

At the moment, there are several ways to circumvent this issue:

{{#if: 0{{{a|}}} | a was specified and was set to "{{{a}}}" | a was not specified }}

or

{{#ifeq: {{{a|}}} || a was not specified | a was specified and was set to "{{{a}}}"}}

--Algorithm 23:45, 13 April 2006 (UTC)[reply]

Ah. Yes. Thanks. I admit I had totally neglected that #ifeq. Apologies. --Ligulem 09:17, 14 April 2006 (UTC)[reply]

The only reason I made it so that #if treats 0 as false was to allow it to branch on the result of a #expr function. That need will be removed if I implement #ifexpr. I'll implement both changes simultaneously unless there are any objections. If any burning need remains to branch on the result of #expr (for example if the result is returned via a meta-template), then you can use #ifeq 0. -- Tim Starling 03:50, 14 April 2006 (UTC)[reply]

Cool. Thanks! No objections from me. --Ligulem 09:17, 14 April 2006 (UTC)[reply]
Wow. Tim has already implemented that: [6]. --Ligulem 09:45, 14 April 2006 (UTC)[reply]

#var[edit]

Would it be possible to provide functionality to set variables? This would be very useful when dealing with unreliable values (such as those generated by #rand). I was thinking something along the lines of {{#var:bar=bar}} which could then be referenced by {{{bar}}}. Too procedural? --Algorithm 01:17, 14 April 2006 (UTC)[reply]

Variables would be a pain to implement, since there's currently no well-defined evaluation order and keeping it that way is good for efficiency and flexibility of implementation. I think it would be more sensible to make #rand return the same result every time, for a given revision. This would hide the confusing nature of the parser cache from the user. -- Tim Starling 04:21, 14 April 2006 (UTC)[reply]

expression – additional notes[edit]

  • Halló! I was wondering what sort of "mathematics" is implemented, what addional notes should be added. What is revision (php etc.) dependend and what not. Sorry if I missed somthing in the discussion.
  • What types are used, are allowed and what ranges? I assume that "floating" would be an inapropriate type.
  • Might there be overflows?
see: http://test.wikipedia.org/wiki/ParserFunctions
The function uses the same mathematical behaviour as PHP. Integers are used if the input is integral, but are automatically converted to double-precision floating point numbers on overflow. Divison always produces floating-point numbers. Division by zero produces a warning in PHP, so I check for it explicitly. Floating-point overflow silently produces INF or 1.#INF depending on the system (here INF). Floating-point underflow silently rounds to zero. There is no way to specify numbers in scientific notation at present, so these situations should be rare. -- Tim Starling 10:49, 14 April 2006 (UTC)[reply]
Thanks a lot for the clarifications. Gangleri · Th · T 10:55, 14 April 2006 (UTC)[reply]