Skip to content

Commit 7ce46bf

Browse files
committed
Thêm Detect singular vào Other
1 parent 0440746 commit 7ce46bf

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

‎Other/Detect singular.lua‎

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
local p = {}
2+
local getArgs = require('Module:Arguments').getArgs
3+
local yesNo = require('Module:Yesno')
4+
5+
-- function to determine whether "sub" occurs in "s"
6+
local function plainFind(s, sub)
7+
return mw.ustring.find(s, sub, 1, true)
8+
end
9+
10+
-- function to count the number of times "pattern" (a regex) occurs in "s"
11+
local function countMatches(s, pattern)
12+
local _, count = mw.ustring.gsub(s, pattern, '')
13+
return count
14+
end
15+
16+
local singular = 1
17+
local likelyPlural = 2
18+
local plural = 3
19+
20+
-- Determine whether a string is singular or plural (i.e., it represents one
21+
-- item or many)
22+
-- Arguments:
23+
-- origArgs[1]: string to process
24+
-- origArgs.no_comma: if false, use commas to detect plural (default false)
25+
-- origArgs.parse_links: if false, treat wikilinks as opaque singular objects (default false)
26+
-- origArgs.any_comma: if true, allow any comma to cause likely plural, including ones between digits (default false)
27+
-- origArgs.no_and: if false, use existence of "and" to detect plural (default false)
28+
-- origArgs.parse_number: if true, parse number in argument: if 1, singular; if >1, plural (default false)
29+
-- Returns:
30+
-- singular, likelyPlural, or plural (see constants above), or nil for completely unknown
31+
function p._main(origArgs)
32+
origArgs = type(origArgs) == 'table' and origArgs or {}
33+
local args = {}
34+
-- canonicalize boolean arguments
35+
for key, default in pairs({no_comma=false,parse_links=false,any_comma=false,
36+
no_and=false,parse_number=false}) do
37+
if origArgs[key] == nil then
38+
args[key] = default
39+
else
40+
args[key] = yesNo(origArgs[key],default)
41+
end
42+
end
43+
local checkComma = not args.no_comma
44+
local checkAnd = not args.no_and
45+
local rewriteLinks = not args.parse_links
46+
local anyComma = args.any_comma
47+
local parseNumber = args.parse_number
48+
local s = origArgs[1] -- the input string
49+
if not s then
50+
return nil -- empty input returns nil
51+
end
52+
s = tostring(s)
53+
s = mw.text.decode(s,true) --- replace HTML entities (to avoid spurious semicolons)
54+
if plainFind(s,'data-plural="0"') then -- magic data string to return true
55+
return singular
56+
end
57+
if plainFind(s,'data-plural="1"') then -- magic data string to return false
58+
return plural
59+
end
60+
-- count number of list items
61+
local numListItems = countMatches(s,'<%s*li')
62+
-- if exactly one, then singular, if more than one, then plural
63+
if numListItems == 1 then
64+
return singular
65+
end
66+
if numListItems > 1 then
67+
return plural
68+
end
69+
-- if "list of" occurs inside of wlink, then it's plural
70+
if mw.ustring.find(s:lower(), '%[%[[^%]]*list of[^%]]+%]%]') then
71+
return plural
72+
end
73+
if parseNumber then
74+
local m = tonumber(mw.ustring.match(s,"^%s*(%d+)"))
75+
if m then
76+
return m > 1 and plural or singular
77+
end
78+
end
79+
-- fix for trailing br tags passed through [[template:marriage]]
80+
s = mw.ustring.gsub(s, '<%s*br[^>]*>%s*(</div>)', '%1')
81+
-- replace all wikilinks with fixed string
82+
if rewriteLinks then
83+
s = mw.ustring.gsub(s,'%b[]','WIKILINK')
84+
end
85+
-- Five conditions: any one of them can make the string a likely plural or plural
86+
local hasBreak = mw.ustring.find(s,'<%s*br')
87+
-- For the last 4, evaluate on string stripped of wikimarkup
88+
local getPlain = require('Module:Text').Text().getPlain
89+
s = getPlain(s)
90+
local hasBullets = countMatches(s,'%*+') > 1
91+
local multipleQids = mw.ustring.find(s,'Q%d+[%p%s]+Q%d+') -- has multiple QIDs in a row
92+
if hasBullets or multipleQids then
93+
return plural
94+
end
95+
local commaPattern = anyComma and '[,;]' or '%D[,;]%D' -- semi-colon similar to comma
96+
local hasComma = checkComma and mw.ustring.find(s, commaPattern)
97+
local hasAnd = checkAnd and (mw.ustring.find(s,'[,%s]and%s') or mw.ustring.find(s,'&',1,true))
98+
if hasBreak or hasComma or hasAnd then
99+
return likelyPlural
100+
end
101+
return singular
102+
end
103+
104+
function p._pluralize(args)
105+
args = type(args) == 'table' and args or {}
106+
local singularForm = args[3] or args.singular or ""
107+
local pluralForm = args[4] or args.plural or ""
108+
local likelyForm = args.likely or pluralForm
109+
local link = args[5] or args.link
110+
if link then
111+
link = tostring(link)
112+
singularForm = '[['..link..'|'..singularForm..']]'
113+
pluralForm = '[['..link..'|'..pluralForm..']]'
114+
likelyForm = '[['..link..'|'..likelyForm..']]'
115+
end
116+
if args[2] then
117+
return pluralForm
118+
end
119+
local detect = p._main(args)
120+
if detect == nil then
121+
return "" -- return blank on complete failure
122+
end
123+
if detect == singular then
124+
return singularForm
125+
elseif detect == likelyPlural then
126+
return likelyForm
127+
else
128+
return pluralForm
129+
end
130+
end
131+
132+
function p.main(frame)
133+
local args = getArgs(frame)
134+
-- For template, return 1 if singular, blank if plural or empty
135+
local result = p._main(args)
136+
if result == nil then
137+
return 1
138+
end
139+
return result == singular and 1 or ""
140+
end
141+
142+
function p.pluralize(frame)
143+
local args = getArgs(frame)
144+
return p._pluralize(args)
145+
end
146+
147+
return p

0 commit comments

Comments
 (0)