置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Loop

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [查看] [编辑] [历史] [刷新]

简介

该模块可以循环执行语句。相较于解析器函数,因为使用Lua模块进行循环,所以没有100次上限的限制

用法和功能与{{loop}}类似,但可以处理模板的接收参数(也即被三对大括号包裹的参数,如{{{1}}}

用法

注意:

  • 第一层循环的代码需要用<nowiki>标签包裹。
  • 多层循环中内层循环的代码不需要<nowiki>标签包裹。
loop
{{#invoke:loop|main| 自增/减变量名 = 初始值 | 最大值 | 自增/减量 |do= <nowiki>
循环执行的代码...
</nowiki>}}
  • main亦可作loopfor
  • 使用自增/减变量的写法为:{{#var:变量名}},如:{{#var:time}}
  • 默认的自增/减量在初始值小于最大值为1,在初始值大于最大值时为-1。
while/dowhile
{{#invoke:loop|while| condition = <nowiki>循环条件</nowiki> |do= <nowiki>
循环执行的代码...
</nowiki>}}
{{#invoke:loop|dowhile| condition = <nowiki>循环条件</nowiki> |do= <nowiki>
循环执行的代码...
</nowiki>}}
fornumargs
{{#invoke:loop|fornumargs| 变量名前缀 | 索引变量名 | 值变量名 |<nowiki>
循环执行的代码...
</nowiki>}}

示例

示例1

{{#vardefine:count|0}}<!--
-->{{#invoke:loop|main|time=1|101|do=
<nowiki>{{#vardefine:count| {{#expr: {{#var:count}} + {{#var:time}} }} }}</nowiki> }}
结果:{{#var:count}}

结果:5151

示例2

{{#vardefine:count|0}}<!--
-->{{#invoke:loop|main|time1=1|5|do=<nowiki>
  {{#invoke:loop|main|time2=1|100|do=
    {{#vardefine:count| {{#expr: {{#var:count}} + {{#var:time1}} * {{#var:time2}} }} }}
  }}
</nowiki>}}
结果:{{#var:count}}

结果:75750

示例3

{{#invoke:loop|main|time=1|5
|do=<nowiki>
{{#expr:{{#var:time}} + {{{1|0}}} }}{{{split|、}}}
</nowiki>
}}

1、2、3、4、5、

  1. local module = {}
  2. local getArgs = require('Module:Arguments').getArgs
  3. local nowiki_blocks = { 'do', 'condition' }
  4. function pack_inner_loop(loop)
  5. -- 给内层循环的do参数包裹<nowiki>标签
  6. loop = mw.ustring.gsub(loop, '{{%s-[Ll]oop%s-|', '{{#invoke:loop|loop|')
  7. loop = mw.ustring.gsub(loop, '{{%s-[Ww]hile%s-|', '{{#invoke:loop|while|')
  8. loop = mw.ustring.gsub(loop, '{{%s-[Dd]o[Ww]hile%s-|', '{{#invoke:loop|dowhile|')
  9. return mw.ustring.gsub(loop, '({{#invoke:loop.*)', function(a)
  10. local i = 1
  11. local stack = {}
  12. local block_begin = -1
  13. local block_end = -1
  14. while (i < mw.ustring.len(a)) do
  15. for _, block in ipairs(nowiki_blocks) do
  16. if block_begin == -1 and mw.ustring.find(a, '^|%s-'..block..'%s-=', i) then
  17. _, block_begin = mw.ustring.find(a, '^|%s-'..block..'%s-=', i)
  18. block_begin = block_begin + 1
  19. i = block_begin
  20. break
  21. end
  22. end
  23. if block_begin ~= -1 then
  24. if mw.ustring.sub(a, i, i + 2) == '{{{' then
  25. i = i + 3
  26. table.insert(stack, 3)
  27. elseif mw.ustring.sub(a, i, i + 1) == '{{' then
  28. i = i + 2
  29. table.insert(stack, 2)
  30. elseif mw.ustring.sub(a, i, i + 2) == '}}}' then
  31. if #stack ~= 0 and stack[#stack] == 3 then
  32. i = i + 3
  33. table.remove(stack)
  34. elseif #stack ~= 0 and stack[#stack] == 2 then
  35. i = i + 2
  36. table.remove(stack)
  37. else
  38. block_end = i - 1
  39. break
  40. end
  41. elseif mw.ustring.sub(a, i, i + 1) == '}}' then
  42. if #stack ~= 0 then
  43. i = i + 2
  44. table.remove(stack)
  45. else
  46. block_end = i - 1
  47. break
  48. end
  49. elseif mw.ustring.sub(a, i, i) == '|' and #stack == 0 then
  50. block_end = i - 1
  51. break
  52. else
  53. i = i + 1
  54. end
  55. else
  56. i = i + 1
  57. end
  58. end
  59. if block_begin ~= -1 and block_end == -1 then block_end = i - 1 end
  60. if block_begin ~= -1 and block_end ~= -1 then
  61. -- mw.log('发现内层循环 <nowiki>'..mw.ustring.sub(a, block_begin, block_end)..'</nowiki>')
  62. return mw.ustring.sub(a, 1, block_begin - 1)..'<nowiki>'..
  63. mw.text.trim(mw.ustring.sub(a, block_begin, block_end))..'</nowiki>'..
  64. pack_inner_loop(mw.ustring.sub(a, block_end + 1, -1))
  65. else
  66. return a
  67. end
  68. end )
  69. end
  70. function _loop(args, frame)
  71. local name = ''
  72. local _min = 1
  73. local _max = tonumber(args['max'] or args[1] or 10)
  74. local addend = tonumber(args[2] or 1)
  75. local loop = args['do'] or ''
  76. loop = mw.text.unstripNoWiki(loop)
  77. loop = string.gsub(loop, '<!%-%-.-%-%->', '')
  78. loop = pack_inner_loop(loop)
  79. local trim = mw.text.split(loop, '\n')
  80. loop = ''
  81. for i, v in ipairs(trim) do
  82. loop = loop..mw.text.trim(v)
  83. end
  84. for k, v in pairs(args) do
  85. if(k ~= 'do' and k ~= 'max' and k ~= 1 and k ~= 2) then
  86. name = string.gsub(k, '([%%%(%)%.%+%-%*%?%[%]%^%$])', '%%%1')
  87. _min = tonumber(v)
  88. break
  89. end
  90. end
  91. if name == '' then error('必须设置自增/自减的变量名!') end
  92. loop = mw.text.decode(loop)
  93. -- mw.log('循环体= '..loop)
  94. local result = ''
  95. if type(args[2]) == 'nil' and _min > _max and addend > 0 then addend = -1 end
  96. for i=_min, _max, addend do
  97. frame:callParserFunction('#vardefine', name, i)
  98. -- mw.log('执行循环体('..name..'='..tostring(i)..') '..loop)
  99. result = result..frame:preprocess(loop)
  100. end
  101. -- mw.log('循环结果 '..result)
  102. return result
  103. end
  104. function module.loop(frame)
  105. if (frame:getParent() or frame):getTitle() == 'Template:Loop' and
  106. frame.args['do'] == nil then
  107. args = getArgs(frame)
  108. else
  109. args = frame.args
  110. end
  111. return _loop(args, frame:getParent() or frame)
  112. end
  113. -- 向后兼容
  114. function module.main(frame)
  115. return module.loop(frame)
  116. end
  117. -- 别名
  118. module["for"] = function(frame)
  119. return module.loop(frame)
  120. end
  121. local _while = function(args, frame, dowhile)
  122. --初步处理条件语句
  123. local condition = args['condition'] or ''
  124. condition = mw.text.unstripNoWiki(condition)
  125. condition = string.gsub(condition, '<!%-%-.-%-%->', '')
  126. --修整条件语句的格式
  127. local trim = mw.text.split(condition, '\n')
  128. condition = ''
  129. for i, v in ipairs(trim) do
  130. condition = condition..mw.text.trim(v)
  131. end
  132. condition = mw.text.decode(condition)
  133. -- mw.log('循环体= '..condition)
  134. --初步处理循环体
  135. local loop = args['do'] or ''
  136. loop = mw.text.unstripNoWiki(loop)
  137. loop = string.gsub(loop, '<!%-%-.-%-%->', '')
  138. --处理循环体中的次级循环语句
  139. loop = pack_inner_loop(loop)
  140. --修整循环体中语句的格式
  141. local trim = mw.text.split(loop, '\n')
  142. loop = ''
  143. for i, v in ipairs(trim) do
  144. loop = loop..mw.text.trim(v)
  145. end
  146. loop = mw.text.decode(loop)
  147. -- mw.log('循环体= '..loop)
  148. local result = ''
  149. if dowhile then
  150. -- mw.log('执行循环体('..name..'='..tostring(i)..') '..loop)
  151. repeat result = result..frame:preprocess(loop) until frame:preprocess(condition) == ''
  152. else
  153. -- mw.log('执行循环体('..name..'='..tostring(i)..') '..loop)
  154. while frame:preprocess(condition) ~= '' do result = result..frame:preprocess(loop) end
  155. end
  156. -- mw.log('循环结果 '..result)
  157. return result
  158. end
  159. module["while"] = function(frame)
  160. if (frame:getParent() or frame):getTitle() == 'Template:While' and
  161. frame.args['do'] == nil then
  162. args = getArgs(frame)
  163. else
  164. args = frame.args
  165. end
  166. return _while(args, frame:getParent() or frame, false)
  167. end
  168. module.dowhile = function(frame)
  169. if (frame:getParent() or frame):getTitle() == 'Template:While' and
  170. frame.args['do'] == nil then
  171. args = getArgs(frame)
  172. else
  173. args = frame.args
  174. end
  175. return _while(args, frame:getParent() or frame, true)
  176. end
  177. function module.fornumargs(frame)
  178. local args = frame.args
  179. local parent = frame:getParent()
  180. local prefix = mw.text.trim(args[1] or '')
  181. local numname = mw.text.trim(args[2] or '')
  182. local valname = mw.text.trim(args[3] or '')
  183. local cond = mw.text.decode(mw.text.unstripNoWiki(mw.text.trim(args.cond or '')))
  184. local text = mw.text.decode(mw.text.unstripNoWiki(mw.text.trim(args[4] or '')))
  185. if not parent or numname == '' or valname == '' or text == '' then return '' end
  186. local expr = '^' .. mw.ustring.gsub(prefix, '([-+*?%%])', '%%%1') .. '(%d+)$'
  187. local keys = {}
  188. local output = {}
  189. for key, _ in pairs(parent.args) do
  190. local num = mw.ustring.match(key, expr)
  191. if num then
  192. table.insert(keys, tonumber(num))
  193. end
  194. end
  195. table.sort(keys)
  196. for _, idx in ipairs(keys) do
  197. parent:callParserFunction('#vardefine', numname, idx)
  198. parent:callParserFunction('#vardefine', valname, parent.args[prefix .. idx])
  199. if cond == '' or parent:preprocess(cond) ~= '' then
  200. table.insert(output, parent:preprocess(text))
  201. end
  202. end
  203. return table.concat(output)
  204. end
  205. return module