Постоянно защищенный модуль
Из Википедии, свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация по модулю [ просмотреть ] [ изменить ] [ историю ] [ очистить ]

Этот модуль обеспечивает простую обработку аргументов, переданных из #invoke. Это мета-модуль, предназначенный для использования другими модулями, и его не следует вызывать напрямую из #invoke. Его особенности включают в себя:

  • Легкая обрезка аргументов и удаление пустых аргументов.
  • Аргументы могут передаваться как текущим кадром, так и родительским кадром одновременно. (Подробнее см. Ниже.)
  • Аргументы могут быть переданы непосредственно из другого модуля Lua или из консоли отладки.
  • Большинство функций можно настроить.

Основное использование

Во-первых, вам нужно загрузить модуль. Он содержит одну функцию с именем getArgs.

local  getArgs  =  require ( 'Модуль: аргументы' ). getArgs

В самом базовом сценарии вы можете использовать getArgs внутри своей основной функции. Переменная argsпредставляет собой таблицу, содержащую аргументы из #invoke. (Подробнее см. Ниже.)

local  getArgs  =  require ( 'Модуль: аргументы' ). getArgs local  p  =  {}функция  p . main ( frame ) local  args  =  getArgs ( frame ) - Здесь идет код основного модуля. конецвернуть  p

Рекомендуемая практика

Однако рекомендуется использовать функцию только для обработки аргументов из #invoke. Это означает, что если кто-то вызывает ваш модуль из другого модуля Lua, вам не нужно иметь доступный объект кадра, что повышает производительность.

local  getArgs  =  require ( 'Модуль: аргументы' ). getArgs local  p  =  {}функция  p . main ( frame ) local  args  =  getArgs ( frame ) return  p . _main ( аргументы ) конецфункция  p . _main ( args ) - здесь находится код основного модуля. конецвернуть  p

То, как это вызывается из шаблона {{#invoke:Example|main}}(необязательно с некоторыми параметрами, например {{#invoke:Example|main|arg1=value1|arg2=value2}}), и то, как это вызывается из модуля . Второй - создает таблицу с аргументами в ней, а затем передает эту таблицу функции p._main (args), которая использует ее изначально.require('Module:Example')._main({arg1 = 'value1', arg2 = value2, 'spaced arg3' = 'value3'})

Множественные функции

Если вы хотите, чтобы несколько функций использовали аргументы, и вы также хотите, чтобы они были доступны из #invoke, вы можете использовать функцию-оболочку.

local  getArgs  =  require ( 'Модуль: аргументы' ). getArgsместный  p  =  {}локальная  функция  makeInvokeFunc ( funcName ) return  function  ( frame ) local  args  =  getArgs ( frame ) return  p [ funcName ] ( args ) end endстр . func1  =  makeInvokeFunc ( '_func1' )функция  p . _func1 ( args ) - здесь идет код для первой функции. конецстр . func2  =  makeInvokeFunc ( '_func2' )функция  p . _func2 ( args ) - здесь идет код второй функции. конецвернуть  p

Опции

Доступны следующие варианты. Они объяснены в разделах ниже.

local  args  =  getArgs ( frame ,  { trim  =  false , removeBlanks  =  false , valueFunc  =  function  ( key ,  value ) - Код для обработки конца одного аргумента , frameOnly  =  true , parentOnly  =  true , parentFirst  =  true , wrappers  =  { 'Template : Шаблон оболочки ' , ' Шаблон: другой шаблон оболочки ' },readOnly  =  true , noOverwrite  =  true })

Обрезка и удаление заготовок

Пустые аргументы часто сбивают с толку программистов, плохо знакомых с преобразованием шаблонов MediaWiki в Lua. В синтаксисе шаблона пустые строки и строки, состоящие только из пробелов, считаются ложными. Однако в Lua пустые строки и строки, состоящие из пробелов, считаются истинными. Это означает, что если вы не обращаете внимания на такие аргументы при написании модулей Lua, вы можете рассматривать что-то как истинное, что на самом деле должно рассматриваться как ложное. Чтобы этого избежать, по умолчанию этот модуль удаляет все пустые аргументы.

Точно так же пробелы могут вызвать проблемы при работе с позиционными аргументами. Хотя пробелы обрезаются для именованных аргументов, поступающих из #invoke, они сохраняются для позиционных аргументов. В большинстве случаев этот дополнительный пробел нежелателен, поэтому этот модуль по умолчанию обрезает его.

Однако иногда вы хотите использовать в качестве входных данных пустые аргументы, а иногда вы хотите оставить дополнительные пробелы. Это может быть необходимо для преобразования некоторых шаблонов в том виде, в котором они были написаны. Если вы хотите сделать это, вы можете установить trimи removeBlanksаргументы false.

local  args  =  getArgs ( frame ,  { trim  =  false , removeBlanks  =  false })

Пользовательское форматирование аргументов

Иногда вы хотите удалить одни пустые аргументы, но не другие, или, возможно, вы можете захотеть поместить все позиционные аргументы в нижний регистр. Для подобных действий вы можете использовать valueFuncопцию. Входными данными для этой опции должна быть функция, которая принимает два параметра, keyи value, и возвращает одно значение. Это значение вы получите при доступе к полю keyв argsтаблице.

Пример 1: эта функция сохраняет пробелы для первого позиционного аргумента, но обрезает все остальные аргументы и удаляет все остальные пустые аргументы.

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 конец })

