首页
随机
登录
设置
关于NeuroWiki
免责声明
NeuroWiki
搜索
查看“Module:Arguments/doc”的源代码
←
Module:Arguments/doc
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您必须确认您的电子邮件地址才能编辑页面。请通过
参数设置
设置并确认您的电子邮件地址。
您可以查看和复制此页面的源代码。
此模块是调用其他模块的模块。 此模块提供了对通过<code><nowiki>{{#invoke:}}</nowiki></code>(以下简称#invoke)传递参数的简单处理。这是元模块(meta-module),只能被其他模块使用,而不应被#invoke直接调用。其特性如下: * 对参数的简易修整,移除空白参数。 * 参数可以在当前框架或父框架中同时传递。(具体见下) * 参数可以直接通过其他Lua模块或调试控制台传递。 * 可自定义更多特性。 == 基本用法 == 首先,您需要通过require函数加载这个模块。这个模块包含了一个名为<code>getArgs</code>的函数。 <syntaxhighlight lang="lua"> local getArgs = require('Module:Arguments').getArgs </syntaxhighlight> 最简单的方法是在使用getArgs函数。变量<code>args</code>是包含#invoke参数的表(table)。(详见下文。) <syntaxhighlight lang="lua"> local getArgs = require('Module:Arguments').getArgs local p = {} function p.main(frame) local args = getArgs(frame) -- 主要的模块放此处。 end return p </syntaxhighlight> === 最佳实践 === 最佳的做法是,先用专门的函数来处理来自#invoke的参数。这样,其他Lua模块直接调用该模块时,就无需再需要弄一个frame对象,从而提升性能,减小开销。 <syntaxhighlight lang="lua"> local getArgs = require('Module:Arguments').getArgs local p = {} function p.main(frame) local args = getArgs(frame) -- 从#invoke中获得的参数 return p._main(args) end function p._main(args) -- 主要模块放此处。 end return p </syntaxhighlight> === 多个函数 === 如果你需要多个函数使用这些参数,而且你希望这些函数可用于#invoke,你可以使用包装函数(wrapper function)。 <syntaxhighlight lang="lua"> local getArgs = require('Module:Arguments').getArgs local p = {} local function makeInvokeFunc(funcName) return function (frame) local args = getArgs(frame) return p[funcName](args) end end p.func1 = makeInvokeFunc('_func1') function p._func1(args) -- 第一个函数的代码。 end p.func2 = makeInvokeFunc('_func2') function p._func2(args) -- 第二个函数的代码。 end return p </syntaxhighlight> === 选项 === 你可以使用如下面这段代码所示的选项。这些选项会在下文中介绍。 <syntaxhighlight lang="lua"> local args = getArgs(frame, { trim = false, removeBlanks = false, valueFunc = function (key, value) -- 用于处理一个参数的函数的代码。 end, frameOnly = true, parentOnly = true, parentFirst = true, wrappers = { 'Template:一个包装模板', 'Template:另一个模板' }, readOnly = true, noOverwrite = true }) </syntaxhighlight> === 修整参数和移除空白的参数 === 将模板转换为Lua的新手易在空白参数上犯错。在模板语法中,空白字符串和仅包含空白字符(whitespace,空格、换行等)的字符串被视为假(false)。然而,在Lua,空白字符串和只包含空白字符的字符串则会被视为真(true)。这就是说,如果你在写Lua模块时,不注意这些参数,你可能会把本想视为假的东西视为真。为了避免这种情况,这个模块默认会移除所有的空白参数。 类似地,空白字符在处理位置参数(positional arguments)时会发生问题。虽然来自#invoke的具名参数(named arguments)中的多余空白字符会被修整(trim),但是对一些位置参数仍然保留。大多数时候,多余的空白字符是不需要的,所以这个模块默认剔除这些空白字符。 然而,有时输入时又需要使用这些空白字符,或者需要保留空白参数。把某些模板准确地转化为模块时,可能有必要这么做。如果你需要这样,你可以将<code>trim</code>和<code>removeBlanks</code>参数设为<code>false</code>。 <syntaxhighlight lang="lua"> local args = getArgs(frame, { trim = false, removeBlanks = false }) </syntaxhighlight> === 对参数进行自定义格式化 === 有时,你需要移除某些空白参数,但是还有些空白参数又不想移除,或者,你需要将所有位置参数转化为小写字母。你可以使用<code>valueFunc</code>选项。这个参数的值必须是一个接收两个参数<code>key</code>和<code>value</code>并且只返回一个值的函数,这个值是你在{{code|args}}表中索引名为{{code|key}}的域时得到的值。 例1:这个函数不会动第一个参数的空白字符,但是其他参数的空白字符会剔除并移除其他所有空白参数。 <syntaxhighlight lang="lua"> local args = getArgs(frame, { valueFunc = function (key, value) if key == 1 then return value elseif value then value = mw.text.trim(value) if value ~= '' then return value end end return nil end }) </syntaxhighlight> 例2:这个函数移除空白参数并将所有参数转化为小写字母,但是不会剔除位置参数的空白字符。 <syntaxhighlight lang="lua"> local args = getArgs(frame, { valueFunc = function (key, value) if not value then return nil end value = mw.ustring.lower(value) if mw.ustring.find(value, '%S') then return value end return nil end }) </syntaxhighlight> 注:如果传入了既不是字符串又不是空值(nil)的值,上面这个函数会失败。当你在你的模块的主函数使用<code>getArgs</code>函数,而且那个函数被另一个Lua模块调用时,就可能出现此情况。这种情况下,你需要检查你输入的内容的类型(type)。如果你使用一个专门用于来自#invoke的参数的函数时,不会有这个问题,你如你有<code>p.main</code>和<code>p._main</code>函数,或者类似。 {{cot|带有数据类型检查功能的例1和例2}} 例1: <syntaxhighlight lang="lua"> local args = getArgs(frame, { valueFunc = function (key, value) if key == 1 then return value elseif type(value) == 'string' then value = mw.text.trim(value) if value ~= '' then return value else return nil end else return value end end }) </syntaxhighlight> 例2: <syntaxhighlight lang="lua"> local args = getArgs(frame, { valueFunc = function (key, value) if type(value) == 'string' then value = mw.ustring.lower(value) if mw.ustring.find(value, '%S') then return value else return nil end else return value end end }) </syntaxhighlight> {{cob}} 而且,请注意,每次从{{code|args}}表中请求参数时,都会调用{{code|valueFunc}}函数,所以请留意性能,确保不要加入低效的代码。 === 框架与父框架 === <code>args</code>表中的参数可以从当前框架或父框架同时传递。这句话有点难懂,可以看下面的例子。假设我们有个称为<code>模块:ExampleArgs</code>的模块,这个模块输出(print)前两个传入的位置参数。 {{cot|模块:ExampleArgs的代码}} <syntaxhighlight lang="lua"> local getArgs = require('Module:Arguments').getArgs local p = {} function p.main(frame) local args = getArgs(frame) return p._main(args) end function p._main(args) local first = args[1] or '' local second = args[2] or '' return first .. ' ' .. second end return p </syntaxhighlight> {{cob}} 然后,<code>模块:ExampleArgs</code>被<code>模板:ExampleArgs</code>调用,<code>模板:ExampleArgs</code>内容如下:<code><nowiki>{{#invoke:ExampleArgs|main|firstInvokeArg}}</nowiki></code>。它会输出内容firstInvokeArg。 现在,如果我们调用<code>模板:ExampleArgs</code>,其结果如下表所示: {| class="wikitable" style="width: 50em; max-width: 100%;" |- ! style="width: 60%;" | 代码 ! style="width: 40%;" | 结果 |- | <code><nowiki>{{ExampleArgs}}</nowiki></code> | firstInvokeArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code> | firstInvokeArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code> | firstInvokeArg secondTemplateArg |} 有三个选项可以用来改变行为:<code>frameOnly</code>、<code>parentOnly</code>和<code>parentFirst</code>。如果设置<code>frameOnly</code>,那么只有从当前框架传入的参数可以被接受;如果设置 <code>parentOnly</code>,那么只有从父框架传入的参数会被接受;如果你设置<code>parentFirst</code>,那么当前框架和父框架的参数都会接受,但是父框架优先于当前框架。以下是对于<code>模板:ExampleArgs</code>的结果: ; 设为frameOnly时 {| class="wikitable" style="width: 50em; max-width: 100%;" |- ! style="width: 60%;" | 代码 ! style="width: 40%;" | 结果 |- | <code><nowiki>{{ExampleArgs}}</nowiki></code> | firstInvokeArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code> | firstInvokeArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code> | firstInvokeArg |} ; 设为parentOnly时 {| class="wikitable" style="width: 50em; max-width: 100%;" |- ! style="width: 60%;" | 代码 ! style="width: 40%;" | 结果 |- | <code><nowiki>{{ExampleArgs}}</nowiki></code> | |- | <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code> | firstTemplateArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code> | firstTemplateArg secondTemplateArg |} ; 设为parentFirst时 {| class="wikitable" style="width: 50em; max-width: 100%;" |- ! style="width: 60%;" | 代码 ! style="width: 40%;" | 结果 |- | <code><nowiki>{{ExampleArgs}}</nowiki></code> | firstInvokeArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code> | firstTemplateArg |- | <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code> | firstTemplateArg secondTemplateArg |} 注意: # 如果你同时设置了<code>frameOnly</code>和<code>parentOnly</code>两个选项,模块将不会从#invoke获取任何参数。这显然不是你需要的。 # 有时,父框架可能无效,比如getArgs是从父框架传入的,而不是当前框架。这种情况下,只有框架参数会被使用(除非设置了parentOnly,那种情况下不会使用任何参数),而且<code>parentFirst</code>和<code>frameOnly</code>选项都会没有效果。 === 包装 === ''包装(wrapper)''选项用于指定一部分模板作为''包装模板(wrapper templates)'',也就是说,要调用模块的模板。如果模块检测到是被包装模板调用的,则只会检查父框架中的参数;否则,只检查传递到getArgs的框架的参数。这允许模块要么被#invoke调用,要么通过包装模板调用,而不会由于为每次参数寻找(argument lookup)同时检查框架和父框架而损失性能。 比如,[[Template:Side box]]的内容(除了{{tag|noinclude}}标签内的)为<code><nowiki>{{#invoke:Side box|main}}</nowiki></code>。检查直接传递到模板的#invoke语句的参数是没有道理的,因为这里没有指定参数。我们可以通过''parentOnly''选项避免检查传递到#invoke的参数,但如果这样做,#invoke也不会从其他页面起作用。如果是这样,代码<code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code>中的{{para|text|Some text}}会直接忽略,无论是从哪个页面使用的。使用<code>wrappers</code>选项以指定“Template:Side box”为包装,我们可以使得<code><nowiki>{{#invoke:Side box|main|text=一些文本}}</nowiki></code>能够从大多数页面使用,而不需要检查[[Template:Side box]]页面自身的参数。 容器可以指定为字符串,或字符串的数组。 <syntaxhighlight lang="lua"> local args = getArgs(frame, { wrappers = 'Template:Wrapper template' }) </syntaxhighlight> <syntaxhighlight lang="lua"> local args = getArgs(frame, { wrappers = { 'Template:Wrapper 1', 'Template:Wrapper 2', -- 可以在此处添加多个包装模板。 } }) </syntaxhighlight> 注意: # 模块会自动检测是否是从包装模板的/sandbox子页面调用的,所以不需要清楚地指定沙盒页面。 # ''wrappers''选项有效改变''frameOnly''和''parentOnly''的默认的选项。如果,比如,设置了''wrappers''时清楚地将''parentOnly''设为false,通过包装模板调用会导致同时加载框架和父框架的参数,尽管非经由包装模板的调用会导致只加载框架参数。 # 如果设置了''wrappers''但是没有可用的父框架,模块总是会从传递给<code>getArgs</code>的框架中得到参数。 === 写入参数表 === 有时给参数表写入新值会很有用。这可以通过此模块的默认设置实现。(然而,记住最好的代码风格是,将需要的参数表中的参数复制到一个新的表中。) <syntaxhighlight lang="lua"> args.foo = '一些值' </syntaxhighlight> 可以带有<code>readOnly</code>和<code>noOverwrite</code>选项修改此行为。如果设置了<code>readOnly</code>,则完全不可能将任何值写到参数表中。如果设置了<code>noOverwrite</code>,则可以将新值添加到此表,但是如果需要重写从#invoke传递的任何参数则不可能添加值。 === ref标签 === 模块使用[[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#Metatables|元表]]以从#invoke中获取参数。这允许不使用<code>pairs()</code>函数就获取框架参数和父框架参数。如果你需要将{{tag|ref}}标签作为输入时,这会很有用。 {{tag|ref}}标签是从Lua中获取的,因此会被MediaWiki软件处理,引用会在文章底部的参考文献列表中显示。如果模块继续从输出中省略索引标签,则会产生一个假引用<!-- If your module proceeds to omit the reference tag from the output, you will end up with a phantom reference --> —— 在参考文献列表中显示,但是没有与之链接的数字。模块如果使用<code>pairs()</code>来检测是否从框架或父框架中使用参数,就会出现此问题,因为这些模块会自动处理每一个可用变量。 此模块允许既获取框架又获取父框架而仅在需要时获取这些参数,从而解决此问题。然而,模块其他位置使用<code>pairs(args)</code>时,仍会出现此问题。 === 已知限制 === 元表(metatable)的使用也有其缺点。大多数正常Lua表工具都不会对args表正常工作,包括<code>#</code>操作符号、<code>next()</code>函数和表库(table library)中的函数。如果这对你的模块重要,你需要使用你自己的用来处理参数的函数,而不是这个模块。<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox|| [[Category:元模块]] }}</includeonly>
该页面使用的模板:
Template:Cob
(
查看源代码
)
Template:Code
(
查看源代码
)
Template:Cot
(
查看源代码
)
Template:Para
(
查看源代码
)
Template:Para/styles.css
(
查看源代码
)
Template:TSLoader
(
查看源代码
)
Template:Tag
(
查看源代码
)
Template:Tsl
(
查看源代码
)
Module:Array
(
查看源代码
)
Module:ProcessArgs
(
查看源代码
)
Module:Static
(
查看源代码
)
Module:TSLoader
(
查看源代码
)
返回
Module:Arguments/doc
。