•  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
r2 vs r5
11
-- This module provides easy processing of arguments passed to Scribunto from
22
-- #invoke. It is intended for use by other Lua modules, and should not be
33
-- called from #invoke directly.
44
-- [invoke(모듈 이름)]
55
local libraryUtil = require('libraryUtil')
66
local checkType = libraryUtil.checkType
77
88
local arguments = {}
99
1010
-- Generate four different tidyVal functions, so that we don't have to check the
1111
-- options every time we call it.
1212
1313
local function tidyValDefault(key, val)
1414
if type(val) == 'string' then
1515
val = val:match('^%s*(.-)%s*$')
1616
if val == '' then
1717
return nil
1818
else
1919
return val
2020
end
2121
else
2222
return val
2323
end
2424
end
2525
2626
local function tidyValTrimOnly(key, val)
2727
if type(val) == 'string' then
2828
return val:match('^%s*(.-)%s*$')
2929
else
3030
return val
3131
end
3232
end
3333
3434
local function tidyValRemoveBlanksOnly(key, val)
3535
if type(val) == 'string' then
3636
if val:find('%S') then
3737
return val
3838
else
3939
return nil
4040
end
4141
else
4242
return val
4343
end
4444
end
4545
4646
local function tidyValNoChange(key, val)
4747
return val
4848
end
4949
5050
local function matchesTitle(given, title)
5151
local tp = type( given )
5252
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
5353
end
5454
5555
local translate_mt = { __index = function(t, k) return k end }
5656
5757
function arguments.getArgs(frame, options)
5858
checkType('getArgs', 1, frame, 'table', true)
5959
checkType('getArgs', 2, options, 'table', true)
6060
frame = frame or {}
6161
options = options or {}
6262
6363
--[[
6464
-- Set up argument translation.
6565
--]]
6666
options.translate = options.translate or {}
6767
if getmetatable(options.translate) == nil then
6868
setmetatable(options.translate, translate_mt)
6969
end
7070
if options.backtranslate == nil then
7171
options.backtranslate = {}
7272
for k,v in pairs(options.translate) do
7373
options.backtranslate[v] = k
7474
end
7575
end
7676
if options.backtranslate and getmetatable(options.backtranslate) == nil then
7777
setmetatable(options.backtranslate, {
7878
__index = function(t, k)
7979
if options.translate[k] ~= k then
8080
return nil
8181
else
8282
return k
8383
end
8484
end
8585
})
8686
end
8787
8888
--[[
8989
-- Get the argument tables. If we were passed a valid frame object, get the
9090
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
9191
-- on the options set and on the parent frame's availability. If we weren't
9292
-- passed a valid frame object, we are being called from another Lua module
9393
-- or from the debug console, so assume that we were passed a table of args
9494
-- directly, and assign it to a new variable (luaArgs).
9595
--]]
9696
local fargs, pargs, luaArgs
9797
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
9898
if options.wrappers then
9999
--[[
100100
-- The wrappers option makes Module:Arguments look up arguments in
101101
-- either the frame argument table or the parent argument table, but
102102
-- not both. This means that users can use either the #invoke syntax
103103
-- or a wrapper template without the loss of performance associated
104104
-- with looking arguments up in both the frame and the parent frame.
105105
-- Module:Arguments will look up arguments in the parent frame
106106
-- if it finds the parent frame's title in options.wrapper;
107107
-- otherwise it will look up arguments in the frame object passed
108108
-- to getArgs.
109109
--]]
110110
local parent = frame:getParent()
111111
if not parent then
112112
fargs = frame.args
113113
else
114114
local title = parent:getTitle():gsub('/sandbox$', '')
115115
local found = false
116116
if matchesTitle(options.wrappers, title) then
117117
found = true
118118
elseif type(options.wrappers) == 'table' then
119119
for _,v in pairs(options.wrappers) do
120120
if matchesTitle(v, title) then
121121
found = true
122122
break
123123
end
124124
end
125125
end
126126
127127
-- We test for false specifically here so that nil (the default) acts like true.
128128
if found or options.frameOnly == false then
129129
pargs = parent.args
130130
end
131131
if not found or options.parentOnly == false then
132132
fargs = frame.args
133133
end
134134
end
135135
else
136136
-- options.wrapper isn't set, so check the other options.
137137
if not options.parentOnly then
138138
fargs = frame.args
139139
end
140140
if not options.frameOnly then
141141
local parent = frame:getParent()
142142
pargs = parent and parent.args or nil
143143
end
144144
end
145145
if options.parentFirst then
146146
fargs, pargs = pargs, fargs
147147
end
148148
else
149149
luaArgs = frame
150150
end
151151
152152
-- Set the order of precedence of the argument tables. If the variables are
153153
-- nil, nothing will be added to the table, which is how we avoid clashes
154154
-- between the frame/parent args and the Lua args.
155155
local argTables = {fargs}
156156
argTables[#argTables + 1] = pargs
157157
argTables[#argTables + 1] = luaArgs
158158
159159
--[[
160160
-- Generate the tidyVal function. If it has been specified by the user, we
161161
-- use that; if not, we choose one of four functions depending on the
162162
-- options chosen. This is so that we don't have to call the options table
163163
-- every time the function is called.
164164
--]]
165165
local tidyVal = options.valueFunc
166166
if tidyVal then
167167
if type(tidyVal) ~= 'function' then
168168
error(
169169
"bad value assigned to option 'valueFunc'"
170170
.. '(function expected, got '
171171
.. type(tidyVal)
172172
.. ')',
173173
2
174174
)
175175
end
176176
elseif options.trim ~= false then
177177
if options.removeBlanks ~= false then
178178
tidyVal = tidyValDefault
179179
else
180180
tidyVal = tidyValTrimOnly
181181
end
182182
else
183183
if options.removeBlanks ~= false then
184184
tidyVal = tidyValRemoveBlanksOnly
185185
else
186186
tidyVal = tidyValNoChange
187187
end
188188
end
189189
190190
--[[
191191
-- Set up the args, metaArgs and nilArgs tables. args will be the one
192192
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
193193
-- arguments are memoized in nilArgs, and the metatable connects all of them
194194
-- together.
195195
--]]
196196
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
197197
setmetatable(args, metatable)
198198
199199
local function mergeArgs(tables)
200200
--[[
201201
-- Accepts multiple tables as input and merges their keys and values
202202
-- into one table. If a value is already present it is not overwritten;
203203
-- tables listed earlier have precedence. We are also memoizing nil
204204
-- values, which can be overwritten if they are 's' (soft).
205205
--]]
206206
for _, t in ipairs(tables) do
207207
for key, val in pairs(t) do
208208
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
209209
local tidiedVal = tidyVal(key, val)
210210
if tidiedVal == nil then
211211
nilArgs[key] = 's'
212212
else
213213
metaArgs[key] = tidiedVal
214214
end
215215
end
216216
end
217217
end
218218
end
219219
220220
--[[
221221
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
222222
-- and are only fetched from the argument tables once. Fetching arguments
223223
-- from the argument tables is the most resource-intensive step in this
224224
-- module, so we try and avoid it where possible. For this reason, nil
225225
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
226226
-- in the metatable of when pairs and ipairs have been called, so we do not
227227
-- run pairs and ipairs on the argument tables more than once. We also do
228228
-- not run ipairs on fargs and pargs if pairs has already been run, as all
229229
-- the arguments will already have been copied over.
230230
--]]
231231
232232
metatable.__index = function (t, key)
233233
--[[
234234
-- Fetches an argument when the args table is indexed. First we check
235235
-- to see if the value is memoized, and if not we try and fetch it from
236236
-- the argument tables. When we check memoization, we need to check
237237
-- metaArgs before nilArgs, as both can be non-nil at the same time.
238238
-- If the argument is not present in metaArgs, we also check whether
239239
-- pairs has been run yet. If pairs has already been run, we return nil.
240240
-- This is because all the arguments will have already been copied into
241241
-- metaArgs by the mergeArgs function, meaning that any other arguments
242242
-- must be nil.
243243
--]]
244244
if type(key) == 'string' then
245245
key = options.translate[key]
246246
end
247247
local val = metaArgs[key]
248248
if val ~= nil then
249249
return val
250250
elseif metatable.donePairs or nilArgs[key] then
251251
return nil
252252
end
253253
for _, argTable in ipairs(argTables) do
254254
local argTableVal = tidyVal(key, argTable[key])
255255
if argTableVal ~= nil then
256256
metaArgs[key] = argTableVal
257257
return argTableVal
258258
end
259259
end
260260
nilArgs[key] = 'h'
261261
return nil
262262
end
263263
264264
metatable.__newindex = function (t, key, val)
265265
-- This function is called when a module tries to add a new value to the
266266
-- args table, or tries to change an existing value.
267267
if type(key) == 'string' then
268268
key = options.translate[key]
269269
end
270270
if options.readOnly then
271271
error(
272272
'could not write to argument table key "'
273273
.. tostring(key)
274274
.. '"; the table is read-only',
275275
2
276276
)
277277
elseif options.noOverwrite and args[key] ~= nil then
278278
error(
279279
'could not write to argument table key "'
280280
.. tostring(key)
281281
.. '"; overwriting existing arguments is not permitted',
282282
2
283283
)
284284
elseif val == nil then
285285
--[[
286286
-- If the argument is to be overwritten with nil, we need to erase
287287
-- the value in metaArgs, so that __index, __pairs and __ipairs do
288288
-- not use a previous existing value, if present; and we also need
289289
-- to memoize the nil in nilArgs, so that the value isn't looked
290290
-- up in the argument tables if it is accessed again.
291291
--]]
292292
metaArgs[key] = nil
293293
nilArgs[key] = 'h'
294294
else
295295
metaArgs[key] = val
296296
end
297297
end
298298
299299
local function translatenext(invariant)
300300
local k, v = next(invariant.t, invariant.k)
301301
invariant.k = k
302302
if k == nil then
303303
return nil
304304
elseif type(k) ~= 'string' or not options.backtranslate then
305305
return k, v
306306
else
307307
local backtranslate = options.backtranslate[k]
308308
if backtranslate == nil then
309309
-- Skip this one. This is a tail call, so this won't cause stack overflow
310310
return translatenext(invariant)
311311
else
312312
return backtranslate, v
313313
end
314314
end
315315
end
316316
317317
metatable.__pairs = function ()
318318
-- Called when pairs is run on the args table.
319319
if not metatable.donePairs then
320320
mergeArgs(argTables)
321321
metatable.donePairs = true
322322
end
323323
return translatenext, { t = metaArgs }
324324
end
325325
326326
local function inext(t, i)
327327
-- This uses our __index metamethod
328328
local v = t[i + 1]
329329
if v ~= nil then
330330
return i + 1, v
331331
end
332332
end
333333
334334
metatable.__ipairs = function (t)
335335
-- Called when ipairs is run on the args table.
336336
return inext, t, 0
337337
end
338338
339339
return args
340340
end
341341
342342
return arguments
343343
344344
345345
[[분류:루아]]