Wikipedia talk:Lua/Archive 12

Archive 5Archive 10Archive 11Archive 12

nbsp

Easy question this time: how do I produce a non-breaking space in lua? — Martin (MSGJ · talk) 19:50, 12 June 2023 (UTC)

 ?
Trappist the monk (talk) 20:35, 12 June 2023 (UTC)
Thank you. For some reason I thought that would produce the literal text. — Martin (MSGJ · talk) 21:06, 12 June 2023 (UTC)
It will produce the literal text  . Presumably, that will then be passed to a browser or similar software which will render it as a space. Lua doesn't have to do anything clever to achieve that. Certes (talk) 21:50, 12 June 2023 (UTC)

Help with Module:Location map

Hello.

I encountered a problem after uploading a map that uses Module:Location map, and was hoping to get help with it.

The file I uploaded is a close-up location map of Cairo and Giza, Egypt, to use it in articles such as 2023–24 Egyptian Premier League and 2023–24 Egyptian Second Division A, to indicate where each club is exactly located, since there are multiple clubs from these two governorates playing in the leagues (something similar to London in Premier League seasons' articles).

Once I uploaded the map and tried to use it, the following error appears:

Lua error in Module:Location_map/multi at line 27: Unable to find the specified location map definition: "Module:Location map/data/Egypt Cairo Giza" does not exist.

That error is clickable while in preview. When I click on it, a list of script errors appears, and to be honest, I have no clue how to solve these errors, as I have close to 0 experience with programming languages.

Can someone tell me what exactly I'm supposed to do to fix it? I'd really appreciate that. Thanks. Ben5218 (talk) 10:53, 15 June 2023 (UTC)

It's looking for a definition in Module:Location map/data/Egypt Cairo Giza. Pleasee see the documentation at Template:Location map — Martin (MSGJ · talk) 11:17, 15 June 2023 (UTC)
Thank you, MSGJ. I'll check it out. Instructions about everything I have to do should be located there and at Template:Location map/Creating a new map definition, right? Ben5218 (talk) 11:41, 15 June 2023 (UTC)

Read data outside the module namespace

Is there something like Module:Data that can parse JSON outside the module namespace? Specifically, I'd like to work with Wikipedia:New pages patrol/Backlog chart/daily in a template. – Joe (talk) 08:07, 19 June 2023 (UTC)

I believe the answer is no. A typical use is at {{London ward populations}} which reads items from Module:Data/London ward populations based on a key supplied as a parameter to the template. In other words, Module:Data requires a Lua table. However, a dedicated module could extract data from Wikipedia:New pages patrol/Backlog chart/daily rather easily. What do you need? Johnuniq (talk) 08:28, 19 June 2023 (UTC)
Well ideally, something like {{NPP backlog size|<date>}} and {{NPP backlog size|redirect|<date>}}, for an arbitrary date. Or would it be feasible to move the daily stats to the module namespace, MusikAnimal? – Joe (talk) 08:45, 19 June 2023 (UTC)
More than moving it would be required. The wikitext at Wikipedia:New pages patrol/Backlog chart/daily is currently in JSON. Module:Data needs the information stored as a Lua table. That's easy but MusikAnimal may not have much spare time. Are you saying you want a new template ({{NPP backlog size}}) and it should accept, for example, 2022-12-16 as a parameter and return 1355? What would your redirect template do? Johnuniq (talk) 08:53, 19 June 2023 (UTC)
Exactly. NPP used to rely quite heavily on Wikipedia:New pages patrol/Backlog chart to keep an eye on whether the backlog was growing or not. Since the graph extension doesn't appear to be coming back any time soon, I'm trying to put together a text-based 'dashboard' that could fulfil the same purpose. It would state the current size of the backlog (from User:DatBot/newpagesbacklog) and how much it is up/down compared to yesterday/last week/last month, sort of like a stock ticker. The "redirect" part is aspirational because as far as I can tell MusikBot doesn't track the size of the unreviewed redirect backlog (though the API does). – Joe (talk) 09:04, 19 June 2023 (UTC)
There is no need to look at the following links—I'm mentioning them for background if needed. GreenC and I cooperated on {{NUMBEROF}} which uses Module:NUMBEROF to read values written by a bot to c:Data:Wikipedia statistics/data.tab (Module:NUMBEROF/data translates that page into a Lua table). If the NPP info were written to Commons in a similar way, it would be easy for a module to extract any data required. A bot could also write data from the API (a module cannot access the API). I suggest you prepare a draft of what would be wanted in a sandbox using some of the current data. If you show the output that is wanted, it would be easier for people here to see what is needed. It might be easier for a module to return the whole wanted wikitext rather than implement a template which extracts items one-by-one. Johnuniq (talk) 09:19, 19 June 2023 (UTC)
mw.loadJsonData will read data in JSON format, and I think it will happily read from any page in that format, regardless of namespace. For example Module:Class reads the data at Module:Class/definition.json — Martin (MSGJ · talk) 09:20, 19 June 2023 (UTC)
Oh! I haven't been paying attention to new features. That makes reading the existing page even easier and means adding structured data at Commons is probably not required. A draft of the wanted output would still be desirable. Johnuniq (talk) 09:33, 19 June 2023 (UTC)
Putting the data on Commons is still sounds like a nice idea in the long term; this is a useful dataset that can't, as far as I know, be extracted from the database retrospectively. But as you say that'd require some bot work. For now, mw.loadJsonData did the trick. Thanks for the help, both! – Joe (talk) 10:46, 19 June 2023 (UTC)

Calculation in string

I have something like '2+3' stored as a string and I would like to calculate it as a number. tonumber doesn't work here. What's the best method? — Martin (MSGJ · talk) 09:09, 26 June 2023 (UTC)

tonumber won't work as it doesn't attempt to evaluate the expression. A quick glance at mw:Extension:Scribunto/Lua reference manual brings up mw.ext.ParserFunctions.expr(string), which works like the {{#expr: parser function and would likely work for your scenario. Aidan9382 (talk) 09:25, 26 June 2023 (UTC)
And there is an example at Module:Math#L-605. Johnuniq (talk) 09:57, 26 June 2023 (UTC)
Thanks, that's working nicely — Martin (MSGJ · talk) 11:25, 26 June 2023 (UTC)
depending on the source of the string and how much control you have over it, you may want to wrap it in pcall().
mw.ext.ParserFunctions.expr("my father is a holy man"), like any input that won't compute (e.g. 14 / 0) will throw an error.
it is preferable to do something like
local okeydokey, result = pcall( mw.ext.ParserFunctions.expr, myExpressionVar )
if okeydokey then
-- in this scope, "result" is good
else
-- handle the error here, like 
    result = someDefaultValue
end
peace - קיפודנחש (aka kipod) (talk) 20:15, 30 June 2023 (UTC)
Umm, are you sure? pcall( mw.ext.ParserFunctions.expr, "my father is a holy man" ) returns false for okeydokey and nil for result. Shouldn't the test be: if okeydokey then (without the not token)?
Trappist the monk (talk) 21:06, 30 June 2023 (UTC)
sorry, you are correct. in original code i had the error handling in first hunk, and decided it looks better when the first hunk is success, but forgot to remove the "not"... doing it now (the name of the "success variable is a strong hint that true means success and false means error).
peace. קיפודנחש (aka kipod) (talk) 22:43, 30 June 2023 (UTC)

Unexpected result when setting table value to nil

Consider the following code (from Module:Sandbox/MSGJ):

function p.main(frame)
 args = frame.args
 args.category = nil
 return args.category
end

What would you expect from {{#invoke:Sandbox/MSGJ|main|category=Foo}} — Martin (MSGJ · talk) 14:20, 6 July 2023 (UTC)

I would expect that it returns "Foo"; the frame.args object uses a custom metatable that handles gets so the value overwrite is ignored. * Pppery * it has begun... 14:24, 6 July 2023 (UTC)
I can overwrite it to other values. Why is nil different? And is there any method I can set it to nil? — Martin (MSGJ · talk) 14:25, 6 July 2023 (UTC)
You can't overwrite to nil because the aforementioned metatable is based on the __index metamethod, which, per the documentation, is used when a table access t[key] would return nil. I don't know of any way around this, although if you were to use Module:Arguments instead of reading directly from frame.args then that handles setting nil properly. * Pppery * it has begun... 14:33, 6 July 2023 (UTC)
You can copy the table with a for k, v in pairs( args) do loop. Then you can set the values to nil. —  Jts1882 | talk  14:54, 6 July 2023 (UTC)
I don't know what to expect because I gave up trying to understand how args works (with or without Module:Arguments) for anything other than a read-only table. Spelling out Pppery's reply, args.category = nil actually removes args.category from args so when return args.category is executed, the value does not exist in the table and that causes the __index function attached to args to be called, and that reads the underlying value ('Foo') from the wikitext. The generic method for manipulating frame.args is to clone args and adjust it as wanted, then use the clone with newChild and pass the result to whatever is needed. There may be a way of avoiding that complex workaround in whatever the use case is. Johnuniq (talk) 04:13, 7 July 2023 (UTC)
I also personally try to treat frame.args as read-only, even if you can overwrite it (with things other than nil). It's more in keeping with the functional ethos of minimizing mutation and avoiding what is often treated as global state in many of our modules. As alternatives indeed, either you can clone the whole table and then mutate the resultant, or you can create your own variables that take on relevant values. I prefer this second option myself because this also allows you to give the variables nicer names than what are often abbreviations and smushed words and duplicate parameter names in the template interface. Izno (talk) 04:53, 8 July 2023 (UTC)

Thanks everyone. This created a bug in my code which I found really hard to find! Basically I am calling a module which has nearly the same set of arguments, so for convenience I just passed the whole table of arguments from the calling module. But it turns out one argument ("category") was conflicting as the other module was using this for a different purpose. So I thought I would just set that one to nil before sending the table but that didn't work either. So I am now doing as recommended and constructing a new table of arguments for the other module. — Martin (MSGJ · talk) 10:53, 9 July 2023 (UTC)

Testing the new Module:Params

I wrote a new general-purpose module, Module:Params, somewhat similar to Module:TemplatePar but more flexible and powerful. The module is already being used by {{Template journal}} and {{Template journal inline}}. If you people have time I would like to ask to have a look at it, test it, collect ideas, help with the documentation, report bugs. --Grufo (talk) 01:17, 10 July 2023 (UTC)

We already have too many modules in this area. We don't need even more ways to do the same thing. * Pppery * it has begun... 01:25, 10 July 2023 (UTC)
Hi Pppery, thank you for your early feedback. If I had known a module that did the same things I would not have written this new module. But the problem is that I did not know any other way to overcome the limitation of accepting maximum 50 parameters and drastically reduce the complexity like i did in {{Template journal}} and {{Template journal inline}}. I suggest you try and experiment with Module:Params, you might be pleased by its simplicity and the possibilities that it offers. --Grufo (talk) 01:33, 10 July 2023 (UTC)

Make changes to copied table element not reflect on old target elements of copying

I recently updated Module:Wikipedia ads/data. Part of the implementation fixes the id field of a table element (skippedEntries[i]) before copying it into the output tables (one of them is list[id]) when needed, multiple times. However, it has a problem. For some reason, after I've copied the first skippedEntries[i] with id 40, if I change the skippedEntries[i]'s id to another value, the old element with id 40 also turns its id into the updated id. How do I fix that? Aaron Liu (talk) 01:32, 16 July 2023 (UTC)

I'm having trouble thinking at the moment so take what I say with caution. However, if you have a table t, and then execute a = t; b = t, variables a and b refer to the same table. Executing a.id = 42 will also set b.id to the same value. If you want different different tables in a and b, you have to use a = mw.clone(t) and same for b. I would rearrange the code. I gather that Module:Wikipedia ads/list is loaded somewhere with mw.loadData. In that case (and if it's not used in another way), you can delete Module:Wikipedia ads/data and edit Module:Wikipedia ads/list to return the fixed table. Maybe that's a bit adventurous although quite achievable. If data is kept, I would edit it to construct the missing table rather than cloning it: t = {}; t.id = ...; t.image = ...; and so on for the other fields, then insert t. Or just use clone. Johnuniq (talk) 03:46, 16 July 2023 (UTC)
/data returns an additional table so I don't think I should do that. I'll try clone tomorrow. Aaron Liu (talk) 03:59, 16 July 2023 (UTC)

Producing a list

I have a template (Template:WPBannerDoc) which outputs an asterisk followed by text. When called with wikitext it produces an unordered list. I am trying to call this template from a module via frame:expandTemplate but the literal text is displayed without the list structure. Even prefixing <br> doesn't help. You can see the output at Template:WikiProject Medicine/sandbox#Parameters. My question is: how can I get my bullet points working correctly by using this template? — Martin (MSGJ · talk) 19:02, 20 July 2023 (UTC)

Is this a case where you need to do something like return frame:preprocess ('* '''class''' – valid values are listed ...')?
Trappist the monk (talk) 19:28, 20 July 2023 (UTC)
At Template:WikiProject Medicine/sandbox#Parameters, the Parameters section at the bottom showed "*class – valid values are ... *importance – valid values are ..." where the asterisks were displayed. I think my edit at Module:WikiProject banner/templatepage/sandbox has resolved the issue. I inserted some newlines so asterisks were at the start of a physical line. I hope there are no bad side effects. Johnuniq (talk) 01:27, 21 July 2023 (UTC)
Ah nice, thanks. I was using '<br>' and you were used '\n'. I should have known. — Martin (MSGJ · talk) 07:20, 21 July 2023 (UTC)

Help with Russian module

Wikipedia:Village pump (technical) § Modify a module could use a few eyes from people to see if the Russian module can be adjusted as requested. Izno (talk) 21:00, 26 July 2023 (UTC)

Invoke detection

What is the easiest way for a module to detect if it has been called via #invoke or from a wrapper template? — Martin (MSGJ · talk) 16:46, 27 July 2023 (UTC)

I believe the following works.
local function main(frame)
	local result
	if frame == mw.getCurrentFrame() then
		result = "Module called via #invoke"
	else
		result = "Module called via require or debug console"
	end
	return result
end
return { main = main }
Let me know if you confirm this works. Johnuniq (talk) 04:32, 28 July 2023 (UTC)
Thanks. That is interesting, but does not answer my specific question which is about distinguishing between #invoke and wrapper template (which is also calling #invoke). I think what I want is to check if there is a parent frame or not. — Martin (MSGJ · talk) 20:57, 28 July 2023 (UTC)
Try frame:getParent():getTitle() (if frame is available) or mw.getCurrentFrame():getParent():getTitle() (if not). Maybe something in the title would be helpful. Johnuniq (talk) 09:58, 30 July 2023 (UTC)
If I understand the question correctly, then this will throw an error if the module has been called via a direct invoke. The existence of a parent frame at all means there is a wrapper template, so you just need to check if mw.getCurrentFrame():getParent() is not nil. On a side note, it’s more reliable to check mw.getCurrentFrame() instead of frame unless you can guarantee that the frame object is actually the frame for the current page, which may not always be the case. Theknightwho (talk) 14:29, 31 July 2023 (UTC)
Ignore all of that - I forgot that the original frame has the module title, and the parent frame is the page with the #invoke: on it. The actual solution is to check whether mw.getCurrentFrame():getParent():getTitle() == mw.title.getCurrentTitle().fullText. This checks whether the title of the page with the #invoke: (i.e. the parent frame) is the same as the title of the page being rendered (i.e. the current title). If there is no wrapper template, these will be the same. If there is one, they'll be different. Theknightwho (talk) 17:26, 31 July 2023 (UTC)
Ummm... are you sure? I have used the value returned by mw.title.getCurrentTitle().namespace as a way to limit categorization to article name-space only. That means that mw.title.getCurrentTitle().fullText returns the name of the article that contains the #invoke: whether #invoke: is directly instanced in the article or hidden inside a template instance. If mw.title.getCurrentTitle() returned a title object for the template that holds the #invoke:, mw.title.getCurrentTitle().fullText would return the name of the template; mw.title.getCurrentTitle().namespace would always return the number for the Template namespace (it doesn't).
Trappist the monk (talk) 17:46, 31 July 2023 (UTC)
@Trappist the monk - yes, that’s correct. mw.title.getCurrentTitle().fullText is the page being rendered (usually an article). mw.getCurrentFrame():getParent():getTitle(), on the other hand, is always the page with the #invoke on it. If there is a wrapper template, these will be different; if there is no wrapper template, they will be the same. You need to compare the fullText field of the current title object, because the title stored in the frame object is a literal string. Theknightwho (talk) 04:51, 1 August 2023 (UTC)

Maintain state between Module invocations

I originally posted Wikipedia:Help_desk#How_to_update_a_LUA_global_variable_between_multiple_Module_function_calls_from_a_wiki_page? about essentially maintaining the state of a global variable between multiple invocations of a Module from a single article page. The answer was that preserving the state of a global variable between multiple invocations is not possible. That in itself, begs the question, wouldn't it make LUA much more useful if it could preserve state within a wiki page? Is this limitation self-imposed by the Wiki infrastructure or cannot be done due to technical limitations in the Scribunto/Lua interface? Anyways, as an alternate solution, is there a way I can feed in multiple lines of data via Module parameters so I can maintain a counter that is used in formatting Module output? Or am I going to run into a Module parameters length limitation as some point?
For example:

{{#invoke:Sandbox/RedWolf|list|delim=/|mountains=
Mount Logan /m/5959/-1/[[Saint Elias Mountains]]/fa=1925/notes=Highest point in Canada/refs=<ref name=fr>First reference</ref>
Mount Robson/m/3954/2829/Rainbow Range/fa=1913/notes=Highest point in the Canadian Rockies
Mount Temple (Alberta){{!}}Mount Temple/m/3543/1544/[[Bow Range]]/fa=1894
}}

RedWolf (talk) 18:09, 3 August 2023 (UTC)

You will probably run into post expansion transclusion limit with that approach. And also, that's not wikitext which is not friendly for users. Izno (talk) 18:19, 3 August 2023 (UTC)
I haven't examined the above example but I have been told that it is a design decision that templates and modules have no state information. The idea is that different people should be able to simultaneously edit different sections of an article and preview/publish should not depend on other parts of the page. Johnuniq (talk) 23:26, 3 August 2023 (UTC)

Module:Mock title

I made a module for mocking Scribunto title objects. It can be used when testing code that uses title constructors like mw.title.new; normally the output of test code like this would depend on the state of the relevant wiki pages (and so people could break your tests by editing them), but by using mock titles you can make your tests independent of the state of the wiki. Please take a look at it and let me know if you have any feedback. — Mr. Stradivarius ♪ talk ♪ 13:47, 23 August 2023 (UTC)

Conversion of Template:Marriage to Lua

I checked the source for Template:Marriage and it keeps on using so much code and parser functions. I suggest that the conversion should make the template more workable. RMXY (talk) 05:18, 20 September 2023 (UTC)

I agree that a conversion would make a lot of sense. Do you fancy learning lua? — Martin (MSGJ · talk) 07:08, 20 September 2023 (UTC)
I want to learn how to do Lua. RMXY (talk) 08:25, 22 September 2023 (UTC)
This is a solution in search of a problem. The template's quest for omniscience and built-in opinions should be pared back, rather than entrenching them by creating a module. * Pppery * it has begun... 14:22, 22 September 2023 (UTC)
What do you mean by "built-in opinions"? I'm looking at it and not seeing a problem. Looks like a template that provides considerable utility.  — SMcCandlish ¢ 😼  19:07, 22 September 2023 (UTC)
See Template talk:Marriage/Archive 8#Use of circa for an example of what I mean. I may well hold a minority opinion here, though. * Pppery * it has begun... 22:19, 22 September 2023 (UTC)
I see what you mean, but this seems like it should be reasonably easy to fix in the code, namely by no longer "helpfully" policing the input. At bare minimum, something like |circa=y parameter could turn those checks off?  — SMcCandlish ¢ 😼  22:34, 22 September 2023 (UTC)
My point is that once you remove the input policing it will hopefully reach the point where it's no longer complicated enough to warrant a Lua module. * Pppery * it has begun... 00:05, 23 September 2023 (UTC)

Help with understanding Lua module

I'm very new to Lua and am trying to understand how Module:Settlement short description uses the contents of the infobox to automatically generate a short description for the page if one does not exist already. I can tell this is all done in the p.main() function through usage of p.shortdesc(), but I don't understand where frame comes from. It looks like it would contain the specific contents of the page. How can I provide the module with Wikipedia article titles, such as Morning Glory, Texas or Stoneham-et-Tewkesbury for example, to see how the text parameter provided to p.shortdesc() is built in p.main()? Then once I am able to do so, how can I view the contents of variable like subdivision_names or location within p.main? BaduFerreira (talk) 15:38, 27 September 2023 (UTC)

The frame object contains all the parameters/arguments that is passed to the module. There are only really two frames you need to know about: frame.args is a table of arguments from the template that calls #invoke, and frame:getParent().args is a table of arguments passed by the page that called that template. This particular module only uses the latter. I'm not familiar with the code but I believe it is mainly using the parameters that are defined in Template:Infobox settlement. The actual title of the article is only used once, rather obliquely, with mw.title.getCurrentTitle().text — Martin (MSGJ · talk) 20:29, 28 September 2023 (UTC)
Okay, that makes sense. Thank you for the link, this looks like a very helpful resource. Is it possible to dump the table of arguments that any given page using this template passes to the module? I'd like to play around with the module and I think concentrating my efforts offline to a local copy would be more effective and less disruptive. BaduFerreira (talk) 22:10, 28 September 2023 (UTC)
mw.dumpObject (frame.args) – dumping just frame is interesting too.
Results are available under the Lua logs dropdown in the Parser profiling data dropdown when you preview an article (or testcases page) that uses your module.
Trappist the monk (talk) 22:55, 28 September 2023 (UTC)
What do you mean by results? Would that be the output of mw.dumpObject (frame.args)? I'm not sure where I would execute that function. Additionally, where would I find the Parser profiling data dropdown? I don't know what you mean by preview article (I thought maybe edit preview but I can't find anything there). Hope you don't mind all the questions 🙂 BaduFerreira (talk) 00:50, 29 September 2023 (UTC)
You edit the module and add the line somewhere in the function where frame is passed as an argument. Do not save the edit (you will finish by abandoning it, leaving the module unchanged). Underneath the edited module, find "Preview page with this template" and paste the title of a page where the module is used. Click Show preview to see how that page would look if the edit to the module were saved. Then the stuff at the bottom of the page should show the dump. Johnuniq (talk) 01:02, 29 September 2023 (UTC)
Ah okay, I see. I didn't realize I could do that. I'm able to preview a page that uses Module:Settlement short description after adding the mw.dumpObject(frame.args) function to p.main(), but I'm getting nil as the output so I'll keep poking around. Thank you everyone for all the help so far! BaduFerreira (talk) 01:55, 29 September 2023 (UTC)
Sorry, it's mw.logObject(frame.args) (log, not dump; dump gives a string). However, I just tried it (using Anah as the preview page) and the output is just table#1 { metatable = table#2 }. That's because args is a magic table that doesn't do anything until you ask for a specific argument. You would need something like mw.logObject(frame:getParent().args.short_description) but that outputs nil because no parameters are passed to the template. Johnuniq (talk) 02:21, 29 September 2023 (UTC)

Compacting Template:Weather box

The syntax for Template:Weather box is unnecessarily verbose as each data entry receives its own row. I have no prior knowledge of Lua and am trying to condense the template:

Example: Template:New York City weatherbox would be condensed to something like this:

{{Compact weather box
|location = New York City
|source 1 = [[NOAA]] (relative humidity and sun 1961–1990; dew point 1965–1984)<ref name = "New York City Weatherbox NOAA" >{{cite web |url=https://w2.weather.gov/climate/xmacis.php?wfo=okx |title = NowData – NOAA Online Weather Data |publisher = [[National Oceanic and Atmospheric Administration]] |access-date = May 4, 2021}}</ref><ref name="New York City Weatherbox NOAA txt">{{cite web |archive-url=http://web.archive.org/web/20210504224841/https://www.ncei.noaa.gov/access/services/data/v1?dataset=normals-monthly-1991-2020&startDate=0001-01-01&endDate=9996-12-31&stations=USW00094728&format=pdf |archive-date=May 4, 2021 |url=https://www.ncei.noaa.gov/access/services/data/v1?dataset=normals-monthly-1991-2020&startDate=0001-01-01&endDate=9996-12-31&stations=USW00094728&format=pdf |publisher=[[National Oceanic and Atmospheric Administration]] |title=Summary of Monthly Normals 1991–2020 |access-date=May 4, 2021}}</ref><ref name = noaasun>{{cite web|title=New York Central Park, NY Climate Normals 1961−1990|url=ftp://ftp.atdd.noaa.gov/pub/GCOS/WMO-Normals/TABLES/REG_IV/US/GROUP2/00305801.TXT|publisher=[[National Oceanic and Atmospheric Administration]] |access-date=July 18, 2020}}</ref>
|source 2 = Weather Atlas<ref name="Weather Atlas NYC">{{cite web |url=https://www.weather-us.com/en/new-york-usa/new-york-climate |title=New York, New York, USA - Monthly weather forecast and Climate data |publisher=Weather Atlas |access-date=July 4, 2019 }}</ref>
|units = imperial |preferred units = imperial
|temp color = default |precip color = green |snow color = blue |humidity color = blue
<!-- month     Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec  Year-->
|record high   |72  |78  |86  |96  |99  |101 |106 |104 |102 |94  |84  |75
|monthly high  |60.4|60.7|70.3|82.9|88.5|92.1|95.7|93.4|89.0|79.7|70.7|62.9|97.0
|high          |39.5|42.2|49.9|61.8|71.4|79.7|84.9|83.3|76.2|64.5|54.0|44.3
|mean          |33.7|35.9|42.8|53.7|63.2|72.0|77.5|76.1|69.2|57.9|48.0|39.1
|low           |27.9|29.5|35.8|45.5|55.0|64.4|70.1|68.9|62.3|51.4|42.0|33.8
|monthly low   |9.8 |12.7|19.7|32.8|43.9|52.7|61.8|60.3|50.2|38.4|27.7|18.0|7.7
|record low    |-6  |-15 |3   |12  |32  |44  |52  |50  |39  |28  |5   |-13
|precip        |3.64|3.19|4.29|4.09|3.96|4.54|4.60|4.56|4.31|4.38|3.58|4.38
|snow          |8.8 |10.1|5.0 |0.4 |0.0 |0.0 |0.0 |0.0 |0.0 |0.1 |0.5 |4.9
|precip day threshold = 0.01 in
|precip days   |10.8|10.0|11.1|11.4|11.5|11.2|10.5|10.0|8.8 |9.5 |9.2 |11.4
|snowy day threshold = 0.1 in
|snowy days    |3.7 |3.2 |2.0 |0.2 |0.0 |0.0 |0.0 |0.0 |0.0 |0.0 |0.2 |2.1
|humidity      |61.5|60.2|58.5|55.3|62.7|65.2|64.2|66.0|67.8|65.6|64.6|64.1
|dew point     |18.0|19.0|25.9|34.0|47.3|57.4|61.9|62.1|55.6|44.1|34.0|24.6
|sun           |163 |163 |213 |226 |257 |257 |268 |268 |219 |211 |151 |139
|percent sun   |54  |55  |57  |57  |57  |57  |59  |63  |59  |61  |51  |48
|uv            |2   |3   |4   |6   |7   |8   |8   |8   |6   |4   |2   |1
}}

In addition to having only one row for each monthly statistic, rather than 12-13 rows, the suggested configuration would resemble a table, allowing better readability and editing of data. Unlike Template:Weather box/concise C and Template:Weather box/concise F, this template would support all the data provided in Template:Weather box. For the rows with 12 values rather than 13 (everything except monthly high and monthly low), the yearly value would be automatically calculated. Crossover1370 (talk | contribs) 19:12, 30 September 2023 (UTC)

I agree that would be a better procedure and is something I thought about that while implementing Module:Weather box but it was already a bit over human comprehension. Some delimiter other than pipe would be used so each row could be parsed. Module:Football manager history does something similar in that it extracts fields from text rows. Another to-do item is to use mw.html to generate the table rather than wikitext. Johnuniq (talk) 23:36, 30 September 2023 (UTC)
Would the comma be an acceptable delimiter? (as in |high = 40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44)? Would there have to be quotation marks, as in |high = "40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44"? I'm trying to develop this myself but I know nothing about Lua or how it is used in Wikipedia. Crossover1370 (talk | contribs) 01:13, 1 October 2023 (UTC)
I guess comma would never conflict with any of the parameters that weatherbox expects (if a value could ever contain a comma, you would want to pick a different delimiter). It might be ok to use spaces with a dash for missing items. Johnuniq (talk) 01:35, 1 October 2023 (UTC)
Would there have to be quotation marks at the beginning and the end of the sequence of values? As in: |high = "40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44"? Or would |high = 40, 42, 49, 62, 71, 80, 85, 83, 76, 65, 54, 44 (without quotes) be acceptable? Crossover1370 (talk | contribs) 01:55, 1 October 2023 (UTC)
Quotes not needed. Everything in a template is a string (1.5 is three ASCII characters). Johnuniq (talk) 02:51, 1 October 2023 (UTC)
Just use whitespace as delimiter instead of comma for even more readable template syntax: mw.text.split(datarow, '%s+') Dexxor (talk) 08:17, 1 October 2023 (UTC)

JSON

Do we have a Lua module that can read a JSON table, something equivalent to Module:Data? I found Module:Jf-JSON but it looks way more complicated than I need. — Martin (MSGJ · talk) 11:33, 19 July 2023 (UTC)

mw.loadJsonData, mw.text.jsonDecode, and mw.text.jsonEncode. mw.ext.data.get may also be relevant. Izno (talk) 16:25, 19 July 2023 (UTC)
I'm thinking we could adapt Module:Data so that it can read JSON pages as well. There could be a parameter to switch between the modes or possibly it could be deduced using mw.title.contentModel — Martin (MSGJ · talk) 20:55, 19 July 2023 (UTC)
Do you want to access the data on the JSON page from Lua, or from a template? (From your later post, I'm guessing from a template.) To provide access from a template, if it's just one JSON page, you could create a simple wrapper module that calls mw.loadJsonData on it, and returns the value from the call. This module can then be used as an argument to Module:Data. If the template is using a lot of data from the JSON page, converting the template to a Lua implementation may be worth considering. isaacl (talk) 17:58, 29 September 2023 (UTC)
A module which I could invoke in a template would be just fine. Could an additional function be added to Module:Data to call mw.loadJsonData and then pass to its main function? I'm not familiar with metatables so don't want to touch that module! — Martin (MSGJ · talk) 14:47, 4 October 2023 (UTC)
In a kind of kludgy manner. The syntax {{#invoke:Data|Module:''some module''|...}} maps to Scribunto taking the object returned by Module:Data and invoking a method called Module:some module on it, which means using Module:some module as a key to the underlying table in the object, and treating the return value as a function. Since Module:Data can't hardcode functions for every single possible module that might be used with it, it sets up a metatable with an __index() function that returns a function. This function uses the key value that was passed to __index() as the name of the module page to access. The essential logic of this function could be extracted into a helper function, and the __index() function could be modified to treat specific values differently: say, a key in the format of JSON:page name could return a new utility function that calls mw.loadJsonData() on the specified page and then passes its return value to the helper function. isaacl (talk) 16:43, 4 October 2023 (UTC)
Not going to pretend I understood half of that! But if you would have time to sandbox some code I will gladly test it, and maybe other people would find this useful too — Martin (MSGJ · talk) 20:21, 4 October 2023 (UTC)
Module:Data doesn't have any test cases, so I'd have to first figure out its use cases and create tests in order to do regression testing. Thus unfortunately it's a bigger project than I'm looking to do at present. If you could describe your intended use case, maybe a simpler solution could be found. isaacl (talk) 02:06, 5 October 2023 (UTC)
My immediate needs were met by Module:Women in Green event (main function) which was certainly simple enough. Don't worry if you haven't got time, this is on my long-term wishlist. — Martin (MSGJ · talk) 08:00, 5 October 2023 (UTC)

Colon

I notice that string.upper(s) is equivalent to s:upper() - is that correct? Why is the "string" not needed in the second format? — Martin (MSGJ · talk) 13:28, 6 October 2023 (UTC)

This is correct behaviour, and I believe is called a method call.
If you call a function of an object using : instead of ., the first argument will automatically become the object the call was made from. For example, t:xyz(...) is just an alternate way of typing t.xyz(t, ...)
Since all strings have the string functions as methods (E.g. ("").upper is string.upper), this means s:upper() is functionally acting as string.upper(s).
You can see an example in mw:Extension:Scribunto/Lua reference manual § Function calls. There's also some special rules when using : to define a function, which you can read about at the bottom of this section on the lua manual. Aidan9382 (talk) 13:59, 6 October 2023 (UTC)
Thank you, that's helpful. I had no idea you could replace the word "string" with any string. Is that part documented somewhere? — Martin (MSGJ · talk) 20:54, 6 October 2023 (UTC)
This behavior is part of Lua but I forget where I saw it documented originally. Whether or not s:upper() works depends on what s is. It needs to be based on a table with a member called upper and that member has to be a function. Strings in Lua (but not mw.ustring) work like that. Johnuniq (talk) 23:06, 6 October 2023 (UTC)
The reason this logic applies to string objects is because their metatable's __index is the string table.lua docs This means attempting to index (access a member of) a string object will actually index the string table for that object. Aidan9382 (talk) 06:32, 7 October 2023 (UTC)

Module to sum table column

I am an absolute beginner in lua and wanted to develop a module Module:Sandbox/Miria~01 that automatically sums the values ​​of the columns in a wiki table like this one created in my sandbox User:Miria~01/sandbox.

Games Athletes Gold Silver Bronze Total Rank
2008 Beijing 92 0 1 2 3 61
2012 London 116 1 1 2 4 43
2016 Rio de Janeiro 103 2 4 2 8 32
2020 Tokyo 87 3 1 5 9 28
2024 Paris future events
2028 Los Angeles
2032 Brisbane
Total 6 7 11 24 67

edited table on 11 September 2023 to show no error, original in the revision history Wikipedia_talk:Lua&oldid=1174743806

last row (total) with invoke to load module:
 
!colspan=2| Total !! {{#invoke:Sandbox/Miria~01|calculateSum|Gold|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Silver|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Bronze|User:Miria~01/sandbox}} !! {{#invoke:Sandbox/Miria~01|calculateSum|Total|User:Miria~01/sandbox}} !! [[All-time Olympic Games medal table|67]]

However, only zeros are ever generated as a sum. I would be grateful for any small help.

local p = {}

function p.calculateSum(frame)
    local args = frame.args
    local column = args[1]
    local wikitext = args[2]
    local sum = 0

    -- Iterate through the rows of the table
    for row in mw.text.gsplit(wikitext, "\n") do
        -- Check if the row contains the specified column
        if mw.ustring.find(row, "|" .. column .. "|") then
            -- Extract the value from the specified column
            local value = mw.ustring.match(row, "||%s*([0-9]+)%s*||")
            if value then
                -- Attempt to convert the value to a number, or default to 0 if conversion fails
                local numValue = tonumber(value)
                if numValue then
                    sum = sum + numValue
                end
            end
        end
    end
    return tostring(sum)
end
return p

Miria~01 (talk) 11:28, 10 September 2023 (UTC)

@Miria~01: It looks like you are trying to parse the contents of User:Miria~01/sandbox, but your code above instead tries to parse the literal string User:Miria~01/sandbox as a wikitable. Instead you want to fetch the content of the page using title:getContent(). So instead of this:
    local wikitext = args[2]
You can do this:
    local wikitext = mw.title.new(args[2]):getContent()
Best — Mr. Stradivarius ♪ talk ♪ 11:43, 10 September 2023 (UTC)
Thanks for the quick reply. The suggestion with title:getContent() obviously makes sense. Unfortunately only zeros are still generated. But I'll take a look at the module Module:USN fleet totals from User:Trappist the monk, how he did it, to hopefully find a solution for my issue. Miria~01 (talk) 12:56, 10 September 2023 (UTC)
Not going to work as you want it to work because args[2] is just the text string User:Miria~01/sandbox.
I wrote some code to render List of current ships of the United States Navy § Fleet totals by extracting the appropriate data from tables. See {{USN fleet totals}}, Module:USN fleet totals, and Module:USN fleet totals/data. You might want to look at that code to see how I did it.
I can imagine difficulties in the future because editors have varying beliefs regarding how wikitext should be formatted. It might be best to have your module create the whole table from data stored in a module's subpage. There would be no parsing required for that.
Seems odd to me that MediaWiki doesn't have Javascript to sum table contents. After all, MediaWiki does provide Javascript to sort columns so it would seem that they could also supply a script to sum columns and/or rows. That they don't suggests that there are difficulties that I am not aware of.
Trappist the monk (talk) 12:04, 10 September 2023 (UTC)
Thanks for the suggestion, I'll definitely take a look at your modules and try to build on that with the previous save data in a module's subpage, summing the columns/rows in tables.
I'm actually also surprised that, if at all, calculations can only be made on Wiki using {{#expr:expression}}, but only explicitly numbers and not, for example, cells (cell_ID could be assigned) from tables. Miria~01 (talk) 12:59, 10 September 2023 (UTC)
The line if mw.ustring.find(row, "|" .. column .. "|") then is searching for text "|Gold|" which never gets a result (hence sum=0). You want to find lines beginning with "|align=left|" or just "|" and then iterate the results of mw.ustring.match(row, "||%s*([0-9]+)%s*||"). You need some way of deciding which column to extract or output all the sums in a single call. —  Jts1882 | talk  14:01, 10 September 2023 (UTC)
Which all complexity is why I suggested building the table on the fly from data in a ~/data module...
Trappist the monk (talk) 14:20, 10 September 2023 (UTC)
Yes, data modules are much more flexible. I've used them before at Module:Goalscorers and Module:SportsRankings.
In the meantime, I made a quick and dirty version of Module:Sandbox/Miria~01 that automatically sums the values of the columns Gold, Silver, Bronze and Total and outputs the sums for the table in User:Miria~01/sandbox. —  Jts1882 | talk  14:58, 10 September 2023 (UTC)
All added a column option "All" to output the sums as four table cells in one module call. —  Jts1882 | talk  15:07, 10 September 2023 (UTC)
Thank you very much, I had a wrong thought how to recognize the correct line with the value. Also realize that data-modules is actually the best and cleanest solution.
In the end, the driving force was that the total sum of medals in the medal tables of the individual nations (by Olympic event, by sports, etc.) at the Olympic Games (e.g. Russia_at_the_Olympics#Medal_tables) at the Olympic Games is correct. Since in the case of stripped medals (stripped after several years due to doping), individual users change accordingly the entry for the event, but neglect the total sum or change the entry for the year, but neglect to change it also at the sport itself and so incorrect numbers arise. Miria~01 (talk) 16:18, 10 September 2023 (UTC)
As a note, "align=left" is deprecated/obsolete HTML and is likely to be removed. In general, this whole endeavor is indeed brittle at best. Izno (talk) 16:24, 10 September 2023 (UTC)
Just because I've not done much with the html library, this seemed like a useful learning opportunity so I have hacked Module:Sandbox/trappist the monk/html which creates a table along the lines of the table that Miria~01 posted in the OP. It ignores future events (I'm not sure that en.wiki looks favorably on stuff that has not yet occurred). The experiment relies on two tables; one for the all-time ranking (bottom right table cell) and one containing all of the necessary row data. To test it add this to a sandbox:
{{#invoke:Sandbox/trappist_the_monk/html|html_table_build|srb|sog}}
Trappist the monk (talk) 16:46, 10 September 2023 (UTC)

Just for completeness: I created for my request in Module:Sandbox/Miria~01/sumMedals, that after specifying a targetClass as args[1], the type of medals should be searched for. e.g. for summer class="summerMedals" and for winter class="winterMedals". For the existing medal tables of all countries ("xxx"_at_the_olympics, e.g. Croatia at the Olympics) class="summerMedals" or class="winterMedals" would then have to be inserted into the table rows. At the same time, the infbox for the individual countries can also be updated directly on the same page

| gold  =  {{#expr: {{#invoke:Sandbox/Miria~01/sumMedals|calculateSum|summerMedals|Gold|{{FULLPAGENAME}}}} + {{#invoke:Sandbox/Miria~01/sumMedals|calculateSum|winterMedals|Gold|{{FULLPAGENAME}}}}}}

In Wikipedia talk:WikiProject Olympics#Module to calculate sum in medal tables(+update of infobox) I explained this in more detail using an example. Of course it's not the cleanest solution, but I think it's okay temporarily. The goal, however, is a large-scale database that automatically creates the correct medal tables in the pages for the individual countries based on the data at the pages of the individual Olympics medal table e.g 2014 Winter Olympics medal table.
Miria~01 (talk) 11:44, 11 September 2023 (UTC)

@Miria~01 I think that I have finish playing around. My module at Module:Sandbox/trappist the monk/html and Module:Sandbox/trappist the monk/html/data renders summer and winter tables for Serbia and Mexico. Expanding to support other countries should mostly be a matter of clerical drudgery though no doubt, an awb script could be written to extract the pertinent data from articles using plain wikitext tables. The module also has an exported function to calculate total numbers of gold/silver/bronze medals for use in infoboxen. See this version of my sandbox for example renderings.

The modules should be sufficiently documented to make expansion and maintenance of ~/data relatively easy.

Trappist the monk (talk) 16:42, 11 September 2023 (UTC)

Adding line to Module:Interlinear

I want to add a parameter to {{fs interlinear}} to allow for a right-to-left gloss for Semitic languages. I tinkered a little bit with the HTML that the template produces, and it seems like all that's needed to do this is change line #44 of Module:Interlinear so that it can read float: right; rather than float: left; if a certain parameter (perhaps |RTL=yes) is set. I asked the person who usually edits that template, but their last edit was in April so I don't think I'm hearing back on that anytime soon. Can someone here help me figure out how to make this alteration? Eievie (talk) 01:57, 19 October 2023 (UTC)

Up until just now Template:WikiProject Cephalopods invoked Module:WikiProject banner with a parameter containing a template, i.e.

|HOOK_ASSESS = {{WPBannerMeta/hooks/bchecklist}}

Template:WikiProject Cephalopods was not listed at Special:WhatLinksHere/Template:WPBannerMeta/hooks/bchecklist, however, a page like Talk:Vampire squid which transcludes Template:WikiProject Cephalopods was listed in WhatLinksHere, which surprised me. Why was the page listed but not the template? — Martin (MSGJ · talk) 07:20, 10 November 2023 (UTC)

The point of WhatLinksHere is so MediaWiki knows what pages need to be regenerated when a template or module is changed. The page Template:WikiProject Cephalopods did not contain anything that would change if the now deleted Template:WPBannerMeta/hooks/bchecklist were changed. However, Talk:Vampire squid transcluded {{WikiProject Cephalopods}} and its wikitext used to transclude {{WPBannerMeta/hooks/bchecklist}}, so Talk:Vampire squid needed to be regenerated when Template:WPBannerMeta/hooks/bchecklist changed. In conclusion, the WhatLinksHere feature is not very helpful for those maintaining templates/modules. Johnuniq (talk) 07:59, 10 November 2023 (UTC)
This is the reason I quite regularly do insource searches when messing around with templates. This has the problem of not detecting redirects, but it is definitely useful in some circumstances. --Trialpears (talk) 08:28, 10 November 2023 (UTC)

Regex question

I am using :gmatch('{{{([^|]+)') to find valid parameters in a template's code. It is not working quite right.

For example the code contains {{{event}}} {{{event-type|edit-a-thon}}} but it seems to be matching with event}}} {{{event-type but not the event-type which I require. — Martin (MSGJ · talk) 13:00, 11 January 2024 (UTC)

[^|]+ will go as far as it can to capture text before running into a pipe, which is why the first capture is so long and contains text from both event and event-type. gmatch then continues from the pipe it got stopped at last time so won't pick event-type up since its beyond it at this point. I'd recommend adding } inside of that negated list, which should prevent it from over-capturing event (and therefore pick up event-type afterwards too). Aidan9382 (talk) 13:31, 11 January 2024 (UTC)
I'm guessing here, but try "-" instead of "+" in the capture. You could also try escaping characters that might have another meaning (e.g.{ and | which would need escaping in regex proper). —  Jts1882 | talk  13:36, 11 January 2024 (UTC)
For some reason I didn't get an edit warning message and missed the reply above. —  Jts1882 | talk  13:38, 11 January 2024 (UTC)
Apparently - is an alias for *. That would not help here — Martin (MSGJ · talk) 14:06, 11 January 2024 (UTC)
Perfect, thanks! — Martin (MSGJ · talk) 14:03, 11 January 2024 (UTC)
Another alternative might be to gmatch the whole parameter and then parse that. In the debug console I get these results using string.match() in place of string.gmatch():
=string.match ('{{{event}}} {{{event-type|edit-a-thon}}}', '{{{([^}]+)}}}')event – this would be the first string.match() result
=string.match ('{{{event-type|edit-a-thon}}}', '{{{([^}]+)}}}')event-type|edit-a-thon – and this would be the second string.match() result
Trappist the monk (talk) 14:39, 11 January 2024 (UTC)
Beware that the parameter default often contains braces in a nested parameter, magic word or template call, e.g. {{{display_text|{{{title}}}}}} or {{{page_name|{{PAGENAME}}}}. In some very clever templates, they even crop up in the parameter name itself. Certes (talk) 14:50, 11 January 2024 (UTC)

How to make multilangual parameters in Module:Navbox

Hello!

I'm translated Navbox module into Kazakh Wikipedia, but have one issue. We've already have a kk:Module:Navbox, but I want to upgrade it. Additionally in the some templates we also used English version of Navbox (english parameters). So I need to add english versions of parameters (Aliases?) to new kk:Module:Шолғы exactly to kk:Module:Шолғы/configuration. I've already ask this question on talk page of Module:Navbox, but nobody replied, that's why I'm writing here Thanks--Amangeldi Mukhamejan (talk) 15:15, 27 October 2023 (UTC)

@Amangeldi Mukhamejan: i only saw this now, sorry about that. i hope it's not too late.
a while ago i wrote a utility module that enables you to use any module from another language with localized parameter names. the idea is simple - i'm sure you won't have any trouble grasping it and figuring out how it's done. see he:יחידה:תרגום יחידה
in a nutshell: for each module you want "translated", you create a "translation" module (in retrospect i guess it could have been a JSON rather than module). then you call the utility module, passing it the target module, the target function, the name of the "translation module", and any parameter you want to pass directly.
the utility module clones the frame (such that the "parent" of the clone is the real parent, not the utility module), it then enriches the "args" and the parent's args with the translated parameters, and then it calls the target module/function with this enriched frame.
note that i said "enriches", not "replace". this means that the caller can use either the original param name _or_ the translated name, which i think is part of your requirements, you can mix and match - some of the parameters can be the translated ones and others can be the original ones
there is some rudimentary documentation as a comment at the top of the module (the doc is not very long, but it's still 50% of the whole thing - the code is short and sweet and pretty easy to understand - no magic. i wrote it per some request on hewiki, and tested it to verify it works, but eventually the requestor decided not to use it, so you can say it's not "tried and tested", only "tested"...
this of course is not specific to "navbox": once you install it, you can use it for any module, at the cost of creating "translation module" for each imported module you want to use with native language parameter names.
if you do decide to use it, i'll be grateful if you can let me know, and of course, if you find bugs let me know too.
peace. קיפודנחש (aka kipod) (talk) 04:24, 26 January 2024 (UTC)

Escape character

I have a string with a "#" character. When I use the string it produces a numbered list, but I just want to use it as a string. I have tried mw.text.nowiki without success. I have also tried using \u0023 but it just converts it back to #. Any other suggestions? — Martin (MSGJ · talk) 12:01, 9 February 2024 (UTC)

You can see the issue at the top of Category:WikiProject Women in Red meetup 2017 articles. It is supposed to be producing Category:WikiProject Women in Red #1day1woman articles but that link is not even working so perhaps it is impossible to have "#" in a page name? — Martin (MSGJ · talk) 12:01, 9 February 2024 (UTC)
Seems to me the problem isn't that # isn't escaped but that a line break is inserted before it where it shouldn't be. Nardog (talk) 12:09, 9 February 2024 (UTC)
Seems I just need to remove that character because the category name is not valid anyway — Martin (MSGJ · talk) 12:12, 9 February 2024 (UTC)
Oh, it's a hashtag, not a section link. Yeah, that's impossible. Nardog (talk) 12:16, 9 February 2024 (UTC)
Page names cannot contain # due to a MediaWiki restriction documented in Wikipedia:Page name#Technical restrictions and limitations. # is reserved for dividing the page name from a following anchor (typically a section header), e.g. Wikipedia talk:Lua/Archive 12#Escape character. Certes (talk) 22:13, 9 February 2024 (UTC)

As Nardog pointed out above, Lua modules seem to return strings which begin with "#" in an unexpected way. Compare below. My sandbox module just returns the string '#1day1woman' and you can see it behaves differently — Martin (MSGJ · talk) 10:38, 10 February 2024 (UTC)

  • a#1day1womanb - look no line break
  • aLua error in mw.text.lua at line 25: bad argument #1 to 'match' (string expected, got nil).b - working now
This is probably the same issue as was experienced at Template talk:R § Space before colon in pop-up, where the # gets interpreted as defining a list item since it was the start of the string returned by the module. You can use mw.text.nowiki or manually encode it depending on your circumstance to get it to display normally. Aidan9382 (talk) 11:46, 10 February 2024 (UTC)
Thanks Aidan, yes that works as expected — Martin (MSGJ · talk) 14:24, 10 February 2024 (UTC)

A new template parser

Hi - I mostly do work on Wiktionary, but wondered if anyone had a use for a powerful recursive backtracking template parser which I've put together, which is designed to scrape large amounts of template data from pages very quickly: wikt:Module:template parser. It's (very loosely) based on mwparserfromhell, and builds a node tree of objects on the page that can then be traversed in order to retrieve data. The two available functions are described in the module, but - in short - parseTemplate is a function that you feed a rawstring template into, and it'll return the template name and arguments, while findTemplates is an iterator that returns data about each template it finds in the input text. Some features:

  • It can handle arbitrary nesting of templates ({{ }}), arguments ({{{ }}}), headings, wikilinks, HTML comments, parser tags and include tags, and has been designed to be as accurate to the native PHP parser as possible. This includes replicating some of the bugs in the native parser, to ensure full consistency. With one caveat (see below), I haven't yet been able to find a testcase it fails, even with really extreme or bizarre inputs.
  • HTML comments and the <noinclude>, <includeonly> and <onlyinclude> tags are all handled correctly. By default, it assumes that the input text should be treated as transcluded, for the purpose of the include tags. This can be changed with a parameter.
  • It's extremely fast and lightweight for what it is: e.g. wikt:人 scrapes data from hundreds of other pages to retrieve Chinese transliterations, which requires calling this module every time. By far the biggest drain on resources in that is the unavoidable time taken by mw.title's :getContent() method, not the parsing itself (which can be seen in the parse profile on that page).
  • The caveat is that it doesn't (yet) have special handling for parser tags like <ref>. It knows that they're there, but it doesn't yet know the various special ways that each one needs to be handled. In some cases this is very straightforward (e.g. <nowiki>) and in some cases not (e.g. <gallery>), so support for these will take some time. At the moment, anything between such tags is treated as raw text (i.e. as though it were in nowiki tags).

I'm reasonably confident it's the most powerful wiki markup parser that has yet been written in Lua (though I'm happy to be proven wrong!). Do let me know if you think this could come in handy for anything, and I'm happy to help in designing any implementations. Theknightwho (talk) 16:21, 13 February 2024 (UTC)

Need help with edge case in my Lua Module

I wanted to port the following templates over to the Afrikaans Wikipedia: Template:Millenniumbox, Template:Centurybox, Template:Decadebox.

After an initial look at how they worked, I was overwhelmed by the sheer amount of nested templates that were used by these templates. I decided to instead copy the look of the templates, but to use Lua Modules instead for the backend logic.

Porting Template:Millenniumbox and Template:Centurybox over to Afrikaans Wikipedia using Lua Modules was easy enough for me and I am happy with the results.

However I am stuck on porting Template:Decadebox. This template has 2 edge cases which do not exist in the Millenniumbox or Centurybox. There is no 0th millennium nor 0th Century. However there is a 0th Decade and 0th Decade BC. See 0s and 0s BC.

I was aware of these edge cases when I was writing my Lua Module, but still the output does not work as I expect.

Here is my ported template af:Sjabloon:Dekadeboks, and here is the Lua Module that it uses : af:Module:Dekadeboks. On the template page documentation, you can see my different "test cases" All the examples work as expected except for my 2 edge cases.

The problem seems to be caused by the Lua not being statically typed.

I am passing the selected decade as an argument. For the 0s the argument value is "0" and for the 0s BC it is "-1".

Most of my calculations read the argument to the function as a number, but for this edge case, I read it as a string instead. So that I can handle "-0" as an argument.

I know it is kinda hacky, but I can't think of a better way to do it. Furthermore when I run my functions in an external IDE, or pass it to a local Lua interpreter, the function behaves as I expect.

For the simplest example see my function to get the category for birth years: "kry_geboortes_kat_str" it is at the very end of the module. Also see my function to get the category for deaths: "kry_sterf_kat_str" which is a slightly different approach, but also doesn't work.

Please can anyone advise how I could get these functions to correctly handle "0" and "-0" as an argument? Am I missing something here?

I would greatly appreciate any feedback/advice on this issue. - Rooiratel (talk) 09:43, 13 February 2024 (UTC)

I think the 0s should be the first decade. That would resolve the hacky "-0" — Martin (MSGJ · talk) 10:41, 13 February 2024 (UTC)
That is an idea, and it does make sense in that the 0s is technically the 1st decade AD. But if I went with this method, I would have to rewrite the entire module completely. I also think it will be more confusing for users. The enwiki template also uses 0 as an argument for the page on 0s. But I will definitely consider this approach as a last resort. But I didn't actually notice that I was doing this template different from the others, so I will definitely update the docs to explicitly state what it expects the arguments to be, and what they represent (whichever solution I go with). - Rooiratel (talk) 07:29, 14 February 2024 (UTC)
It would better if you gave a couple of precise examples and say what the input is, what the output is, and what is wanted. It's not clear to me what the testcases show so please spell it out. I don't want to spend too much time at the moment so I'll just mention some points. Are you aware that -0 is equal to zero and is not negative? At line 230, num will be -0 if args[1] is '-0'. You can use tostring on negative zero and the first character will be a dash if the number was -0 (I see that line 238 covers that). Assuming you are using a normal frame and not something created artificially, frame.args[1] can only be a string (or nil if there is no args[1]). But any argument that exists can only be a string so tostring at line 229 won't help. I'll be away for many hours but will look again if the issue hasn't been resolved. Johnuniq (talk) 10:52, 13 February 2024 (UTC)
> It would better if you gave a couple of precise examples and say what the input is, what the output is, and what is wanted.
Apologies, I thought the template doc page was enough to give examples of the input and output. I do realize that it was not very clear on what the expected output should be.
> Are you aware that -0 is equal to zero and is not negative?
Yes, which is why I was attempting to use the tostring() method to handle it as a string instead of a number. I am using the "dek" variable for the string representation and "num" for the numeric representation.
> But any argument that exists can only be a string so tostring at line 229 won't help.
I thought as much, but in that case it is "converting" a string to a string, so it should still work as I expect.
My main problem at the moment is not the specific output, but I am trying to hit a conditional-block when the dek variable is equal to "0" or "-0", but the function never seems to reach it.
So essentially I need is: a function that takes a single argument which it stores in one variable as a string, and another variable as a number.
If the number variable is greater than 0 then execute a block of code.
If the number variable is less than 0 then execute a block of code.
Else if the string variable equals "0" then execute a block of code.
Else if the string variable equals "-0" then execute a block of code.
I am not able to get these last 2 conditions to execute.
I have added a very simplified test function which just returns a string saying which conditional block it reached. If you could please assist with that I would be very grateful. On my template page at the very bottom you can see the outputs, for my last 2 cases above those code blocks never execute. - Rooiratel (talk) 07:48, 14 February 2024 (UTC)
@Rooiratel: The problems is that af:Template:Dekadeboks#Test Function used to show "Reached else block" for the last two cases. In the last case, the parameter is "-0*" where I have written an asterisk where there is actually a space. It is an unnumbered parameter so MediaWiki does not trim the leading/trailing whitespace. You need code to remove the spaces which I did in an edit at af:Module:Dekadeboks. Johnuniq (talk) 09:00, 14 February 2024 (UTC)
Thank you so much @Johnuniq! I knew it had to be something stupid like that. At least now I will never forget to trim out any whitespace from the arguments. I can apply the same fix to the rest of the functions, and it should resolve all outstanding issues I have with this Module. - Rooiratel (talk) 09:22, 14 February 2024 (UTC)

Template:Category disambiguation

Can {{category disambiguation}} be made to use Lua? There has to be a better way than using 50 conditionals. Thanks! HouseBlaster (talk · he/him) 22:49, 13 February 2024 (UTC)

Templates are not converted to Lua simply because they are repetitious. They can be, but I don't think I would here. Izno (talk) 00:29, 14 February 2024 (UTC)
@Izno If I'm honest, this seems like the perfect sort of template to convert to Lua, for three reasons:
  • It would massively reduce the amount of code, because it would be a simple loop. Repetitious code is a maintenance headache and annoying to edit.
  • There's no arbitrary upper limit to the number of arguments which can be passed into it (currently 100).
  • Tons of template calls like this is very slow by comparison, which can impact large pages.
Theknightwho (talk) 14:29, 14 February 2024 (UTC)
Is anyone really going to want to disambiguate more than 50 different categories? Will there ever a time when {{category disambiguation}} is not the only thing on the page, and thus it's performance on large pages matters? I don't think so. Given the average edit rate of one edit per two years I don't think maintainablility is an issue - more time is spent discussing and doing the conversion than will ever be saved by it having been done. * Pppery * it has begun... 14:49, 14 February 2024 (UTC)
These are all benefits of Lua in general. Do they aid this specific template? No, not really. There isn't anything complex about it such that the positive of the different language outweigh the negatives of the different language.
That said, given this feedback, maybe you should try converting it. Simple templates are the best ones to start with. Izno (talk) 18:10, 14 February 2024 (UTC)
You're replying to Theknightwho, author of one of the most complex Lua modules I have ever seen. I don't think they need simple templates to start with :) — Martin (MSGJ · talk) 21:17, 14 February 2024 (UTC)
I think that comment was meant to be addressed to HouseBlaster, despite its indentation. * Pppery * it has begun... 21:43, 14 February 2024 (UTC)
No, it was intended for Theknightwho, I just 1) didn't realize they were a different person from House, and 2) don't know everyone's credits. :) I'm not stopping anyone from converting anything to Lua if they want to take the time for it (WP:VOLUNTEER), I just am singularly convinced that this template doesn't need it for already stated reasons. But I am happy to redirect the suggestion to House. Izno (talk) 22:01, 14 February 2024 (UTC)
@Pppery @Izno You make good points, and I had only looked at the raw code when I made my earlier comment. That being said, I've done a sandboxed version at Module:Sandbox/Theknightwho/Category disambiguation, which is designed to replace the Cmbox call in the template, since this seemed relatively straightforward. The one difference is that throws an error if you supply fewer than four parameters (since that's the minimum to specify two categories), but that can easily be taken out. Theknightwho (talk) 01:14, 15 February 2024 (UTC)

Lua errors at ln:

ln: is a small wikipedia with less than 10 active users per month and non of them with lua knowledge. There are some lua errors in templates that were probably copy pasted in the past from fr: The pages can be seen here: https://ln.wikipedia.org/w/index.php?title=Cat%C3%A9gorie:Pages_avec_des_erreurs_de_script&action=edit&redlink=1

Could someone who knows lua have a look to the templates ("modèle") and give us a hand or at least some advice? Thank you for helping. Bombo (talk) 21:35, 18 April 2024 (UTC)

I've cleared all of the Lua errors from mainspace articles. Most of the template errors are due to the template being called but without parameters and will work on mainspace. * Pppery * it has begun... 23:14, 18 April 2024 (UTC)

Process template parameter in Lua before MediaWiki does its thing

I'm working on a module that let's the user to use some predefined placeholders to add categories/text. For example, on the "Category:144 births" category they can add the following template

{{YearCategory
|__DECADE__s births
|Births by year
|RD(__CENTURY__)-century births
|__YEAR__ beginnings
|header=In this category you can find people who were born on [[__YEAR__]].
}}

And it will add the 140s births, Births by year, 2nd-century births and 144 beginnings categories to the page and will display a header with "In this category you can find people who were born on 144." content. The code is at hy:Մոդուլ:ԺամանակիԿատեգորիա and an example of usage at hy:Կատեգորիա:1944 ծնունդներ. It work fine except when I want to use those placeholders inside a template or an {{#if: block. As I understand, mediawiki parses the text before sending it to the Lua module. Is there a way to change this? ԱշոտՏՆՂ (talk) 01:26, 21 April 2024 (UTC)

@ԱշոտՏՆՂ: Why not simply copy our Template:Birth year category header and its underlying modules? --Redrose64 🌹 (talk) 07:24, 21 April 2024 (UTC)
The module I made works without typing the parameters and it is very generic, the same module can be used for Category:Buildings and structures completed in the 1850s and it adds all the necessary categories (e.g. Buildings and structures completed in the 19th century, 1850s establishments1850s works, 1850s architecture, Buildings and structures by decade of completion). Basically, as long as the category title contains a year/decade/century, the module will work and will create the navigation box too, see hy:Կատեգորիա:1990-ականների կառուցումն ավարտված շենքեր և կառույցներ as an example. The only thing I can't do with this is using wikitext logic inside the header. For example, I can't write {{#ifexist:__YEAR__ in film|See the main article at [[__YEAR__ in film]]}} but for some reason I can do "See the main article at [[__YEAR__ in film]]" and it will replace __YEAR__ with the appropriate year. I feel like it does the ifexist check before my script can replace the placeholder __YEAR__ with an actual number. ԱշոտՏՆՂ (talk) 07:45, 21 April 2024 (UTC)
ԱշոտՏՆՂ, I assume you'd need to wrap it in nowiki tags and then unstrip it in the module, to stop the wikitext being processed. — Qwerfjkltalk 11:19, 21 April 2024 (UTC)
For example, Module:Demo does it, as can be seen in function get. —⁠andrybak (talk) 01:05, 22 April 2024 (UTC)
An alternative approach is to use nested templates, e.g. {{YearCategory|{{Decade|2024}} births.. to implement the decade handling. You may need {{PAGENAME}} or something derived from it as the template parameter. Certes (talk) 09:34, 22 April 2024 (UTC)
... which is done by the {{Title year}} family of templates, heavily used in the Chronology category header templates.
Sometimes this is done in two steps to avoid extra calculations. For example, Template:Sport clubs (dis)established in YYYY category header and Template:Sport clubs (dis)established in YYYY category header/core. The "core" template does include a conversion from {{{year}}} to a decade using {{DECADE}}. —⁠andrybak (talk) 15:44, 22 April 2024 (UTC)

"too many expensive function calls"

I wrote the following function:

local function linkToWikipage(link, text)
	local page = mw.title.new(link)
	if page.exists == true then
		if page.redirectTarget then
			local redir = page.redirectTarget.fullText
						or page.redirectTarget.prefixedText
			return "[[" .. redir .. "|" .. text .. "]]"
		else
			return "[[" .. link ..  "|" .. text .. "]]"
		end
	else
		return text
	end
end

It works on a small scale, but on a larger scale I'm told too many expensive function calls. Can anyone help me find something cheaper that still fulfills the goals of:

  • If the page exists, link to that. If the page doesn't exist, don't link to anything.
  • If the page is a redirect, link to the redirect target.

Eievie (talk) 03:35, 23 April 2024 (UTC)

It can't be done. Each check requires a page to be examined and that is expensive. MediaWiki protects itself from denial-of-service attacks and other bad ideas that would affect performance. A workaround, if really necessary, would be to have a bot periodically do the checking and update the page of links but that won't be suitable for many cases. Johnuniq (talk) 04:44, 23 April 2024 (UTC)
This doesn't ping the same response, though. What makes it different?
frame:expandTemplate{title = 'Link if exists', args = link}
Eievie (talk) 05:44, 23 April 2024 (UTC)
Are you sure? HELP:ifexist (which {{Link if exists}} uses) says it has the same limit of 500 although multiple checks of the same title are counted as one. Johnuniq (talk) 06:08, 23 April 2024 (UTC)
Yes, I'm sure it actually works that way in my testcases. I agree it conceptually seems odd, that's why I'm asking. Eievie (talk) 06:41, 23 April 2024 (UTC)
I tried it at User:Johnuniq/sandbox2 and only 500 calls are allowed. Johnuniq (talk) 08:06, 23 April 2024 (UTC)
Yeah, I had this issue at Module:ATP rankings and its related template, in that checking to see if every redirect existed was causing issues. We ended up hard-coding known outliers into a separate submodule and had the main module check that first before doing any sort of #ifexist. Primefac (talk) 11:16, 23 April 2024 (UTC)
I'm doing this at Module:Unicode chart/sandbox. There are 2 types of links needed:
  • The header link
    • Don't need to check page existence (I'm pretty sure wikipedia has pages for all the blocks)
    • Need to link to the redirect target, so that the bolding feature works correctly (ie. if the template was being included on the page Greek and Coptic, the link would turn bold if the link said Greek and Coptic but not if it said Greek and Coptic (Unicode block))
  • The unicode character links
    • Need to check of page exists (many characters do not have pages)
    • Linking to redirect target would be ideal, but isn't absolutely necessary
Right now I'm using Module:Redirect for the former and {{Link if exists}} for the latter. This does work (see testcases here). It creates the links I need and doesn't create a "too many expensive function calls" error.
I just tried to create the above helper function to cover both, and I'm confused as to why that got that error when this doesn't. My understanding is that:
  • mw.title.new() is the expensive part
  • once you've already done that, checking page.exists and page.redirectTarget are both cheap
  • Module:Redirect and {{Link if exists}} both do the mw.title.new() call
So how is the above function more expensive than either {{Link if exists}} and Module:Redirect? Eievie (talk) 16:14, 23 April 2024 (UTC)
No, creating a title object alone doesn't increase the expensive count, nor does redirectTarget. So you can check redirectTarget (which returns false if the page doesn't exist) before checking exists, which does increase it. Nardog (talk) 16:20, 23 April 2024 (UTC)
You're saying that page.exists is the expensive part? So ordering the function this way would be cheaper?
local function linkToWikipage(pageStr, text)
	local pageObj = mw.title.new(pageStr)
	if pageObj.redirectTarget then
		local redir = pageObj.redirectTarget.fullText
					or pageObj.redirectTarget.prefixedText
		return "[[" .. redir .. "|" .. text .. "]]"
	elseif pageObj.exists == true then
		return "[[" .. pageStr ..  "|" .. text .. "]]"
	else
		return text
	end
end
I'm trying that now, and it's still creating Lua error: too many expensive function calls. Eievie (talk) 16:34, 23 April 2024 (UTC)
Yes, that should at least reduce the expensive parser function count, even if it still exceeds the limit on a particular page. You can compare them in the parser profiling data at the bottom of the edit form. Nardog (talk) 16:50, 23 April 2024 (UTC)
Ok, I figured it out: Calling the other templates, rather than calling the functions myself, just silences the error messages. Eievie (talk) 17:34, 23 April 2024 (UTC)

Discussion at MediaWiki talk:Scribunto-doc-page-header#Category:Module documentation pages

  You are invited to join the discussion at MediaWiki talk:Scribunto-doc-page-header § Category:Module documentation pages. —⁠andrybak (talk) 09:27, 14 May 2024 (UTC)

parsing the first sentence

Does anybody know a parsing method to reliably get the first sentence of an article on a Lua module, removing templates such as infoboxes completely? -1ctinus📝🗨 00:13, 3 June 2024 (UTC)

Module:Excerpt is at least one or two users' attempt to date. Izno (talk) 02:23, 3 June 2024 (UTC)
Using {{excerpt|Lion|paragraph=1|only=paragraphs|hatnote=no}} gets the first paragraph of the Lion article (minus infoboxes, templates, etc). Add |links=no to get plain text. It should be straightforward to get the first sentence from that.  —  Jts1882 | talk  11:49, 3 June 2024 (UTC)

Editing the args metatable of a child frame

Module:Params offers the possibility to map or rename parameters using either helper templates or modules or parser functions. Currently, in the case of mapping_by_invoking and renaming_by_invoking, while iterating, a new child frame gets created for each parameter (#1, #2). This means that if the parameters to map or rename are more than about a hundred the code breaks, because, as the Scribunto-Lua manual says, “The number of frames that may be created at any one time is limited”.

I have tried to solve the problem in Module:Params/sandbox, but all my attempts at keeping only one child frame throughout the loop failed (#3, #4, #5, #6). The reason is that once the child frame object gets created I can no longer edit its .args metatable. Yet, I would need to do that, because each module invocation needs to receive different parameters.

Testcases are available at Module:Params/testcases/tmaps and Module:Params/testcases/tmaps sandbox. Any idea on how to solve the problem and being able to map more than 100 parameters using a module? --Grufo (talk) 15:41, 3 June 2024 (UTC)

Update. I have mentioned the problem at MediaWiki. --Grufo (talk) 12:09, 4 June 2024 (UTC)

Looking for an existing module that takes a page name and converts it into wikitext

Is there an existing Lua module like that either (a) takes a page name and converts it into wikitext or (b) takes a page name and regex and returns the result text (something similar to Module:String2#findpagetext)? Don't want to write a new module if one already exists and I thought something like this exists but I can't find it. Gonnym (talk) 09:20, 6 June 2024 (UTC)

I am not sure I understood exactly what you are looking for, but for getting the wikitext of a page there is {{msgnw}} – you should use the double colon if the page is in the main namespace, as in {{msgnw::Richard Feynman}}. That text transcluded in this way can then be passed as a parameter to a template or a module (and this includes {{#invoke:string|match}}, if that's what you are looking for). And so
{{#invoke:string|match|s={{msgnw::Richard Feynman}}|pattern=known%s+for%s+([^.]+)|nomatch=}}
yields
his work in the [[path integral formulation]] of [[quantum mechanics]], the theory of [[quantum electrodynamics]], the physics of the [[superfluidity]] of supercooled [[liquid helium]], as well as his work in [[particle physics]] for which he proposed the [[parton model]]
--Grufo (talk) 11:01, 6 June 2024 (UTC)
I think that was what I was looking for, thanks! Gonnym (talk) 11:04, 6 June 2024 (UTC)
I am glad that helped! --Grufo (talk) 11:16, 6 June 2024 (UTC)
Isn't "takes a page name and converts it into wikitext" just getContent? Izno (talk) 15:58, 6 June 2024 (UTC)
Yes, but I was asking how to access it from wikitext and not Lua. Gonnym (talk) 16:00, 6 June 2024 (UTC)
That sounds like transclusion: {{:Page name}}. Certes (talk) 17:12, 6 June 2024 (UTC)
Already solved above. Gonnym (talk) 17:56, 6 June 2024 (UTC)

Looking for module that processes black/white text.

Hi. I'm looking for a module that can output 000000 or FFFFFF depending on the color code inputted. Is one available? Thanks. '''[[User:CanonNi]]''' (talkcontribs) 04:20, 11 June 2024 (UTC)

How would the module decide which of the two colors to output? Izno (talk) 06:25, 11 June 2024 (UTC)
I saw this post on Stack Overflow. Could this be implemented in Lua? '''[[User:CanonNi]]''' (talkcontribs) 09:36, 11 June 2024 (UTC)
{{Infobox television season}} uses {{Greater color contrast ratio|{{If empty|{{{bg_colour|}}}|#CCCCFF}}|black|white}} (simplified it), if this is can help you. Gonnym (talk) 09:36, 11 June 2024 (UTC)
@Gonnym this should work, thanks! '''[[User:CanonNi]]''' (talkcontribs) 09:38, 11 June 2024 (UTC)

Methods

If x is a string why can I use x:lower() as a shortcut for string.lower(x) but if y is a table then I can't use y:concat() as a shortcut for table.concat(y)? — Martin (MSGJ · talk) 13:01, 22 March 2024 (UTC)

@MSGJ: This is because string objects in Lua have a metatable where the __index points to the the string table in the standard library. Tables, by default, do not have a metatable (presumably as programmers often use custom metatables for tables in their programs). To unpack that explanation, you need to know how metatables work; there is a pretty good explanation in chapter 13 in the Programming in Lua book. Also there is a little bit more detailed treatment of the string library metatable here. — Mr. Stradivarius ♪ talk ♪ 13:51, 22 March 2024 (UTC)
Does that mean if you use setmetatable(t, y) you could then use t:concat()? —  Jts1882 | talk  14:29, 22 March 2024 (UTC)
Not unless t.concat is a function.
t:concat() is defined as t.concat(t).
For the latter to work, t.concat has to be a function.
A working example:
t = { 'abc', 'def', 'z' }
y = { __index = { concat = function(x) return string.reverse(table.concat(x)) end } }
setmetatable(t, y)
z = t:concat()  -- z = 'zfedcba'
Johnuniq (talk) 05:33, 23 March 2024 (UTC)
Thanks both for your replies. A lot to process there, but looks very useful/interesting. Is there an easy way to do the following:
  • Associate a particular table with the standard table library
  • Associate all tables by default with the standard table library
— Martin (MSGJ · talk) 09:34, 25 March 2024 (UTC)
No, there is no good way to alter the way table works. I recommend using standard table.concat and living with it. However, it is possible to muck around with something like this for a single table.
t = { 'def', 'abc', 'A' }
mt = { __index = { concat = table.concat, sort = table.sort } }
setmetatable(t, mt)
a = t:concat()  -- 'defabcA'
t:sort()
b = t:concat()  -- 'Aabcdef'
Search for Collection at Module:Age to see how I have sometimes defined a simple list. It's very weird to follow but Module:IPblock has more examples includings :sort(). Johnuniq (talk) 04:24, 26 March 2024 (UTC)
That seems like it could be worth splitting off into its own module… jlwoodwa (talk) 07:18, 24 June 2024 (UTC)

Executing and scraping results from an advanced search url

Is a module capable of executing an WP:Advanced search via a url param that is passed to it, and then processing the output of the search? I would like to be able to pass this url to a Module, have it execute the search, and return the total number of results by scraping it out of the content. For example, it should return value 4 given this url:

https://en.wikipedia.org/w/index.php?search=Draft%3A+hastemplate%3AOKA++hastemplate%3AAfC_submission%2Fdraft&title=Special:Search&profile=default&fulltext=1

The resulting Html contains the following which looks easily scrapable, if a module can access it:

<div class="results-info" data-mw-num-results-offset="0" data-mw-num-results-total="4">Results <strong>1 – 4</strong> of <strong>4</strong></div>

The module should be capable of handling any url that represents an advanced search, and find the total results. Is that possible? Mathglot (talk) 07:04, 6 July 2024 (UTC)

No. Searching uses Special:Search and modules cannot access special pages which are not based on wikitext. I don't know what API may be available for use by JavaScript. Johnuniq (talk) 08:01, 6 July 2024 (UTC)
Thanks. I suspected as much, but wasn't sure. I'll look into other avenues. Mathglot (talk) 08:06, 6 July 2024 (UTC)

Request for Lua code review: New language module

Reposting this village pump post for visibility: Wikipedia:Village_pump_(technical)#Request_for_Lua_code_review:_New_language_module

Feedback welcome on the talk page here.

--Nonabelian (talk) 15:27, 25 July 2024 (UTC)

Is there an expensive-parser-function-count counter?

It would be very useful to know how much overhead remains at any given time during execution.   ~ Tom.Reding (talkdgaf)  14:20, 10 August 2024 (UTC)

Not that I know of. It is interesting that there is a function mw.incrementExpensiveFunctionCount() to increment the count but none (documented) to fetch the current count. I suspect that mw.incrementExpensiveFunctionCount() is used internally by MediaWiki functions to bump the counter when an expensive function is executed.
Trappist the monk (talk) 14:48, 10 August 2024 (UTC)
There is the extremely ugly hack Module:Preview expense, but that's almost certainly not what you want. * Pppery * it has begun... 00:27, 11 August 2024 (UTC)
If you are willing to look further than lua, there is parser_function_count.py in pywikipediabot which counts ALL parser functions. In theory, that could be changed to count expensive parser functions. Then you need another script to get all templates used on a page. That would result in a list of pages with their maximum possible expensive parser function counts. (some of those parser functions are guarded with if statements, which the script would not take account for) Snævar (talk) 09:01, 17 August 2024 (UTC)
You could also do the same with getContent() in lua, with the same limitations. Snævar (talk) 09:03, 17 August 2024 (UTC)
Thanks, but I'm looking for something like mw.getExpensiveFunctionCount() that I can easily query inside a lua loop to know when to break out of it.   ~ Tom.Reding (talkdgaf)  10:41, 17 August 2024 (UTC)

Category detection (using new feature!)

After 11 years in Phabricator purgatory, T50175 has now been completed, and Lua can now detect the categories used on a page. Would someone be able to implement this at {{If in category}} to make it less expensive/less error-prone/substable? Sdkbtalk 15:23, 16 August 2024 (UTC)

Thanks for letting us know. Sounds as though it could be useful — Martin (MSGJ · talk) 16:29, 22 August 2024 (UTC)

Problem with escape character

This is from Module:Chessboard:

res = mw.ustring.gsub( res,'\| \|', '| |' )

This is being identified as an error when you try to save it, but not exactly sure how to fix. — Martin (MSGJ · talk) 16:28, 22 August 2024 (UTC)

Use % as the Lua escape character.  —  Jts1882 | talk  16:34, 22 August 2024 (UTC)
Umm, pipe isn't a special character in lua patterns so does not need to be escaped. See mw:Extension:Scribunto/Lua_reference_manual#Patterns.
Trappist the monk (talk) 16:39, 22 August 2024 (UTC)
If you look at the code in the module you will see
Error: [243:31] invalid escape sequence near '\|'
Perhaps it is the pipe which needs escaping — Martin (MSGJ · talk) 06:18, 23 August 2024 (UTC)
It seems the syntax highlighter is pointing out that the escape sequence doesn't make any sense (it's expecting something like \120 or \n), but it's still legal code, and just gets interpreted as | since a pipe has no special meaning when escaped. Aidan9382 (talk) 08:01, 23 August 2024 (UTC)
Is there anyway this can be coded which prevents the warning? At the moment you get a warning every time you try to save the page — Martin (MSGJ · talk) 08:04, 23 August 2024 (UTC)
Just remove the \, since "\|" and "|" are the same in lua (e.g. try printing it). Aidan9382 (talk) 08:09, 23 August 2024 (UTC)
That would render the gsub completely redundant/useless, so maybe this is not doing what it was supposed to do ... — Martin (MSGJ · talk) 08:19, 23 August 2024 (UTC)
Have just realised that the function that contains this appears to be completely unused, and it is also not documented. So it is simplest if I just remove this function from the module and the error disappears — Martin (MSGJ · talk) 08:26, 23 August 2024 (UTC)
Sorry Aidan, just noticed your edit to the sandbox. I had not noticed the extra space between the pipes, so that makes sense. If it turns out the function is being used, then I will put your version back in — Martin (MSGJ · talk) 08:30, 23 August 2024 (UTC)
Did you try using %| as I suggested above?  —  Jts1882 | talk  08:27, 23 August 2024 (UTC)
I think I did, but it doesn't make the syntax highlighter any happier — Martin (MSGJ · talk) 08:31, 23 August 2024 (UTC)
It gets rid of the error messages on the lines for me.  —  Jts1882 | talk  08:46, 23 August 2024 (UTC)
(Lua patterns are not regex.) Izno (talk) 19:07, 22 August 2024 (UTC)