Jump to content

Wikipedia talk:Lua/Archive 1

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia
Archive 1Archive 2Archive 3Archive 5

New request page

I've created a new request page for Lua scripts at Wikipedia:Lua requests. If you're a Lua developer, please watchlist it. If you'd like to make a request, please do that too! Dcoetzee 23:09, 23 February 2013 (UTC)

Location for experimental/practice code

There's a discussion at the technical pump currently about where to put code that you're experimenting with; as a result Module:Sandbox has been created. — Hex (❝?!❞) 16:39, 24 February 2013 (UTC)

Better factorial code?

the following code is arguably better than the current one ;-) [Note: It also highlights more Lua features - assertion, type checking, local scoping, tail call recursion etc.]

function factorial(k)

    assert(type(k)=="number" and k>=0, "factorial: argument must be a number >= 0")

    local function facto_helper(n, p)
        if n == 0 or n == 1 then
            return p
        else
            return facto_helper(n-1, p*n)
        end
    end

    return facto_helper(k, 1)

end
Tail calls are kind of cool, yet... if the point is that you merely return a function, so there is no need to keep track of the original frame after going to the tail call, then it seems like this is just a loop: i.e. you check your variables, do your multiplications, and move on to the start of the function again, just like you were doing a goto. I'm not sure I appreciate the unique power of it. Wnt (talk) 21:50, 24 March 2013 (UTC)

Lua - parser functions- templates relations

So templates can call Lua modules, parser functions and pages in MediaWiki namespace. Can templates, MediaWiki pages or parser functions be called from Lua? Can one call lua function that returns sevaral strings and pass them to a template? --Jarekt (talk) 16:24, 14 March 2013 (UTC)

You can call a template from a Lua module using frame:expandTemplate. Page content can be retrieved with the getContent() method of the title object. Support for calling a parser function is coming soon with frame:callParserFunction, or you could do it today by passing the markup to frame:preprocess. Toohool (talk) 19:25, 14 March 2013 (UTC)

Licensing

Are module authors permitted to use other licenses (presumably in addition to the CC-BY-SA license) for modules they develop? -happy5214 14:32, 15 March 2013 (UTC)

That's a very good question. Creative Commons licenses are explicitly not recommended for software. — Hex (❝?!❞) 15:57, 15 March 2013 (UTC)

