Extension talk:Loops

From MediaWiki.org

Jump to: navigation, search

Contents

[edit] Feedback

Doesn't only work on MW 1.12 Alpha, works also on 1.12. I hope it also will work on 1.13. This extension is very helpful, for example for building well arranged templates without copy paste and change 100 times for "array" parameters. Found no Bugs as yet. Hope somone will develope on this extension that we can see it with stable Status as soon as possible! --77.191.205.221 10:13, 6 August 2008 (UTC)

Thanks for the feedback! Though no one has reported any bugs, I know of only three or four people who use this extension (present company included), so I don't feel comfortable updating the status to "stable" yet. —Sledged (talk) 15:59, 6 August 2008 (UTC)
I use this extension! ([1]). I have a template calling it here. We discuss the necessity of this template all the time on the mailing list. Keep up the great work! --Aquatiki 22:09, 6 August 2008 (UTC)
Glad to know it works well for you. I'll go ahead and change it to stable, since no bugs have been found with the bread-and-butter functions (while and dowhile). foreachnamedarg, however, is still experimental and subject to change. —Sledged (talk) 18:26, 21 August 2008 (UTC)
I use this extension, too! ([2]). It's crucial to my [|Random Image Gallery] template as used on the homepage. Awesome work! --Arodicus 22:36, 8 October 2008 (UTC)

Ok, It also works on MW 1.13.1, tested now! --77.191.216.80 15:03, 30 September 2008 (UTC)

I use this template at [3] for a lot of templates, the most complex of which is here: [4] Thanks a lot Sledged! --J.nesta 14:08, 2 November 2009 (UTC)

[edit] Foreachnamedarg

Foreachnamedarg is really amazing! But why don't you allow to use it without prefix? I have some templates where I allow the users to use parameter 1, 2, 3 and so on without any limitation, I really could use it there so I would save the increment variable, the condition and the asigning of the parameter value to a variable. If Foreachnamedarg is significant faster than the common loops or it allows to do more loop runs than the other loops before you get a php error message because of memory or something, It would a fortiori make sense to allow it. With many loops in my pages they get really slow sometimes. --Danwe 21:38, 13 February 2009 (UTC)

I'm glad you find it useful. Foreachnamedarg is a pilot parser function for an idea I'm still fleshing out. Eventually, I plan to replace it with foreacharg which will do exactly what you're describing while still keeping the current functionality. I have no time frame for this though. —Sledged (talk) 20:07, 19 February 2009 (UTC)
#forargs replaces #foreachnamedarg and works on all template arguments that match the supplied prefix which can be left empty. In which case it will access all template arguments. #fornumargs will access only the numbered arguments, whether they're set explicitly or implicitly. —Sledged (talk) 22:22, 2 May 2009 (UTC)
Thats amazing. I especially love the #forargs feature which allows to access ALL arguments. #fornumargs Is great as well, Its helpfull to save some code. Can you tell us if #fornumargs brings any performance bonus compared with the old method with {{{ {{#var:i}} |}}}? Thanks for the release! --Danwe 15:22, 4 May 2009 (UTC)
No clue. I haven't made any benchmarks on the performance. —Sledged (talk) 21:26, 15 May 2009 (UTC)

[edit] Bug #1 - Invisible characters around generated text of the loop

Phew, I spent two evenings now untill I found that bugs source... It seems like the Bug is, that the Loops extension creates some invisible characters arround the text which is created inside the loop. So when you run a loop to create some text for a template the length of the text the template will return is much longer than the text you can see. In some cases this behavior causes problems, for example when you use the return value with string functions or inside a Semantic Media Wiki Property.

Example: The following loop:

