<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ADetect_singular</id>
	<title>Module:Detect singular - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ADetect_singular"/>
	<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Detect_singular&amp;action=history"/>
	<updated>2026-04-04T13:08:58Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://the-democratika.com/wiki/index.php?title=Module:Detect_singular&amp;diff=5861&amp;oldid=prev</id>
		<title>&gt;Hike395: when flag is set, parse number and determine plurality from that</title>
		<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Detect_singular&amp;diff=5861&amp;oldid=prev"/>
		<updated>2025-03-05T07:06:22Z</updated>

		<summary type="html">&lt;p&gt;when flag is set, parse number and determine plurality from that&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
local yesNo = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
local getPlain = require(&amp;#039;Module:Text&amp;#039;).Text().getPlain&lt;br /&gt;
&lt;br /&gt;
-- function to determine whether &amp;quot;sub&amp;quot; occurs in &amp;quot;s&amp;quot;&lt;br /&gt;
local function plainFind(s, sub)&lt;br /&gt;
	return mw.ustring.find(s, sub, 1, true)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- function to count the number of times &amp;quot;pattern&amp;quot; (a regex) occurs in &amp;quot;s&amp;quot;&lt;br /&gt;
local function countMatches(s, pattern)&lt;br /&gt;
	local _, count = mw.ustring.gsub(s, pattern, &amp;#039;&amp;#039;)&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local singular = 1&lt;br /&gt;
local likelyPlural = 2&lt;br /&gt;
local plural = 3&lt;br /&gt;
&lt;br /&gt;
-- Determine whether a string is singular or plural (i.e., it represents one&lt;br /&gt;
-- item or many)&lt;br /&gt;
-- Arguments:&lt;br /&gt;
--   origArgs[1]: string to process&lt;br /&gt;
--   origArgs.no_comma:  if false, use commas to detect plural (default false)&lt;br /&gt;
--   origArgs.parse_links: if false, treat wikilinks as opaque singular objects (default false)&lt;br /&gt;
-- Returns:&lt;br /&gt;
--   singular, likelyPlural, or plural (see constants above), or nil for completely unknown&lt;br /&gt;
function p._main(origArgs)&lt;br /&gt;
	origArgs = type(origArgs) == &amp;#039;table&amp;#039; and origArgs or {}&lt;br /&gt;
	local args = {}&lt;br /&gt;
	-- canonicalize boolean arguments&lt;br /&gt;
	for key, default in pairs({no_comma=false,parse_links=false,any_comma=false,&lt;br /&gt;
                               no_and=false,parse_number=false}) do&lt;br /&gt;
		if origArgs[key] == nil then&lt;br /&gt;
			args[key] = default&lt;br /&gt;
		else&lt;br /&gt;
			args[key] = yesNo(origArgs[key],default)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local checkComma = not args.no_comma&lt;br /&gt;
	local checkAnd = not args.no_and&lt;br /&gt;
	local rewriteLinks = not args.parse_links&lt;br /&gt;
	local anyComma = args.any_comma&lt;br /&gt;
    local parseNumber = args.parse_number&lt;br /&gt;
	local s = origArgs[1]  -- the input string&lt;br /&gt;
	if not s then&lt;br /&gt;
		return nil -- empty input returns nil&lt;br /&gt;
	end&lt;br /&gt;
	s = tostring(s)&lt;br /&gt;
	s = mw.text.decode(s,true)  --- replace HTML entities (to avoid spurious semicolons)&lt;br /&gt;
	if plainFind(s,&amp;#039;data-plural=&amp;quot;0&amp;quot;&amp;#039;) then -- magic data string to return true&lt;br /&gt;
		return singular&lt;br /&gt;
	end&lt;br /&gt;
	if plainFind(s,&amp;#039;data-plural=&amp;quot;1&amp;quot;&amp;#039;) then -- magic data string to return false&lt;br /&gt;
		return plural&lt;br /&gt;
	end&lt;br /&gt;
	-- count number of list items&lt;br /&gt;
	local numListItems = countMatches(s,&amp;#039;&amp;lt;%s*li&amp;#039;)&lt;br /&gt;
	-- if exactly one, then singular, if more than one, then plural&lt;br /&gt;
	if numListItems == 1 then&lt;br /&gt;
		return singular&lt;br /&gt;
	end&lt;br /&gt;
	if numListItems &amp;gt; 1 then&lt;br /&gt;
		return plural&lt;br /&gt;
	end&lt;br /&gt;
	-- if &amp;quot;list of&amp;quot; occurs inside of wlink, then it&amp;#039;s plural&lt;br /&gt;
	if mw.ustring.find(s:lower(), &amp;#039;%[%[[^%]]*list of[^%]]+%]%]&amp;#039;) then&lt;br /&gt;
		return plural&lt;br /&gt;
	end&lt;br /&gt;
    if parseNumber then&lt;br /&gt;
        local m = tonumber(mw.ustring.match(s,&amp;quot;^%s*(%d+)&amp;quot;))&lt;br /&gt;
        if m then&lt;br /&gt;
            return m &amp;gt; 1 and plural or singular&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
	-- fix for trailing br tags passed through [[template:marriage]]&lt;br /&gt;
	s = mw.ustring.gsub(s, &amp;#039;&amp;lt;%s*br[^&amp;gt;]*&amp;gt;%s*(&amp;lt;/div&amp;gt;)&amp;#039;, &amp;#039;%1&amp;#039;)&lt;br /&gt;
	-- replace all wikilinks with fixed string&lt;br /&gt;
	if rewriteLinks then&lt;br /&gt;
		s = mw.ustring.gsub(s,&amp;#039;%b[]&amp;#039;,&amp;#039;WIKILINK&amp;#039;) &lt;br /&gt;
	end&lt;br /&gt;
	-- Five conditions: any one of them can make the string a likely plural or plural&lt;br /&gt;
	local hasBreak = mw.ustring.find(s,&amp;#039;&amp;lt;%s*br&amp;#039;)&lt;br /&gt;
	-- For the last 4, evaluate on string stripped of wikimarkup&lt;br /&gt;
	s = getPlain(s)&lt;br /&gt;
	local hasBullets = countMatches(s,&amp;#039;%*+&amp;#039;) &amp;gt; 1&lt;br /&gt;
	local multipleQids = mw.ustring.find(s,&amp;#039;Q%d+[%p%s]+Q%d+&amp;#039;) -- has multiple QIDs in a row&lt;br /&gt;
	if hasBullets or multipleQids then&lt;br /&gt;
		return plural&lt;br /&gt;
	end&lt;br /&gt;
	local commaPattern = anyComma and &amp;#039;[,;]&amp;#039; or &amp;#039;%D[,;]%D&amp;#039;  -- semi-colon similar to comma&lt;br /&gt;
	local hasComma = checkComma and mw.ustring.find(s, commaPattern)&lt;br /&gt;
	local hasAnd = checkAnd and mw.ustring.find(s,&amp;#039;[,%s]and%s&amp;#039;)&lt;br /&gt;
	if hasBreak or hasComma or hasAnd then&lt;br /&gt;
		return likelyPlural&lt;br /&gt;
	end&lt;br /&gt;
	return singular&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._pluralize(args)&lt;br /&gt;
	args = type(args) == &amp;#039;table&amp;#039; and args or {}&lt;br /&gt;
	local singularForm = args[3] or args.singular or &amp;quot;&amp;quot;&lt;br /&gt;
	local pluralForm = args[4] or args.plural or &amp;quot;&amp;quot;&lt;br /&gt;
	local likelyForm = args.likely or pluralForm&lt;br /&gt;
	local link = args[5] or args.link&lt;br /&gt;
	if link then&lt;br /&gt;
		link = tostring(link)&lt;br /&gt;
		singularForm = &amp;#039;[[&amp;#039;..link..&amp;#039;|&amp;#039;..singularForm..&amp;#039;]]&amp;#039;&lt;br /&gt;
		pluralForm = &amp;#039;[[&amp;#039;..link..&amp;#039;|&amp;#039;..pluralForm..&amp;#039;]]&amp;#039;&lt;br /&gt;
		likelyForm = &amp;#039;[[&amp;#039;..link..&amp;#039;|&amp;#039;..likelyForm..&amp;#039;]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if args[2] then&lt;br /&gt;
		return pluralForm&lt;br /&gt;
	end&lt;br /&gt;
	local detect = p._main(args)&lt;br /&gt;
	if detect == nil then&lt;br /&gt;
		return &amp;quot;&amp;quot;   -- return blank on complete failure&lt;br /&gt;
	end&lt;br /&gt;
	if detect == singular then&lt;br /&gt;
		return singularForm&lt;br /&gt;
	elseif detect == likelyPlural then&lt;br /&gt;
		return likelyForm&lt;br /&gt;
	else&lt;br /&gt;
		return pluralForm&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	-- For template, return 1 if singular, blank if plural or empty&lt;br /&gt;
	local result = p._main(args)&lt;br /&gt;
	if result == nil then&lt;br /&gt;
		return 1&lt;br /&gt;
	end&lt;br /&gt;
	return result == singular and 1 or &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.pluralize(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	return p._pluralize(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>&gt;Hike395</name></author>
	</entry>
</feed>