How Can We Help?
You are here:
< Back

nbsp

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

&nbsp;?
Trappist the monk (talk) 20:35, 12 June 2023 (UTC)[reply]
Thank you. For some reason I thought that would produce the literal text. — Martin (MSGJ · talk) 21:06, 12 June 2023 (UTC)[reply]
It will produce the literal text &nbsp;. 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)[reply]

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)[reply]

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)[reply]
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)[reply]

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)[reply]

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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]

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)[reply]

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)[reply]
And there is an example at Module:Math#L-605. Johnuniq (talk) 09:57, 26 June 2023 (UTC)[reply]
Thanks, that's working nicely — Martin (MSGJ · talk) 11:25, 26 June 2023 (UTC)[reply]
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)[reply]
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)[reply]
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)[reply]

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)[reply]

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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]

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)[reply]

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)[reply]

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)[reply]
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)[reply]

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)[reply]

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)[reply]
/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)[reply]

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)[reply]

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)[reply]
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)[reply]

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)[reply]

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)[reply]
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)[reply]
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)[reply]

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)[reply]

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)[reply]

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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
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)[reply]
@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)[reply]

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)[reply]

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)[reply]
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)[reply]

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)[reply]

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 Lua error: bad argument #1 to 'title.new' (number or string expected, got nil). Lua error: bad argument #1 to 'title.new' (number or string expected, got nil). Lua error: bad argument #1 to 'title.new' (number or string expected, got nil). Lua error: bad argument #1 to 'title.new' (number or string expected, got nil). 67
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)[reply]

Categories
Table of Contents