Пример 2: эта функция удаляет пустые аргументы и преобразует все аргументы в нижний регистр, но не удаляет пробелы из позиционных параметров.

местные  арги  =  getArgs ( рама ,  { valueFunc  =  функция  ( ключ ,  значение ) , если  не  значение ,  то возвращает  ноль конечного значения  =  МВт . ustring . понизить ( значение ) если  МВт . ustring . найти ( значение ,  «% S» ) ,  то возвращает  значение конец возврат  ноль конец })

Примечание: указанные выше функции завершатся ошибкой, если переданы входные данные, не относящиеся к типу stringили nil. Это может быть так, если вы используете getArgsфункцию в основной функции вашего модуля, и эта функция вызывается другим модулем Lua. В этом случае вам нужно будет проверить тип вашего ввода. Это не проблема , если вы используете функцию специально для аргументов из #invoke (то есть у вас есть p.mainи p._mainфункция, или что - то подобное).

Также обратите внимание, что valueFuncфункция вызывается более или менее каждый раз, когда аргумент запрашивается из argsтаблицы, поэтому, если вам важна производительность, вы должны убедиться, что вы не делаете ничего неэффективного с вашим кодом.

Фреймы и родительские фреймы

Аргументы в argsтаблице могут передаваться из текущего кадра или из его родительского кадра одновременно. Чтобы понять, что это значит, проще всего привести пример. Допустим, у нас есть модуль с именем Module:ExampleArgs. Этот модуль печатает первые два переданных позиционных аргумента.