{{#len:{{#vardefine:i | -1 }}{{
  #while:
  | {{ #vardefine:i | {{ #expr: {{ #var:i }} + 1 }} }}
    {{#ifexpr: {{#var:i}} < 5 |true|}}
  |<nowiki/>{{#var:i}}
}}}}

would return the output "01234", looks like its 5 chars long. But the #len function couns exactly 220 (!) characters!

I found a litte workarround for that: You can use the sub parser function from string functions to avoid this: {{#sub:<The loop>|0|-99999}} but you have to store the generated return value in a variable if it is generated in the loop because the variable has to print their content behind the loop and sub function. So return values of templates dont give back some invisible characters and you can use the string wherever you want without problems.

I hope you will fix this litte bug soon, I dont like my workarround pretty much :-/

--77.191.145.123 19:20, 29 January 2009 (UTC)

Try it without the <nowiki/> tag, like so:
{{#len:{{#vardefine:i | -1 }}{{
  #while:
  | {{ #vardefine:i | {{ #expr: {{ #var:i }} + 1 }} }}
    {{#ifexpr: {{#var:i}} < 5 |true|}}
  |{{#var:i}}
}}}}
and see how it works. I use the nowiki tags in my examples so that the new line characters immediately after the tags are preserved. —Sledged (talk) 20:39, 29 January 2009 (UTC)
Thank you, this works like expected! --77.191.253.66 22:33, 1 February 2009 (UTC)

[edit] Help me please

I can't seem to get this to work: In my wiki theres a table at the bottom of many pages that go to different versions of the content on the page, so i want to use a template instead. I want to make a table that has one row (starting with the row heading "Inputs" in bold and the two-input version), and in each cell links to a page called: (first parameter) then "_(" then the i value then " bit)" with a label of the value of i. the variable i increments by 2 until i is less than the second parameter. Below is my attempt but it always seems to time out.


{| class="wikitable" border="1"
|-
| '''Inputs'''
| [[{{1}}|2]]

{{ #vardefine: i | 1 }}
{{
  #while:
  | {{ #ifexpr: {{ #var: i }} <= {{{2}}} | true }}
  | <nowiki/>
| [[{{{1}}} ({{ #var: i }} bit)|{{ #var: i }}]]{{ #vardefine: i | {{ #expr: {{ #var: i }} + 2 }} }}
}}

|}


Example: {{Templatename|Thing|9}} Should produce:

Input 2 3 5 7 9
You need to hide the pipe character after <nowiki/> tag in a template. Otherwise, MW thinks it's the start of another parameter. Standard practice is to create the template Template:!, whose only content that is included is a pipe character. —Sledged (talk) 18:01, 30 December 2008 (UTC)

[edit] #while and header

i'm using MW 1.13.4

A problem with headers. if i try to create header within cycle, then only the 1st header resulted as header and the rest - as plain text. For example,

{{#vardefine: i | 0 }}{{#vardefine: n | 5 }}
{{#while:
  | {{#ifexpr: {{#var: i }} < {{#var: n }} | true }}
  | 
===header===
<br><br>text<br><br>
{{#vardefine: i | {{#expr: {{#var: i }} + 1 }} }} }}

it can be half-solved using var-wrap.

{{#vardefine: i | 0 }}{{#vardefine: n | 5 }}{{#vardefine: rez | }}
{{#while:
  | {{#ifexpr: {{#var: i }} < {{#var: n }} | true }}
  | {{#vardefine: rez | {{#var:rez}}
===header===
<br><br>text<br><br>}}
{{#vardefine: i | {{#expr: {{#var: i }} + 1 }} }} }}
{{#var:rez}}

in my real page i'm using my array extension, so my real code is useful

{{#vardefine: i | 0 }}{{#vardefine: rez | }}
{{#while:
  | {{#ifexpr: {{#var: i }} < {{#var: n }} | true }}
  | {{#vardefine: rez | {{#var:rez}}
==={{#array:pagename|{{#var:i}}}}===
<br><br>{{:Songs:{{#array:pagetitle|{{#var:i}}}}}}<br><br>}}
{{#vardefine: i | {{#expr: {{#var: i }} + 1 }} }} }}
{{#var:rez}}

--Schthaxe 09:12, 5 March 2009 (UTC)

Whitespace (including newlines) is stripped from the beginning and end of all the arguments of the parser function. Add a non-whitespace character (e.g. the HTML encoding for a whitespace character &#32;, or a <nowiki/> tag) before the newline preceding each heading. —Sledged (talk) 17:35, 6 March 2009 (UTC)

[edit] let's use for-cycle

    public static function forHook( &$parser, $frame, $args ) {
	global $wgExtVariables;
	$iter_var_name = array_shift( $args );
	$iter_var_name = $iter_var_name !== '' ? $iter_var_name : 'i';
	$startval = $frame->expand( array_shift( $args ) );
	$startval = isset( $startval ) ? intval( $startval ) : 0;
        $endval = $frame->expand( array_shift( $args ) );
	$endval = isset( $endval ) ? intval( $endval ) : 0;
        $loopStatement = array_shift( $args );
        $output = '';
 
	$wgExtVariables->mVariables[ $iter_var_name ] = $startval;
        while ( $startval < $endval ) {
            if ( self::$maxLoops >= 0 &&
                ++$parser->loops_count > self::$maxLoops )
                return wfMsgForContent( 'loops_max' );
 
            $output .= isset( $loopStatement ) ?
                trim( $frame->expand( $loopStatement ) ) : '';
 
	    $wgExtVariables->mVariables[ $iter_var_name ] = ++$startval;
        }
        return $output;
    }

then we can use

{{#for:i|0|10| {{#var:i}} }}

and get

0123456789

--Schthaxe 10:33, 12 March 2009 (UTC)

I used #loop instead of #for, because another extension already uses #for. It works like so:
{{#loop: variable name | starting value | number of loops to be performed | wiki markup }}
if a negative value is supplied for the third argument, the value stored in the variable will decrease with each iteration. —Sledged (talk) 22:22, 2 May 2009 (UTC)

[edit] Version 0.3.0 only works with MW 1.14 and later

Since you use functions in forargs and/or fornumargs like getNamedArguments which were added in MW r38981 the Loops plugin isn't full compatible to MW <1.14 anymore. I tested it in 1.13. Perhaps you should use SVN for the project so that MW 1.13 or less users could download an older version of the plugin. --Danwe 12:06, 2 June 2009 (UTC)

I may do that down the road, but for now later versions can be accessed through the page's history. —Sledged (talk) 18:12, 2 November 2009 (UTC)

[edit] ExtLoops count for -1 loops

In case you config ExtLoops::$maxLoops = -1; the html comment information in the pages source code always shows ExtLoops count: 0/-1. Would be usefull sometimes to know how many loops have been performed on a page. --Danwe 13:52, 11 October 2009 (UTC)

Sounds reasonable. —Sledged (talk) 18:12, 2 November 2009 (UTC)

[edit] Using #while to pass parameters to a subtemplate (I think I might have found a bug with Extension:Loops)

Has anybody had success in doing this? For example, the following code (with Arg1 being IceCream)

{{#vardefine:i|1}}{{
	#while:
	|{{#ifexpr:{{#var:i}}=1|true}}
	|Arg1={{{Arg1}}}{{#vardefine:i|{{#expr:{{#var:i}}+1}}}}}}
}}

will result in:

Arg1=IceCream

But the following code

{{Subtemplate|{{#vardefine:i|1}}{{
	#while:
	|{{#ifexpr:{{#var:i}}=1|true}}
	|Arg1={{{Arg1}}}{{#vardefine:i|{{#expr:{{#var:i}}+1}}}}}}
}}}}

will not pass the argument to the subtemplate! *throws brick through computer monitor* plz hralp( --J.nesta 14:26, 2 November 2009 (UTC)

[edit] Found a work-around

It seems to work if you just use non-named arguments, like {{{1}}} and so forth. WTF? --J.nesta 14:26, 2 November 2009 (UTC)

With templates, parser functions, and magic words (i.e. anything that uses the {{...}} syntax), when specifying an argument, MediaWiki only recognizes the equal sign if it's outside a nested template-like call in the argument. It doesn't process equals signs that are the result of a template-like call. For instance, the markup sample cases
{{tplate|arg1=val1}}
{{tplate|arg1={{#if:|| val1 }} }}
{{tplate|{{#if:|| arg1 }}=val1 }}
and
{{tplate|{{#if:|| arg1 }}={{#if:|| val1 }} }}
all set the argument arg1 to the value of val1, because the equal sign is not inside a nested {{#if:}} call. Conversely, the markup
{{tplate|{{#if:|| arg1=val1 }} }}
implicitly sets argument 1 to arg1=val1, because the equal sign is inside the nested {{#if:}} call. —Sledged (talk) 18:12, 2 November 2009 (UTC)
Interesting. So... is there a work-around that you know of? How would I go about programming this? =) --J.nesta 19:59, 3 November 2009 (UTC)
I haven't been able to think of any workaround that doesn't involve creating another extension. —Sledged (talk) 22:30, 3 November 2009 (UTC)
Out of curiosity, do you know of an easy way to pass all template parameters to a subtemplate? ;) Thanks for all your help Sledged. --J.nesta 00:30, 4 November 2009 (UTC)

[edit] Code for passing arguments to a subtemplate

Well, even though Sledged hasn't given me a final answer yet, I'll go ahead and post my workaround. It's not pretty, but I did a little searching on google and AFAIK this is the only code I've seen on the internet that will do this. If someone knows a better way to do this, please let me know.

The premise: since MediaWiki won't process either equals signs or pipes, you can't write up a nice little loop to pass a bunch of arguments to a subtemplate. So, I just used strings to pass them (for the noobs reading this, you have to download the StringFunctions extension for this to work).

Note: The code uses {{!}} (a.k.a. a pipe) as a separator between the arguments, but since it is a string, you can use whatever symbol of string of characters that you want.

The top template code:

{{subtemplate|{{#vardefine:i|1}}{{
	#while:
	|{{{Arg{{#var:i}}|}}}
	|{{{Arg{{#var:i}}|}}}{{!}}{{#vardefine:i|{{#expr:{{#var:i}}+1}}}}
}}}}

The subtemplate code:

{{#vardefine:AllArgs|{{{1}}}}}{{#vardefine:i|1}}{{
	#while:
	|{{#ifexpr:{{#len:{{#var:AllArgs}}}}>1|true}}
	|{{
		#vardefine:Arg{{#var:i}}
		|{{
			#sub:{{#var:AllArgs}}
			|0
			|{{#pos:{{#var:AllArgs}}|{{!}}}}
		}}
	}}{{
		#vardefine:AllArgs
		|{{
			#sub:{{#var:AllArgs}}
			|{{
				#expr:{{#pos:{{#var:AllArgs}}|{{!}}}}+1
			}}
		}}
	}}{{#vardefine:i|{{#expr:{{#var:i}}+1}}}}
}}

Now all the args are stored as vars in the subtemplate, i.e. Arg1, Arg2, etc.

Hopefully this helps out someone out there! And hopefully one day someone over at MediaWiki will implement something like a {{Subtemplate|%PASSALL%}} to automatically pass all parameters to a subtemplate so people don't have to hurt their brains figuring this shit out. =p --J.nesta 01:50, 5 November 2009 (UTC)