You own the copyright, you can grant whatever licenses you want (in addition, as you say, to the CC-BY-SA license that you've already granted). That would only apply to your contributions though, not to later modifications made by other editors. This is typically done with a copyright template placed on your user page... though you might want to modify one of them to specify that it only applies to Lua modules. Toohool (talk) 18:13, 15 March 2013 (UTC)

There is talk at the WMF about offering a central Lua repository and probably using more permissive licenses there. Of course that is all well in the future. Dragons flight (talk) 03:46, 16 March 2013 (UTC)

Module index and comments

I just quickly sorted out the present Lua modules to Wikipedia:Lua/Modules/Overview. Looking them all over, I would make some comments about the naming so far...

  • We have an even split on people who do personal testing in Sandbox/... and people who do it in User:... At this point, either of us could pull up stakes and migrate to the other pretty easily. We really ought to decide, flip a coin, something so we get this sort of stuff to a predictable spot.
  • We have a lot of cases where related modules have the same name with "/" to indicate subpages, and some others where apparently related modules simply extend a name. With those it's not entirely clear if they are meant to go together or not. Normally this wouldn't be an issue, except I was wondering... if you write a Lua module that requires another Lua module or mw.title.new()s a data file, is the target module or file protected when the main module is cascade-protected? I don't know, but with some of these things being transcluded on every page in the wiki, and having elaborate powers to write anything they can slip by the interface, we should be wary of security holes, and the first step is to know quickly and certainly which are a unit, I think.
  • The approach of Module:Sandbox - having every user put scripts into a common receptacle - seems unworkable. You couldn't keep track of your old experiments, and my experience is that yes, I do forget how I did things and have to look back at them. I think we might want to give up on that suggestion.
  • Almost all of us to be a lot better about putting comments up front in the module and/or documentation saying what the heck our modules are FOR. Wnt (talk) 23:28, 17 March 2013 (UTC)
If we have to decide, I personally prefer "User:..." as that also allows a space for things that aren't sandbox. For example, if someone needs some custom Lua method for their userpage, or has some code snippets they like to use for debugging or copying and pasting. But why not allow both? Anomie 11:36, 18 March 2013 (UTC)
Cascading protection should work fine, since use of modules is recorded in the templatelinks table. And I see that Module:Math is currently in use on Main Page, and is correctly showing the cascading protection notice when I try to edit it. BJorsch (WMF) (talk) 11:41, 18 March 2013 (UTC)
I noticed that much - my question is, if the person who wrote Module:Math had decided to include some code file=mw.title.new("Module talk:Math/TableOfUnicodeMathCharacters") and used it to parse in certain characters (to make it so that he could fine-tune the font and size of pi, etc. independently of the module), could a random vandal edit that file and insert a picture of a big beautiful bottom? If so then clearly you'd want some finer control, maybe have people make a nominal invoke of all the subtemplates from the main template page or something. Wnt (talk) 14:06, 18 March 2013 (UTC)
title:getContent() records as a transclusion, so cascade protection will extend to pages fetched in that manner. BJorsch (WMF) (talk) 00:31, 19 March 2013 (UTC)
Documentation should go on the module's documentation page, since any edit to the module itself, even to update comments, causes everything using the module to be reparsed (just like with templates). This is why we ultimately decided not to try parsing luadoc comments to automatically generate documentation. Comments about the code itself should of course go with the code. BJorsch (WMF) (talk) 11:41, 18 March 2013 (UTC)
Good point! Wnt (talk) 14:06, 18 March 2013 (UTC)

Novice friendly tutorial

I tried to start learning Lua and immediately hit the wall after the "hello, world" part and all I got afterward are "script error". I wonder if there's any actually helpful tutorial for those already familiar with Wikisyntax but without other computer language experience like Lua or C. The tutorials I found usually begin with a simple code to tell you to copy-and-paste (hello, world) then look at the outcome. Immediately afterward it gives you another line of codes which I have absolutely no idea where to insert it to make it functional at all. The tutorial I actually want is how a template with parser functions translate into a Lua module with explanation of what syntax equal what variable/function or whatever. It may sound like asking to be babysat or spoon-fed, but I'm totally stuck. -- Sameboat - 同舟 (talk) 07:07, 18 March 2013 (UTC)

There will be two office hours this week on IRC where the discussion will focus on Lua. In addition, you can ask questions on the MediaWiki wiki. If all else fails, there are plenty of people here willing to help, myself included. -happy5214 08:12, 18 March 2013 (UTC)
To give a different reply to the same question: this tutorial on the Lua website is a great source of information. It also helps to look at existing modules, to get an idea of what one would look like. -happy5214 08:12, 18 March 2013 (UTC)
I don't know if there's any question I can ask because I'm actually having trouble to get to the basic. I think Lua for Wiki lacks a helpful documentation like help:table which with that I can pretty much self-learning without asking any question. To me, mw:Extension:Scribunto/Lua reference manual is just a long list of specification without teaching novice like me anything to start with. mw:Lua scripting/Tutorial is also very lacking. I just stuck at local arg2 = frame.args[2] or "" which I don't know where to add it to make it functional. -- Sameboat - 同舟 (talk) 08:35, 18 March 2013 (UTC)
That line would go in p.hello (in the tutorial), before the return statement. Then, replace "frame.args[2]" at the end of the return statement with "arg2". Also see Module:BananasArgs for more help with arguments. -happy5214 08:45, 18 March 2013 (UTC)
Like this Module:Sandbox/sameboat? -- Sameboat - 同舟 (talk) 09:03, 18 March 2013 (UTC)
My bad, I meant the return statement in the p.hello function. -happy5214 09:08, 18 March 2013 (UTC)
There you go! You can do the same thing with the first argument. -happy5214 09:12, 18 March 2013 (UTC)
I must say that tutorial has missed one hell of important instruction. (If possible, would you rewrite that part of the tutorial? Because I'm unable to make it sound natural.) But then I'm curious, can the .hello be omitted like in the template? -- Sameboat - 同舟 (talk) 09:18, 18 March 2013 (UTC)
Which instruction? Where to put the variable declaration? To your second question, no, it can't be omitted. p.hello basically means the function is stored in the "hello" entry of the "p" table, which is returned by the module to MediaWiki. -happy5214 09:22, 18 March 2013 (UTC)
mw:Lua_scripting/Tutorial, from "results in frame.args[2] being an empty string (which will not, although the resulting text will look odd). One way to work around this is to assign the desired parameters to a local variable, and replacing nils with empty strings at this step; e.g.,". This instruction oversimplifies the full procedure of where to add that code (local arg2 =... ) and what should be replaced. -- Sameboat - 同舟 (talk) 09:30, 18 March 2013 (UTC)
Again, the official tutorial on the Lua website would probably explain it much better. -happy5214 09:32, 18 March 2013 (UTC)
Specifically, this section deals with local variables in Lua. -happy5214 09:33, 18 March 2013 (UTC)
Call me stupid please. I'm stuck at page 1 [1] instantly. How do I invoke the code as simple as print("Hello World") in Wikipedia honestly (Module_talk:Sandbox/sameboat). I think my problem is that I only learn Lua to contribute Wikipedia so I only want to know what I do in Wiki will get what right in wiki. I don't want to fiddle with a separate software like lua executable because I guess the usage is different to how you invoke lus's code in Wiki. -- Sameboat - 同舟 (talk) 01:53, 19 March 2013 (UTC)
The first and foremost thing to have posted prominently on every page a newbie might hit is that Script error is a link if you enable Javascript. (Which I am loath to do because it enables that awful custom editor, but that's another story...) Wnt (talk) 14:14, 18 March 2013 (UTC)
I know the "script error" explains something when you click it, but the message is far from useful, to me. -- Sameboat - 同舟 (talk) 14:35, 18 March 2013 (UTC)
Different people learn differently and I hope we can all work together to accommodate people who learn via videos, people who learn via worked examples and equivalence tables, people who learn by reading reference material, and people who learn via step-by-step instructions. Please check out Brad Jorsch's eleven-slide PDF and perhaps check out the accompanying video. It sounds like the Getting started ("hello world") portion of the Lua reference documentation didn't have what you needed -- maybe you could add some "what's missing from hello world" notes to the talk page to help us fix that omission?
I hear Sameboat's wish for an equivalence table ("you used to do x to get y result, now do z instead") and will try to encourage one -- has someone already started one? Sumana Harihareswara, Wikimedia Foundation Engineering Community Manager (talk) 15:54, 18 March 2013 (UTC)
I appreciate the comparison of {{convert}}'s before and after, but the template is very inaccessible to most Wikipedians. So yes, I do hope for a much simpler example... -- Sameboat - 同舟 (talk) 01:45, 19 March 2013 (UTC)

Thank Dragons flight for clearing something for me. But with the banning of the print function and the extra steps to validate the lua code in Wiki, I can't tell if the lua.org tutorial truly helpful to me as I don't know how to convert all those examples to comply with MediaWiki's lua standard. Ultimately MediaWiki should issue another tutorial for Wikipedians (without prior knowledge of C and Lua) due to the differences from standard Lua. (At least script error should be shown when print function is detected.) -- Sameboat - 同舟 (talk) 04:26, 19 March 2013 (UTC)

I should note Help:Lua for beginners is now being developed. Wnt (talk) 21:46, 24 March 2013 (UTC)

Documentation

We now have the /doc system somewhat integrated/forced trough the Scribunto extension. I've taken some steps to bring it partially in line with our Template documentation system.

  1. Automatic transclusion of protection templates was added. MediaWiki:Scribunto-doc-page-show and MediaWiki:Scribunto-doc-page-does-not-exist
  2. Automatic insertion of the green 'chrome' of our template documentation. MediaWiki:Scribunto-doc-page-show
  3. Automatic insertion of the {{documentation subpage}} template. MediaWiki:Scribunto-doc-page-header
  4. Editnotice for /doc page. {{Editnotices/Namespace/Module}}
  5. Link/Create testcases link for Module pages. {{Editnotices/Namespace/Module}}

There is still lots of work to do of course

  • Is it a good idea to deviate from the template standard of calling pages with testcases, tests for the module namespace ? I don't think it was really a active decision.
  • The messages for /doc inclusion are currently added as contentlanguage, where really only their parameter should be included as such. Also explains why the uselang=qqq hack doesn't work to show the scribunto messages.
  • Create a toolbox for MediaWiki:Scribunto-doc-page-does-not-exist to create doc pages and provide access to tests
  • The documentation toolbox does not yet know about Module testcases (though the editnotice 'sort of' does).

But it's a start —TheDJ (talkcontribs) 22:18, 18 March 2013 (UTC)

So it is in development. For now, there is {{ml}}. -DePiep (talk) 22:43, 18 March 2013 (UTC)
Should be a bit further today. Some examples of pages and their edit page notices:
For this to work, I currently have a {{documentation/link box}} template which is basically a fork of {{documentation/end box}}. The idea is to merge them again at some point if the module part is a bit more developed/stable. Of course it is also probably easier to generate them using lua, because they have quite a bit of logic. If you have ideas on how to improve.
Ideas for links, and tips that should be in the elements are welcome. —TheDJ (talkcontribs) 22:29, 19 March 2013 (UTC)
I might sound pricky, but what are you aiming at? We know {{documentation}} in templates, and I have started {{ml}} greatly (thank you). What do you want to add? -DePiep (talk) 23:55, 19 March 2013 (UTC)
The same as with Templates, a structure that helps make sure we use the same subpages for the same purposes, points at explanatory links for those who don't know the technology, reminds people to update testcases and documentation, has preload templates that help you start documentation/testcase pages from scratch in a consistent manner etc. Some of it is there now, some requires rewording, some requires linking to lua/scribunto best practices in Wikipedia namespace, some smaller things are still missing. —TheDJ (talkcontribs) 09:46, 20 March 2013 (UTC)
Thank you for explaining. I think I get it now. -DePiep (talk) 12:20, 20 March 2013 (UTC)

Protection and management of scripts?

See discussion at Village Pump (policy)#Protection and management of scripts?. Relevant to Lua, userscripts, and user scripting generally. Comments appreciated.

FT2 (Talk | email) 02:07, 20 March 2013 (UTC)

Guide for beginners

I found this guide for learning how to code Lua, may be of help or use www.lua.org/pil/contents.html#P1

It is linked in the page header "Resources". -DePiep (talk) 00:10, 21 March 2013 (UTC)
As I have stated in the previous thread. If no one tells the beginner how to convert print function (disabled by Scribunto) into return, they might get stuck on page 1 like me. -- Sameboat - 同舟 (talk) 01:18, 21 March 2013 (UTC)
I've just started Help:Lua for beginners, just rushing through ... I'm sure there's much more to add and possibly a few things to ehm rephrase. Wnt (talk) 20:09, 22 March 2013 (UTC)
Link added to Wikipedia:Lua/Resources -DePiep (talk) 22:14, 22 March 2013 (UTC)

Template:Mlx

I feel like I must have reinvented the wheel here, but I copied Template:Tlx to Template:Mlx with minor modifications, so we can type

{{Mlx|ConvertNumeric|decToHex|99 33}}

and get {{#invoke:ConvertNumeric|decToHex|99 33}}

It would be good if someone could look this over for any flaws before it gets cascade-protected by something. Wnt (talk) 23:14, 21 March 2013 (UTC)

Actually, I might suggest someone could write a simple Module to replace Tlx, Mlx, and related extended parameter families with something that will happily accept and format arbitrarily many parameters rather than having a giant #if tree. Dragons flight (talk) 23:29, 21 March 2013 (UTC)
I did that for {{tlx}} at Wikibooks with Module:Template, if anyone wants to try to adapt it for Wikipedia. --darklama 01:36, 26 March 2013 (UTC)

#invoke overhead and timing

I've been seeing people talk about the overhead of #invoke, etc. Is it known which is the better way? (Can we try with a module and a template and just compare the data in the HTML source comments, or does that not represent both things?) Wnt (talk) 00:58, 22 March 2013 (UTC)
The overhead is quite modest, unless you are running the command 100s of times. For something simple like this, I wouldn't worry about it. If you can improve functionality or make the code less of a tangle then it is generally worth doing. To give a concrete example, I estimate that Module:Citation formats a citation in about 10.5 milliseconds. Of that 10.5 ms, about 4.5 ms is Lua overhead which will be present for the typical invoke. Even so, you would have to generate quite a large number of iterations before the impact is noticeable to the user. Out of curiosity, I also tried timing {{Mlx}} and estimated it as running at about 6.5 ms per iteration right now. As long as the module is simple (far simpler than Citation anyway), you'll probably end up with a module version of Mlx that is similar in speed to the current template. Dragons flight (talk) 05:32, 22 March 2013 (UTC)
Is there somewhere that you have mentioned how to time scripts or templates like Mlx? I know about the NewPP report and Anomie's script, but I have seen a lot of variability in the NewPP Lua time usage and am not confident about the results. There is a tantalizing remark with "I repeated your 10× tests twenty times" here, but I haven't yet tried to work out what exactly that meant.
It does not particularly matter, but I am curious about any methods to get timings. My sandbox has 1689 calls to {{convert/sandboxlua}}, and the current Lua time usage is 2.062s, which is 2062/1689 = 1.2 ms/invoke. Of course 1689 calls is very atypical, and I have more pages with just 10 and 2 calls at test2—they show 4.5 ms/call for 10 calls, and 12 ms/call for 2 calls. Johnuniq (talk) 08:30, 22 March 2013 (UTC)
First, you have to know what you're looking at. "Lua time used" is just the time inside Lua, and doesn't include things like #invoke overhead. The Lua time usage should be fairly consistent for multiple parses of the exact same input. The "Served by" time is the entire time required for the page, including internal network delays and time lost to multitasking, and may vary significantly depending on various factors. Dragons flight used the latter to measure the #invoke overhead, by comparing the time needed to render an empty page versus a page with many invocations of a module with a single do-nothing function. As far as "I repeated your 10× tests twenty times", it means just that: You have a test that transcludes the template 10 times. I ran (a variation of) that test 20 times, recorded the timing for each run, and averaged. And regarding "4.5 ms/call for 10 calls, and 12 ms/call for 2 calls", that reflects the fact that mw.loadData is much faster for runs after the first, so the more calls there are the more that first call's slowness is amortized. BJorsch (WMF) (talk) 11:39, 22 March 2013 (UTC)
On a side note, that 4.5 ms overhead per #invoke should go down to about 2–2.5 ms with 1.22wmf1, and I have a change pending review to show timing information at the bottom of the preview page instead of requiring that the source be viewed. BJorsch (WMF) (talk) 11:39, 22 March 2013 (UTC)
  • Lua time usage varies 1%-60% depending on busy servers: Although the Lua portion of total reformat time is more stable than markup parsing, which often varies over 200% slower (rarely over 300% slower), the Lua time clock tends to stay within ±20% of the seconds consumed. However, the Lua time usage can also vary wildly, as sometimes +30%, and on one occasion, I measured the Lua clock as nearly +60% longer than the quickest timing. Hence, if the combined Lua functions typically run over 6.3 seconds, then there is the rare danger of a 10-second Lua timeout on busy servers, as 6.3*160%=10.08 seconds. Fortunately, the Lua interface checks the clock before the next Lua function, and so a tedious Lua function could run 11 seconds but no timeout if the excess occurred during the final Lua function run (with no other Lua functions pending execution). -Wikid77 (talk) 19:29, 22 March 2013 (UTC)

Direct #invoke is 20%-30% faster for tiny functions

I have run many timing tests, to compare using shell templates which contain #invoke versus direct use of {#invoke:}, and for tiny templates, such as string-handling functions, the template versions often ran upto 50% slower than direct #invoke of each tiny Lua function. The related, but separate issue, for speed of #invoke, can quicken every use of Lua, if 1.22wmf1 successfully doubles the speed of each #invoke. The #invoke speed in March 2013 has been about 180/second, compared to short templates running 350-600 per second, or parser functions >750/second, or character-insertion templates running 2,400/second. Similar to avoiding use of prior utility templates, when writing other utility templates, I would recommend to use the direct #invoke to access Lua functions from a utility template. Each layer of "shell templates" (to #invoke a Lua function) also increases the expansion depth by about +2 levels of the 41-level limit (shows "41/40"). For infoboxes, which use just a few Lua functions, then running the shell-template versions, rather than direct #invoke in the infobox, would be efficient enough, but still must beware the +2 expansion depth when running a shell-template version instead of direct #invoke in the infobox. -Wikid77 (talk) 19:29, 22 March 2013 (UTC)

Moving modules

When moving a module there is no redirect left behind and existing invocations should be fixed. The message from MediaWiki:Movepagetext-noredirectfixer should warn about this, perhaps a warning like MediaWiki:Moveuserpage-warning. Currently it is misleading advising to check for double redirects. Also, this page should explain that it is not possible to move a module to another namespace or vice versa, except doc pages (I think). --Vriullop (talk) 11:07, 22 March 2013 (UTC)

Sandbox naming pattern

At the moment, we have three patterns in naming a module sandbox page:

  1. Module:Citation/CS1/sandbox
  2. Module:User:Dcoetzee/Sandbox
  3. Module:Sandbox/isaacl/ColourSpace/Tuple

I suggest that is one too much. To maintain similarity with other sandbox pages (in template space and user space), I propose:

  • #2 pattern should use lowercase /sandbox.
  • Ditch the Module:Sandbox/isaacl ... pattern.

If we agree on this, we can encourage/discourage patterns. -DePiep (talk) 11:51, 22 March 2013 (UTC)

I think I started the Module:User/Sandbox pattern, before all the Module:X/testcases pages began. But before I switch ... where are we getting the lowercase pattern from? We have pages like WP:Lua/Modules, WP:Reference desk/Science. I remember there is some bug involving upper case and sandboxes, but I think that only affects the Module:Sandbox/Name pattern that you would be avoiding (not sure I have that right though). Still, I agree on the desire for consistency - at some point we want Lua virgins to be able to click on a link to "My Lua Sandbox" and get to a standard location. Wnt (talk) 13:20, 22 March 2013 (UTC)
The lowercase is used in both template and user space. This is possible because they are subpages always (by common practice). Subpages are fully case-sensitive (X/Sandbox =/= X/sandbox). Differences between spaces are irksome, so I suggested lowercase in Module too.
I don't know if there is a bug associated with Module:Sandbox/.... But surely the first letter of a page title is capitalised (also when creating Module:cherry). This would prevent us from writing the lowercase consistently everywhere. Anyway, if we discourage the third option, this question is gone. -DePiep (talk) 16:46, 22 March 2013 (UTC)
I started pattern 3. I have to say I'm not fond of pattern 2. The pseudo-namespace "User:" embedded in it is quite unlike the naming pattern of any existing pages and looks like a kludge. The other benefit of Module:Sandbox is that it's searchable with Special:PrefixIndex, allowing the Lua learner (most people at this point) to explore anyone else's experimental code that's put there. Pattern 2 creates silos. — Hex (❝?!❞) 16:09, 22 March 2013 (UTC)
Good points. The main goal is to have only two patterns, whichever. And this early in the development, that is easier to achieve. I'll drop a note in VPT. -DePiep (talk) 16:55, 22 March 2013 (UTC)
May I restate. The issue is simply limited to User sandboxes. Otherwise, any Module can use a sandbox. -DePiep (talk) 01:18, 23 March 2013 (UTC)
When I think about it, I see a subtle difference between the meaning between "Module:User:" and "Module:Sandbox/". I checked WP:About the Sandbox and noted this definition: "The Wikipedia Sandbox is a page designed for testing and experimenting with wiki syntax"; therefore to me, "Module:Sandbox/" are just for temporary testing purpose. And for "Module:User:", I imagine that is the place to reside any modules for long-term personal use, (though I can't come up with a use case for that now). To me, this is like the difference between a User page and the WP:Sandbox; while one can use one's own User page to actively experiment wiki syntax, User page should better contain long-term and useful contents.
And after all, I agree to figure out the naming early. – PeterCX&Talk 01:05, 23 March 2013 (UTC)
I'm not sure what "silos" are about, but the appeal of keeping a separate module "userspace" is that people will often want to work on a module but then put it aside for a while. To figure out bugs, html code, etc. while keeping it out of the way, so people don't settle on it for a template and have it submerge unexpectedly. Wnt (talk) 03:46, 23 March 2013 (UTC)
Is requesting on bugzilla a way to have Lua modules in some sort of userspace a good idea? Maybe a "User Module:" namespace? Martijn Hoekstra (talk) 15:27, 14 May 2013 (UTC)

Passing 1,000 parameters exponentially slower

While running tests to simulate a large #switch function of 3,000 branches, I repeatedly confirmed how passing thousands of parameters is typically exponentially slower beyond the first 500 parameters. Hence, passing 2,000 parameters runs 3 seconds, 4,000 parameters runs 13 seconds, or 6,000 parameters run 27 seconds. It would be much faster to pass a single parameter, as a single string of delimited choices, alternating with resultant values, rather than try to pass 3,000 choices as 6,000 parameters, which has been running about 27 seconds in the parser. Although Lua can still process the 6,000 parameters, to compare choices, within "0.02" Lua seconds, the load time of the #invoke interface is 27 seconds. The NewPP parser hits the huge delays when passing 6,000 parameters whether to Lua, or to a template, or to a #switch parser function of 6,000 "|x=" branches.

Time-delay formula: The initial tests show a time-delay formula as roughly delay=3^(n/2000) seconds, where n is the number of parameters passed, and for n=6,000, the delay has been 3^3 or 27 seconds, or for n=7,000 then the delay has been 3^3.5 or 47 seconds. Formula: Of course, the specific delay depends on server load, but follows the general exponential slowdown formula, where 7,000 parameters is far slower than a linear extension of 7000/6000 or 17% slower, and runs closer to 47 seconds (+70% slower) rather than 27+17%=31.6 seconds.

Affects Lua, templates & parser functions: Again, the time-delay overhead, to pass thousands of parameters, not only affects the Lua #invoke interface, it extends the same exponential time-delay slowdown in passing parameters to templates as well as "|x=" branch-choices in a #switch function (which also runs 27 seconds to process 6,000 branches). Passing just 1,000 parameters run about 1 second, and splitting 6,000 into 6×1,000 groups could process all 6,000 within 6 seconds, rather than 27.

Hence, for Lua, the alternative is to pass fewer parameters, but as strings of choices delimited by separator characters within each string. -Wikid77 (talk) 12:07, 24 March 2013 (UTC)

Why on Earth would you construct a Lua-based switch that way? If you want it to be fast, the switch options should be stored in Lua and cached with mw.loadData. Trying to import thousands of options via invoke just seems like the wrong way to go about it. Here is an example of a switch alternative that processes 6000 options in about 10 ms using Module:Switch: {{#invoke: Switch | switch | list=Switch/LongTest | case=6000 }}, where the case values are stored in Module:Switch/LongTest. Dragons flight (talk) 15:52, 24 March 2013 (UTC)

when to use mw.title.new

While we're at it - could somebody explain our decision tree for when to use mw.title.new, mw.title.makeTitle, mw.loadData, or to pass the page into the module as a transcluded parameter? Wnt (talk) 21:44, 24 March 2013 (UTC)
While we're at it you say - I don't get the joke. I made it a new thread. -DePiep (talk) 00:05, 25 March 2013 (UTC)
mw.title.new() uses the namespace in the string, if any, while mw.title.makeTitle() forces the specified namespace. mw:Extension:Scribunto/Lua reference manual#mw.title.makeTitle has an example illustrating the difference. Whether it's "better" to use mw.title.getCurrentTitle().prefixedText or to pass in {{FULLPAGENAME}} as a parameter, I don't know.
mw.loadData() can be used instead of require() to load a very large submodule that returns only data when the requiring module is likely to be used multiple times per page. It has nothing to do with the mw.title methods. Anomie 23:48, 24 March 2013 (UTC)
Well, you can also get data by opening a page with mw.title, or by transclusion. Does loading a module full of data have any advantages? To me it seems like it is more user-friendly to have data files independent of Lua code so that people who don't know it can work on them. Isn't it? Wnt (talk) 03:32, 25 March 2013 (UTC)
Information loaded via mw.loadData is parsed into a Lua table once per page render. Information passed via mw.title or transclusion will have to be parsed during every #invoke call, which may translate to many occurrences per page render. Hence, if a large table is likely to be needed during many separate invoke calls, then there is an inherent advantage to using mw.loadData. Dragons flight (talk) 04:10, 25 March 2013 (UTC)
Oh, OK. So Module:Sprite would be a good candidate for this: I was thinking to use it for pages with 170 flags, so 170 calls, and the whole point is to be super efficient if it can be. Wnt (talk) 04:23, 25 March 2013 (UTC)
Well, I transferred it over to use this... one 'feature' is that the data for loadData needs to be in Module: space. Given the extreme restrictions I would wonder if this restriction can be relaxed, but ... well, anyway, for now I can do it, but I'm sensing a tsunami of extra module: names (one for each file in this case; for other modules one for each page). Wnt (talk) 05:04, 25 March 2013 (UTC)

Frame question

I've been trying to get to grips with the concept of frames, and I think I'm almost there. There are still a few things I'm not sure about, though. For example, Module:Navbar contains the code:

    local origArgs
    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame
    end

In what case would frame not be equal to mw.getCurrentFrame()? Does this apply if you are accessing the module from another Lua module, and not directly from a wiki page? Or is it something else? If anyone could help me to work this out I'd be very grateful. Best — Mr. Stradivarius ♪ talk ♪ 10:42, 27 March 2013 (UTC)

  • The if and else statements respectively seem to correspond to line 1 and line 2 of the comments at the top, judging by this. It seems that local args (e.g. for testing), rather than args passed via invoke, are described here; possibly refers to this example. LittleBen (talk) 11:21, 27 March 2013 (UTC)

You've got it pretty much right. That's a bit of boilerplate code that I've been using in all the modules I write. The first clause supports the case where the module is being invoked from a template as {{#invoke: Navbar | navbar}}. The second clause supports a simple way to invoke the function from another module (such as from Module:Navbox), or from the debug console: Navbar.navbar({arg1 = 'foo', arg2 = 'bar'});. In Module:Sidebar, I extended the boilerplate further to allow a third way, invoking the module from a template and passing args in explicitly (instead of using whatever args were passed to the template), like {{#invoke: Navbar | arg1 = foo | arg2 = bar}}. Toohool (talk) 17:18, 27 March 2013 (UTC)

Thanks for the replies! This makes a lot more sense now - basically, I need to start using the debug console. :) I'm going to pinch that code from Module:Sidebar as well, as it's just what I need. — Mr. Stradivarius ♪ talk ♪ 18:29, 27 March 2013 (UTC)

I have another related question. I've been trying to use some of the other frame functions, and I can get them working via #invoke, but not through the debug console. For example, Module:User:Mr. Stradivarius/sandbox2 produces the right result when used via invoke from User:Mr. Stradivarius/Sandbox, but when I use the code = p.test() in the debug console I get the error "Lua error at line 4: attempt to index local 'frame' (a nil value)." What am I doing wrong? — Mr. Stradivarius ♪ talk ♪ 16:45, 29 March 2013 (UTC)

You're not passing it a frame, so frame in your function is nil.
You can use mw.getCurrentFrame() to get a frame (i.e. call your function as =p.test( mw.getCurrentFrame() )), and if you need to put arguments into the frame you can use mw.getCurrentFrame():newChild(). Anomie 01:00, 30 March 2013 (UTC)
mw:getCurrentFrame():newChild() can also be used as an alternative to adding an exception for when frame is not mw:getCurrentFrame() to functions. --darklama 01:20, 30 March 2013 (UTC)
Thanks both of you, that really helps. I've started using the code in the debug console for testing:
frame = mw.getCurrentFrame()
frame.args = {"a", "b", c="d"}
=p.test(frame)
That way everything works as it should. I'll have to add all of this to the help pages at some point, as I'm sure others will be having the same problems. Best — Mr. Stradivarius ♪ talk ♪ 04:28, 30 March 2013 (UTC)
p.test(mw:getCurrentFrame():newChild{title='A', args={"a", "b", c="d"}}); is like your example using newChild, with the addition of title which may be needed by some methods of frame. Using newChild twice can also be useful to test the getParent() cases as well, which some functions may assume exist:
 p.test((mw:getCurrentFrame():newChild{
   title = 'B',
   args = { "a", "b", c="d" }
 }):newChild{
   title = 'A',
   args = {}
 })
Also your example may have the unintended side effect of changing an attribute for the current frame anywhere the current frame is used, where as newChild creates a new copy. --darklama 13:19, 30 March 2013 (UTC)

Lua replacement for {{Repeat}}

I decided to implement a Lua replacement for the innards of {{Repeat}} as a learning project for my first Lua module. Please take a look at Module:RepeatString and Template talk:Repeat and see what you think. My initial thought is that having a module named after a single string function may be a bit extravagant, so perhaps it would be better grouped with other similar functions, if those exist somewhere. — Hex (❝?!❞) 16:49, 3 April 2013 (UTC)

Any reason you aren't using the builtin "string.rep( str, n )"? Dragons flight (talk) 17:01, 3 April 2013 (UTC)
Because I didn't know about it? Well, that makes that easier, then. Ho hum! I'll fix it up tomorrow when I next have some code time, then. Thanks for the tip! — Hex (❝?!❞) 17:17, 3 April 2013 (UTC)
Hmmm, you inspired me to write Module:LuaCall, with one small caveat... it doesn't work. Apparently tostring(_G["string.rep"]) is "nil", not "function". If anyone points me to the right tree I'll be grateful. (No, coroutines are not implemented) Wnt (talk) 16:01, 17 April 2013 (UTC)
That's because if you use "string.rep" Lua tries to find a key called "string.rep" in the table _G, but that key doesn't exist - there's only one called "string". Instead you can use tostring(_G.string.rep) or tostring(_G["string"]["rep"]). — Mr. Stradivarius ♪ talk ♪ 16:36, 17 April 2013 (UTC)
I should have thought of that! Somehow I just assumed the periods would be parsed like the rest of it. Anyway, I now have it working, so
{{#invoke:LuaCall|main|a=test |b=7|string.rep(a,b)}} produces
testtesttesttesttesttesttest
Wnt (talk) 19:49, 17 April 2013 (UTC)

Lua module rating

I've created five categories for different levels of Lua module progress: since each explains the others, Category:Modules in alpha should be sufficient. In brief, the categories I set up were pre-alpha, alpha, beta, release, and protected. Right now I'm putting ratings on the documentation subpages, which I think is what someone suggested before at one point for categories. My own modules populate only the pre-alpha and alpha categories, but there are some here which I know have reached the other levels. I would welcome comments, and if people think the scheme is OK, please consider rating your modules... Wnt (talk) 23:31, 16 April 2013 (UTC)

Looks like a good idea, and the categories look sensible. How about using a template instead of typing in the whole category every time? I'm thinking of something where you could type, say, {{module rating|alpha}} at the top of the /doc subpage, and it would generate a notice and categorise the module in one go. — Mr. Stradivarius ♪ talk ♪ 02:15, 17 April 2013 (UTC)
In fact, I've gone ahead and created a pre-alpha version of {{module rating}}. Have a play around with it and see what you think. — Mr. Stradivarius ♪ talk ♪ 02:49, 17 April 2013 (UTC)
My lord, but you've just given me the idea for the kind of awful hack I think of that makes Anomie giggle (I hope). We could have an editnotice for the entire Module: namespace which #invokes a module that reads the doc namespace and looks for your template and then returns the Category: tag to be displayed on the Module instead of the doc page... nay, forget I ever said anything. :) Besides, I'm not actually that leet - I still haven't actually figured out how the heck Module:BananasArgs/testcases is placed in a category, and that's a "hello world" program! Wnt (talk) 14:27, 17 April 2013 (UTC)
That would be {{Module test cases notice}}. I found that out from the "View templates on this page" section on the edit screen of the template. I assume that this is done by some magic somewhere in the MediaWiki namespace, but I wasn't leet enough to find where it is. :) The hack I used should have the same effect though - the template just checks that the subpage name isn't "doc" and categorises all other pages - which yes, includes the module pages. I've put it in action on my modules already - see Module:Csdcheck and Module:UrlToWiki for a couple of examples. — Mr. Stradivarius ♪ talk ♪ 14:51, 17 April 2013 (UTC)
Oh, of course! I should have realized that since doc is already transcluded you can just do that. Meanwhile, I found the code at Template:Editnotices/Namespace/Module - but not by a proper method, but by an ad hominem search of the editor TheDJ on the notice you found. Wnt (talk) 15:13, 17 April 2013 (UTC)
That ad hominem search was a good idea - the MediaWiki pages are MediaWiki:Scribunto-doc-page-show, MediaWiki:Scribunto-doc-page-does-not-exist, and MediaWiki:Scribunto-doc-page-header. We might be able to do some category magic with those if there's a good reason for it. — Mr. Stradivarius ♪ talk ♪ 15:43, 17 April 2013 (UTC)
Thanks. By the way - you've made a great choice of icons so far, and I was wondering if you can suggest one more: we should have a category for pages that will never be rated because they are "Hello world" programs, teaching demonstrations, bug examples, user scripts, sandboxes etc. Wnt (talk) 16:29, 17 April 2013 (UTC)

How to share code among wikis (like for images in Commons)

I have opened a discussion here: en:Module_talk:String#Replication on other wikis. Cya. --Rotpunkt (talk) 12:35, 1 May 2013 (UTC)

Would be nice for example if the modules on Commons (http://commons.wikimedia.org/wiki/Commons:Lua/Modules) could be called from all wikis, so that we could put there the most used libraries (like String), in the same way we use Commons for images. --Rotpunkt (talk) 12:46, 1 May 2013 (UTC)
A central code wiki is planned, but no date is set to start working on it yet. Note this central code wiki is not going to be Commons; they don't want to be it, and I know there are some in the community who wouldn't want it there either. BJorsch (WMF) (talk) 00:15, 2 May 2013 (UTC)
Thanks for answer. Which are the problems with sharing the modules on Commons among wikis in the same way we already share images from it? I am new to Scribunto, but I tought it was an ideal pattern. Anyway if with "central code wiki" you mean a way of sharing modules like we share images from Commons now, it would be perfect! I think that such a repository (Commons on something else) for sharing code without cut&paste over and over among wikis is essential, already in the first stages of this project for avoiding a useless fragmentation (like 22 versions of String [2]).--Rotpunkt (talk) 10:53, 2 May 2013 (UTC)
Because code was specially written for images, and the existing code for attempting this doesn't work very well. And for Commons specifically, as I said, Commons doesn't want to be the central wiki for code and some people don't want them to. BJorsch (WMF) (talk) 11:14, 2 May 2013 (UTC)
Thanks again for the explanation. Anyway, you talked about a "planned central code wiki". Will it work in the same way ("write once and run on each wiki")? can I find some discussion or project documentation about it? thanks in advance. --Rotpunkt (talk) 17:45, 2 May 2013 (UTC)

Is there a counting page element module yet?

Hello, I'm wondering if there is currently a module that counts elements on a page. Perhaps li in a list or tr in a table? Technical 13 (talk) 12:12, 9 May 2013 (UTC)

Scribunto is intended to insert into a page the wikitext returned from running a Lua script. However, input to the Lua script consists of arguments explicitly passed in the {{#invoke}} that runs the script, and any arguments passed by wikitext to a template, where the template invokes the script. In other words, it is not possible to pass HTML or a selected portion of the wikitext in a page to Lua. There are some "expensive" (that is, slow) procedures that allow a script to read the wikitext of an entire page. I haven't tried that, but I suspect it would not be useful for more than occasional use. Johnuniq (talk) 01:18, 10 May 2013 (UTC)
Well, there is Module:TextMarkup. It counts the number of {{inc}} templates on a page. I suppose you can modify it to fit your needs. Just use it with care, like Johnuniq mentioned.--Snaevar (talk) 10:41, 10 May 2013 (UTC)
Thank you both for your answers. This question was not actually a question for me, but more as a follow up question for a {{Help me}} request on Help talk:Template#Counting items in numbered list (and I subsequently found out WT:WikiProject Templates#Counting items in numbered list and Wikipedia:Help desk#Counting items in numbered list too). I've linked back here so that if the original asker would like to try using the Module User:Snaevar has mentioned, they will likely have a lot of questions need some assistance in doing it. Anyways, I feel that my work is done for that request. Have a nice day! Technical 13 (talk) 11:38, 10 May 2013 (UTC)

fullurl magic word equivalent

What is the equivalent of {{fullurl:page name}} ?

I have used the mw.title library with a call like mw.title.new(page_name):fullUrl({uselang=lang}), but mw.title.new() is marked as an expensive function so I would like to known if there are alternative.--Moroboshi (talk) 07:06, 18 May 2013 (UTC)

mw.uri.fullUrl(mw.title.getCurrentTitle().text)Bility (talk) 07:22, 18 May 2013 (UTC)

Use of Mediawiki API

Is there a way to use the Mediawiki API inside Lua? Greetings Stephan Kulla (talk) 15:54, 19 May 2013 (UTC)

No, and the general view is that Lua should not be able to make HTTP calls, so it is unlikely that any access to the API will be added. That said, it is envisioned that Lua will ultimately be extended to allow access to most of the same Mediawiki information that one can get from the API. Dragons flight (talk) 19:54, 19 May 2013 (UTC)
Thanks for your answer Stephan Kulla (talk) 20:26, 19 May 2013 (UTC)

Module Help

(Sorry for writing here. if u can help me)
I imported Module:Citation, Module:Citation/CS1/Configuration, Module:Citation/CS1 in bn.wikipedia. after imported i find error in article with this Category:Pages with script errors. now i wanted to translate Category:Pages with script errors in bn language. how can i do this (on which module, i find this Category for translation). --Aftab1995 (talk) 15:50, 23 May 2013 (UTC)

You can translate "Pages with script errors" on betawiki:MediaWiki:Scribunto-common-error-category/bn, in translatewiki. If you have not translated before there, then you will need to create an account and ask for translator rights.--Snaevar (talk) 20:40, 23 May 2013 (UTC)
Thanks--Aftab1995 (talk) 14:32, 25 May 2013 (UTC)

Template:FlagiconLua reaches feature parity with Template:Flagicon

I'm very happy to announce that Template:FlagiconLua has reached feature parity with Template:Flagicon! It relies on Module:Sandbox/QuimGil/Flagicon, which provides the logics, and Module:Sandbox/QuimGil/FlagTranslations, where the flags data is stored. See the demos and more details at WikiProject Flag Template. I'm a rookie! Your help pointing to ways to improve is welcome. Also, your feedback here about the best way to organize the data is also welcome. Thank you!--QuimGil (talk) 07:52, 21 June 2013 (UTC)

mw.ustring.byteoffset bug

Does mw.ustring.byteoffset work correctly with negative offsets? Putting the following into the debug window gives the values shown:

for i = -1, -5, -1 do print(i, mw.ustring.byteoffset('abcde', 0, i)) end
-1   3
-2   2
-3   1
-4   nil
-5   nil

I don't need the function—I'm just asking if it has a bug. Johnuniq (talk) 02:22, 25 June 2013 (UTC)

Yes, that's a bug. Anomie 14:07, 25 June 2013 (UTC)

Returning the concatenation of numerous words

Sorry if this was discussed before, but I did not find relevant links in a couple of minutes.

At Module:DisplayLuaTableContents I see numerous loops as

   for a,b in pairs(j) do
      output = output .. blah-blah-blah
   end

, but I learned that strings are immutable and hence this assignment is rather costly. What should I do to return a large text built from numerous smaller elements? Should I return a sequence of hundreds of strings relying on Scribunto in concatenating it? Incnis Mrsi (talk) 11:59, 2 July 2013 (UTC)

P.S. mediawikiwiki: Extension:Scribunto/Lua reference manual #table.concat is apparently a solution, but I didn’t test it yet. Incnis Mrsi (talk) 12:11, 2 July 2013 (UTC)
You might find string.format useful - see this discussion for some examples. I'm not sure how costly concatenation is, but I'd be interested to hear more if anyone knows. — Mr. Stradivarius ♪ talk ♪ 12:28, 2 July 2013 (UTC)
You can insert your words in a table (table.insert(output_table, word)) and concatenate that table at the end with the function that Incnis Mrsi gave (output = table.concatenate(output_table)). That way the string output will not have to be recreated every time a new word is appended to it. Darkdadaah (talk) 15:00, 2 July 2013 (UTC)
I prefer to not to sweat the small stuff. If something like this is more readable, and the table contains 10 elements, than I don't think anyone will care how performant your solution is. If it's 10.000 elements, that might be a different case. Martijn Hoekstra (talk) 15:47, 2 July 2013 (UTC)
I've written some of these larger data-processing functions and it is definitely the case there - it absolutely makes the difference between being able to run the script or not; you can have more than a 10-fold reduction in your overall run time. Wnt (talk) 17:02, 18 July 2013 (UTC)
You can look at user:Incnis Mrsi/UCS map for a wiki table built with table.concat of about 1,500 pieces. The module uses string.format only for hexadecimal and has not (yet) a single output = output .. blah-blah-blah. Incnis Mrsi (talk) 17:26, 12 August 2013 (UTC)

We need a common repository for Scribunto modules and templates

Hi, your feedback is welcome at Bug 50329 - We need a common repository for Scribunto modules and templates. Please don't take those *personal* suggestions as a criticism to Wikipedia:Lua. I'm a happy user of this space myself with the pet projects I develop in my free time. It's just that a central repository would be so beneficial for everybody (en.wiki devs/editors included) and en.wiki can't really be (in my honest and personal opinion) that place. With a clear upsream in a central place like mediawiki.org then en.wiki and other Wikimedia projects could work better on local support and whatever is specific to their communities. Thank you for your attention!--Qgil (talk) 21:16, 2 July 2013 (UTC)

Module to compare two templates

I created Module:Testcase table, and it seems to work pretty well (see the current transclusions). I was wondering if there is a way to improve the performance. for example, make this work without copying the args to a new table? I was going to deploy it on Template:Year in other calendars/testcases, but in my preview it runs out of time by the time it gets to the last test. also, if someone already wrote a module that does the same thing, let me know and I will have this one deleted. thank you. Frietjes (talk) 00:03, 4 July 2013 (UTC)

I had a go, and you can't pass the arguments through directly from the frame object, as Lua only retrieves them on demand. I also used mw.ustring.format() instead of concatenation to generate the results table, which may have some (small) performance benefit. But most of the slowness is coming from the templates themselves rather than from your module. I was actually considering rewriting Template:Year in other calendars, as doing the maths in Lua would be much more efficient. Anyway, for whatever reason I was able to convert Template:Year in other calendars/testcases to use {{testcase table}}, so that is working at least. — Mr. Stradivarius ♪ talk ♪ 14:44, 4 July 2013 (UTC)
thank you! I remove the intermediate res1 and res2 variables, which also appears to have helped, although it may be that I got lucky and a faster server was used to parse it. rewriting the {{year in other calendars}} template does seem like a good idea. Frietjes (talk) 15:08, 4 July 2013 (UTC)
I don't think the fact that the test cases displayed had anything to do with this edit. Unlike using triple braces in wikitext, assigning variables like that in Lua takes almost no resources, so you may as well go ahead and do it if it makes the code easier to read. In fact, the performance gains in Lua compared to parser functions are so great that it isn't a big deal at all to add input checks for all your functions or to use meta-modules like Module:HtmlBuilder. Performance does matter in some situations, but readability and maintainability of code is usually more important. Best — Mr. Stradivarius ♪ talk ♪ 14:15, 5 July 2013 (UTC)
good to know. my impression is that if I get the ran-out-of-time script error, it will frequently go away the second time I try to save the page. so, it seems like the server cached the code, and the second time it ran faster. in any case, any improvements to the performance of the 'year in other calendars' template would certainly improve the situation. thank you again. Frietjes (talk) 15:34, 5 July 2013 (UTC)

Lua talk template

At the moment we have the {{lua talk}} template to use on talk pages of templates converted to Lua. I think that this is less effective than it could be, however. How about expanding the template's function so that we can also put at the top of template /doc pages? That way it would be obvious straight away which templates have been converted, and would help advertise the fact that we have this neat new programming language available and that we need people to convert existing templates over. We could also use the template to automatically add Category:Lua-based templates to keep track of converted templates more easily. What do people think? — Mr. Stradivarius ♪ talk ♪ 12:54, 10 July 2013 (UTC)

Good idea, I support this.--Kozuch (talk) 09:05, 19 July 2013 (UTC)
Thanks! Actually, I went and implemented this on all my module-based templates yesterday. See for example Template:For loop. I'll go through and do a few more now leaving a link back here in case people want to comment. — Mr. Stradivarius ♪ talk ♪ 09:45, 19 July 2013 (UTC)
I've gone through and added {{lua}} to about half of the pages in Category:Lua-based templates (from A to O). If there are no objections, I'll do the rest over the next few days. — Mr. Stradivarius ♪ talk ♪ 11:07, 19 July 2013 (UTC)
An improvement. Could we allow overruling the cat for a subcategory, like Category:Lua String-based templates (existing) or Category:Lua mathematical templates. I have no actual request for such a category. -DePiep (talk) 23:25, 19 July 2013 (UTC)
Good idea, and done. I was thinking that we probably needed to do that as well. — Mr. Stradivarius ♪ talk ♪ 03:33, 20 July 2013 (UTC)

Lua header: module list incomplete

We have {{WikiProject Lua/header}} that does the header tabs (I started). Now the tab "Modules" does not show all modules, and does not have a 'next page' link. Can someone make a nice SpecialPages adjustment? -DePiep (talk) 23:30, 19 July 2013 (UTC)

There is {{Alpha prefix pages}}, but if we used that then modules that start with non-alphanumeric characters wouldn't be listed. Perhaps this would be better than having half the modules not show up at all, though. — Mr. Stradivarius ♪ talk ♪ 12:05, 26 July 2013 (UTC)

Do these modules do the same thing?

Do Module:WikiLink and voy:ru:Модуль:Wikilinks effectively aim to do the same thing? If so, I can add Module:WikiLink to d:Q14746829. Thanks. It Is Me Here t / c 15:08, 3 September 2013 (UTC)

Sorry for the very late reply. The answer is no, they do really quite different things. They probably shouldn't go in the same Wikidata entry. — Mr. Stradivarius ♪ talk ♪ 14:27, 7 October 2013 (UTC)
Thank you! It Is Me Here t / c 17:02, 10 October 2013 (UTC)

Scribunto issue when output has pre tags

Is a module supposed to do something clever in order to output tags? I want to output wikitext like this:

<pre>
First line.
Second line.
</pre>

I have previously done that and it worked well, but when the text between the tags is more varied, something breaks. A very simple test is:

  1. Module:Sandbox/Johnuniq/testpre ∙ outputs some fixed text in pre tags
  2. Module talk:Sandbox/Johnuniq/testpre ∙ current content {{#invoke:sandbox/Johnuniq/testpre|main}}
  3. Module talk:Sandbox/Johnuniq/grosstonnage ∙ created with content {{subst:#invoke:sandbox/Johnuniq/testpre|main}}

Result #2 is broken—the first line includes a working wikilink (should not happen inside pre, but would happen if had a single space at the beginning of the line, with no pre). Result #3 works correctly. Is this a problem in my module or in Scribunto? What I'm trying to do is much more complicated, see Module:Convert/makeunits, but is the same issue. Johnuniq (talk) 09:37, 7 October 2013 (UTC)

I've noticed this before as well. I agree that it looks like something that probably shouldn't happen - I suggest filing a bug in bugzilla and seeing what the devs say. In the meantime, to get the result you want you can either preprocess the text using frame:preprocess, or you can use mw.text.nowiki on the string between the tags. (The nowiki function will escape html entities, but preprocessing won't.) — Mr. Stradivarius ♪ talk ♪ 11:38, 7 October 2013 (UTC)
It's not a bug. <pre> having the effect of <nowiki> is handled as an extension tags (<nowiki> itself is too, for that matter). And as documented, extension tags are not processed in the wikitext returned by Scribunto, so what you're getting is the <pre> HTML tag rather than the <pre> wikitext tag.
And yes, because <pre> is handled as an extension tag, you could do
frame:extensionTag( 'pre', html, {} )
if you really wanted, although using mw.text.nowiki might be better. Anomie 18:39, 7 October 2013 (UTC)
Thanks all. I did some experimenting with the four methods—see Module talk:Sandbox/Johnuniq/testpre which shows each method mentioned above. Only "mw.text.nowiki(plain_text) in per tags" fully preserves the text (the others render "&nbsp;" as a single nonbreaking space, which is what per does). Another point of minor interest is that this method preserves the tab characters which are in the text, whereas the others don't. Re the Scribunto docs: they are very good in general, but another thirty lines is needed to explain the implications of some of the more esoteric points. Johnuniq (talk) 01:37, 8 October 2013 (UTC)

Another test system

Anyone interested in testing templates may want to try Module:Convert/tester which allows hundreds of tests to be easily defined. The system compares actual template output with fixed text, and is only suitable for templates and results that are reasonably short because each template and its expected result have to be in one line. If those restrictions are not a problem, the new tester provides a convenient way to set up tests on any page, for example:

<pre>
{{convert|12|m}}                            12 metres (39 ft)
{{age|1989|7|23|2003|7|14}}                 13
{{age in days|2007|5|24|2008|4|23}}         335
</pre>

If the above tests were at page "Template:Example/tests", the following would insert a table showing the results of expanding each template and comparing its output with the expected text.

{{#invoke:convert/tester|run_tests|page=Template:Example/tests}}

Johnuniq (talk) 06:53, 11 October 2013 (UTC)

This does look rather nice. I might use this in the future. — Mr. Stradivarius ♪ talk ♪ 13:56, 13 October 2013 (UTC)
I've added make_tests and check_sandbox. The former generates the expected output in the required format, and the latter compares a module with its sandbox version, see the doc. Johnuniq (talk) 00:54, 14 October 2013 (UTC)

GetURL?

Doesn't Wikipedia's version of Lua allow the GetURL function (or equivalent)? I get an error message when I use it. — Preceding unsigned comment added by Ryn78 (talkcontribs) 03:27, 13 October 2013 (UTC)

There are a lot of functions to process URLs in Scribunto (that's the name of Wikipedia's version of Lua). What exactly are you looking to do? — Mr. Stradivarius ♪ talk ♪ 13:56, 13 October 2013 (UTC)
Scribunto does not include a function to fetch an arbitrary URL. GetURL does not appear in standard Lua either; presumably it is something added by whatever other Lua-using platform you are used to working with. Scribunto does include functions for accessing the content of pages on the local wiki, and for constructing and parsing URLs. Anomie 20:35, 13 October 2013 (UTC)
Does it include functions to get the user name and/or IP address of the person accessing the page? Ryn78 (talk) 20:58, 13 October 2013 (UTC)
No. Scribunto runs during the page parse, and visitors are served cached pages as much as possible. See mw:Extension:Scribunto/Lua reference manual to see what is included. Anomie 22:04, 13 October 2013 (UTC)

Calling a module from another module?

Is it possible for a module to invoke another module? I did not see any mention of this in the tutorial.--greenrd (talk) 10:04, 19 October 2013 (UTC)

Yes, it is - you need the require function. :) — Mr. Stradivarius ♪ talk ♪ 10:16, 19 October 2013 (UTC)

Use tabs instead of four spaces?

I've started up a new discussion about this at Wikipedia talk:Lua style guide#CodeEditor switched to tabs. Please comment over there if you're interested. — Mr. Stradivarius ♪ talk ♪ 01:15, 29 October 2013 (UTC)

Security?

How well does Scribunto defend itself against DoS, or possibly XSS, but especially DoS as we are dealing with a Turing-complete language? I ran some local tests and it seems pretty easy to crash it, but then again I'm running it in an unstable environment anyway so it may not reflect how things work here on Wikipedia. The fact that even an IP user may edit the module namespace suggests that it must be really stable and secure. Have there been any major incidents yet? Ginsuloft (talk) 13:39, 30 October 2013 (UTC)

I understand that there are a number of safety features in place. For example, an error is produced if Lua runs out of the alloted amount of memory (not sure exactly how much this is), and a different error is produced if the total runtime of a Lua script (or maybe all Lua scripts on a page?) is more than 10 seconds. I've encountered both of these while writing Scribunto code here. Other editors who are more familiar with the Scribunto internals might be able to give you more specific pointers. — Mr. Stradivarius ♪ talk ♪ 14:27, 30 October 2013 (UTC)
Oh, so these are memoryLimit and cpuLimit documented here. Hopefully it's per-page and not per-user, otherwise that'd be a quite serious DoS! Apparently it's Linux-only for now ("enforced using ulimit"). They should port it to Windows, so I can play around with it more; here's a tip in case the devs are reading this: GetProcessTimes(). Ginsuloft (talk) 15:01, 30 October 2013 (UTC)
The limits are per page. For the "luastandalone" engine, yes, they are enforced using ulimit which is not available on Windows, while for the "luasandbox" engine the limits are enforced for all platforms. Please feel free to submit code to implement a ulimit-like mechanism on Windows.
As for XSS, Scribunto modules' output is wikitext, so it's not possible to do any sort of XSS via Scribunto that isn't also possible in wikitext. If you do figure out a way, please report it as a security bug. BJorsch (WMF) (talk) 17:31, 30 October 2013 (UTC)

formatnum

currently, in Module:Historical populations, I am using a somewhat convoluted method to access 'formatnum' which involves passing 'frame' and using 'callParserFunction'. is there a better way to do this? thank you. Frietjes (talk) 16:17, 30 October 2013 (UTC)

Yes, that would be mw.language:formatnum. Enjoy. :) — Mr. Stradivarius ♪ talk ♪ 16:40, 30 October 2013 (UTC)
great. I am assuming that parseFormattedNumber is the same as {{#formatnum: ... |R}}? I will try it out. thank you. Frietjes (talk) 17:01, 30 October 2013 (UTC)
ugh, it looks like formatNum requires the input is a number, while the parserfunction uses a string, but it works! thank you. Frietjes (talk) 17:27, 30 October 2013 (UTC)

I am trying to create a weblink by concatenating 2 strings and by avoiding the display of the full link in an infobox. So the idea is the next one:

self.text = self.text .. '<a href="' .. args.weblink .. args.value '">' .. args.value  .. '</a></td></tr>'

But lua has a specific way to treat weblink and it is right now impossible to use a web address as a string. Does someone have an idea how to code this feature ? Snipre (talk) 07:52, 31 October 2013 (UTC)

This isn't a Lua problem, it's a wikitext problem - you can't use <a>...</a> tags in wikitext. Instead you need to use the wikitext format for external links, like this:
'[' .. args.weblink .. ' ' .. args.value .. ']'
See if that works for you. Best — Mr. Stradivarius on tour ♪ talk ♪ 08:04, 31 October 2013 (UTC)
Also, have a look at Help:Link for some more help with wikitext link syntax. — Mr. Stradivarius on tour ♪ talk ♪ 08:09, 31 October 2013 (UTC)
It works. thanks Snipre (talk) 08:20, 31 October 2013 (UTC)
you may also be interested in Module:URL, which does the same thing as what you are describing. Frietjes (talk) 17:57, 31 October 2013 (UTC)

Ifexist

Is there a LUA method for '#ifexist' that doesn't generate false incoming links? This came up over at Template talk:Historical populations. I bypassed the most serious problem, but for some reason the method is generating incoming links to nonexisting articles. For example, check Special:WhatLinksHere/3000 United States Census. Thanks! Plastikspork ―Œ(talk) 22:08, 2 November 2013 (UTC)

#ifexist generates "false" incoming links too. It's how MediaWiki tracks that the page using #ifexist depends on the existence of the target page. Anomie 01:51, 3 November 2013 (UTC)
For a little more, see Anomie's explanation at VPT here that any method to test for page existence (such as mw.title.new(page).exists at Module:Historical populations) will generate a "what links here" entry so the test can be re-run if the page's existence changes. Johnuniq (talk) 02:25, 3 November 2013 (UTC)

Module:Pagetype

I've created Module:Pagetype, a replacement for {{pagetype}}, and I am thinking of updating the template to the Lua version later on this week. The Lua version has some differences from the current template, so I would like to get others' comments before making the switch. Please let me know your thoughts over at Template talk:Pagetype#Module:Pagetype. — Mr. Stradivarius ♪ talk ♪ 14:16, 4 November 2013 (UTC)

Replacement for {{unsubst}}

If you're unaware, {{unsubst}} (along with a few other templates) is used to make it so that entering {{subst:citation needed}} in an article results in {{Citation needed| date=November 2013}} rather than dumping all the template code into the article.

So tonight I put together Module:Unsubst, which can be used to do the same thing without all the limitations of {{unsubst}}. Please take a look, critique it, test it, and let me know if there is anything that should change before I look at deploying it to some of the maintenance templates. Anomie 03:36, 1 November 2013 (UTC)

Many things there are way above my head, but I wonder if the following was intended:
    if string.find( v, '=', 1, true ) then
        -- likely something like 1=foo=bar, we need to do it as a named arg
        break
    end
If "1=foo=bar" is encountered, the loop will exit without processing parameters 2, 3, ... It doesn't look like anything bad would happen, but the logic seems strange. Johnuniq (talk) 07:00, 1 November 2013 (UTC)
No, it will process them, just as named parameters rather than numbered parameters. — Mr. Stradivarius ♪ talk ♪ 07:41, 1 November 2013 (UTC)
Sure, and as I say, nothing bad happens, but the logic is strange—why have a loop handling numbered parameters when it would quit if the first such parameter is "foo=bar"? If it's ok to skip parameters 2 and 3, why have the loop for numbered parameters at all? Johnuniq (talk) 09:16, 1 November 2013 (UTC)
If the user enters {{subst:foo|bar|baz}}, it would be nice to output the equivalent instead of {{foo|1=bar|2=baz}} because the latter isn't what users are going to expect. But if the user enters {{subst:foo|bar|baz|3=a=b}}, we must to do the last with the explicit 3= and we have to do any subsequent numbered parameters the same way. Anomie 11:39, 1 November 2013 (UTC)
Thanks–I have pondered related matters when executing frame:expandTemplate(t). I think the lesson is that if a template is called with {{foo|aaa|bbb|3=x=y|ccc}}, the template never sees "x=y" because parameter 3 is replaced with "ccc", so if this module receives "x=y" as parameter 3, any following numbered parameters would need a prefix to avoid replacing the "x=y" which, because it was seen, has not been replaced in practice. Johnuniq (talk) 06:56, 2 November 2013 (UTC)
I don't think there's anything that we can do about this, or indeed should do about it. A user substing a template with that code would lose their "x=y" no matter whether the template was using Module:Unsubst or not. And the limitations in the module brought about my the MediaWiki template system do not seem serious enough to outweigh the benefits of putting the module to use. I did wonder if users would be confused by the order of the parameters they put in being swapped around, but this beats having some of them disappear altogether (as in the current {{unsubst}}), or having a load of template code dumped in their article. I couldn't see any problems with the code - very nice work Anomie. :) — Mr. Stradivarius ♪ talk ♪ 11:50, 2 November 2013 (UTC)
So if anyone wants to try it out, I applied it to Template:Citation needed/sandbox. But since Gerrit change 93019 actually got merged quickly, I think I'll wait until November 14 (when I can use mw.isSubsting() instead of the frame:preprocess hack) to actually deploy it live. Anomie 02:50, 7 November 2013 (UTC)

Lua template style

User:Wnt and I have had a little disagreement over the type parameter of the {{lua}} template. Wnt thinks that the template should use the "style" type (with a yellow background), and I think it should use the "notice" type (with a grey background). I know we are quite far into WP:DEW territory here, but I'd appreciate it if people could comment at the discussion over at Template talk:Lua#Style. — Mr. Stradivarius ♪ talk ♪ 09:47, 11 November 2013 (UTC)

New overview function

I've updated Wikipedia:Lua/Modules/Overview using a Lua module to generate a table from various simple cut and paste data. Hopefully this will be semi-useful again. :) Wnt (talk) 08:16, 20 November 2013 (UTC)

page contents as import

Can Lua take the contents of a Wiki page, and reprocess it? For example, I might want to process the posts on a talk page, and add some extra formatting. --Iantresman (talk) 18:29, 7 December 2013 (UTC)

As you can read here: mw:Extension:Scribunto/Lua_reference_manual#Returning_text a module just returns a string, so it can't edit existing text in the page. You can anyway read the content of any page with the Title library and getContent(), and reprocess it in a different (empty) page (with only the #invoke:module). --Rotpunkt (talk) 20:07, 7 December 2013 (UTC)

Bad idea

I used to be an above average template editor, making significant contributions to even such intricate template as Ambox and Fix. This was possible because the wikimarkup language was very intuitive, and easy to understand even for the layman. Now, with this new LUA language, template editing is becoming more and more the domain of technicians. I very much regret that. I would have been able to continue contributing to these and other interesting templates. Debresser (talk) 10:57, 8 December 2013 (UTC)

There has always been the separation between: logic and data presentation. Data presentation is the field of templates (template are perfect for infobox, nav panels, ...). Logic is the field of lua and modules. In any framework/language, writing complex logic in template language is wrong. --Rotpunkt (talk) 11:37, 8 December 2013 (UTC)
@Debresser I find it interesting that you view it this way. I agree that for simple templates, not involving Lua makes it easier to see exactly what's going on; but the more complex templates are nightmarish without Lua: there are so many brackets involved that even simple changes may require serious concentration to get right. --Njardarlogar (talk) 13:39, 8 December 2013 (UTC)
These brackets can easily be counted, like the layers of an union. :) And layout (indentations) also is a useful indicator, as usual in programming. Debresser (talk) 14:45, 8 December 2013 (UTC)
I think that's the first time I've ever heard wikitext heavily using parser functions described as "very intuitive and easy to understand" rather than "almost as bad as brainfuck". Lua does tend to be easier to follow once you become familiar with the new syntax, and gives us some huge wins such as these replacements for the old versions of Template:str len and Template:str sub and their various subtemplates.
Unfortunately, the increase in power available to Lua has caused a bit of featuritis in some of the more complex templates. And it's still possible to write unclear code (OTOH, parser functions don't give you the option to write unclear code, they require it ). We do have Help:Lua for beginners, but I'm not really qualified to say whether it is really useful for beginners nor to fix the problems it might have. If you would like to take on the task of writing a better beginner's help page, I (and I'm sure others here) would be very happy to answer any questions you have. Anomie 13:49, 8 December 2013 (UTC)
@Rotpunkt I understand your point, but don't think that templates like Fix or Ambox are more logic than representation.
@Anomie Thank you for your offer. I doubt I will have time to take up your offer any time soon, but thank you. I actually did find WikiText intuitive, most of the time, and felt very good with it. Perhaps it connected with Pascal or HTML, which are two languages I am somewhat familiar with. Debresser (talk) 14:43, 8 December 2013 (UTC)

Namespace info box

Is the "Wikipedia namespaces" infobox necessary top right? I'd rather see useful LUA links. A cross between resources, documentation, and useful links. --Iantresman (talk) 13:14, 8 December 2013 (UTC)

Iterating library functions

I can acquire arguments using the frame.args object passed to a script using an iterator function:

for name, value in pairs(frame.args) do
    result = result .. '\n*' .. name .. ': ' .. value
end

But this does not seem to work for a library such as mw.site.*

for name, value in pairs(mw.site) do
    result = result .. '\n*' .. name .. ': ' .. value
end

I'd like to find out which mw.site library options are available, and print their value, without having to specify each one individually, ie. mw.site.currentVersion, mw.site.scriptPath, etc etc. --Iantresman (talk) 14:50, 8 December 2013 (UTC)

Err, did you mean to post basically the same thing twice? (now fixed)
When I try the quoted code, the error message given is "Lua error in console input at line 7: attempt to concatenate local 'value' (a table value).". This is because Lua will not automatically stringify anything other than a string or number. Try using tostring( value ) instead, or if you really want to get fancy you could look at the implementation of mw.logObject. Anomie 15:42, 8 December 2013 (UTC)
Oops, now fixed. Thanks for that. Makes sense. Where do I find the error message? --Iantresman (talk) 16:12, 8 December 2013 (UTC)
If you executed that via an invoke in a page somewhere, it should show up when you click on the "Script error" displayed. If you do it in the debug console at the bottom of any Module page, it shows up in there. Anomie 16:43, 8 December 2013 (UTC)
Easy when you know how, never knew "Script error" was a link, and the debug console is very useful! --Iantresman (talk) 17:44, 8 December 2013 (UTC)

Recursive iterating mw library functions

Is this the right place for Lua programming queries?

My new test module Module:Sandbox/iantresman/sandbox/archive/mw.recursive prints out "frame.args" arguments passed to it, but is not recursively printing "mw.site" library functions/table when accessed from User:Iantresman/sandbox/archive/mw.recursive. For example, it is not printing the string "mw.site.currentVersion", and only two "mw.site.stats" table rows, which might suggest it is not recursing properly, or perhaps something else. Is there a programme wizard who can help see if I've done something stupid? --Iantresman (talk) 11:31, 9 December 2013 (UTC)

It's not correctly printing out the "frame.args" arguments passed to it, it only prints out one. In your loop you're returning after the first key/value pair, instead of constructing a string with all the key/value pairs and returning the combined string. Anomie 12:41, 9 December 2013 (UTC)
I hacked it to get basic recursion working, but it is returning the f value twice for reasons of which I am not really sure. It also explodes when you try and use it with metatables; when using it with mw.site I got a "not enough memory" error. — Mr. Stradivarius ♪ talk ♪ 13:01, 9 December 2013 (UTC)
Many thanks for that. Do you think this is a bug in Lua, perhaps in garbage collection. I wouldn't have thought memory would be an issue. Shall I report it Mediawiki? --Iantresman (talk) 14:36, 9 December 2013 (UTC)
No. The problem is that mw.site.namespaces[0].talk.subject is a reference to mw.site.namespaces[0] itself, and the same for a bunch of other properties in there. Look at how mw.logObject tracks subtables it has already seen. Although even this doesn't work with mw.title objects, because those construct a new title object for some of their properties. Anomie 19:11, 9 December 2013 (UTC)
Does it make sense that they reference themselves? Is there a way to test for it, and take alternative action? --Iantresman (talk) 01:33, 11 December 2013 (UTC)
It's very handy for some situations. For example, to get an edit link for a base page, all you have to do is mw.title.new(pagename).basePageTitle:fullUrl{action='edit'}. That would take a few more lines of code to do if the metatables weren't set up. To check for tables that reference themselves like this, you can try getmetatable() and take your alternative action if the metatable exists. (Although even this will not work if there is a __metatable field set up in the metatable.) — Mr. Stradivarius ♪ talk ♪ 04:17, 11 December 2013 (UTC)

Calling another module

Can modules "call" other modules? I see that I can access Mediawiki libraries as simple as "mw.stat", are modules on Wikipedia accessible as easily? I'd like to include some of the functionality of module:Page in my module, without having to reinvent the wheel. --Iantresman (talk) 00:06, 12 December 2013 (UTC)

Yes indeed. You need the require function. The manual has a pretty good example, but let me know if anything is unclear. — Mr. Stradivarius ♪ talk ♪ 01:00, 12 December 2013 (UTC)
Although looking at what Module:Page actually does, it would be better to just use a mw.title object and use that. Module:Page is just a wrapper module for the features available with mw.title objects, and using mw.title directly should be faster and more intuitive. What are you looking to do exactly? Maybe we can help. :) — Mr. Stradivarius ♪ talk ♪ 03:27, 12 December 2013 (UTC)
That makes better sense, though I am really just playing around at the moment. --Iantresman (talk) 10:52, 12 December 2013 (UTC)

Argument substitution

This works for me:

return tostring(mw.site.currentVersion)

This doesn't, which I was hoping would be equivalent:

a = "currentVersion"
return tostring(mw.site.a)

And, how do I do the reverse, and convert mw.site.currentVersion to the string "mw.site.currentVersion"? --Iantresman (talk) 14:56, 12 December 2013 (UTC)

You need to do this:
a = "currentVersion"
return tostring(mw.site[a])
mw.site.a is actually equivalent to mw.site["a"], so you're getting the string "a" rather than the variable a. The reverse is a bit more involved, and will have to wait for when I'm not typing on my phone. — Mr. Stradivarius on tour ♪ talk ♪ 15:07, 12 December 2013 (UTC)
Ok, so now for the reverse. Actually, in the case of mw.site.currentVersion this isn't possible, at least not for all of it. If you have the current version, and you also know that you are in mw.site, then you can find the value of the table key using pairs:
local version = "1.23wmf6 (c138cf8)"
for k, v in pairs(mw.site) do
    if v == version then
        return k
    end
end
However, if you don't know that you are in mw.site, there isn't any way to do it. — Mr. Stradivarius ♪ talk ♪ 00:04, 13 December 2013 (UTC)
Thanks for all that, much appreciated. --Iantresman (talk) 09:11, 13 December 2013 (UTC)
And thanks yet again, I just noticed the tweaks you did to my sandbox/titlesubscripts page, which is producing some interesting output. Many thanks. --Iantresman (talk) 09:24, 13 December 2013 (UTC)
I just noticed the following using an underscore instead a variable, for the array value in "for _, property". Does this just mean that a variable is not used, or does the underscore have some other special meaning?
for _, property in ipairs(properties) do
	   result = result .. "\n# " .. property .. ": " .. tostring(currentTitle[property])
end

--Iantresman (talk) 09:36, 13 December 2013 (UTC)

Underscores are valid variables, and they are usually used as a placeholder variable, where a variable is required but not actually used. In this case, ipairs returns the key (1, 2, 3 etc.) and the value ('id', 'interwiki', 'namespace', etc.) of the properties table, but we only need the value. — Mr. Stradivarius ♪ talk ♪ 09:57, 13 December 2013 (UTC)
Also, I notice you've been making many test edits to that sandbox module - actually, you can test your code without saving the page. Just type =p.main() into the debug console, and it will run the code currently in the editing window. — Mr. Stradivarius ♪ talk ♪ 10:03, 13 December 2013 (UTC)
I remember reading about a console window, but I'm not seeing it in the latest Firefox 26. Looks find in Chrome. I tried restarting Firefox with no add-ons, and cleared its cache. I also note that the "This is a Scribunto module page" block appears on the page twice (in Firefox). I'll have to move over to Chrome, and see whether anyone else is getting Firefox issues. --Iantresman (talk) 12:05, 13 December 2013 (UTC)
Now fixed, it was the WikiEd editor, which I have now disabled. --Iantresman (talk) 12:09, 13 December 2013 (UTC)

If (User is Logged in) / conditional branching based on username?

Does our implementation allow Lua scripts access to whether the user is logged in or not? Can Lua scripts access the username of the logged in user? --HectorMoffet (talk) 11:05, 29 December 2013 (UTC)

No. We can tell the username of the last user to edit the page, through the magic word {{REVISIONUSER}}, but we can't tell the username of the current user, nor whether they are logged in. If I remember correctly, there is a feature available in MediaWiki to tell the username of the current user, but it was disabled on the English Wikipedia because of the potential for abuse. — Mr. Stradivarius ♪ talk ♪ 14:13, 29 December 2013 (UTC)
Not "abuse" so much as "it breaks caching". Although I don't recall if the feature is actually in MediaWiki now or if it has just been continually rejected on the grounds that it would break caching. (This is leaving aside the former use of REVISIONUSER in edit notices to get the name of the user making the edit, which was disabled for no particular reason that I know of.) Anomie 16:08, 29 December 2013 (UTC)
Thanks for the feedback, Anomie & Mr. Stradivarius. I had a feeling that caching would make this fundamentally impossible.
Next question: What's the best was to display a message that will only be seen by logged in users (as required for Template:DraftChecker)? Should this be done client side or server side?
Template:ShowOnlyToLoggedInUsers requires a line or two of a custom javascript to do the job, but of course this could be done server-side too. The advantage to JS is that it will play nicely with caching and it only requires two lines of JS to be installed (and is already written). I'm less familiar with our server architecture, so I don't know know which choice would be better. HectorMoffet (talk) 22:05, 29 December 2013 (UTC)

How to Get templates passed as parameters without substituting them?

I am trying to implement {{Horizontal timeline}} as a module. The syntax of the template sends another template as parameter. Any suggestion on how to receive this parameter template as a table rather than a substituted string?

Eg: {{example |row1 = {{template2|height=52}} }}

In the above exaple we can get row1 as frame.args.row1 but is it possible to get height from row1. For example like: frame.args.row1

If that is not possible: Please suggest an alternative method to implement it.

P:S Creating separate module for template2 in above example is not feasible because I am trying to reduce the number of template substitution and writing separate modules would defeat the purpose.--Jayarathina (talk) 05:20, 24 December 2013 (UTC)

It's not possible to receive parameters as anything other than a string. When you run #invoke, MediaWiki expands all the wikitext in each of the #invoke parameters before sending them to Lua. This means that Lua never sees the code {{template2|height=52}}; it only sees the string that is output as the result of the template call. To get around this, you will need to implement both templates in the same module (or you can do it in different modules and use the require function, which does pretty much the same thing). It's hard to be more specific than this without knowing more about your situation. What is the template you need to send to {{Horizontal timeline}}? — Mr. Stradivarius ♪ talk ♪ 05:43, 24 December 2013 (UTC)
@Mr. Stradivarius: Thanks for your reply. Template to be send to {{Horizontal timeline}} can be {{Scale row}} or {{Timeline row}} (which in turn calls {{Horizontal bar}}, {{Horizontal scale}} and {{Horizontal scale/Current number}}) Implementation of these twemplates are very easy. It is the mehod to receive these prams is difficult. Here is a working example (please refer code in edit view) :

{{Horizontal timeline}}

Even if it is not possible can you please shed any idea on how to implement such a template as module? I am not asking about technical details of implementing graph etc., I am asking about receiving parameter from user in a template. I mean is there a way to receive group or key-value pair in a single parameter like it is done above (row1, row2, row3). (Kind of multi-dimensional table). --Jayarathina (talk) 07:02, 24 December 2013 (UTC)
This isn't possible to do exactly as you are imagining. You can either implement each of the templates as a different module (which I know you don't want to do), or you can write the whole thing as a module and change all of the template invocations to use the new module parameters. If you were to write the whole thing as a module, then it might look something like this:
Example module code
local getArgs = require('Module:Arguments').getArgs
local TableTools = require('Module:TableTools')

local p = {}

function p.main(frame)
	local args = getArgs(frame)
	return p.horizontalTimeline(args)
end

function p.horizontalTimeline(args)
	local rowNums = TableTools.affixNums(args, 'row') -- Gets numbers for row1, row2, etc. with nil arguments removed.
	local ret = {}
	for _, num in ipairs(rowNums) do
		local rowType = args['rowtype' .. num] -- Gets args.rowtype1, args.rowtype2, etc. with nil arguments removed.
		-- Code for making rowArgs:
		-- local rowArgs = {x, y, z}
		if rowType = 'timeline' then
			ret[#ret + 1] = p.timelineRow(rowArgs)
		elseif rowType = 'scale' then
			ret[#ret + 1] = p.scaleRow(rowArgs)
		end
	end
	return table.concat(ret)
end

function p.timelineRow(rowArgs)
	-- Do stuff with rowArgs.
end

function p.scaleRow(rowArgs)
	-- Do stuff with rowArgs.
end

return p
Perhaps the best thing to do would be to write the module like the example above, and then use AWB to update all of the transclusions. There are only 162 of them, so if you are clever about how you use AWB it shouldn't take too long. Or you might get lucky if you ask nicely at WP:Bot requests. Hope this helps. — Mr. Stradivarius ♪ talk ♪ 07:43, 24 December 2013 (UTC)
@Mr. Stradivarius: Thanks a lot. TableTools.affixNums will do the trick.. :) --Jayarathina (talk) 08:09, 24 December 2013 (UTC)
I think you could jigger the template to return a string copy of its parameters inside a <span style="display:none"></span> - this would not be noticed by usual users (though it still adds to the byte count of pages with the template but not the module) and your program could do mw.ustring.match to capture the data, then gsub to cut the span out of the output. Wnt (talk) 14:26, 2 January 2014 (UTC)

That pesky "extra" #invoke field

I think it's worth checking back about how far we can go toward an ideal bare {{#invoke:SomeName}} format, since the extra parameter is only a nuisance/confusion to many non-Lua users.

  • The easy part is 'getting rid of the function name': assuming p is the variable in the last line of the program, just say p[""] = function (frame) instead of function p.main (frame). (Or just assign it with p.main...)
  • However, I see no way to get rid of the pipe - it must be {{#invoke:SomeName|}} or {{#invoke:SomeName||param=whatever}}, so far as I know...
  • It is also possible to make the function a parameter if it comes from a defined list of choices - just load up your data and set a loop that p[xyz] = function(frame) return p.main(frame, xyz) end.
  • However, I don't think you can get a metatable working. I'd like to have p[anythingnotrecognized] go to a q.__index function and then return for example p.main(frame), or an error, or reuse the function name as the first unnamed parameter. But can you do that? I've failed to so far.

Wnt (talk) 15:07, 2 January 2014 (UTC)

Why don't you just pass #invoke through to a template? That was one goal of the original Scribunto specification, and it is why we have frame:getParent. And if you don't like writing fiddly frame:getParent code, you can just use Module:Arguments which does it for you. :) — Mr. Stradivarius ♪ talk ♪ 16:39, 2 January 2014 (UTC)
Sure, that's what we do now... it's an extra page to fool with, though. Mostly, it's just fun to see what we can do. True, it's nowhere near as useful as being able to get a search passed through to Lua as shown in the section above this, which is just the beginning of all sorts of good stuff! Wnt (talk) 18:29, 2 January 2014 (UTC)

Is it possible to get a list of all pages with a prefix, similar to Special:PrefixIndex?

Currently, there are a reasonable number of templates that try to determine if any of a set of pages exist in order to provide links to those pages. Where I see this is commonly done is in the templates which return links to the archives of talk pages. The general method that has been used is to assume a format for the page archive name and then test for the existence of all such possible pages using {{#ifexist:}}. Given that each {{#ifexist:}} is an expensive parser function (EPF), these templates can consume an excessive number of EPFs. At least one such template will be beyond the 500 EPFs/page limit in 2015.

Is there a way to obtain a list (array) of all pages with a prefix (e.g. the results which can be obtained by a user with the Special:PrefixIndex page)? Makyen (talk) 05:58, 1 January 2014 (UTC)

I do not know a method, and if there were one, it would be likely to have roughly the same overhead as using a template with parser functions. While lurking at User talk:Jimbo Wales, I have sometimes thought that the solution is to manually make an index page (or construct a bot to do it)—the active talk page would show links to recent archives + a link to a fixed index page of older archives. Another factor is that WP:FLOW will replace talk pages, and remove the ability to archive them (I think—I have not studied the docs for a while, and they change because it is in development). Johnuniq (talk) 06:29, 1 January 2014 (UTC)
(edit conflict) :No, there's no way of doing this in Lua that I know of. Perhaps try filing a request in Bugzilla to see if anyone wants to add the code to Scribunto that would make this work? — Mr. Stradivarius on tour ♪ talk ♪ 06:37, 1 January 2014 (UTC)
If I understand correctly, lua can only see the rendered version of a page, couldn't you use it to scrape a rendered version of Special:PrefixIndex to get the list? Technical 13 (talk) 13:01, 1 January 2014 (UTC)
I just tried it with Special:PrefixIndex/User:Mr. Stradivarius, and it looks like we're out of luck. Using mw.title:getContent returns nil, and using frame:preprocess('{{Special:PrefixIndex/User:Mr. Stradivarius}}') returns a strip marker (I got "?UNIQ98c31e5a41fdf151-item-0--QINU?"). — Mr. Stradivarius ♪ talk ♪ 13:33, 1 January 2014 (UTC)
But you can pass the strip marker to mw.text.unstrip(), and then pluck out the page list with string.gmatch(). Not very elegant, but possible. Keφr 19:59, 1 January 2014 (UTC)
I just tried that too, and got the result "Special:PrefixIndex/User:Mr. Stradivarius". It looks like the conversion to the special page output comes at a later stage of processing, so just unstripping the strip marker won't work. — Mr. Stradivarius ♪ talk ♪ 20:13, 1 January 2014 (UTC)
Explain this. Keφr 21:31, 1 January 2014 (UTC)
(Hint: explain this and this.) Keφr 21:41, 1 January 2014 (UTC)
Aha, you're right. I forgot my curly braces the second time round - schoolboy error. (But was the "You suck" really necessary?) — Mr. Stradivarius ♪ talk ♪ 22:18, 1 January 2014 (UTC)
The real answer is more complicated, though. Strip markers seem to behave differently when requesting template expansion only (like action=raw&templates=expand does). And Special:ExpandTemplates expands templates, outputs templateless wikitext, and then renders that — which is not equivalent to doing a full page parse. And I assume you used that. So there is this caveat that it might not behave as expected in all contexts.
(The "You suck" was there before, for some reason I like to keep it. :P) Keφr 22:42, 1 January 2014 (UTC)

That makes sense. I didn't use Special:ExpandTemplates, though - I really did just forget my curly braces. :P Anyway, I have taken that idea and added some parameter checking and some documentation, and called it Module:User:Mr. Stradivarius/PrefixIndex. Makyen, does that look something like what you wanted? — Mr. Stradivarius ♪ talk ♪ 23:06, 1 January 2014 (UTC); Page moved without redirect. Updated link. — Makyen (talk) 04:02, 8 May 2014 (UTC)

Thank you all. From reading the above comments and a brief look at the module it appears to be what I desired. I expect that I will use it later in the week/weekend. Thanks again. Makyen (talk) 11:06, 2 January 2014 (UTC)
I just realised that this will only return the first 200 matches, because of the way the Special:PrefixIndex page works. So if you need to use it for anything that will get more than 200 results, you might be out of luck. There might be a workaround by using Special:AllPages, but it looks like it will be even uglier than the current PrefixIndex hack... — Mr. Stradivarius ♪ talk ♪ 19:09, 2 January 2014 (UTC)
Actually, you can pass |from= and it will work just like with the regular Special:PrefixIndex. You can pass the last link that appeared, and then skip it in the next batch. Keφr 09:26, 3 January 2014 (UTC)
This is an excellent advance in our Lua capabilities. Unfortunately (but in many cases quite understandably), not all Special: pages work this way. Running a sandbox program [3] it appears that out of all the Special: links at Help:Special pages, only Special:AllPages, Special:ListFiles, Special:RecentChanges, Special:RecentChangesLinked, Special:PendingChanges, Special:NewPages, Special:NewFiles, Special:ListUsers, Special:ValidationStatistics, Special:WantedPages, and Special:PrefixIndex produce contents that can be rummaged through when unstripped; the rest deliver only links to themselves. Still, even this list should suggest some useful modules! Wnt (talk) 22:06, 2 January 2014 (UTC)
I've made a practical use of the Special:AllPages in Module:Module overview, which now looks up each of the segments of AllPages (namespace = 828) and extracts the module names from them for a current list. Wnt (talk) 07:27, 5 January 2014 (UTC)

Lua module running on every page _access_

I've heard for quite a while that the Lua scripts only run when the page is parsed, which rules out many interactive features but is efficient. However, after writing up Module:Hex, which hex dumps the contents of strings, I was looking at the talk page when I noticed that the hex-dump of the contents of a strip marker (the example with UNIQ ... QINU) are changing every single time I hit the Talk tab or browser reload button to reload the page, even when I'm completely logged out with scripts disabled! To be sure, this is the strip marker for a current time function, but I'm thinking this is either a bug or a feature, and we should figure out which! :) Wnt (talk) 02:58, 6 January 2014 (UTC)

It appears that transcluding a special page disables caching (Parser.php line 3410). I'd recommend against abusing this, or you're liable to get it removed. Anomie 03:20, 6 January 2014 (UTC)
Actually, even the history versions of this talk page come up with a new value on every reload ([4]).
For example, earlier today (I only noticed this now) I redid Wikipedia:Lua/Modules with an updated index from AllPages, which I thought would be refreshed automatically whenever the page was purged or edited. Do you think I need to replace with a pasted version? Is there any way to further work on the parsed data so that caching is reenabled? Wnt (talk) 03:38, 6 January 2014 (UTC)
As long as the "history" version transcludes a special page, that'll do it. If you don't transclude special pages, you should be fine. Anomie 14:12, 6 January 2014 (UTC)
A more important example: that Module:FindFeatures I mentioned above does a frame:preprocess on PAGENAME. Is that a special page that disables caching? Because nobody had commented on it, I had been just about ready any time now to put that into an infobox that would appear on thousands of pages! If this is a performance issue maybe we'd better tackle it head on ASAP. Wnt (talk) 03:45, 6 January 2014 (UTC)
PAGENAME is fine, that's not a special page. But why are you doing a frame:preprocess on PAGENAME instead of using mw.title.getCurrentTitle()? Anomie 14:12, 6 January 2014 (UTC)
Well, from the old point of view of template coding, transcluding a page doesn't seem like a big deal. If I say frame:preprocess("{{PAGENAME}}") I "know" I'm going to get back a familiar text answer right away, whereas mw.title.getCurrentTitle().fullText involves, well, a double check of the manual about which field gives the title, and perhaps some trial and error to make sure that was the right function. I've been blissfully ignorant of the performance considerations (and indeed, it was only just recently I realized that for some special pages I was getting back something I couldn't process as text that led me to write the hex dump module in the first place) so it seemed like the two were at worst equivalent, and so I stuck with what was familiar. Is there a reason to avoid preprocessing a parser function like this? I've been getting a sense it's somehow gauche - sure, it reminds me of eval() or SQL injection security holes in other systems, but that sort of security consideration just isn't relevant here. Wnt (talk) 14:50, 6 January 2014 (UTC)
Using frame:preprocess is going to be a lot slower than the direct option, since it has to call back into PHP and execute the preprocessor. It's also a bad habit to get into, since it's hard to properly escape parameters when interpolating them into a string—frame:expandTemplate or frame:callParserFunction or frame:extensionTag (which is really just frame:callParserFunction with #tag) would generally be better there. Anomie 20:26, 6 January 2014 (UTC)
Oh, and another example - at [5] I proposed a solution for listing the portals linked from various WikiProjects by frame:preprocess() of at least the first full section of the talk page. If any special page transcluded anywhere in any of those templates could disable caching, this if relevant could affect ... innumerable pages if were put into action. Wnt (talk) 03:48, 6 January 2014 (UTC)
I'd hope those templates aren't trancluding special pages anyway. Note that if anything is transcluding special pages onto talk pages, then caching is already being disabled for those talk pages (i.e. this has nothing to do with Scribunto). Anomie 14:12, 6 January 2014 (UTC)
Outstanding! I don't really understand all that preprocess/unstrip stuff, but it's most impressive (and gives the devs/ops something to worry about)! I did not study the code, but the following may be of interest. A single byte can be converted to hex like this (when runnng interactive Lua, the following displays "<41>"):
c = 'A'; print(string.format('<%02x>', c:byte()))
And a string in hex can be converted to decimal as follows (this shows "175").
hex = 'aF'; print(tonumber('0x'..hex))
Johnuniq (talk) 04:52, 6 January 2014 (UTC)
Well, look at the source for Module talk:Hex - the parameters there tell the module progressively to wrap the name of a page in curly braces, preprocess it into a transclusion (which comes back as a strip marker, at least for special pages), and unstrip it (which turns it into HTML). The strip markers seem to be relatively simple, varying from time to time but not over a very large range of values, and giving old strip markers or point-mutating an existing strip marker seems to render them inert (i.e. displaying as UNIQ ... QINU rather than expanding into HTML). I really ought to read through the PHP source (and learn PHP better) but I supposed it should do no harm to test what happens empirically. Anyway, the way I do the conversion is I generate forward and reverse dictionaries of the 256 values so that I can just look up d2h[dec], h2d[hex] to get my answer. It's a bit of overhead but I think once I generate that array at the highest level in the module, it should remain available to the functions I call every time I do a hex dump on any string in the entire page. (I wish I understood the scope better to know if it's true though!) Wnt (talk) 06:39, 6 January 2014 (UTC)
What's kind of tantalizing if I picture abusing these cache-disabled modules (which I shouldn't, because I have a feeling they will be going away soon) is that when the module is actually re-run every time the page is viewed, you can picture that if you could only somehow communicate parameters to it you could get custom runs with custom data. (For example, a Mandelbrot module where you could click on any segment to recalculate and expand an area in it repeatedly) I keep thinking there's some way to do it, but somehow it just evades my grasp. I also suspect you can rig some crazy interactions, like a module that shows you a red flag in the preview (only) of your signature if someone has read your talk page. All very tempting ... doubtless a really bad idea. possibly justifiable in the name of... basic research. :) Wnt (talk) 06:48, 6 January 2014 (UTC)
Ummm, yes, while quickly looking through the code I saw the conversion table and that is what prompted me to post the above. I am really impressed with the result—I am vaguely aware that html can do clever things, but the hex dump is stunning.
I'm sorry to report that a module is loaded from scratch each time it is invoked, so if you had 100 hex dumps on a page, the conversion table would be created 100 times. It is only if you access a read-only table of data (no code) via mw.loadData() that the table is cached so it is loaded once per page. One way to convince yourself of the truth of this statement is to have a variable that you test early on—say that you return 'SET' if it's value is not nil, otherwise you do normal processing. After testing the variable, set it to some value. You will find that it is never set even if you invoke the module ten times on a page (at least, that's how it was, and I suspect still is).
Wikis rely on serving cached pages, and if a method were found to break that, the method would be eliminated and the perpetrator either given a barnstar for revealing a vulnerability, or given a hammering for abusing the system. Johnuniq (talk) 09:56, 6 January 2014 (UTC)
Hmmm... I thought I could do loadData, but [drivel redacted, sorry - and thanks!] Wnt (talk) 16:25, 6 January 2014 (UTC)
Thanks for all the answers here. I'm glad that the extent of the problem is limited. Even so, when I think about it, I can't help but think you're going to have to crack down sooner rather than later. Because eventually a vandal is going to find a way to transclude one of these specials into some template used on five million pages, including the Main Page, and what happens then? Wnt (talk) 01:18, 7 January 2014 (UTC)

Can loadData return arbitrary data?

I was just trying to return those hex tables via loadData and seem to have run into a nasty surprise. The parser seems to reject any effort to initialize a table in the return statement if one of the indexes is, or could be, interpreted as a number.

For example, return {84 = 132}, or return {'84' = 132}, or return {0 = 00}, give errors demanding a } near the =.

Is there a way for a loadData table to contain these keys? Wnt (talk) 15:56, 6 January 2014 (UTC)

This isn't a mw.loadData problem, it's a syntax problem - you need {[84] = 132}, {['84'] = 132}, and {[0] = 0}. (Note that for that last one, 00 and 0 are equivalent.) mw.loadData itself will accept booleans, numbers, and strings as table keys. — Mr. Stradivarius ♪ talk ♪ 17:11, 6 January 2014 (UTC)
Resolved
Oh, OK, thanks! I should have looked harder - reading the first couple of pages you see in a search usually works, not this time. I should update Help:Lua for beginners so I don't forget. :) Wnt (talk) 19:42, 6 January 2014 (UTC)
OK, I've added Help:Lua_for_beginners#Initializing_a_table - hopefully I can refer to that and keep it straight now. :) Wnt (talk) 20:13, 6 January 2014 (UTC)

Problem with string.format

Hi, is there a way to instruct string.format to not produce trailing zeros with decimal notation? For example:

  • string.format('%f %f %f', 0.00001, 1.2, 3) => 0.000010 1.200000 3.000000
  • string.format('%g %g %g', 0.00001, 1.2, 3) => 1e-05 1.2 3

Instead I need to output: "0.00001 1.2 3". Do I need to use %f and remove the trailing zeros with string.match or string.gsub? It would be a bit odd. --Rotpunkt (talk) 13:50, 9 January 2014 (UTC)

I'm afraid the only choices are ugly. The reasoning is that in a value like 0.00001, the final "1" might be valid, or it might be junk due to floating point limitations after a series of calculations, so the programmer has to force what they want.
Using s = string.format('%f', 1.2):gsub('0+$', '') gives "1.2" as the result, but it gives an empty string if the value is zero. Another problem is that '%f' is an abbreviation of '%.6f', so anything after six decimal places is lost (string.format('%f', 0.0000001) gives '0.000000'). Johnuniq (talk) 22:32, 9 January 2014 (UTC)

mediawikiwiki:Extension talk:Scribunto/Lua reference manual #Example for string.format? may be relevant to this problem. Incnis Mrsi (talk) 22:46, 9 January 2014 (UTC)

@Incnis Mrsi thanks, I already read it, but it doesn't help for printing a number like 0.00001 with decimal notation and without trailing zeros
@Johnuniq thanks, luckily my smallest value is 0.000001 so it's ok. I will work on gsub then. --Rotpunkt (talk) 00:41, 10 January 2014 (UTC)
You can do this in string.format like this: string.format('%.5f %.1f %d', 0.00001, 1.2, 3) → "0.00001 1.2 3". There are some more details near the bottom of the thread that Incnis Mrsi linked to. As an aside, I think it would be a good idea to expand the manual entry with an example or some more explanation, as at the moment it is hard to understand and I suspect that people just skip over it. — Mr. Stradivarius ♪ talk ♪ 03:21, 10 January 2014 (UTC)
But in general we don't know what value we are dealing with (otherwise the code would just be s = "0.00001 1.2 3"). You can take the log of the value and work out its magnitude, and guess the format specifier from that, but it ain't easy. Johnuniq (talk) 03:51, 10 January 2014 (UTC)
Hi Mr. Stradivarius thanks, as Johnuniq said these values aren't known before runtime, 0.00001 1.2 and 3 were just examples. I have a module that returns values from 0.000001 to 360. I don't want the scientific notation (for 0.00001 Lua print 1e-05 for example) so I need to use string.format with %f. But then there is the problem of the trailing zeros. Rotpunkt (talk) 10:31, 10 January 2014 (UTC)
@Johnuniq what about: string.format('%f', myValue):gsub('0+$', ''):gsub('%.$', '')? It gives: for 0 => 0; 1 => 1; 1.1 => 1.1; 0.000001 => 0.000001. Do you see any problems? --Rotpunkt (talk) 13:50, 10 January 2014 (UTC)
You should be able to do it with just one gsub: string.format('%f', myValue):gsub('%.?0+$', ''). Anomie 15:52, 10 January 2014 (UTC)
Thanks Anomie! right. The very last question: is the default function "tostring(number)" overridable (and how) or not? Rotpunkt (talk) 18:25, 10 January 2014 (UTC)

Yes, you can replace built-in functions because they are simply functions accessed from global variables. Caution is desirable because it is very confusing for anyone reading the code later if tostring() does not do what it normally does, however the following is the idea.

local lua_tostring = tostring
local function tostring(n)
    if type(n) == 'number' then
        local integer, fracpart = math.modf(n)
        if fracpart == 0 then
            return string.format('%.0f', n)
        end
        -- Don't need the "%.?0" here but useful if omit above.
        -- The parentheses remove the "number of changes" returned by gsub.
        return (string.format('%f', n):gsub('%.?0+$', ''))
    end
    return lua_tostring(n)
end

For variety, and to match the fact that if you know what values you are dealing with you might have some "if...then...else" statements to handle them, I did the format slightly differently. Needs study to guarantee correctness! Johnuniq (talk) 22:58, 10 January 2014 (UTC)

Thanks very much, nice ideas here. In this way will this function be automatically invoked when I concatenate a number with a string? Rotpunkt (talk) 00:01, 11 January 2014 (UTC)
No. I guess that evaluating 'abc'..42 is done inside the Lua interpreter, and it calls its own "tostring". To call a user-defined function you would need to override the .. operator, and that cannot be done in Lua (for which, my simple mind is very grateful). Johnuniq (talk) 00:43, 11 January 2014 (UTC)
Ok. The previous code is more than enough for me, so thanks again, cya! Rotpunkt (talk) 10:39, 11 January 2014 (UTC)

Antidote to cache disabling by Special: pages?

Because the property from Wikidata is not updated by mw.message, I decided to try it on one of those pesky Special: pages that abolish caching.

The sandbox Wiki code {{Special:AllPages|namespace=666}} {{CURRENTTIMESTAMP}} returns a timestamp that changes each time the page is reloaded, because caching is disabled.

However, I found that returning mw.message.newRawMessage("{{User:Wnt/Templates/Sandbox2}}"):parse() produces a timestamp that never changes when the page invoking the module is reloaded, because the page transcluded is not checked at all.

Unfortunately, I have not yet been able to think of a way to mix this logic to get what I want, namely a way to control whether results are updated daily or weekly, etc., because I haven't thought of a way by which the logic of whether time has passed will always be evaluated but the logic of the page content will not be, unless the time has come, at which point the caching should be updated on that page. Still, there are a lot of options available... maybe someone can think of something? Wnt (talk) 15:43, 13 January 2014 (UTC)

(To be clear... I'm thinking by this point that it would be better to just develop an explicit tool to control caching, and some mechanisms (if they don't already exist) to audit what pages are not cached and identifying the worst reloaders) Wnt (talk) 15:48, 13 January 2014 (UTC)

Formatting in arguments

Text formatting (bold, italics) breaks when the ''/''' tags are not closed for each argument. I'm currently using the following function to get template arguments.

[commented out]

How do I fix this? --SocietyBox (talk) 02:26, 20 January 2014 (UTC)

Re the getArgs code: I guess that instead of returning "parent.args" you intended to return "args"? Since you are using #invoke and not a template, there are no parent.args. You may like to see Module:Arguments.
Re arguments with bold/italics: I don't know what would work, but why not remove all ' from each argument, then insert the formatting in the output? That is on the assumption that the module knows what is supposed to be bold or italic. Johnuniq (talk) 03:56, 20 January 2014 (UTC)
No, the module doesn't know. Here's a simpler example. --SocietyBox (talk) 07:33, 20 January 2014 (UTC)
local text1 = '\'\'\'bold'
local text2 = 'normal'
local tbl = HtmlBuilder.create('div');
tbl.tag('span').wikitext(text1);
tbl.tag('span').wikitext(text2);
return tostring(tbl)
So the args business (in the now-commented-out text) was resolved?
Is the example a bug report about HtmlBuilder? It would be best to briefly describe what you expected and what goes wrong, but it's easy to speculate that mixing broken wikitext ('''bold) with html won't give satisfactory results. In fact, it would probably be safer to stick to either wikitext or html, and not mix them. Johnuniq (talk) 08:36, 20 January 2014 (UTC)
Sorry about the confusions. I'll start over. I wanted to convert a table-generating template (e.g. Template:Round8) to a Lua template without different behaviour for broken wikitext. Broken bold tags work fine with non-Lua templates (and these broken tags are in common use). I am uncertain whether there is a bug or this is intended behaviour. I originally thought I may be reading the args wrong. --SocietyBox (talk) 12:31, 20 January 2014 (UTC)
It's probably because you haven't added in new lines. Bolid and italic formatting with ''/''' only affects a single line of wikitext. For example:
'''Some bold text
This text isn't bold'''

produces:

Some bold text This text isn't bold

If you're using Module:HtmlBuilder you can try adding in .newline() and see if that makes a difference. — Mr. Stradivarius ♪ talk ♪ 15:34, 20 January 2014 (UTC)
That worked. Thank you. --SocietyBox (talk) 23:45, 20 January 2014 (UTC)

Should protected modules use local copies for require()?

A [6] question at Module:Redirect reminded me of a remarkable statement by @Wikid77: that updating some Lua modules can cause 7 million pages to be reformatted on the WP:Job queue. Clearly it's worth thinking about ways to reduce this impact as much as possible.

The first question, of course, is whether we should require() at all. Often the linked module contains bells and whistles that aren't really necessary; why not bring it into the module and slim it down?

But what I'd like to ask now is: as a matter of general policy, does it ever make sense to link from a module that is in such widespread use that it needs to be protected to the current copy of another module? Instead of requiring Module:Redirect from a protected module (or in this case a template, Template:Submit an edit request, which serves MediaWiki:Protectedpagetext), you would simply require or link to a copy (Module:Submit an edit request/Redirect).

The advantages are a) edits to Redirect to add irrelevant features don't lead to massive queue usage, b) Redirect doesn't have to be protected, and c) in case a required module isn't protected, you don't get confused and fool around with a module you think is in limited use only to find out that you've created a huge server load. (In the case of Module:Redirect, when I look at the pages that link to it I could easily think, meh, it's not even used by 50 pages, why not start making a series of small edits as long as they preview OK?)

The disadvantage of course is that bugfixes in modules like Redirect don't get passed on. However, if we standardize this, with the names copied verbatim and the fairly distinctive capital letter after the /, it should be easy to have a bot notify the author(s) of Module:Submit an edit request automatically when Redirect is updated. (alright, the bot might miss that one, unless it knows to go back and check a template by the same name also, but you understand) My feeling is that if the reuser is going to put millions of pages on the queue, he should have the chance to decide whether he wants the latest update in the module to be passed along, or if it can wait. Wnt (talk) 15:52, 22 January 2014 (UTC)

I would say no. In the (actually quite rare) case that you have to update a widely transcluded module to add some functionality, I think it's better just to take the hit to the job queue in order to avoid fragmenting the codebase. To have a module namespace that makes some sort of sense it will be best to have just one module that does one thing, without having to worry about copies of a module that may or may not do the same thing slightly differently. Also, check out the job queue graphs on Ganglia to see how fast the job queue actually goes down. It may be quicker than you think, but there is also a discrepancy between the speed the graphs show and my experience in how quick categories have been to update recently. Maybe someone who knows more about the job queue can fill you in on what's going on there exactly. — Mr. Stradivarius ♪ talk ♪ 16:21, 22 January 2014 (UTC)
Exactly, if we really run into long term problems with the job queue, we can probably make some requests to further optimize it for these scenarios. Updating category pages is a very low priority job and at the end of the cascading effect of updating a template, so that's why you see a mismatch in pace. Other than that the same rules as always apply. Don't worry about performance, but don't do things that you know are problematic without a reason. So don't go updating the same template/module with over a gazillion usages, 3 days in a row, if you could have done it in one go. —TheDJ (talkcontribs) 16:29, 22 January 2014 (UTC)
It seems like the argument you're making is proportional - that because the job queue can drop by up to a million pages a day (if I read those graphs correctly) we don't have to worry much. But I should ask - do we have any sense of the absolute costs? Electricity, carbon footprint, that kind of stuff? If Wikipedia is big enough some extra work at the human scale might be worth it. Also, Lua is still new, and modules worth requiring even a little newer. Can we be confident that as the number of requires increases that we're not going to reach a point where a person makes one change to, say, Module:Arguments, and the entire cache is wiped out? Wnt (talk) 16:49, 22 January 2014 (UTC)
Don't worry about the costs. Human effort does in no way measure up to the technology here in carbon footprint, i'm quite sure :D However, micro modules like arguments might indeed be better off not used in bigger templates. Copying htmlbuilder into another module however seems like a less smart thing to do. Elementary math, re implement it for the big boys perhaps. Just think smartly about it. How often can this realistically change, how small/big is it and how many other modules use it. This is not limited to lua scripts, it's actually a golden rule of any software system. (you usually don't go poll another server for a small fact, if you can get the same data locally by reimplementing it). —TheDJ (talkcontribs) 17:00, 22 January 2014 (UTC)
After discussing jobs on IRC, chad created bugzilla:60348 to improve the job queue. —TheDJ (talkcontribs) 16:53, 22 January 2014 (UTC)
  • Creating local, redundant forks is often faster but needs planning: Decades ago, when personal computers were much slower/smaller, I had to partition the source code into redundant, local copies of C programming language functions, not due to reformatting for customers, but rather due to extensive sets of test data needed to catch glitches during cumbersome regression testing of financial software, which would have run for months unless partitioned. Beyond mere rocket science, the invented rules of finance (ask Jimbo) exceed the meagre problems of travelling in space-time, with over 18 independent variables due to special calculation options for single/joint credit life insurance of financial payments. Of course, the chances of introducing a bug in the underlying "require()" modules can seem rare, but once such a bug occurs, then the whole delay becomes "double-trouble" to re-deploy with the new bugfix, as now double the effort to install a 2nd new version. The design of near-redundant configuration forks requires some extra tracking (and documentation), but it works: the NASA Space Shuttles were actually all technology forks of the prior shuttles, allowing new features (new computer technology) in the next Shuttle, but providing some basic compatibility which remained constant between the various shuttles. I think the split, among the redundant configuration forks, would be more like the 80/20 Rule (rather than 50-50% forking), and so 80% of pages would use a stable fork (rarely changed), but the other 20% of usage might be 5 different (but similar) forks which are updated more often, and at times all 5 extra forks of the 20% would be updated for the same new feature, but separate from the original 80% version, which might be retro-fitted months later. For a real-life example of deployment horrors (when no forks are allowed), see: "Template_talk:Convert#Deploying updates now 18,000x slower". To split Template:Convert into configuration forks, the split could be done by unit type: m/ft, km/miles, pounds/kg would be separate forks (rarely changed), while perhaps 25% of conversions use other units which require more new features. The concept is to duplicate the code base according to the likelihood of new/changed features in particular subsets of the total, then stabilize and separate the non-changing portions (which are likely to be ~70%-80% of usage). -Wikid77 (talk) 17:29, 22 January 2014 (UTC)

MfD nomination of Wikipedia:Lua/To do

Wikipedia:Lua/To do, a page you substantially contributed to, has been nominated for deletion. Your opinions on the matter are welcome; please participate in the discussion by adding your comments at Wikipedia:Miscellany for deletion/Wikipedia:Lua/To do and please be sure to sign your comments with four tildes (~~~~). You are free to edit the content of Wikipedia:Lua/To do during the discussion but should not remove the miscellany for deletion template from the top of the page; such a removal will not end the deletion discussion. Thank you. DePiep (talk) 23:55, 21 May 2015 (UTC)

The result was Keep. -DePiep (talk) 11:27, 9 June 2015 (UTC)