Module:ExampleArgsзатем вызывается Template:ExampleArgs, который содержит код {{#invoke:ExampleArgs|main|firstInvokeArg}}. Это дает результат firstInvokeArg.

Если бы мы позвонили Template:ExampleArgs, произошло бы следующее:

Есть три варианта , которые можно установить , чтобы изменить это поведение: frameOnly, parentOnlyи parentFirst. Если вы установите, frameOnlyто будут приниматься только аргументы, переданные из текущего кадра; если вы установите, parentOnlyто будут приниматься только аргументы, переданные из родительского фрейма; и если вы установите, parentFirstто аргументы будут передаваться как из текущего, так и из родительского фреймов, но родительский фрейм будет иметь приоритет над текущим фреймом. Вот результаты с точки зрения Template:ExampleArgs:

frameOnly
parentOnly
parentFirst

Ноты:

  1. Если вы установите оба параметра frameOnlyи parentOnly, модуль вообще не будет получать никаких аргументов из #invoke. Вероятно, это не то, что вам нужно.
  2. В некоторых ситуациях родительский фрейм может быть недоступен, например, если getArgs передается родительскому фрейму, а не текущему фрейму. В этом случае будут использоваться только аргументы фрейма (если не установлен parentOnly, и в этом случае аргументы не будут использоваться), а параметры parentFirstи не frameOnlyбудут иметь никакого эффекта.

Обертки

Параметр оболочки используется для указания ограниченного числа шаблонов в качестве шаблонов оболочки , то есть шаблонов, единственная цель которых - вызвать модуль. Если модуль обнаруживает, что он вызывается из шаблона оболочки, он будет проверять только аргументы в родительском фрейме; в противном случае он будет проверять только аргументы в кадре, переданном в getArgs. Это позволяет вызывать модули либо с помощью #invoke, либо через шаблон оболочки без потери производительности, связанной с необходимостью проверять и фрейм, и родительский фрейм для каждого поиска аргументов.

Например, единственным содержимым поля Template: Side (за исключением содержимого <noinclude>...</noinclude>тегов) является {{#invoke:Side box|main}}. Нет смысла проверять аргументы, переданные непосредственно оператору #invoke для этого шаблона, поскольку там никогда не будут указаны аргументы. Мы можем избежать проверки аргументов, переданных в #invoke, используя параметр parentOnly , но если мы это сделаем, то #invoke не будет работать и с других страниц. Если бы это было так, то |text=Some textв коде {{#invoke:Side box|main|text=Some text}}полностью игнорировалось бы, независимо от того, с какой страницы он использовался. Используя wrappersпараметр для указания 'Template: Side box' в качестве оболочки, мы можем {{#invoke:Side box|main|text=Some text}}работать с большинством страниц, при этом не требуя, чтобы модуль проверял аргументы в поле Template: Side. саму страницу.

Оболочки могут быть указаны как строка или как массив строк.

local  args  =  getArgs ( frame ,  { wrappers  =  'Template: Wrapper template' })


local  args  =  getArgs ( frame ,  { wrappers  =  { 'Template: Wrapper 1' , 'Template: Wrapper 2' , - Здесь можно добавить любое количество шаблонов оболочки. } })

Ноты:

  1. Модуль автоматически определяет, вызывается ли он из подстраницы шаблона оболочки / песочницы, поэтому нет необходимости явно указывать страницы песочницы.
  2. Параметр оболочки эффективно изменяет значение по умолчанию для параметров frameOnly и parentOnly . Если, например, для parentOnly было явно установлено значение false с установленными оболочками , вызовы через шаблоны оболочки приведут к загрузке как аргументов фрейма, так и родительских аргументов, хотя вызовы не через шаблоны оболочки приведут к загрузке только аргументов фрейма.
  3. Если установлена опция оберток и родительский фрейм недоступен, модуль всегда будет получать аргументы из переданного фрейма getArgs.

Запись в таблицу args

Иногда может быть полезно записать новые значения в таблицу args. Это возможно с настройками этого модуля по умолчанию. (Однако имейте в виду, что обычно лучше создавать новую таблицу с новыми значениями и копировать аргументы из таблицы args по мере необходимости.)

аргументы . foo  =  'какое-то значение'

Можно изменить это поведение с помощью readOnlyи noOverwriteопциями. Если readOnlyустановлено, то вообще невозможно записать какие-либо значения в таблицу args. Если noOverwriteустановлено, то в таблицу можно добавлять новые значения, но невозможно добавить значение, если оно перезапишет любые аргументы, переданные из #invoke.

Ссылочные теги

Этот модуль использует метатаблицы для получения аргументов из #invoke. Это позволяет получить доступ как к аргументам фрейма, так и к аргументам родительского фрейма без использования pairs()функции. Это может помочь, если вашему модулю могут быть переданы <ref>...</ref>теги в качестве входных данных.

Как только <ref>...</ref>теги доступны из Lua, они обрабатываются программным обеспечением MediaWiki, и ссылка появляется в списке ссылок внизу статьи. Если ваш модуль продолжает опускать тег ссылки из вывода, вы получите фантомную ссылку - ссылку, которая появляется в списке ссылок, но без какого-либо номера, связанного с ней. Это была проблема с модулями, которые используются pairs()для определения того, использовать ли аргументы из фрейма или из родительского фрейма, поскольку эти модули автоматически обрабатывают каждый доступный аргумент.

Этот модуль решает эту проблему, разрешая доступ как к аргументам фрейма, так и к аргументам родительского фрейма, при этом выбирая эти аргументы только тогда, когда это необходимо. Однако проблема все равно возникнет, если вы используете в pairs(args)другом месте своего модуля.

Известные ограничения

Использование метатаблиц также имеет свои недостатки. Большинство обычных инструментов для работы с таблицами Lua не будут работать должным образом с таблицей args, включая #оператор, next()функцию и функции в библиотеке таблиц. Если их использование важно для вашего модуля, вы должны использовать свою собственную функцию обработки аргументов вместо этого модуля.

- Этот модуль обеспечивает простую обработку аргументов, переданных в Scribunto из- #invoke. Он предназначен для использования другими модулями Lua и не должен- позвонил напрямую из #invoke.local  libraryUtil  =  требуется ( 'libraryUtil' )локальный  checkType  =  libraryUtil . checkTypeлокальные  аргументы  =  {}- Сгенерируйте четыре разные функции tidyVal, чтобы нам не приходилось проверять- варианты каждый раз, когда мы это называем.локальная  функция  tidyValDefault ( ключ ,  val )если  type ( val )  ==  'string',  тоval  =  val : match ( '^% s * (.-)% s * $' )если  val  ==  ''  товернуть  нольещевернуть  valконецещевернуть  valконецконецлокальная  функция  tidyValTrimOnly ( ключ ,  val )если  type ( val )  ==  'string',  тоreturn  val : match ( '^% s * (.-)% s * $' )ещевернуть  valконецконецлокальная  функция  tidyValRemoveBlanksOnly ( ключ ,  val )если  type ( val )  ==  'string',  тоесли  val : find ( '% S' ),  товернуть  valещевернуть  нольконецещевернуть  valконецконецлокальная  функция  tidyValNoChange ( ключ ,  val )вернуть  valконецлокальная  функция соответствует  заголовку ( задано ,  заголовок )local  tp  =  type (  задано  )return  ( tp  ==  'string'  или  tp  ==  'number' )  и  mw . название . новый (  данный  ). prefixedText  ==  заголовокконецlocal  translate_mt  =  {  __index  =  function ( t ,  k )  return  k  end  } аргументы функции . getArgs ( рамка ,  параметры )checkType ( 'getArgs' ,  1 ,  кадр ,  'таблица' ,  истина )checkType ( 'getArgs' ,  2 ,  параметры ,  'таблица' ,  истина )frame  =  frame  или  {}options  =  options  или  {}- [[- Настроить перевод аргументов.-]]варианты . translate  =  options . перевести  или  {}если  getmetatable ( options . translate )  ==  nil,  тоsetmetatable ( опции . translate ,  translate_mt )конецесли  варианты . backtranslate  ==  nil,  затемварианты . backtranslate  =  {}для  к , V  в  пар ( варианты . перевод )  делатьварианты . обратный перевод [ v ]  =  kконецконецесли  варианты . backtranslate ,  и  GetMetaTable ( опции . backtranslate )  ==  ноль ,  тоsetmetatable ( options . backtranslate ,  {__index  =  функция ( t ,  k )если  варианты . переведите [ k ]  ~ =  k,  затемвернуть  нольещевернуть  kконецконец})конец- [[- Получите таблицы аргументов. Если нам передали допустимый объект кадра, получите- аргументы кадра (fargs) и аргументы родительского кадра (pargs), в зависимости- от установленных опций и доступности родительского фрейма. Если бы мы не были- передан действительный объект кадра, нас вызывают из другого модуля Lua- или из консоли отладки, поэтому предположим, что нам передали таблицу аргументов- напрямую и назначьте его новой переменной (luaArgs).-]]местные  фарги ,  парги ,  luaArgsесли  type ( frame . args )  ==  'table'  и  type ( frame . getParent )  ==  'function',  тоесли  варианты . обертки  тогда- [[- Опция wrappers заставляет Module: Arguments искать аргументы в- либо таблица аргументов фрейма, либо таблица родительских аргументов, но-- не оба. Это означает, что пользователи могут использовать синтаксис #invoke- или шаблон оболочки без потери производительности, связанной с- с поиском аргументов как во фрейме, так и в родительском фрейме.- Модуль: аргументы будут искать аргументы в родительском фрейме.- если он находит заголовок родительского фрейма в options.wrapper;- в противном случае он будет искать аргументы в переданном объекте кадра- получитьArgs.-]]локальный  родитель  =  кадр : getParent ()если  не  родитель,  тоfargs  =  рамка . аргументыещелокальный  заголовок  =  родитель : getTitle (): gsub ( '/ песочница $' ,  '' )местное  найдено  =  ложьесли  matchTitle ( параметры . оболочки ,  заголовок ),  тонайдено  =  правдаelseif  type ( options . wrappers )  ==  'table',  затемдля  _ , v  в  парах ( опция . упаковщики )  сделатьесли  matchTitle ( v ,  title ),  тонайдено  =  правдаперерывконецконецконец- Здесь мы проверяем значение false, чтобы nil (по умолчанию) действовал как true.если  есть  или  варианты . frameOnly  ==  false,  тогдаpargs  =  родитель . аргументыконецесли  не  нашел  ни  вариантов . parentOnly  ==  false,  тогдаfargs  =  рамка . аргументыконецконецеще- options.wrapper не установлен, поэтому проверьте другие параметры.если  не  варианты . parentOnly  thenfargs  =  рамка . аргументыконецесли  не  варианты . frameOnly  thenлокальный  родитель  =  кадр : getParent ()pargs  =  родитель  и  родитель . аргументы  или  нольконецконецесли  варианты . parentFirst  затемfargs ,  pargs  =  pargs ,  fargsконецещеluaArgs  =  frameконец- Установите порядок приоритета таблиц аргументов. Если переменные- nil, в таблицу ничего не будет добавлено, поэтому мы избегаем коллизий- между аргументами кадра / родителя и аргументами Lua.local  argTables  =  { fargs }argTables [ # argTables  +  1 ]  =  pargsargTables [ # argTables  +  1 ]  =  luaArgs- [[- Создайте функцию tidyVal. Если это было указано пользователем, мы- используйте это; в противном случае мы выбираем одну из четырех функций в зависимости от- варианты выбраны. Это сделано для того, чтобы нам не пришлось вызывать таблицу опций.- каждый раз при вызове функции.-]]local  tidyVal  =  options . valueFuncесли  tidyVal  тоесли  type ( tidyVal )  ~ =  'function',  тоошибка ("параметру 'valueFunc' присвоено неверное значение"..  '(ожидаемая функция, получено'..  type ( tidyVal )..  ')' ,2)конецelseif  параметры . обрезать  ~ =  false  тогдаесли  варианты . removeBlanks  ~ =  false,  тогдаtidyVal  =  tidyValDefaultещеtidyVal  =  tidyValTrimOnlyконецещеесли  варианты . removeBlanks  ~ =  false,  тогдаtidyVal  =  tidyValRemoveBlanksOnlyещеtidyVal  =  tidyValNoChangeконецконец- [[- Настройте таблицы args, metaArgs и nilArgs. аргументы будут единственными- доступ из функций, а metaArgs будет содержать фактические аргументы. Ноль- аргументы запоминаются в nilArgs, и метатаблица связывает их все-- все вместе.-]]местные  арги ,  metaArgs ,  nilArgs ,  метатаблица  =  {},  {},  {},  {}setmetatable ( аргументы ,  метатаблица )локальная  функция  mergeArgs ( таблицы )- [[- Принимает несколько таблиц в качестве входных данных и объединяет их ключи и значения.- в одну таблицу. Если значение уже присутствует, оно не перезаписывается;- таблицы, перечисленные ранее, имеют приоритет. Мы также запоминаем ноль- значения, которые могут быть перезаписаны, если они "s" (мягкие).-]]for  _ ,  t  в  ipairs ( таблицы )  делаемдля  ключа ,  вал  в  пар ( т )  делатьесли  metaArgs [ key ]  ==  nil  и  nilArgs [ key ]  ~ =  'h',  толокальная  tidiedVal  =  tidyVal ( ключ ,  вал )если  tidiedVal  ==  nil,  тоnilArgs [ ключ ]  =  's'ещеmetaArgs [ ключ ]  =  tidiedValконецконецконецконецконец- [[- Определите метатабильное поведение. Аргументы запоминаются в таблице metaArgs,- и извлекаются из таблиц аргументов только один раз. Получение аргументов- из таблиц аргументов это самый ресурсоемкий шаг в этом- модуль, поэтому мы стараемся избегать его, где это возможно. По этой причине ноль- аргументы также запоминаются в таблице nilArgs. Также ведем учет- в метатаблице, когда были вызваны пары и ipair, поэтому мы не- запускать пары и ipairs в таблицах аргументов более одного раза. Мы также делаем- не запускать ipairs на фаргах и паргах, если пары уже были запущены, так как все- аргументы уже будут скопированы.-]]метатабильный . __index  =  функция  ( t ,  ключ )- [[- Выбирает аргумент при индексировании таблицы args. Сначала мы проверяем- чтобы увидеть, запомнено ли значение, и если нет, мы пытаемся получить его из- таблицы аргументов. Когда мы проверяем мемоизацию, нам нужно проверить- metaArgs перед nilArgs, так как оба могут быть ненулевыми одновременно.- Если аргумент отсутствует в metaArgs, мы также проверяем,- пары еще не запущены. Если пары уже были запущены, мы возвращаем nil.- Это потому, что все аргументы уже были скопированы в- metaArgs функцией mergeArgs, что означает, что любые другие аргументы- должно быть ноль.-]]если  type ( key )  ==  'string',  тоключ  =  параметры . перевести [ ключ ]конецlocal  val  =  metaArgs [ ключ ]если  val  ~ =  nil,  товернуть  valelseif  метатаблица . donePairs  или  nilArgs [ ключ ],  затемвернуть  нольконецдля  _ ,  argTable  в  ipairs ( argTables )  делаемlocal  argTableVal  =  tidyVal ( ключ ,  argTable [ ключ ])если  argTableVal  ~ =  nil,  тоmetaArgs [ ключ ]  =  argTableValвернуть  argTableValконецконецnilArgs [ ключ ]  =  'ч'вернуть  нольконецметатабильный . __newindex  =  функция  ( t ,  ключ ,  val )- Эта функция вызывается, когда модуль пытается добавить новое значение в- таблица аргументов или пытается изменить существующее значение.если  type ( key )  ==  'string',  тоключ  =  параметры . перевести [ ключ ]конецесли  варианты . readOnly  thenошибка ('не удалось записать в ключ таблицы аргументов "'..  tostring ( ключ )..  '"; таблица только для чтения' ,2)elseif  параметры . noOverwrite  и  args [ ключ ]  ~ =  nil,  тогдаошибка ('не удалось записать в ключ таблицы аргументов "'..  tostring ( ключ )..  '"; перезапись существующих аргументов не разрешена' ,2)elseif  val  ==  nil  тогда- [[- Если аргумент должен быть перезаписан на nil, нам нужно стереть- значение в metaArgs, так что __index, __pairs и __ipairs делают- не использовать предыдущее существующее значение, если оно есть; и нам также нужно- запомнить ноль в nilArgs, чтобы значение не просматривалось- вверх в таблицах аргументов при повторном доступе.-]]metaArgs [ ключ ]  =  нольnilArgs [ ключ ]  =  'ч'ещеmetaArgs [ ключ ]  =  валконецконецлокальная  функция  translatenext ( инвариант )локальная  к ,  v  =  следующий ( инвариант . т ,  инвариантны . к )инвариантный . к  =  кесли  k  ==  nil,  товернуть  нольelseif  type ( k )  ~ =  'строка'  или  нет  параметры . переведите  потомвернуть  k ,  vещеlocal  backtranslate  =  options . обратный перевод [ k ]если  backtranslate  ==  nil,  то- Пропустить. Это хвостовой вызов, поэтому это не вызовет переполнения стека.return  translatenext ( инвариант )ещевернуть обратный  перевод ,  vконецконецконецметатабильный . __pairs  =  функция  ()- Вызывается, когда пары запускаются в таблице аргументов.если  не  метатабельно . donePairs  тогдаmergeArgs ( argTables )метатабильный . donePairs  =  trueконецвернуть  translatenext ,  {  t  =  metaArgs  }конецлокальная  функция  inext ( t ,  i )- Здесь используется наш метаметод __indexместный  v  =  t [ i  +  1 ]если  v  ~ =  nil,  товернуть  i  +  1 ,  vконецконецметатабильный . __ipairs  =  функция  ( t )- Вызывается, когда ipairs запускается для таблицы args.вернуться  назад ,  t ,  0конецвернуть  аргументыконецвернуть  аргументы