Wikipedia tetwiki https://tet.wikipedia.org/wiki/P%C3%A1jina_Mahuluk MediaWiki 1.47.0-wmf.23 first-letter Media Espesiál Diskusaun Uza-na'in Diskusaun Uza-na'in Wikipedia Diskusaun Wikipedia Imajen Diskusaun Imajen MediaWiki Diskusaun MediaWiki Template Diskusaun Template Ajuda Diskusaun Ajuda Kategoria Diskusaun Kategoria TimedText TimedText talk Módulo Módulo Discussão Evento Evento Discussão Wikipedia:Kafé 4 2509 75982 75519 2026-10-09T09:29:08Z MediaWiki message delivery 3558 /* Wikidata Sitelink changes in Recent Changes and Watchlist */ nova secção 75982 wikitext text/x-wiki __NEWSECTIONLINK__ {{/Opening}} __TOC__ == Tulun == Hai maluk sira, oinsa ita boot sira nia hanoin se ita kria notisia aktual iha pájina mahuluk para ita hare furak oituan?? hau hanoin ida ne´e paso positivo ida y ida ne´e furak tebes, tanba ho ida ne´e ema hotu bele hetan informasaun konaba ita nia rain liu-liu timor ona sira nebe mak hela no estuda iha rai liur. hau mos hanoin katak hosi ida ne´e timor ona sira nebe mak hela iha rai liur bele fo sira nia hanoin, kritiko no mos sira bele fo notisias importante ruma nebe sira hetan o konaba realidade nebe mak sira hasoru... ne´e mak hau nia komentario i hau mos hakarak husu ita boot sira dirección ou se E-mail para ami bele kontakto ita boot sira, hau nia E-mail mak ne´e: eulalia@maceo.ijv.sld.cu :Ne'e hanesan paso kapas ida hodi halo furak liu-tan Wikipedia Lian Tetun, maibe? bainhra lo'os mak sei komesan? == [[Geoffrey Hull]] == Hello, could someone of you please make an English version of the article about linguist [[Geoffrey Hull]] please? Franch, Spanish, Catalan, Ocitan or Portuguese would be fine too (in the appropriate wikipedia). Many thanks, --[[Espesiál:Kontribuisaun/79.40.157.170|79.40.157.170]] 16:30, 10 Novembru 2009 (UTC) :This has been done by LombardBeige. Thank you so much!--[[Uza-na'in:Padaneis|Padaneis]] 18:19, 23 Abríl 2010 (UTC) == Avril == Hi! Who can translate [http://tet.wikipedia.org/wiki/Avril_Lavigne this] page? I need so much your help! Is a sample phrase. Thanks in advanced. [[Uza-na'in:Vitor Mazuco|Vitor Mazuco]] ([[Diskusaun Uza-na'in:Vitor Mazuco|talk]]) 12:20, 26 Juñu 2012 (UTC) :Hi, I think it is better not to translate that page. We do not really need "sample phrases" which people would simply copy for not very informative 1-sentence-articles about other singers. --<small>[[User:MF-Warburg|MF-Warburg]]</small> 15:06, 30 Juñu 2012 (UTC) ==Bantuan terjemahan== Mohon bantuan terjemah http://ms.wikipedia.org/wiki/1_SGM kepada bahasa Tetun secara lengkap untuk diguna sebagai template bagi rencana lainnya. [[Uza-na'in:Yosri|Yosri]] ([[Diskusaun Uza-na'in:Yosri|talk]]) 18:31, 11 Fevereiru 2013 (UTC) :I agree with MF-Warburg's comment [[#Avril|above]]. [[Uza-na'in:Bennylin|Bennylin]] ([[Diskusaun Uza-na'in:Bennylin|talk]]) 13:45, 1 Marsu 2013 (UTC) Hi [https://tet.wikipedia.org/wiki/Uza-na%27in:Yosri Yosri] Saya akan mencoba membantu terjemahkan https://ms.wikipedia.org/wiki/1_SGM dalam bahasa Tetun, namun mungkin ada beberapa kata yang harus diadopsi dari bahasa Portugues. Karena belum ada di Bahasa Tetun. Thx --[[Uza-na'in:Abraoximenes|Abraoximenes]] ([[Diskusaun Uza-na'in:Abraoximenes|talk]]) 00:56, 7 Outubru 2014 (UTC) Hi [https://tet.wikipedia.org/wiki/Uza-na%27in:Yosri Yosri] I have just translated the content of https://ms.wikipedia.org/wiki/1_SGM to [[Tetun]] https://tet.wikipedia.org/wiki/1_SGM --[[Uza-na'in:Abraoximenes|Abraoximenes]] ([[Diskusaun Uza-na'in:Abraoximenes|talk]]) 02:27, 7 Outubru 2014 (UTC) :Maybe you should translate [https://en.wikipedia.org/wiki/Census_town this], too to make clear,what is a [[Sidade sensu]]. ;-) --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 21:38, 7 Outubru 2014 (UTC) == [[Lista administrativu Timór Lorosa'e nian]] == Hello! I just copied the Suku-List from German Wikipedia into Tetum Wikipedia. Still the names of the sukus have to be translated into Tetum, but I will do it during the next days as best as I can. Feel free to join me or maybe write the articles about the subdistricts and sukus. Greetings, --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 13:35, 10 Agostu 2014 (UTC) ==Help for translate== Hello and sorry for writing in English. Can anyone help me translate a small article (2 paragraphs) from English to your language and create the article in your wiki? Please, fell free to answer in my talk page in your wiki anytime. Thanks! [[Uza-na'in:Xaris333|Xaris333]] ([[Diskusaun Uza-na'in:Xaris333|talk]]) 00:42, 13 Agostu 2014 (UTC) == Greetings from a friend in Dili: == Obrigado barak ba imi nia tulun ba hau nis rai doben Timor Leste. M.B. (posted by --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 17:15, 22 Agostu 2014 (UTC)) == Timor Telecom ho Wikipedia == "Timor Telecom ho Wikipedia anunsia projetu inovador: Wikipedia 0 Timor-Leste. Asessu gratuitu iha ita nia telemovel." [https://www.facebook.com/media/set/?set=a.897041010325669.1073741882.377387458957696&type=1] --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 18:19, 22 Agostu 2014 (UTC) : [https://www.facebook.com/photo.php?v=896973780332392&set=vb.377387458957696&type=2&theater] Video. :[https://www.facebook.com/TimorTelecomTL/photos/a.385650871464688.105202.377387458957696/897072446989192/?type=1&theater Timor Telecom]: "Quiz Wikipedia! Durante loron lima nia laran ami sei fo pergunta lima kona ba kultura jeral. Liu tiha loron lima, ami sei fo hatene numeru telemovel ami nian, ne'ebe ita tenke haruka SMS ba numeru ne'e ho resposta lima ne'ebe los. Ema nain tolu ne'ebe haruka resposta los no lais liu sei manan telemovel Samsung E1050 ho 10$ pulsa. Partisipa kedas! Wikipedia-Quiz!" --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 19:17, 22 Agostu 2014 (UTC) [http://noticias.sapo.tl/tetum/info/artigo/1404989.html "TT halo parseria ho Wikipedia no oferese asesu gratuitu ba kliente sira"] --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 03:36, 26 Agostu 2014 (UTC) == Facebook group == I started a Facebook group for a little advertisment for Wikipedia in Tetun. Would you like to join? [https://www.facebook.com/groups/368607786648555/] --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 19:19, 6 Outubru 2014 (UTC) == Placenames == I had two requests for changing the spelling of two places in Timor-Leste. There is an inofficial Tetun spelling: [[Lautein]] and [[Bagia]], but it seems like the official speling is the same like the Portuguese: [[Lautém]] and [[Baguia]]. [[Uza-na'in:Abraoximenes|Abraoximenes]]: "Based on our Tetun orthography if we write the name of a place and a person we have to write based its official name, not based its pronunciation. In East Timor, We never write "Baguia" with "Bagia"." Crispim Costa in FB: "I think we can not change the name of the places. Indeed originaly the place in Fataluku was called LAU-TEINU= sacred cloth, but from times on up to know it is written: LAUTÉM." Marco da Silva in FB: "ya, bifor portuguese time we col LAU-TEINU...now in the poblic col LAUTEM." Should we change the place spelling to the official spelling like in this document? [http://www.jornal.gov.tl/public/docs/2009/serie_1/serie1_no33.pdf Jornal da Républica mit dem Diploma Ministerial n.° 199/2009] --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 19:19, 6 Outubru 2014 (UTC) :(tetun) "Lautein", ne'e iha [http://haunialianhauniaidentidade.blogspot.de/2009/04/matadalan-ortografiku-ba-lia-tetum.html Matadalan Ortográfiku ba Lia-Tetun] husi ''Institutu Nasionál Linguístika''. Governu timoroan mós uza "Lautein", porezemplu [http://timor-leste.gov.tl/?p=7487&lang=tp iha ne'e]. :(inglés) "Lautein" is listed in the [http://haunialianhauniaidentidade.blogspot.de/2009/04/matadalan-ortografiku-ba-lia-tetum.html orthographic directory] of the National Institute for Linguistics. The Timorese Government also uses it, for example [http://timor-leste.gov.tl/?p=7487&lang=tp here]. --<small>[[User:MF-Warburg|MF-Warburg]]</small> 23:37, 6 Outubru 2014 (UTC) I far as I know, in East Timor we have 16 local languages. Therefore, some people wrote Tetun inconsistent, not based on the Tetun orthography. I thought their writing was very influenced by their mother language and Bahasa Indonesia. I knew a little bit about Tetun Orthography because six years ago I worked as a consultant of Tetun and bible translation for 3 years. --[[Uza-na'in:Abraoximenes|Abraoximenes]] ([[Diskusaun Uza-na'in:Abraoximenes|talk]]) 01:28, 7 Outubru 2014 (UTC) :I found now an artilce of Geoffrey Hull from Instituto Nacional de Linguística, who said, it is the aim of Projecto Toponímico Nacional to produce "orthographical normative bilingual lists of all EASt Timorese placenames for practical use... ". [http://www.anps.org.au/documents/June_2006.pdf ''The placenames of East Timor'', in: Placenames Australia (ANPS): Newsletter of the Australian National Placenames Survey, Juni 2006, S. 6 & 7] Would be nice to get this lists for our work. It would help much, if we could get contact with the INL. --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|talk]]) 20:55, 12 Outubru 2014 (UTC) == Wikipédia Timor-Leste 2020 == [[Imajen:Wikipedia Timor-Leste 2020.png|miniaturadaimagem|Wikipédia Timor-Leste 2020]] After invitation by some Wikipedians, we are planing to come to Timor-Leste in August 2020 to support the activities of the local community. It is planned to recruit new editors, provide workshops, talk to media and officials and start offline activities of the wiki community. In the moment, we are applying for grants by the Wikimedia Foundation. You can support us by endorsing the grants at the project page on Meta of Wikimedia [https://meta.wikimedia.org/wiki/Grants:Project/J._Patrick_Fischer/Wikipedia_Timor-Leste_2020 here]. If the project will get support by the foundation, we will be happy, if you can support us in August in Dili. See you 2020! --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|discussão]]) 21h00min de 29 de Dezembru de 2019 (UTC) == Feminism and Folklore 2026 starts soon == <div style="border:8px maroon ridge;padding:6px;"> [[File:Feminism and Folklore 2026 logo.svg|centre|550px|frameless]] ::<div lang="en" dir="ltr" class="mw-content-ltr"> <div style="text-align: center; width: 100%;">''{{int:please-translate}}''</div> ;Invitation to Organize Feminism and Folklore 2026 Dear Wiki Community, We are pleased to invite Wikimedia communities, affiliates, and independent contributors to organize the '''[[:m:Feminism and Folklore 2026|Feminism and Folklore 2026]]''' writing competition on your local Wikipedia. The international campaign will run from '''1 February to 31 March 2026''' and aims to improve coverage of feminism, women’s histories, gender-related topics, and folk culture across Wikipedia projects. ;About the Campaign '''Feminism and Folklore''' is a global writing initiative that complements the '''[[:c:Commons:Wiki Loves Folklore 2026|Wiki Loves Folklore]]''' photography competition. While Wiki Loves Folklore focuses on visual documentation, this writing campaign addresses the '''gender gap on Wikipedia''' by improving encyclopedic content related to folk culture and marginalized voices. ;What Can Participants Write About? Communities can contribute by creating, expanding, or translating articles related to: * Folk festivals, rituals, and celebrations * Folk dances, music, and traditional performances * Women and queer figures in folklore * Women in mythology and oral traditions * Women warriors, witches, and witch-hunting narratives * Fairy tales, folk stories, and legends * Folk games, sports, and cultural practices Participants may work from curated article lists or generate new article suggestions using campaign tools. ;How to Sign Up as an Organizer Organizers are requested to complete the following steps to register their community: # Create a local project page on your wiki [[:m:Feminism and Folklore/Sample|(see sample)]] # Set up the campaign using the '''CampWiz''' tool # Prepare a local article list and clearly mention: #* Campaign timeline #* Local and international prizes # Request a site notice from local administrators [[:mr:Template:SN-FNF|(see sample)]] # Add your local project page and CampWiz link to the '''[[:m:Feminism and Folklore 2026/Project Page|Meta project page]]''' ;Campaign Tools The Wiki Loves Folklore Tech Team has introduced tools to support organizers and participants: * '''Article List Generator by Topic''' – Helps identify articles available on English Wikipedia but missing in your local language Wikipedia. The tool allows customized filters and provides downloadable article lists in CSV and wikitable formats. * '''CampWiz''' – Enables communities to manage writing campaigns effectively, including jury-based evaluation. This will be the third year CampWiz is officially used for Feminism and Folklore. Both tools are now available for use in the campaign. '''[https://tools.wikilovesfolklore.org/ Click here to access the tools]''' ;Learn More & Get Support For detailed information about rules, timelines, and prizes, please visit the '''[[:m:Feminism and Folklore 2026|Feminism and Folklore 2026 project page]]'''. If you have any questions or need assistance, feel free to reach out via: * '''[[:m:Talk:Feminism and Folklore 2026/Project Page|Meta talk page]]''' * Email us using details on the contact page. ;Join Us We look forward to your collaboration and coordination in making Feminism and Folklore 2026 a meaningful and impactful campaign for closing gender gaps and enriching folk culture content on Wikipedia. Thank you and best wishes, '''[[:m:Feminism and Folklore 2026|Feminism and Folklore 2026 International Team]]''' ---- ''Stay connected:'' [[File:B&W Facebook icon.png|link=https://www.facebook.com/feminismandfolklore/|30x30px]]&nbsp; [[File:B&W Twitter icon.png|link=https://twitter.com/wikifolklore|30x30px]] </div></div> == Invitation to Host Wiki Loves Folklore 2026 in Your Country == <div lang="en" dir="ltr" class="mw-content-ltr"> <div style="text-align: center; width: 100%;">''{{int:please-translate}}''</div> [[File:Wiki Loves Folklore Logo.svg|right|150px|frameless]] Hello everyone, We are delighted to invite Wikimedia affiliates, user groups, and community organizations worldwide to participate in '''Wiki Loves Folklore 2026''', an international initiative dedicated to documenting and celebrating folk culture across the globe. ;About Wiki Loves Folklore '''Wiki Loves Folklore''' is an annual international photography competition hosted on Wikimedia Commons. The campaign runs from '''1 February to 31 March 2026''' and encourages photographers, cultural enthusiasts, and community members to contribute photographs that highlight: * Folk traditions and rituals * Cultural festivals and celebrations * Traditional attire and crafts * Performing arts, music, and dance * Everyday practices rooted in folk heritage Through this campaign, we aim to preserve and promote diverse folk cultures and make them freely accessible to the world. [[:c:Commons:Wiki_Loves_Folklore_2026|Project page on Wikimedia Commons]] ; Host a Local Edition As we celebrate the '''eight edition''' of Wiki Loves Folklore, we warmly invite communities to organize a local edition in their country or region. Hosting a local campaign is a great opportunity to: * Increase visibility of your region’s folk culture * Engage new contributors in your community * Enrich Wikimedia Commons with high-quality cultural content '''[[:c:Commons:Wiki_Loves_Folklore_2026/Organize|Sign up to organize]]:''' If your team prefers to organize the competition in ''either February or March only'', please feel free to let us know. If you are unable to organize, we encourage you to share this opportunity with other interested groups or organizations in your region. ;Get in Touch If you have any questions, need support, or would like to explore collaboration opportunities, please feel free to contact us via: * The project Talk pages * Email: '''support@wikilovesfolklore.org''' We are also happy to connect via an online meeting if your team would like to discuss planning or coordination in more detail. Warm regards, '''The Wiki Loves Folklore International Team''' </div> [[Uza-na'in:MediaWiki message delivery|MediaWiki message delivery]] ([[Diskusaun Uza-na'in:MediaWiki message delivery|discussão]]) 13h21min de 18 de Janeiru de 2026 (UTC) <!-- Mensagem enviada por User:Tiven2240@metawiki utilizando a lista em https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery/Wikipedia&oldid=29228188 --> == Join the sixth Ukraine’s Cultural Diplomacy Month on Wikipedia! == <div lang="en" dir="ltr"> [[File:Ukraine’s Cultural Diplomacy Month on Wikipedia 2026.png|right|250px|thumb|link=https://meta.wikimedia.org/wiki/Ukraine%27s_Cultural_Diplomacy_Month_2026|Join our campaign!]] {{int:please-translate}} Dear Wikipedians! [[:m:Special:MyLanguage/Wikimedia Ukraine|Wikimedia Ukraine]], in cooperation with the [[:en:Ministry of Foreign Affairs of Ukraine|MFA of Ukraine]] and [[:en:Ukrainian Institute|Ukrainian Institute]], has launched the sixth edition of writing challenge "'''[[:m:Special:MyLanguage/Ukraine's Cultural Diplomacy Month 2026|Ukraine's Cultural Diplomacy Month]]'''", which lasts from '''1st April''' until '''30th April 2026'''. The initiative aims to promote knowledge about Ukrainian culture abroad by creating and improving Wikipedia articles in multiple languages. This year marks the sixth edition of the campaign, which will focus on contemporary culture, making today’s artistic voices and practices more visible to international audiences. 🧩'''How to participate?''' Choose an article from the suggested list → Write an article in your language, or improve an existing one according to the rules → Add your contribution to the contest page and calculate your points → Win prizes and receive a certificate of participation → Become a promoter of truthful knowledge about Ukraine. 🧩'''[[m:Special:MyLanguage/Ukraine's Cultural Diplomacy Month 2026|Check our main page for more information]]'''. '''If you are interested in coordinating long-term community engagement for the campaign and becoming a local ambassador, we would love to hear from you! Please let us know your interest.''' If not, then we encourage you to translate the [[m:Special:MyLanguage/Ukraine's Cultural Diplomacy Month 2026|landing page of the contest]] and [https://meta.wikimedia.org/wiki/Special:MessageGroupStats?group=Centralnotice-tgroup-UCDM2026banner&messages=&language=en&x=D banner] into your own language. Also, we set up a [[:m:CentralNotice/Request/Ukraine's Cultural Diplomacy Month 2026|banner]] to notify users of the possibility to participate in this challenge! [[:m:User:OlesiaLukaniuk (WMUA)|OlesiaLukaniuk (WMUA)]] ([[:m:User talk:OlesiaLukaniuk (WMUA)|talk]]) 04:35, 1 April 2026 (UTC) </div> <!-- Mensagem enviada por User:OlesiaLukaniuk (WMUA)@metawiki utilizando a lista em https://meta.wikimedia.org/w/index.php?title=User:OlesiaLukaniuk_(WMUA)/list_of_wikis&oldid=28552112 --> == Temporary adminship for WikiTraining TL == Hi everyone, sorry for writing in English. For the [https://www.facebook.com/share/p/1DF3b8aLJo/?mibextid=wwXIfr upcoming WikiTraining] planned to be held in Dili, I would like to confirm your approval to add two temporary admins (me and @[[User:Robertsky|Robertsky]]) to manage this wiki during and after the event. Thank you! [[Uza-na'in:Swarabakti|Swarabakti]] ([[Diskusaun Uza-na'in:Swarabakti|discussão]]) 10h42min de 18 de Juñu de 2026 (UTC) :There is also a concurrent request for administrator discussion just opened a couple of hours ago as well by @[[Uza-na'in:Diamantino Soares|Diamantino Soares]] at [[Wikipedia:Administradór Sira/Eleisaun#Diamantino Soares]]. :If there is no issues with mine and @[[Uza-na'in:Swarabakti|Swarabakti]]'s requests, at least for myself, I would like to help out Diamantino as much as possible on here post event as well. I am currently an admin on English Wikipedia if experience is required. :(Google translated Tetum: Iha mós pedidu konkorente ida ba diskusaun administradór nian ne'ebé foin loke oras balun liubá hanesan mós hosi @[[Uza-na'in:Diamantino Soares|Diamantino Soares]] iha [[Wikipedia:Administradór Sira/Eleisaun#Diamantino Soares]]. :Se laiha problema ho ha'u nia no @[[Uza-na'in:Swarabakti|Swarabakti]] nia pedidu sira, pelumenus ba ha'u rasik, ha'u hakarak ajuda Diamantino ho posivel iha eventu post ida-ne'e mós. Agora daudaun ha'u hanesan admin ida iha Wikipedia Inglés se presiza esperiénsia.) [[Uza-na'in:Robertsky|Robertsky]] ([[Diskusaun Uza-na'in:Robertsky|discussão]]) 11h08min de 18 de Juñu de 2026 (UTC) Suporta </br> * [[Uza-na'in:BJ Sinaga|Binsar de Jesus]] ([[Diskusaun Uza-na'in:BJ Sinaga|discussão]]) * --[[Uza-na'in:J. Patrick Fischer|J. Patrick Fischer]] ([[Diskusaun Uza-na'in:J. Patrick Fischer|discussão]]) 19h56min de 24 de Juñu de 2026 (UTC) == Call to participate: Proposed baseline Neutral Point of View (NPOV) standard == Hello-hello! I am inviting you to participate in the public discussion regarding a proposed baseline Neutral Point of View (NPOV) standard. The proposed baseline is meant for the Wikipedias which do not yet have an NPOV policy, for these communities to adopt, use, and build upon. [[m:Proposed_baseline_NPOV_standard#Proposed_baseline_NPOV_standard|You can find the proposed text here]]. As your Wikipedia does not seem to have an NPOV policy, we hope that this public discussion and proposed baseline standard will support your project community in adopting one. [[m:Talk:Proposed_baseline_NPOV_standard|You can join the public discussion on meta]]<nowiki>. The timeframe for the discussion is from June 17 - July 15, 2026. Looking forward to engagement from your community and hopefully seeing your community to adopt the Neutral Point of View policy! --~~~~</nowiki> [[Uza-na'in:KVaidla (WMF)|KVaidla (WMF)]] ([[Diskusaun Uza-na'in:KVaidla (WMF)|discussão]]) 09h09min de 19 de Juñu de 2026 (UTC) == Scouts related articles should be renamed? == * [[EXISTÊNCIA ESCUTISMO CATÓLICO IHA TIMOR-LESTE]] * [[FORMASAUN ESCUTISTA CEC-TL]] * [[SISTEMA PATRULLA CEC-TL NIA]] what do we rename these articles to? There is a fourth article: originally at [[Historia Fundador Escutismo Mundial Badem Powell]], but I have already redirected it to [[Robert Baden-Powell]]. [[Uza-na'in:Robertsky|Robertsky]] ([[Diskusaun Uza-na'in:Robertsky|discussão]]) 18h47min de 12 de Jullu de 2026 (UTC) == Your feedback wanted: Remove ''(Language link added:) and co.'' edits from Special:RecentChanges == ''(Apologies for posting in English. You can help by translating it)'' Hello, I’m Danny from [[:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/> We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader). We are currently planning to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/> Language link changes are also known as sitelink or interlanguage links and describe when a Wikidata item is connected to a Wiki, connecting it to the language dropdown tool from other connected Wikis. [[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]] {{clear}} The request for your feedback is whether you would support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why? Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]] Thank you for any participation or feedback you give, --[[Uza-na'in:MediaWiki message delivery|MediaWiki message delivery]] ([[Diskusaun Uza-na'in:MediaWiki message delivery|discussão]]) 08h03min de 21 de Setembru de 2026 (UTC) <!-- Mensagem enviada por User:Danny Benjafield (WMDE)@metawiki utilizando a lista em https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31055245 --> == Wikidata Sitelink changes in Recent Changes and Watchlist == ''(Apologies for cross-posting in English, translating it will help spread the message)'' Earlier last month, all Wikis were contacted for feedback on our proposal to remove language link changes, this change has already been deployed to Wikisource, Wikibooks, Wikivoyage, Wikiquote, Wikiversity and Wiktionary. The same change is now being rolled out globally to all Wikipedias on '''October 13, 07:00 UTC'''. Editors will no longer see notifications after this time on their [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item (it does not affect language link notifications to the home wiki). There will then be a two-week monitoring period to observe if a reduction of high-volume but low-value notifications takes place, or if higher-value changes become easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the Wikidata For Wikimedia [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|Projects talk page]].<br/> Wikidata's own Recent Changes page is not affected as it serves as the repository for these changes. Please reach out if you have any questions, or if your wiki would like to opt-out, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[Uza-na'in:MediaWiki message delivery|MediaWiki message delivery]] ([[Diskusaun Uza-na'in:MediaWiki message delivery|discussão]]) 09h29min de 9 de Outubru de 2026 (UTC) <!-- Mensagem enviada por User:Danny Benjafield (WMDE)@metawiki utilizando a lista em https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_Test_List&oldid=31142775 --> 6o6xbjtvj1657lynsic5n8wflnbzpj3 Módulo:Params 828 7871 75981 74649 2026-10-08T16:39:50Z Grufo 11486 Update from [[d:Special:GoToLinkedPage/mediawikiwiki/Q122696746|master]] using [[mw:Synchronizer| #Synchronizer]] 75981 Scribunto text/plain require[[strict]] --- --- --- PRIVATE ENVIRONMENT --- --- ________________________________ --- --- --- --[[ Abstract utilities ]]-- ---------------------------- -- Helper function for `string.gsub()` (for managing zero-padded numbers) local function zero_padded (str) return ('%03d%s'):format(#str, str) end -- Helper function for `table.sort()` (for natural sorting) local function natural_sort (var1, var2) return var1:gsub('%d+', zero_padded) < var2:gsub('%d+', zero_padded) end -- Return a copy or a reference to a table local function copy_or_ref_table (src, refonly) if refonly then return src end local newtab = {} for key, val in pairs(src) do newtab[key] = val end return newtab end -- Copy at most N items (of all kinds) from `src` to `dest` and return `dest` local function copy_table_maxn (dest, src, len) local idx = 1 for key, val in pairs(src) do dest[key], idx = val, idx + 1 if idx > len then break end end return dest end -- Remove some numeric elements from a table, shifting everything to the left local function remove_numeric_keys (tbl, idx, len) local cache, tmp = {}, idx + len - 1 for key, val in pairs(tbl) do if type(key) == 'number' and key >= idx then if key > tmp then cache[key - len] = val end tbl[key] = nil end end for key, val in pairs(cache) do tbl[key] = val end end -- Make a reduced copy of a table (shifting in both directions if necessary) local function copy_table_reduced (tbl, idx, len) local ret, tmp = {}, idx + len - 1 if idx > 0 then for key, val in pairs(tbl) do if type(key) ~= 'number' or key < idx then ret[key] = val elseif key > tmp then ret[key - len] = val end end elseif tmp > 0 then local nshift = 1 - idx for key, val in pairs(tbl) do if type(key) ~= 'number' then ret[key] = val elseif key > tmp then ret[key - tmp] = val elseif key < idx then ret[key + nshift] = val end end else for key, val in pairs(tbl) do if type(key) ~= 'number' or key > tmp then ret[key] = val elseif key < idx then ret[key + len] = val end end end return ret end -- Make an expanded copy of a table (shifting in both directions if necessary) local function copy_table_expanded (tbl, idx, len) local ret, tmp = {}, idx + len - 1 if idx > 0 then for key, val in pairs(tbl) do if type(key) ~= 'number' or key < idx then ret[key] = val else ret[key + len] = val end end elseif tmp > 0 then local nshift = idx - 1 for key, val in pairs(tbl) do if type(key) ~= 'number' then ret[key] = val elseif key > 0 then ret[key + tmp] = val elseif key < 1 then ret[key + nshift] = val end end else for key, val in pairs(tbl) do if type(key) ~= 'number' or key > tmp then ret[key] = val else ret[key - len] = val end end end return ret end -- Given a table, create two new tables containing the sorted list of keys local function get_key_list_sorted (tbl, sort_fn) local nums, words, nn, nw = {}, {}, 0, 0 for key, val in pairs(tbl) do if type(key) == 'number' then nn = nn + 1 nums[nn] = key else nw = nw + 1 words[nw] = key end end table.sort(nums) table.sort(words, sort_fn) return nums, words, nn, nw end -- Parse a parameter name string and return it as a string or a number local function get_parameter_name (par_str) local ret = par_str:match'^%s*(.-)%s*$' if ret ~= '0' and ret:find'^%-?[1-9]%d*$' == nil then return ret end return tonumber(ret) end -- Move a key from a table to another, but only if under a different name and -- always parsing numeric strings as numbers local function steal_if_renamed (val, src, skey, dest, dkey) local realkey = get_parameter_name(dkey) if skey ~= realkey then dest[realkey], src[skey] = val, nil end end --[[ Public strings ]]-- ------------------------ -- Special match keywords (functions and modifiers MUST avoid these names) local mkeywords = { ['or'] = 0, pattern = 1, plain = 2, strict = 3 } -- Sort functions (functions and modifiers MUST avoid these names) local sortfunctions = { alphabetically = false, naturally = natural_sort } -- Callback styles for the `mapping_*` and `renaming_*` class of modifiers -- (functions and modifiers MUST avoid these names) --[[ Meanings of the columns: col[1] = Loop type (0-3) col[2] = Number of module arguments that the style requires (1-3) col[3] = Minimum number of sequential parameters passed to the callback col[4] = Name of the callback parameter where to place each parameter name col[5] = Name of the callback parameter where to place each parameter value col[6] = Argument in the modifier's invocation that will override `col[4]` col[7] = Argument in the modifier's invocation that will override `col[5]` A value of `-1` indicates that no meaningful value is stored (i.e. `nil`) ]]-- local mapping_styles = { names_and_values = { 3, 2, 2, 1, 2, -1, -1 }, values_and_names = { 3, 2, 2, 2, 1, -1, -1 }, values_only = { 1, 2, 1, -1, 1, -1, -1 }, names_only = { 2, 2, 1, 1, -1, -1, -1 }, names_and_values_as = { 3, 4, 0, -1, -1, 2, 3 }, names_only_as = { 2, 3, 0, -1, -1, 2, -1 }, values_only_as = { 1, 3, 0, -1, -1, -1, 2 }, blindly = { 0, 2, 0, -1, -1, -1, -1 } } -- Memory slots (functions and modifiers MUST avoid these names) local memoryslots = { h = 'header', f = 'footer', i = 'itersep', l = 'lastsep', n = 'ifngiven', p = 'pairsep', s = 'oxfordsep' } -- Possible trimming modes for the `parsing` modifier local trim_parse_opts = { trim_none = { false, false }, trim_positional = { false, true }, trim_named = { true, false }, trim_all = { true, true } } -- Possible string modes for the iteration separator in the `parsing` and -- `reinterpreting` modifiers local isep_parse_opts = { splitter_pattern = false, splitter_string = true } -- Possible string modes for the key-value separator in the `parsing` and -- `reinterpreting` modifiers local psep_parse_opts = { setter_pattern = false, setter_string = true } -- Possible position references for the `splicing` modifier local position_references = { add_nothing = 0, add_smallest_number = 1, add_last_of_sequence = 2, add_largest_number = 3 } -- Possible modes for the `reassigning` modifier local a_modes = { transfer = 0, clone = 1, rename = 2, copy = 3, sacrifice = 4, provide = 5, spare = 7 } -- Functions and modifiers MUST avoid these names too: `here`, `in_substack`, -- `let`, `expose`, `use`, `with_flushed_glue`, `without_flushed_glue` -- `without_sorting` --[[ Private constants ]]-- --------------------------- -- Hard-coded name of the module (to avoid going through `frame:getTitle()`) local modulename = 'Module:Params' -- The functions listed here declare that they don't need the `frame.args` -- metatable to be copied into a regular table; if they are modifiers they also -- guarantee that they will make their own (modified) copy available local refpipe = { call_for_each_group = true, --coins = true, count = true, evaluating = true, for_each = true, list = true, list_values = true, list_maybe_with_names = true, value_of = true } -- The functions listed here declare that they don't need the -- `frame:getParent().args` metatable to be copied into a regular table; if -- they are modifiers they also guarantee that they will make their own -- (modified) copy available local refparams = { call_for_each_group = true, combining = true, combining_by_calling = true, combining_values = true, concat_and_call = true, concat_and_invoke = true, concat_and_magic = true, count = true, grouping_by_calling = true, mixing_names_and_values = true, keeping_at_most = true, renaming_by_mixing = true, renaming_to_sequence = true, renaming_to_uppercase = true, renaming_to_lowercase = true, --renaming_to_values = true, shifting = true, splicing = true, --swapping_names_and_values = true, value_of = true, with_name_matching = true } -- Maximum number of numeric parameters that can be filled, if missing (we -- chose an arbitrary number for this constant; you can discuss about its -- optimal value at Module talk:Params) local maxfill = 1024 -- The private table of functions local library = {} -- Functions and modifiers that can only be invoked in first position local static_iface = {} --[[ Private functions ]]-- --------------------------- -- Create a new context local function context_new (child_frame) local main_frame = child_frame:getParent() return { frame = main_frame, opipe = child_frame.args, oparams = main_frame.args, firstposonly = static_iface, iterfunc = pairs, sorttype = 0, n_parents = 0, n_children = 0, n_available = maxfill } end -- Move to the next action within the user-given list local function context_iterate (ctx, n_forward) local nextfn if ctx.pipe[n_forward] ~= nil then nextfn = ctx.pipe[n_forward]:match'^%s*(.*%S)' end if nextfn == nil then error(modulename .. ': You must specify a function to call', 0) end if library[nextfn] == nil then if ctx.firstposonly[nextfn] == nil then error(modulename .. ': The function ‘' .. nextfn .. '’ does not exist', 0) else error(modulename .. ': The ‘' .. nextfn .. '’ directive can only appear in first position', 0) end end remove_numeric_keys(ctx.pipe, 1, n_forward) return library[nextfn] end -- Main loop local function main_loop (ctx, start_with) local fn = start_with repeat fn = fn(ctx) until not fn if ctx.n_parents > 0 then error(modulename .. ': One or more ‘merging_substack’ directives are missing', 0) end if ctx.n_children > 0 then error(modulename .. ', For some of the snapshots either the ‘flushing’ directive is missing or a group has not been properly closed with ‘merging_substack’', 0) end end -- Load a `setting`-like directive string into the `dest` table local function set_strings_from_opts (dest, opts, start_from) local cmd if opts[start_from] == nil then return start_from - 1 end cmd = opts[start_from]:gsub('%s+', ''):gsub('/+', '/') :match'^/*(.*[^/])' if cmd == nil then return start_from end local vname, chr local amap, sep, argc = {}, string.byte('/'), start_from + 1 for idx = 1, #cmd do chr = cmd:byte(idx) if chr == sep then for key, val in ipairs(amap) do dest[val], amap[key] = opts[argc], nil end argc = argc + 1 else vname = memoryslots[string.char(chr)] if vname == nil then error(modulename .. ', ‘setting’: Unknown slot ‘' .. string.char(chr) .. '’', 0) end table.insert(amap, vname) end end for key, val in ipairs(amap) do dest[val] = opts[argc] end return argc end -- Add a new stack of parameters to `ctx.children` local function new_substack (ctx) local currsnap, newparams = ctx.n_children + 1, {} if ctx.children == nil then ctx.children = { newparams } else ctx.children[currsnap] = newparams end ctx.n_children = currsnap return newparams end -- Parse a raw argument containing a `sortfunctions` directive, or -- `'without_sorting'`, or `nil` local function load_sort_opt (raw_arg) if raw_arg == nil then return nil, 1, false end local trarg = raw_arg:match'^%s*(.-)%s*$' if trarg == 'without_sorting' then return nil, 2, false, trarg end local tmp = sortfunctions[trarg] if tmp == nil then return nil, 1, false, trarg end return tmp or nil, 2, true, trarg end -- Parse optional user arguments of type `...|[let/use]|[...]|[let/use]|[...]| -- [number of additional parameters]|[parameter 1]|[parameter 2]|[...]` local function load_child_opts (src, start_from, append_after, params) local tnamed, tmp1, tmp2 local pin, tbl, mem = start_from, {}, {} while src[pin] ~= nil and src[pin + 1] ~= nil do tmp1 = src[pin]:match'^%s*(.*%S)' if tmp1 == 'let' and src[pin + 2] ~= nil then tmp1 = get_parameter_name(src[pin + 1]) mem[tmp1], tbl[tmp1], pin = nil, src[pin + 2], pin + 3 --[[ elseif tmp1 == 'expose' then tmp1 = get_parameter_name(src[pin + 1]) tmp2 = params[tmp1] mem[tmp1], tbl[tmp1], pin = tmp2, tmp2, pin + 2 ]]-- elseif tmp1 == 'use' and src[pin + 2] ~= nil then tmp1 = get_parameter_name(src[pin + 2]) tmp2 = params[tmp1] mem[tmp1], tbl[get_parameter_name(src[pin + 1])], pin = tmp2, tmp2, pin + 3 else break end end local tnew = copy_or_ref_table(params, next(mem) == nil) for key in pairs(mem) do tnew[key] = nil end if pin ~= start_from then tnamed, tbl = tbl, {} end tmp1 = tonumber(src[pin]) if tmp1 ~= nil and math.floor(tmp1) == tmp1 then if tmp1 < 0 then tmp1 = -1 end tmp2 = append_after - pin for idx = pin + 1, pin + tmp1 do tbl[idx + tmp2] = src[idx] end pin = pin + tmp1 + 1 end if tnamed ~= nil then for key, val in pairs(tnamed) do tbl[key] = val end end return tbl, pin, tnew, mem end -- Load the optional arguments of some of the `mapping_*` and `renaming_*` -- class of modifiers local function load_callback_opts (src, n_skip, default_style, params) local style, shf local tmp = src[n_skip + 1] if tmp ~= nil then style = mapping_styles[tmp:match'^%s*(.-)%s*$'] end if style == nil then style, shf = default_style, n_skip - 1 else shf = n_skip end local n_exist, karg, varg = style[3], style[4], style[5] tmp = style[6] if tmp > -1 then karg = src[tmp + shf]:match'^%s*(.-)%s*$' if karg == '0' or karg:find'^%-?[1-9]%d*$' ~= nil then karg = tonumber(karg) n_exist = math.max(n_exist, karg) end end tmp = style[7] if tmp > -1 then varg = src[tmp + shf]:match'^%s*(.-)%s*$' if varg == '0' or varg:find'^%-?[1-9]%d*$' ~= nil then varg = tonumber(varg) n_exist = math.max(n_exist, varg) end end local dest, argc, tnew, mem = load_child_opts(src, style[2] + shf, n_exist, params) tmp = style[1] if (tmp == 3 or tmp == 2) and dest[karg] ~= nil then tmp = tmp - 2 end if (tmp == 3 or tmp == 1) and dest[varg] ~= nil then tmp = tmp - 1 end return dest, argc, tmp, karg, varg, tnew, mem end -- Parse the arguments of some of the `mapping_*` and `renaming_*` class of -- modifiers local function load_replace_args (opts, whoami) if opts[1] == nil then error(modulename .. ', ‘' .. whoami .. '’: No pattern string was given', 0) end if opts[2] == nil then error(modulename .. ', ‘' .. whoami .. '’: No replacement string was given', 0) end local ptn, repl, nmax, argc = opts[1], opts[2], tonumber(opts[3]), 3 if nmax ~= nil or (opts[3] or ''):match'^%s*$' ~= nil then argc = 4 end local flg = opts[argc] if flg ~= nil then flg = mkeywords[flg:match'^%s*(.-)%s*$'] end if flg == 0 then flg = nil elseif flg ~= nil then argc = argc + 1 end return ptn, repl, nmax, flg, argc, (nmax ~= nil and nmax < 1) or (flg == 3 and ptn == repl) end -- Parse the arguments of the `with_*_matching` class of modifiers local function load_pattern_args (opts, whoami) local keyw local ptns, state, nptns, cnt = {}, 0, 0, 1 for _, val in ipairs(opts) do if state == 0 then nptns, state = nptns + 1, -1 ptns[nptns] = { val, false, false } else keyw = val:match'^%s*(.*%S)' if keyw == nil or mkeywords[keyw] == nil or ( state > 0 and mkeywords[keyw] > 0 ) then break else state = mkeywords[keyw] if state > 1 then ptns[nptns][2] = true end if state == 3 then ptns[nptns][3] = true end end end cnt = cnt + 1 end if state == 0 then error(modulename .. ', ‘' .. whoami .. '’: No pattern was given', 0) end return ptns, nptns, cnt end -- Load the optional arguments of the `parsing`, `reinterpreting` and -- `evaluating` modifiers local function load_parse_opts (opts, start_from, isp, psp) local tmp local optslots, noptslots, argc, trimn, trimu, iplain, pplain = { true, true, true }, 3, start_from, true, false, true, true repeat noptslots, tmp = noptslots - 1, opts[argc] if tmp == nil then break end tmp = tmp:match'^%s*(.-)%s*$' if optslots[1] ~= nil and trim_parse_opts[tmp] ~= nil then tmp = trim_parse_opts[tmp] trimn, trimu, optslots[1] = tmp[1], tmp[2], nil elseif optslots[2] ~= nil and isep_parse_opts[tmp] ~= nil then argc = argc + 1 iplain, isp, optslots[2] = isep_parse_opts[tmp], opts[argc], nil elseif optslots[3] ~= nil and psep_parse_opts[tmp] ~= nil then argc = argc + 1 pplain, psp, optslots[3] = psep_parse_opts[tmp], opts[argc], nil else break end argc = argc + 1 until noptslots < 1 return isp, iplain, psp, pplain, trimn, trimu, argc end -- Map parameters' values using a custom callback and a referenced table local value_maps = { [0] = function (tbl, margs, karg, varg, fn) for key in pairs(tbl) do tbl[key] = fn() end end, [1] = function (tbl, margs, karg, varg, fn) for key, val in pairs(tbl) do margs[varg] = val tbl[key] = fn() end end, [2] = function (tbl, margs, karg, varg, fn) for key in pairs(tbl) do margs[karg] = key tbl[key] = fn() end end, [3] = function (tbl, margs, karg, varg, fn) for key, val in pairs(tbl) do margs[karg], margs[varg] = key, val tbl[key] = fn() end end } -- Private table for `map_names()` local name_thieves = { [0] = function (cache, tbl, rargs, karg, varg, fn) for key, val in pairs(tbl) do steal_if_renamed(val, tbl, key, cache, fn()) end end, [1] = function (cache, tbl, rargs, karg, varg, fn) for key, val in pairs(tbl) do rargs[varg] = val steal_if_renamed(val, tbl, key, cache, fn()) end end, [2] = function (cache, tbl, rargs, karg, varg, fn) for key, val in pairs(tbl) do rargs[karg] = key steal_if_renamed(val, tbl, key, cache, fn()) end end, [3] = function (cache, tbl, rargs, karg, varg, fn) for key, val in pairs(tbl) do rargs[karg], rargs[varg] = key, val steal_if_renamed(val, tbl, key, cache, fn()) end end } -- Map parameters' names using a custom callback and a referenced table local function map_names (tbl, rargs, karg, varg, looptype, fn) local cache = {} name_thieves[looptype](cache, tbl, rargs, karg, varg, fn) for key, val in pairs(cache) do tbl[key] = val end end -- Return a new table that contains `src` regrouped according to the numeric -- suffixes in its keys local function make_groups (src) -- NOTE: `src` might be the original metatable! local prefix, gid local groups = {} for key, val in pairs(src) do -- `key` must only be a string or a number... if type(key) == 'string' then prefix, gid = key:match'^%s*(.-)%s*(%-?%d*)%s*$' gid = tonumber(gid) or '' else prefix, gid = '', key end if groups[gid] == nil then groups[gid] = {} end if prefix == '0' or prefix:find'^%-?[1-9]%d*$' ~= nil then prefix = tonumber(prefix) if prefix < 1 then prefix = prefix - 1 end end groups[gid][prefix] = val end return groups end -- Split into parts a string containing the `$#` and `$@` placeholders and -- return the information as a skeleton table, a canvas table and a length local function parse_placeholder_string (target) local idx, s_pos, skel, canvas = 1, 1, {}, {} local e_pos = string.find(target, '%$[@#]', 1, false) while e_pos ~= nil do canvas[idx] = target:sub(s_pos, e_pos - 1) skel[idx + 1] = target:sub(e_pos, e_pos + 1) == '$@' idx = idx + 2 s_pos = e_pos + 2 e_pos = string.find(target, '%$[@#]', s_pos, false) end if (s_pos > target:len()) then idx = idx - 1 else canvas[idx] = target:sub(s_pos) end return skel, canvas, idx end -- Populate a table by parsing a parameter string (heavy lifting for `parsing`, -- `reinterpreting` and `evaluating`) local function parse_parameter_string (tbl, str, isp, ipl, psp, ppl, trn, tru) local key, val, spos1, spos2, pos1, pos2 local pos3, idx, lenplone = 0, 1, #str + 1 if isp == nil or isp == '' then if psp == nil or psp == '' then if tru then tbl[idx] = str:match'^%s*(.-)%s*$' else tbl[idx] = str end return idx end spos1, spos2 = str:find(psp, 1, ppl) if spos1 == nil then key = idx if tru then val = str:match'^%s*(.-)%s*$' else val = str end idx = idx + 1 else key = get_parameter_name(str:sub(1, spos1 - 1)) val = str:sub(spos2 + 1) if trn then val = val:match'^%s*(.-)%s*$' end end tbl[key] = val return idx end if psp == nil or psp == '' then repeat pos1 = pos3 + 1 pos2, pos3 = str:find(isp, pos1, ipl) val = str:sub(pos1, (pos2 or lenplone) - 1) if tru then val = val:match'^%s*(.-)%s*$' end tbl[idx], idx = val, idx + 1 until pos2 == nil return idx end repeat pos1 = pos3 + 1 pos2, pos3 = str:find(isp, pos1, ipl) val = str:sub(pos1, (pos2 or lenplone) - 1) spos1, spos2 = val:find(psp, 1, ppl) if spos1 == nil then key = idx if tru then val = val:match'^%s*(.-)%s*$' end idx = idx + 1 else key = get_parameter_name(val:sub(1, spos1 - 1)) val = val:sub(spos2 + 1) if trn then val = val:match'^%s*(.-)%s*$' end end tbl[key] = val until pos2 == nil return idx end -- Heavy lifting for `snapshotting` and `remembering` local function make_child (ctx, src, whoami) local len = tonumber(ctx.pipe[1]) if len == nil or len == 0 then local stack = new_substack(ctx) for key, val in pairs(src) do stack[key] = val end return len == nil and 1 or 2 end if len < 0 or math.floor(len) ~= len then error(modulename .. ', ‘' .. whoami .. '’: The number of parameters to copy must be an integer greater than zero', 0) end copy_table_maxn(new_substack(ctx), src, len) return 2 end -- Heavy lifting for `setting_by_flushing`, `combining` and `combining_values` local function set_strings_from_substack (ctx, dest, whoami) if ctx.n_children < 1 then error(modulename .. ', ‘' .. whoami .. '’: There are no substacks to flush', 0) end local currsnap = ctx.n_children local stack = ctx.children[currsnap] for key, val in pairs(memoryslots) do if stack[key] ~= nil then dest[val] = stack[key] end end ctx.children[currsnap], ctx.n_children = nil, currsnap - 1 end -- Heavy lifting for `combining` and `combining_values` local function combine_parameters (ctx, keyval_fn, whoami) -- NOTE: `ctx.params` might be the original metatable! This function -- MUST create a copy of it before returning local opts = ctx.pipe if ctx.pipe[1] == nil then error(modulename .. ', ‘' .. whoami .. '’: No parameter name was provided', 0) end local argc local tbl, vars = ctx.params, {} local sortfn, varsarg0, do_sort, tmp = load_sort_opt(opts[2]) if varsarg0 == 2 then tmp = opts[3] and opts[3]:match'^%s*(.-)%s*$' end if tmp == 'with_flushed_glue' then varsarg0 = varsarg0 + 1 argc = set_strings_from_opts(vars, opts, varsarg0 + 1) set_strings_from_substack(ctx, vars, whoami) else if tmp == 'without_flushed_glue' then varsarg0 = varsarg0 + 1 end argc = set_strings_from_opts(vars, opts, varsarg0 + 1) end if argc < varsarg0 then error(modulename .. ', ‘' .. whoami .. '’: No setting directive was given', 0) end if next(tbl) == nil then if vars.ifngiven ~= nil then ctx.params = { [get_parameter_name(ctx.pipe[1])] = vars.ifngiven } elseif tbl == ctx.oparams then ctx.params = {} end return argc end local cache, len if do_sort then local words cache, words, len, tmp = get_key_list_sorted(tbl, sortfn) for idx = 1, tmp do cache[len + idx] = words[idx] end len = len + tmp else len, cache = 0, {} for key in pairs(tbl) do len = len + 1 cache[len] = key end end local pmap, nss, kvs, pps = {}, 0, vars.pairsep or '', vars.itersep or '' for idx = 1, len do tmp, pmap[nss + 1] = cache[idx], pps pmap[nss + 2] = keyval_fn(tmp, tbl[tmp], kvs) nss = nss + 2 end tmp = vars.oxfordsep or vars.lastsep if tmp ~= nil and nss > 4 then pmap[nss - 1] = tmp elseif nss > 2 and vars.lastsep ~= nil then pmap[nss - 1] = vars.lastsep end pmap[1] = vars.header or '' if vars.footer ~= nil then pmap[nss + 1] = vars.footer end ctx.params = { [get_parameter_name(ctx.pipe[1])] = table.concat(pmap) } return argc end -- Concatenate the numeric keys from the table of parameters to the numeric -- keys from the table of options; non-numeric keys from the table of options -- will prevail over colliding non-numeric keys from the table of parameters local function concat_params (ctx) local retval, tbl, nmax = {}, ctx.params, table.maxn(ctx.pipe) if ctx.subset == 1 then -- We need only the sequence for key, val in ipairs(tbl) do retval[key + nmax] = val end else if ctx.subset == -1 then for key in ipairs(tbl) do tbl[key] = nil end end for key, val in pairs(tbl) do if type(key) == 'number' and key > 0 then retval[key + nmax] = val else retval[key] = val end end end for key, val in pairs(ctx.pipe) do retval[key] = val end return retval end -- Flush the parameters by calling a custom function for each value (after this -- function has been invoked `ctx.params` will be no longer usable) local function flush_params (ctx, fn) local tmp local tbl = ctx.params if ctx.subset == -1 then for key, val in ipairs(tbl) do tbl[key] = nil end elseif ctx.subset == 1 then if ctx.pins == nil then for key, val in ipairs(tbl) do fn(key, val) end return end tmp = {} for key, val in ipairs(tbl) do tmp[key] = val end tbl = tmp end if ctx.pins ~= nil then local marker = ctx.sorttype < 1 and ctx.subset ~= -1 or nil for idx = 1, #ctx.pins do tmp = ctx.pins[idx] if tbl[tmp] ~= nil then fn(tmp, tbl[tmp]) tbl[tmp] = marker end end if ctx.subset == 1 then for key, val in ipairs(tbl) do if val ~= true then fn(key, val) end end return end end if ctx.sorttype > 0 then local nums, words, nn, nw = get_key_list_sorted(tbl, natural_sort) if ctx.sorttype == 2 then for idx = 1, nw do fn(words[idx], tbl[words[idx]]) end for idx = 1, nn do fn(nums[idx], tbl[nums[idx]]) end return end for idx = 1, nn do fn(nums[idx], tbl[nums[idx]]) end for idx = 1, nw do fn(words[idx], tbl[words[idx]]) end return end if ctx.subset == -1 or ctx.pins == nil then for key, val in ipairs(tbl) do fn(key, val) tbl[key] = nil end for key, val in pairs(tbl) do fn(key, val) end return end for key, val in ipairs(tbl) do if val ~= true then fn(key, val) end tbl[key] = nil end for key, val in pairs(tbl) do if val ~= true then fn(key, val) end end end -- Flush the parameters by calling one of two custom functions for each value -- (after this function has been invoked `ctx.params` will be no longer usable) local function mixed_flush_params (ctx, fn_seq, fn_oth) if ctx.subset == 1 then flush_params(ctx, fn_seq) return end if ctx.subset == -1 then flush_params(ctx, fn_oth) return end local tbl = ctx.params if ctx.pins == nil and ctx.sorttype < 1 then for key, val in ipairs(tbl) do fn_seq(key, val) tbl[key] = nil end for key, val in pairs(tbl) do fn_oth(key, val) end return end local tseq = {} for key, val in ipairs(tbl) do tseq[key] = val end if ctx.pins ~= nil then local tmp local marker = ctx.sorttype < 1 or nil for idx = 1, #ctx.pins do tmp = ctx.pins[idx] if tseq[tmp] ~= nil then fn_seq(tmp, tbl[tmp]) tbl[tmp], tseq[tmp] = nil, marker elseif tbl[tmp] ~= nil then fn_oth(tmp, tbl[tmp]) tbl[tmp] = nil end end end if ctx.sorttype > 0 then local nums, words, nn, nw = get_key_list_sorted(tbl, natural_sort) if ctx.sorttype == 2 then for idx = 1, nw do fn_oth(words[idx], tbl[words[idx]]) end end for idx = 1, nn do if tseq[nums[idx]] ~= nil then fn_seq(nums[idx], tseq[nums[idx]]) else fn_oth(nums[idx], tbl[nums[idx]]) end end if ctx.sorttype ~= 2 then for idx = 1, nw do fn_oth(words[idx], tbl[words[idx]]) end end return end for key, val in ipairs(tseq) do if val ~= true then fn_seq(key, val) tbl[key] = nil end end for key, val in pairs(tbl) do fn_oth(key, val) end end -- Finalize and return a concatenated list local function finalize_and_return_concatenated_list (ctx, lst, len, modsize) if len > 0 then local tmp = ctx.oxfordsep or ctx.lastsep if tmp ~= nil and len > modsize * 2 then lst[len - modsize + 1] = tmp elseif len > modsize and ctx.lastsep ~= nil then lst[len - modsize + 1] = ctx.lastsep end lst[1] = ctx.header or '' if ctx.footer ~= nil then lst[len + 1] = ctx.footer end ctx.text = table.concat(lst) else ctx.text = ctx.ifngiven or '' end end --- --- --- PUBLIC ENVIRONMENT --- --- ________________________________ --- --- --- --[[ Modifiers ]]-- ------------------- -- Syntax: #invoke:params|sequential|pipe to library.sequential = function (ctx) if ctx.subset == 1 then error(modulename .. ': The ‘sequential’ directive has been provided more than once', 0) end if ctx.subset == -1 then error(modulename .. ': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other', 0) end if ctx.sorttype > 0 then error(modulename .. ': The ‘all_sorted’ and ‘reassorted’ directives are redundant when followed by ‘sequential’', 0) end ctx.iterfunc, ctx.subset = ipairs, 1 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|non-sequential|pipe to library['non-sequential'] = function (ctx) if ctx.subset == -1 then error(modulename .. ': The ‘non-sequential’ directive has been provided more than once', 0) end if ctx.subset == 1 then error(modulename .. ': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other', 0) end ctx.iterfunc, ctx.subset = pairs, -1 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|all_sorted|pipe to library.all_sorted = function (ctx) if ctx.sorttype == 1 then error(modulename .. ': The ‘all_sorted’ directive has been provided more than once', 0) end if ctx.subset == 1 then error(modulename .. ': The ‘all_sorted’ directive is redundant after ‘sequential’', 0) end if ctx.sorttype == 2 then error(modulename .. ': The two directives ‘reassorted’ and ‘sequential’ are in contradiction with each other', 0) end ctx.sorttype = 1 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|reassorted|pipe to library.reassorted = function (ctx) if ctx.sorttype == 2 then error(modulename .. ': The ‘reassorted’ directive has been provided more than once', 0) end if ctx.subset == 1 then error(modulename .. ': The ‘reassorted’ directive is redundant after ‘sequential’', 0) end if ctx.sorttype == 1 then error(modulename .. ': The two directives ‘sequential’ and ‘reassorted’ are in contradiction with each other', 0) end ctx.sorttype = 2 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|pinned_until|sentinel|[parameter name 1]|[parameter -- name 2]|...|parameter name N|sentinel|pipe to library.pinned_until = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘pinned_until’: No sentinel was provided', 0) end local tmp, bucket, curr, ncurr local sntl, idx = opts[1]:match'^%s*(.-)%s*$', 2 if ctx.pin_bucket == nil then bucket, curr, ncurr = {}, {}, 0 ctx.pin_bucket, ctx.pins = bucket, curr else bucket, curr, ncurr = ctx.pin_bucket, ctx.pins, ctx.npins end while opts[idx] ~= nil do tmp = opts[idx]:match'^%s*(.-)%s*$' if tmp == sntl then if idx == 2 then error(modulename .. ', ‘pinned_until’: No parameters to pin were provided', 0) end ctx.npins = ncurr + idx - 2 return context_iterate(ctx, idx + 1) end if tmp == '0' or tmp:find'^%-?[1-9]%d*$' ~= nil then tmp = tonumber(tmp) end if bucket[tmp] then error(modulename .. ', ‘pinned_until’: Duplicate pinned parameter ‘' .. tostring(tmp) .. '’', 0) end curr[ncurr + idx - 1], bucket[tmp], idx = tmp, true, idx + 1 end error(modulename .. ', ‘pinned_until’: Missing sentinel in position #' .. tostring(idx), 0) end -- Syntax: #invoke:params|setting|directives|...|pipe to library.setting = function (ctx) local argc = set_strings_from_opts(ctx, ctx.pipe, 1) if argc < 2 then error(modulename .. ', ‘setting’: No directive was given', 0) end return context_iterate(ctx, argc + 1) end -- Syntax: #invoke:params|scoring|new parameter name|[container]|pipe to library.scoring = function (ctx) if ctx.pipe[1] == nil then error(modulename .. ', ‘scoring’: No parameter name was provided', 0) end local tmp local retval, opts = 0, ctx.pipe for _ in pairs(ctx.params) do retval = retval + 1 end if opts[2] ~= nil then tmp = opts[2]:match'^%s*(.*%S)' end if tmp == 'in_substack' then new_substack(ctx)[get_parameter_name(opts[1])] = tostring(retval) return context_iterate(ctx, 3) end ctx.params[get_parameter_name(opts[1])] = tostring(retval) return context_iterate(ctx, tmp == 'here' and 3 or 2) end -- Syntax: #invoke:params|squeezing|pipe to library.squeezing = function (ctx) local store, indices, tbl, newlen = {}, {}, ctx.params, 0 for key, val in pairs(tbl) do if type(key) == 'number' then newlen = newlen + 1 indices[newlen], store[key], tbl[key] = key, val, nil end end table.sort(indices) for idx = 1, newlen do tbl[idx] = store[indices[idx]] end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|filling_the_gaps|pipe to library.filling_the_gaps = function (ctx) local newval, tbl, tmp, nmin, nmax, nnums = ctx.pipe[1], ctx.params, {}, 1, nil, -1 if newval == nil then error(modulename .. ', ‘filling_the_gaps’: No value was provided', 0) end for key, val in pairs(tbl) do if type(key) == 'number' then if nmax == nil then if key < nmin then nmin = key end nmax = key elseif key > nmax then nmax = key elseif key < nmin then nmin = key end tmp[key], nnums = val, nnums + 1 end end if nmax ~= nil and nmax - nmin > nnums then ctx.n_available = ctx.n_available + nmin + nnums - nmax if ctx.n_available < 0 then error(modulename .. ', ‘filling_the_gaps’: It is possible to fill at most ' .. tostring(maxfill) .. ' parameters', 0) end for idx = nmin, nmax, 1 do tbl[idx] = newval end for key, val in pairs(tmp) do tbl[key] = val end end return context_iterate(ctx, 2) end -- Syntax: #invoke:params|clearing|pipe to library.clearing = function (ctx) local tbl, numerics = ctx.params, {} for key, val in pairs(tbl) do if type(key) == 'number' then numerics[key], tbl[key] = val, nil end end for key, val in ipairs(numerics) do tbl[key] = val end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|cutting|left cut|right cut|pipe to library.cutting = function (ctx) local lcut = tonumber(ctx.pipe[1]) if lcut == nil or math.floor(lcut) ~= lcut then error(modulename .. ', ‘cutting’: Left cut must be an integer number', 0) end local rcut = tonumber(ctx.pipe[2]) if rcut == nil or math.floor(rcut) ~= rcut then error(modulename .. ', ‘cutting’: Right cut must be an integer number', 0) end local tbl = ctx.params local len = #tbl if lcut < 0 then lcut = len + lcut end if rcut < 0 then rcut = len + rcut end local tot = lcut + rcut if tot > 0 then local cache = {} if tot >= len then for key in ipairs(tbl) do tbl[key] = nil end tot = len else for idx = len - rcut + 1, len, 1 do tbl[idx] = nil end for idx = 1, lcut, 1 do tbl[idx] = nil end end for key, val in pairs(tbl) do if type(key) == 'number' and key > 0 then if key > len then cache[key - tot] = val else cache[key - lcut] = val end tbl[key] = nil end end for key, val in pairs(cache) do tbl[key] = val end end return context_iterate(ctx, 3) end -- Syntax: #invoke:params|cropping|left crop|right crop|pipe to library.cropping = function (ctx) local lcut = tonumber(ctx.pipe[1]) if lcut == nil or math.floor(lcut) ~= lcut then error(modulename .. ', ‘cropping’: Left crop must be an integer number', 0) end local rcut = tonumber(ctx.pipe[2]) if rcut == nil or math.floor(rcut) ~= rcut then error(modulename .. ', ‘cropping’: Right crop must be an integer number', 0) end local tbl = ctx.params local nmin, nmax for key in pairs(tbl) do if type(key) == 'number' then if nmin == nil then nmin, nmax = key, key elseif key > nmax then nmax = key elseif key < nmin then nmin = key end end end if nmin ~= nil then local len = nmax - nmin + 1 if lcut < 0 then lcut = len + lcut end if rcut < 0 then rcut = len + rcut end if lcut + rcut - len > -1 then for key in pairs(tbl) do if type(key) == 'number' then tbl[key] = nil end end elseif lcut + rcut > 0 then for idx = nmax - rcut + 1, nmax do tbl[idx] = nil end for idx = nmin, nmin + lcut - 1 do tbl[idx] = nil end local lshift = nmin + lcut - 1 if lshift > 0 then for idx = lshift + 1, nmax, 1 do tbl[idx - lshift], tbl[idx] = tbl[idx], nil end end end end return context_iterate(ctx, 3) end -- Syntax: #invoke:params|purging|start offset|length|pipe to library.purging = function (ctx) local idx = tonumber(ctx.pipe[1]) if idx == nil or math.floor(idx) ~= idx then error(modulename .. ', ‘purging’: Start offset must be an integer number', 0) end local len = tonumber(ctx.pipe[2]) if len == nil or math.floor(len) ~= len then error(modulename .. ', ‘purging’: Length must be an integer number', 0) end local tbl = ctx.params if len < 1 then len = len + table.maxn(tbl) if idx > len then return context_iterate(ctx, 3) end len = len - idx + 1 end ctx.params = copy_table_reduced(tbl, idx, len) return context_iterate(ctx, 3) end -- Syntax: #invoke:params|backpurging|start offset|length|pipe to library.backpurging = function (ctx) local last = tonumber(ctx.pipe[1]) if last == nil or math.floor(last) ~= last then error(modulename .. ', ‘backpurging’: Start offset must be an integer number', 0) end local len = tonumber(ctx.pipe[2]) if len == nil or math.floor(len) ~= len then error(modulename .. ', ‘backpurging’: Length must be an integer number', 0) end local idx local tbl = ctx.params if len > 0 then idx = last - len + 1 else for key in pairs(tbl) do if type(key) == 'number' and (idx == nil or key < idx) then idx = key end end if idx == nil then return context_iterate(ctx, 3) end idx = idx - len if last < idx then return context_iterate(ctx, 3) end len = last - idx + 1 end ctx.params = copy_table_reduced(ctx.params, idx, len) return context_iterate(ctx, 3) end -- Syntax: #invoke:params|shifting|addend|pipe to library.shifting = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local nshift = tonumber(ctx.pipe[1]) if nshift == nil or nshift == 0 or math.floor(nshift) ~= nshift then error(modulename .. ', ‘shifting’: A non-zero integer number must be provided', 0) end local tbl = {} for key, val in pairs(ctx.params) do if type(key) == 'number' then tbl[key + nshift] = val else tbl[key] = val end end ctx.params = tbl return context_iterate(ctx, 2) end -- Syntax: #invoke:params|reversing_numeric_names|pipe to library.reversing_numeric_names = function (ctx) local tbl, numerics, nmax = ctx.params, {}, 0 for key, val in pairs(tbl) do if type(key) == 'number' then numerics[key], tbl[key] = val, nil if key > nmax then nmax = key end end end for key, val in pairs(numerics) do tbl[nmax - key + 1] = val end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|pivoting_numeric_names|pipe to --[[ library.pivoting_numeric_names = function (ctx) local tbl = ctx.params local shift = #tbl + 1 if shift < 2 then return library.reversing_numeric_names(ctx) end local numerics = {} for key, val in pairs(tbl) do if type(key) == 'number' then numerics[key] = val tbl[key] = nil end end for key, val in pairs(numerics) do tbl[shift - key] = val end return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|mirroring_numeric_names|pipe to --[[ library.mirroring_numeric_names = function (ctx) local nmax, nmin local tbl, numerics = ctx.params, {} for key, val in pairs(tbl) do if type(key) == 'number' then numerics[key] = val tbl[key] = nil if nmax == nil then nmin, nmax = key, key elseif key > nmax then nmax = key elseif key < nmin then nmin = key end end end for key, val in pairs(numerics) do tbl[nmax + nmin - key] = val end return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|swapping_numeric_names|pipe to --[[ library.swapping_numeric_names = function (ctx) local tmp local tbl, cache, nsize = ctx.params, {}, 0 for key in pairs(tbl) do if type(key) == 'number' then nsize = nsize + 1 cache[nsize] = key end end table.sort(cache) for idx = math.floor(nsize / 2), 1, -1 do tmp = tbl[cache[idx] ] tbl[cache[idx] ] = tbl[cache[nsize - idx + 1] ] tbl[cache[nsize - idx + 1] ] = tmp end return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|sorting_sequential_values|[criterion]|pipe to library.sorting_sequential_values = function (ctx) local sortfn if ctx.pipe[1] ~= nil then sortfn = sortfunctions[ctx.pipe[1]:match'^%s*(.-)%s*$'] end if sortfn then table.sort(ctx.params, sortfn) else table.sort(ctx.params) end -- i.e. either `false` or `nil` if sortfn == nil then return context_iterate(ctx, 1) end return context_iterate(ctx, 2) end -- Syntax: #invoke:params|splicing|[add to position]|position|increment| -- [number of elements to write]|...|pipe to library.splicing = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local tmp2, argc, pos, refp local opts, tbl = ctx.pipe, ctx.params local tmp1 = opts[1] if tmp1 ~= nil then tmp2 = tonumber(tmp1) if tmp2 == nil or math.floor(tmp2) ~= tmp2 then pos, argc, tmp2 = tonumber(opts[2]), 4, tmp1:match'^%s*(.*%S)' if tmp2 ~= nil then refp = position_references[tmp2] if refp == nil then error(modulename .. ', ‘splicing’: ‘' .. tostring(tmp2) .. '’ is not a valid first argument', 0) end else refp = 0 end else pos, argc, refp = tmp2, 3, 0 end else pos, argc, refp = tonumber(opts[2]), 4, 0 end if pos == nil or math.floor(pos) ~= pos then error(modulename .. ', ‘splicing’: The position must be an integer number', 0) end local len = tonumber(opts[argc - 1]) if len == nil or math.floor(len) ~= len then error(modulename .. ', ‘splicing’: The increment must be an integer number', 0) end local insn = tonumber(opts[argc]) if len == 0 and (insn == nil or insn < 1) then error(modulename .. ', ‘splicing’: When the increment is zero the number of elements to write cannot be zero', 0) end if refp == 2 then for _ in ipairs(tbl) do pos = pos + 1 end refp = 0 end tmp1, tmp2 = nil, nil if refp ~= 0 or len ~= 0 then for key, val in pairs(tbl) do if type(key) == 'number' then if tmp1 == nil then tmp1, tmp2 = key, key elseif key < tmp1 then tmp1 = key elseif key > tmp2 then tmp2 = key end end end end if tmp2 == nil then len = 0 elseif refp == 3 then pos = pos + tmp2 elseif refp == 1 then pos = pos + tmp1 end if len > 0 and pos + len > tmp1 and pos <= tmp2 then tbl = copy_table_expanded(tbl, pos, len) elseif len < 0 and pos - len > tmp1 and pos <= tmp2 then tbl = copy_table_reduced(tbl, pos, -len) else tbl = copy_or_ref_table(tbl, tbl ~= ctx.oparams) end ctx.params = tbl if insn == nil or insn < 0 or math.floor(insn) ~= insn then return context_iterate(ctx, argc) end tmp1 = argc - pos + 1 for key = pos, pos + insn - 1 do tbl[key] = opts[key + tmp1] end return context_iterate(ctx, argc + insn + 1) end -- Syntax: #invoke:params|imposing|name|value|pipe to library.imposing = function (ctx) if ctx.pipe[1] == nil then error(modulename .. ', ‘imposing’: Missing parameter name to impose', 0) end ctx.params[get_parameter_name(ctx.pipe[1])] = ctx.pipe[2] return context_iterate(ctx, 3) end -- Syntax: #invoke:params|providing|name|value|pipe to library.providing = function (ctx) if ctx.pipe[1] == nil then error(modulename .. ', ‘providing’: Missing parameter name to provide', 0) end local key = get_parameter_name(ctx.pipe[1]) if ctx.params[key] == nil then ctx.params[key] = ctx.pipe[2] end return context_iterate(ctx, 3) end -- Syntax: #invoke:params|reassigning|source|destination|[mode]|pipe to library.reassigning = function (ctx) local opts, tbl = ctx.pipe, ctx.params if opts[1] == nil then error(modulename .. ', ‘reassigning’: Missing source parameter', 0) end if opts[2] == nil then error(modulename .. ', ‘reassigning’: Missing destination parameter', 0) end local mode, argc local src = get_parameter_name(opts[1]) local val = tbl[src] if opts[3] ~= nil then mode = a_modes[opts[3]:match'^%s*(.-)%s*$'] end if mode == nil then mode, argc = 0, 3 else argc = 4 end if val == nil and mode > 1 then return context_iterate(ctx, argc) end local dest = get_parameter_name(opts[2]) local tmp = tbl[dest] == nil if mode % 2 == 0 or (mode == 7 and tmp) then tbl[src] = nil end if tmp or mode < 4 then tbl[dest] = val end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|discarding|name|[how many]|pipe to library.discarding = function (ctx) if ctx.pipe[1] == nil then error(modulename .. ', ‘discarding’: Missing parameter name to discard', 0) end local len = tonumber(ctx.pipe[2]) if len == nil then ctx.params[get_parameter_name(ctx.pipe[1])] = nil return context_iterate(ctx, 2) end local key = tonumber(ctx.pipe[1]) if key == nil or math.floor(key) ~= key then error(modulename .. ', ‘discarding’: A range was provided, but the initial parameter name is not an integer number', 0) end if len < 1 or math.floor(len) ~= len then error(modulename .. ', ‘discarding’: A range can only be an integer number greater than zero', 0) end for idx = key, key + len - 1 do ctx.params[idx] = nil end return context_iterate(ctx, 3) end -- Syntax: #invoke:params|excluding_non-numeric_names|pipe to library['excluding_non-numeric_names'] = function (ctx) local tmp = ctx.params for key, val in pairs(tmp) do if type(key) ~= 'number' then tmp[key] = nil end end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|excluding_numeric_names|pipe to library.excluding_numeric_names = function (ctx) local tmp = ctx.params for key, val in pairs(tmp) do if type(key) == 'number' then tmp[key] = nil end end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|with_name_matching|target 1|[plain flag 1]|[or]| -- [target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag -- N]|pipe to library.with_name_matching = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local tmp, ptn local targets, nptns, argc = load_pattern_args(ctx.pipe, 'with_name_matching') local tbl, newparams = ctx.params, {} for idx = 1, nptns do ptn = targets[idx] if ptn[3] then tmp = ptn[1] if tmp == '0' or tmp:find'^%-?[1-9]%d*$' ~= nil then tmp = tonumber(tmp) end newparams[tmp] = tbl[tmp] else for key, val in pairs(tbl) do if tostring(key):find(ptn[1], 1, ptn[2]) then newparams[key] = val end end end end ctx.params = newparams return context_iterate(ctx, argc) end -- Syntax: #invoke:params|with_name_not_matching|target 1|[plain flag 1]| -- [and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain -- flag N]|pipe to library.with_name_not_matching = function (ctx) local targets, nptns, argc = load_pattern_args(ctx.pipe, 'with_name_not_matching') local tbl = ctx.params if nptns == 1 and targets[1][3] then local tmp = targets[1][1] if tmp == '0' or tmp:find'^%-?[1-9]%d*$' ~= nil then tbl[tonumber(tmp)] = nil else tbl[tmp] = nil end return context_iterate(ctx, argc) end local yesmatch, ptn for key in pairs(tbl) do yesmatch = true for idx = 1, nptns do ptn = targets[idx] if ptn[3] then if tostring(key) ~= ptn[1] then yesmatch = false break end elseif not tostring(key):find(ptn[1], 1, ptn[2]) then yesmatch = false break end end if yesmatch then tbl[key] = nil end end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|with_value_matching|target 1|[plain flag 1]|[or]| -- [target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag -- N]|pipe to library.with_value_matching = function (ctx) local nomatch, ptn local tbl = ctx.params local targets, nptns, argc = load_pattern_args(ctx.pipe, 'with_value_matching') for key, val in pairs(tbl) do nomatch = true for idx = 1, nptns do ptn = targets[idx] if ptn[3] then if val == ptn[1] then nomatch = false break end elseif val:find(ptn[1], 1, ptn[2]) then nomatch = false break end end if nomatch then tbl[key] = nil end end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|with_value_not_matching|target 1|[plain flag 1]| -- [and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain -- flag N]|pipe to library.with_value_not_matching = function (ctx) local yesmatch, ptn local tbl = ctx.params local targets, nptns, argc = load_pattern_args(ctx.pipe, 'with_value_not_matching') for key, val in pairs(tbl) do yesmatch = true for idx = 1, nptns do ptn = targets[idx] if ptn[3] then if val ~= ptn[1] then yesmatch = false break end elseif not val:find(ptn[1], 1, ptn[2]) then yesmatch = false break end end if yesmatch then tbl[key] = nil end end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|keeping_at_most|number of parameters to pick|pipe to library.keeping_at_most = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local len = tonumber(ctx.pipe[1]) if len == nil or len < 1 or math.floor(len) ~= len then error(modulename .. ', ‘keeping_at_most’: The number of parameters to keep must be an integer greater than zero', 0) end ctx.params = copy_table_maxn({}, ctx.params, len) return context_iterate(ctx, 2) end -- Syntax: #invoke:params|trimming_values|pipe to library.trimming_values = function (ctx) local tbl = ctx.params for key, val in pairs(tbl) do tbl[key] = val:match'^%s*(.-)%s*$' end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|mapping_to_lowercase|pipe to library.mapping_to_lowercase = function (ctx) local tbl = ctx.params for key, val in pairs(tbl) do tbl[key] = val:lower() end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|mapping_to_uppercase|pipe to library.mapping_to_uppercase = function (ctx) local tbl = ctx.params for key, val in pairs(tbl) do tbl[key] = val:upper() end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|mapping_by_calling|template name|[call -- style]|[let/use]|[...]|[let/use]|[...]|[number of additional -- parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe to library.mapping_by_calling = function (ctx) local tname local opts = ctx.pipe if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end if tname == nil then error(modulename .. ', ‘mapping_by_calling’: No template name was provided', 0) end local margs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 1, mapping_styles.values_only, ctx.params) local model = { title = tname, args = margs } value_maps[looptype](tbl, margs, karg, varg, function () return ctx.frame:expandTemplate(model) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|mapping_by_invoking|module name|function name|[call -- style]|[let/use]|[...]|[let/use]|[...]|[number of additional -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to library.mapping_by_invoking = function (ctx) local mname, fname local opts = ctx.pipe if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end if mname == nil then error(modulename .. ', ‘mapping_by_invoking’: No module name was provided', 0) end if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end if fname == nil then error(modulename .. ', ‘mapping_by_invoking’: No function name was provided', 0) end local margs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 2, mapping_styles.values_only, ctx.params) local model = { title = 'Module:' .. mname, args = margs } local mfunc = require(model.title)[fname] if mfunc == nil then error(modulename .. ', ‘mapping_by_invoking’: The function ‘' .. fname .. '’ does not exist', 0) end value_maps[looptype](tbl, margs, karg, varg, function () return tostring(mfunc(ctx.frame:newChild(model))) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|mapping_by_magic|parser function|[call -- style]|[let/use]|[...]|[let/use]|[...]|[number of additional -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to library.mapping_by_magic = function (ctx) local magic local opts = ctx.pipe if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end if magic == nil then error(modulename .. ', ‘mapping_by_magic’: No parser function was provided', 0) end local margs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 1, mapping_styles.values_only, ctx.params) value_maps[looptype](tbl, margs, karg, varg, function () return ctx.frame:callParserFunction(magic, margs) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|mapping_by_replacing|target|replace|[count]|[plain -- flag]|pipe to library.mapping_by_replacing = function (ctx) local ptn, repl, nmax, flg, argc, die = load_replace_args(ctx.pipe, 'mapping_by_replacing') if die then return context_iterate(ctx, argc) end local tbl = ctx.params if flg == 3 then for key, val in pairs(tbl) do if val == ptn then tbl[key] = repl end end else if flg == 2 then -- Copied from Module:String's `str._escapePattern()` ptn = ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]', '%%%0') end for key, val in pairs(tbl) do tbl[key] = val:gsub(ptn, repl, nmax) end end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|mapping_by_mixing|mixing string|pipe to library.mapping_by_mixing = function (ctx) if ctx.pipe[1] == nil then error(modulename .. ', ‘mapping_by_mixing’: No mixing string was provided', 0) end local tbl, mix = ctx.params, ctx.pipe[1] if mix == '$#' then for key in pairs(tbl) do tbl[key] = tostring(key) end return context_iterate(ctx, 2) end local skel, cnv, n_parts = parse_placeholder_string(mix) for key, val in pairs(tbl) do for idx = 2, n_parts, 2 do if skel[idx] then cnv[idx] = val else cnv[idx] = tostring(key) end end tbl[key] = table.concat(cnv) end return context_iterate(ctx, 2) end -- Syntax: #invoke:params|mapping_to_names|pipe to --[[ library.mapping_to_names = function (ctx) local tbl = ctx.params for key in pairs(tbl) do tbl[key] = tostring(key) end return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|renaming_to_lowercase|pipe to library.renaming_to_lowercase = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local cache = {} for key, val in pairs(ctx.params) do if type(key) == 'string' then cache[key:lower()] = val else cache[key] = val end end ctx.params = cache return context_iterate(ctx, 1) end -- Syntax: #invoke:params|renaming_to_uppercase|pipe to library.renaming_to_uppercase = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local cache = {} for key, val in pairs(ctx.params) do if type(key) == 'string' then cache[key:upper()] = val else cache[key] = val end end ctx.params = cache return context_iterate(ctx, 1) end -- Syntax: #invoke:params|renaming_to_sequence|[sort order]|pipe to library.renaming_to_sequence = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local cache, len local tbl = ctx.params local sortfn, argc, do_sort = load_sort_opt(ctx.pipe[1]) if do_sort then local words, wl cache, words, len, wl = get_key_list_sorted(tbl, sortfn) for idx = 1, len do cache[idx] = tbl[cache[idx]] end for idx = 1, wl do cache[len + idx] = tbl[words[idx]] end else len, cache = 0, {} for _, val in pairs(tbl) do len = len + 1 cache[len] = val end end ctx.params = cache return context_iterate(ctx, argc) end -- Syntax: #invoke:params|renaming_by_calling|template name|[call -- style]|[let/use]|[...]|[let/use]|[...]|[number of additional -- parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe to library.renaming_by_calling = function (ctx) local tname local opts = ctx.pipe if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end if tname == nil then error(modulename .. ', ‘renaming_by_calling’: No template name was provided', 0) end local rargs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 1, mapping_styles.names_only, ctx.params) local model = { title = tname, args = rargs } map_names(tbl, rargs, karg, varg, looptype, function () return ctx.frame:expandTemplate(model) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|renaming_by_invoking|module name|function -- name|[call style]|[let/use]|[...]|[let/use]|[...]|[number of -- additional arguments]|[argument 1]|[argument 2]|[...]|[argument -- N]|pipe to library.renaming_by_invoking = function (ctx) local mname, fname local opts = ctx.pipe if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end if mname == nil then error(modulename .. ', ‘renaming_by_invoking’: No module name was provided', 0) end if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end if fname == nil then error(modulename .. ', ‘renaming_by_invoking’: No function name was provided', 0) end local rargs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 2, mapping_styles.names_only, ctx.params) local model = { title = 'Module:' .. mname, args = rargs } local mfunc = require(model.title)[fname] if mfunc == nil then error(modulename .. ', ‘renaming_by_invoking’: The function ‘' .. fname .. '’ does not exist', 0) end map_names(tbl, rargs, karg, varg, looptype, function () return tostring(mfunc(ctx.frame:newChild(model))) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|renaming_by_magic|parser function|[call -- style]|[let/use]|[...]|[let/use]|[...]|[number of additional -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to library.renaming_by_magic = function (ctx) local opts = ctx.pipe local magic if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end if magic == nil then error(modulename .. ', ‘renaming_by_magic’: No parser function was provided', 0) end local rargs, argc, looptype, karg, varg, tbl, mem = load_callback_opts(opts, 1, mapping_styles.names_only, ctx.params) map_names(tbl, rargs, karg, varg, looptype, function () return ctx.frame:callParserFunction(magic, rargs) end) for key, val in pairs(mem) do tbl[key] = val end ctx.params = tbl return context_iterate(ctx, argc) end -- Syntax: #invoke:params|renaming_by_replacing|target|replace|[count]|[plain -- flag]|pipe to library.renaming_by_replacing = function (ctx) local ptn, repl, nmax, flg, argc, die = load_replace_args(ctx.pipe, 'renaming_by_replacing') if die then return context_iterate(ctx, argc) end local tbl = ctx.params if flg == 3 then ptn = get_parameter_name(ptn) local val = tbl[ptn] if val ~= nil then tbl[ptn], tbl[get_parameter_name(repl)] = nil, val end else if flg == 2 then -- Copied from Module:String's `str._escapePattern()` ptn = ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]', '%%%0') end local cache = {} for key, val in pairs(tbl) do steal_if_renamed(val, tbl, key, cache, tostring(key):gsub(ptn, repl, nmax)) end for key, val in pairs(cache) do tbl[key] = val end end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|renaming_by_mixing|mixing string|pipe to library.renaming_by_mixing = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning if ctx.pipe[1] == nil then error(modulename .. ', ‘renaming_by_mixing’: No mixing string was provided', 0) end local mix = ctx.pipe[1]:match'^%s*(.-)%s*$' local cache = {} if mix == '$@' then for _, val in pairs(ctx.params) do cache[get_parameter_name(val)] = val end else local skel, canvas, n_parts = parse_placeholder_string(mix) for key, val in pairs(ctx.params) do for idx = 2, n_parts, 2 do if skel[idx] then canvas[idx] = val else canvas[idx] = tostring(key) end end cache[get_parameter_name(table.concat(canvas))] = val end end ctx.params = cache return context_iterate(ctx, 2) end -- Syntax: #invoke:params|renaming_to_values|pipe to --[[ library.renaming_to_values = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local cache = {} for _, val in pairs(ctx.params) do cache[val] = val end ctx.params = cache return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|grouping_by_calling|template -- name|[let/use]|[...]|[let/use]|[...]|[number of additional -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to library.grouping_by_calling = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local tmp, argc, tbl, mem = load_child_opts(ctx.pipe, 2, 0, ctx.params) local gargs = {} for key, val in pairs(tmp) do if type(key) == 'number' and key < 1 then gargs[key - 1] = val else gargs[key] = val end end tmp = ctx.pipe[1] if tmp ~= nil then tmp = tmp:match'^%s*(.*%S)' end if tmp == nil then error(modulename .. ', ‘grouping_by_calling’: No template name was provided', 0) end local model = { title = tmp } local groups = make_groups(tbl) for gid, group in pairs(groups) do for key, val in pairs(gargs) do group[key] = val end group[0], model.args = gid, group groups[gid] = ctx.frame:expandTemplate(model) end for key, val in pairs(mem) do groups[key] = val end ctx.params = groups return context_iterate(ctx, argc) end -- Syntax: #invoke:params|parsing|string to parse|[trim flag]|[iteration -- delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe to library.parsing = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘parsing’: No string to parse was provided', 0) end local isep, iplain, psep, pplain, trimnamed, trimunnamed, argc = load_parse_opts(opts, 2, '|', '=') parse_parameter_string(ctx.params, opts[1], isep, iplain, psep, pplain, trimnamed, trimunnamed) return context_iterate(ctx, argc) end -- Syntax: #invoke:params|reinterpreting|parameter to reinterpret|[trim -- flag]|[iteration delimiter setter]|[...]|[key-value delimiter -- setter]|[...]|pipe to library.reinterpreting = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘reinterpreting’: No parameter to reinterpret was provided', 0) end local isep, iplain, psep, pplain, trimnamed, trimunnamed, argc = load_parse_opts(opts, 2, '|', '=') local tbl, tmp = ctx.params, get_parameter_name(opts[1]) local str = tbl[tmp] if str ~= nil then tbl[tmp] = nil parse_parameter_string(tbl, str, isep, iplain, psep, pplain, trimnamed, trimunnamed) end return context_iterate(ctx, argc) end -- Syntax: #invoke:params|evaluating|string to parse|[trim flag]|[iteration -- delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe to library.evaluating = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘evaluating’: No string to parse was provided', 0) end local isep, iplain, psep, pplain, trimnamed, trimunnamed, argc = load_parse_opts(opts, 2, '!', ':') if opts[1]:match'^%s*(.*%S)' == nil then ctx.pipe = copy_or_ref_table(opts, opts ~= ctx.opipe) return context_iterate(ctx, argc) end local new_opts, cache = {}, {} local shift = parse_parameter_string(cache, opts[1], isep, iplain, psep, pplain, trimnamed, trimunnamed) - argc for key, val in pairs(opts) do if type(key) ~= 'number' or key < 1 then new_opts[key] = val elseif key >= argc then new_opts[key + shift] = val end end for key, val in pairs(cache) do new_opts[key] = val end ctx.pipe = new_opts return context_iterate(ctx, 1) end -- Syntax: #invoke:params|mixing_names_and_values|mixing string|pipe to library.mixing_names_and_values = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning if ctx.pipe[1] == nil then error(modulename .. ', ‘mixing_names_and_values’: No mixing string was provided for parameter names', 0) end if ctx.pipe[2] == nil then error(modulename .. ', ‘mixing_names_and_values’: No mixing string was provided for parameter values', 0) end local tmp local mix_k = ctx.pipe[1]:match'^%s*(.-)%s*$' local cache, mix_v = {}, ctx.pipe[2] if mix_k == '$@' and mix_v == '$@' then for _, val in pairs(ctx.params) do cache[get_parameter_name(val)] = val end elseif mix_k == '$@' and mix_v == '$#' then for key, val in pairs(ctx.params) do cache[get_parameter_name(val)] = tostring(key) end elseif mix_k == '$#' and mix_v == '$#' then for key in pairs(ctx.params) do cache[key] = tostring(key) end else local skel_k, cnv_k, n_parts_k = parse_placeholder_string(mix_k) local skel_v, cnv_v, n_parts_v = parse_placeholder_string(mix_v) for key, val in pairs(ctx.params) do tmp = tostring(key) for idx = 2, n_parts_k, 2 do if skel_k[idx] then cnv_k[idx] = val else cnv_k[idx] = tmp end end for idx = 2, n_parts_v, 2 do if skel_v[idx] then cnv_v[idx] = val else cnv_v[idx] = tmp end end cache[get_parameter_name(table.concat(cnv_k))] = table.concat(cnv_v) end end ctx.params = cache return context_iterate(ctx, 3) end -- Syntax: #invoke:params|swapping_names_and_values|pipe to --[[ library.swapping_names_and_values = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local cache = {} for key, val in pairs(ctx.params) do cache[val] = key end ctx.params = cache return context_iterate(ctx, 1) end ]]-- -- Syntax: #invoke:params|combining|new parameter name|[sort -- order]|[with/without flushed glue]|setting directives|...|pipe to library.combining = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning return context_iterate(ctx, combine_parameters( ctx, function (key, val, kvs) return key .. kvs .. val end, 'combining' ) + 1) end -- Syntax: #invoke:params|combining_values|new parameter name|[sort -- order]|[with/without flushed glue]|setting directives|...|pipe to library.combining_values = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning return context_iterate(ctx, combine_parameters( ctx, function (key, val, kvs) return val end, 'combining_values' ) + 1) end -- Syntax: #invoke:params|combining_by_calling|template name|new parameter -- name|pipe to library.combining_by_calling = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local tname = ctx.pipe[1] if tname ~= nil then tname = tname:match'^%s*(.*%S)' else error(modulename .. ', ‘combining_by_calling’: No template name was provided', 0) end if ctx.pipe[2] == nil then error(modulename .. ', ‘combining_by_calling’: No parameter name was provided', 0) end ctx.params = { [get_parameter_name(ctx.pipe[2])] = ctx.frame:expandTemplate{ title = tname, args = ctx.params } } return context_iterate(ctx, 3) end -- Syntax: #invoke:params|combining_by_invoking|module name|function name|new -- parameter name|pipe to library.combining_by_invoking = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local mname = ctx.pipe[1] if mname ~= nil then mname = mname:match'^%s*(.*%S)' else error(modulename .. ', ‘combining_by_invoking’: No module name was provided', 0) end local fname = ctx.pipe[2] if fname ~= nil then fname = fname:match'^%s*(.*%S)' else error(modulename .. ', ‘combining_by_invoking’: No function name was provided', 0) end if ctx.pipe[3] == nil then error(modulename .. ', ‘combining_by_invoking’: No parameter name was provided', 0) end local model = { title = 'Module:' .. mname, args = ctx.params } local mfunc = require(model.title)[fname] if mfunc == nil then error(modulename .. ', ‘mapping_by_invoking’: The function ‘' .. fname .. '’ does not exist', 0) end ctx.params = { [get_parameter_name(ctx.pipe[3])] = tostring(mfunc(ctx.frame:newChild(model))) } return context_iterate(ctx, 4) end -- Syntax: #invoke:params|combining_by_magic|parser function|new parameter -- name|pipe to library.combining_by_magic = function (ctx) -- NOTE: `ctx.params` might be the original metatable! As a modifier, -- this function MUST create a copy of it before returning local magic = ctx.pipe[1] if magic ~= nil then magic = magic:match'^%s*(.*%S)' else error(modulename .. ', ‘combining_by_magic’: No parser function was provided', 0) end if ctx.pipe[2] == nil then error(modulename .. ', ‘combining_by_magic’: No parameter name was provided', 0) end ctx.params = { [get_parameter_name(ctx.pipe[2])] = ctx.frame:callParserFunction(magic, ctx.params) } return context_iterate(ctx, 3) end -- Syntax: #invoke:params|snapshotting|[maximum number]|pipe to library.snapshotting = function (ctx) return context_iterate(ctx, make_child(ctx, ctx.params, 'snapshotting')) end -- Syntax: #invoke:params|remembering|[maximum number]|pipe to library.remembering = function (ctx) return context_iterate(ctx, make_child(ctx, ctx.oparams, 'remembering')) end -- Syntax: #invoke:params|entering_substack|[new]|pipe to library.entering_substack = function (ctx) local tbl, ncurrparent = ctx.params, ctx.n_parents + 1 if ctx.parents == nil then ctx.parents = { tbl } else ctx.parents[ncurrparent] = tbl end ctx.n_parents = ncurrparent if ctx.pipe[1] ~= nil and ctx.pipe[1]:match'^%s*new%s*$' then ctx.params = {} return context_iterate(ctx, 2) end local currsnap = ctx.n_children if currsnap > 0 then ctx.params, ctx.children[currsnap], ctx.n_children = ctx.children[currsnap], nil, currsnap - 1 else local newparams = {} for key, val in pairs(tbl) do newparams[key] = val end ctx.params = newparams end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|pulling|parameter name|pipe to library.pulling = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘pulling’: No parameter to pull was provided', 0) end local tmp = ctx.n_parents local parent = tmp < 1 and ctx.oparams or ctx.parents[tmp] tmp = get_parameter_name(opts[1]) if parent[tmp] ~= nil then ctx.params[tmp] = parent[tmp] end return context_iterate(ctx, 2) end -- Syntax: #invoke:params|recalling|parameter name|pipe to library.recalling = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘recalling’: No parameter to recall was provided', 0) end local arg = get_parameter_name(opts[1]) if ctx.oparams[arg] ~= nil then ctx.params[arg] = ctx.oparams[arg] end return context_iterate(ctx, 2) end -- Syntax: #invoke:params|finding|parameter name|pipe to --[[ library.finding = function (ctx) local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘finding’: No parameter to find was provided', 0) end local arg = get_parameter_name(opts[1]) local parent for idx = ctx.n_parents, 1, -1 do parent = ctx.parents[idx] if parent[arg] ~= nil then ctx.params[arg] = parent[arg] return context_iterate(ctx, 2) end end if ctx.oparams[arg] ~= nil then ctx.params[arg] = ctx.oparams[arg] end return context_iterate(ctx, 2) end ]]-- -- Syntax: #invoke:params|picking|number of parameters to pick|pipe to --[[ library.picking = function (ctx) local len = tonumber(ctx.pipe[1]) if len == nil or len < 1 or math.floor(len) ~= len then error(modulename .. ', ‘picking’: The number of parameters to pick must be an integer greater than zero', 0) end if ctx.n_parents < 1 then copy_table_maxn(ctx.params, ctx.oparams, len) else copy_table_maxn(ctx.params, ctx.parents[ctx.n_parents], len) end return context_iterate(ctx, 2) end ]]-- -- Syntax: #invoke:params|detaching_substack|pipe to library.detaching_substack = function (ctx) local ncurrparent = ctx.n_parents if ncurrparent < 1 then error(modulename .. ', ‘detaching_substack’: No substack has been created', 0) end local parent = ctx.parents[ncurrparent] for key in pairs(ctx.params) do parent[key] = nil end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|dropping_substack|pipe to library.dropping_substack = function (ctx) local ncurrparent = ctx.n_parents if ncurrparent < 1 then error(modulename .. ', ‘dropping_substack’: No substack has been created', 0) end ctx.params, ctx.parents[ncurrparent], ctx.n_parents = ctx.parents[ncurrparent], nil, ncurrparent - 1 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|leaving_substack|pipe to library.leaving_substack = function (ctx) local ncurrparent = ctx.n_parents if ncurrparent < 1 then error(modulename .. ', ‘leaving_substack’: No substack has been created', 0) end local currsnap = ctx.n_children + 1 if ctx.children == nil then ctx.children = { ctx.params } else ctx.children[currsnap] = ctx.params end ctx.params, ctx.parents[ncurrparent], ctx.n_parents, ctx.n_children = ctx.parents[ncurrparent], nil, ncurrparent - 1, currsnap return context_iterate(ctx, 1) end -- Syntax: #invoke:params|merging_substack|pipe to library.merging_substack = function (ctx) local ncurrparent = ctx.n_parents if ncurrparent < 1 then error(modulename .. ', ‘merging_substack’: No substack has been created', 0) end local parent, child = ctx.parents[ncurrparent], ctx.params ctx.params, ctx.parents[ncurrparent], ctx.n_parents = parent, nil, ncurrparent - 1 for key, val in pairs(child) do parent[key] = val end return context_iterate(ctx, 1) end -- Syntax: #invoke:params|flushing|pipe to library.flushing = function (ctx) if ctx.n_children < 1 then error(modulename .. ', ‘flushing’: There are no substacks to flush', 0) end local parent, currsnap = ctx.params, ctx.n_children for key, val in pairs(ctx.children[currsnap]) do parent[key] = val end ctx.children[currsnap], ctx.n_children = nil, currsnap - 1 return context_iterate(ctx, 1) end -- Syntax: #invoke:params|setting_by_flushing|pipe to library.setting_by_flushing = function (ctx) set_strings_from_substack(ctx, ctx, 'setting_by_flushing') return context_iterate(ctx, 1) end --[[ Functions ]]-- ----------------------------- -- Syntax: #invoke:params|count library.count = function (ctx) -- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables! local retval = 0 for _ in ctx.iterfunc(ctx.params) do retval = retval + 1 end if ctx.subset == -1 then retval = retval - #ctx.params end ctx.text = retval return false end -- Syntax: #invoke:args|concat_and_call|template name|[prepend 1]|[prepend 2]| -- [...]|[item n]|[named item 1=value 1]|[...]|[named item n=value -- n]|[...] library.concat_and_call = function (ctx) -- NOTE: `ctx.params` might be the original metatable! local tname local opts = ctx.pipe if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end if tname == nil then error(modulename .. ', ‘concat_and_call’: No template name was provided', 0) end remove_numeric_keys(opts, 1, 1) ctx.text = ctx.frame:expandTemplate{ title = tname, args = concat_params(ctx) } return false end -- Syntax: #invoke:args|concat_and_invoke|module name|function name|[prepend -- 1]|[prepend 2]|[...]|[item n]|[named item 1=value 1]|[...]|[named -- item n=value n]|[...] library.concat_and_invoke = function (ctx) -- NOTE: `ctx.params` might be the original metatable! local mname, fname local opts = ctx.pipe if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end if mname == nil then error(modulename .. ', ‘concat_and_invoke’: No module name was provided', 0) end if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end if fname == nil then error(modulename .. ', ‘concat_and_invoke’: No function name was provided', 0) end remove_numeric_keys(opts, 1, 2) local mfunc = require('Module:' .. mname)[fname] if mfunc == nil then error(modulename .. ', ‘concat_and_invoke’: The function ‘' .. fname .. '’ does not exist', 0) end ctx.text = mfunc(ctx.frame:newChild{ title = 'Module:' .. mname, args = concat_params(ctx) }) return false end -- Syntax: #invoke:args|concat_and_magic|parser function|[prepend 1]|[prepend -- 2]|[...]|[item n]|[named item 1=value 1]|[...]|[named item n= -- value n]|[...] library.concat_and_magic = function (ctx) -- NOTE: `ctx.params` might be the original metatable! local magic local opts = ctx.pipe if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end if magic == nil then error(modulename .. ', ‘concat_and_magic’: No parser function was provided', 0) end remove_numeric_keys(opts, 1, 1) ctx.text = ctx.frame:callParserFunction(magic, concat_params(ctx)) return false end -- Syntax: #invoke:params|value_of|parameter name library.value_of = function (ctx) -- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables! local opts = ctx.pipe if opts[1] == nil then error(modulename .. ', ‘value_of’: No parameter name was provided', 0) end local val local key = opts[1]:match'^%s*(.-)%s*$' if key == '0' or key:find'^%-?[1-9]%d*$' ~= nil then key = tonumber(key) val = ctx.params[key] -- No worries: #ctx.params is unused when the modifier is in -- first position (and therefore `ctx.params` is a metatable) if val ~= nil and ( ctx.subset ~= -1 or key > #ctx.params or key < 1 ) and ( ctx.subset ~= 1 or (key <= #ctx.params and key > 0) ) then ctx.text = (ctx.header or '') .. val .. (ctx.footer or '') else ctx.text = ctx.ifngiven or '' end else val = ctx.params[key] if ctx.subset ~= 1 and val ~= nil then ctx.text = (ctx.header or '') .. val .. (ctx.footer or '') else ctx.text = ctx.ifngiven or '' end end return false end -- Syntax: #invoke:params|list library.list = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! local ret, nss, kvs, pps = {}, 0, ctx.pairsep or '', ctx.itersep or '' flush_params(ctx, function (key, val) ret[nss + 1], ret[nss + 2], ret[nss + 3], ret[nss + 4], nss = pps, key, kvs, val, nss + 4 end) finalize_and_return_concatenated_list(ctx, ret, nss, 4) return false end -- Syntax: #invoke:params|list_values library.list_values = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! -- NOTE: `library.coins()` and `library.unique_coins()` rely on us local ret, nss, pps = {}, 0, ctx.itersep or '' flush_params(ctx, function (key, val) ret[nss + 1], ret[nss + 2], nss = pps, val, nss + 2 end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|list_maybe_with_names library.list_maybe_with_names = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! local ret, nss, kvs, pps = {}, 0, ctx.pairsep or '', ctx.itersep or '' mixed_flush_params( ctx, function (key, val) ret[nss + 1], ret[nss + 2], ret[nss + 3], ret[nss + 4], nss = pps, '', '', val, nss + 4 end, function (key, val) ret[nss + 1], ret[nss + 2], ret[nss + 3], ret[nss + 4], nss = pps, key, kvs, val, nss + 4 end ) finalize_and_return_concatenated_list(ctx, ret, nss, 4) return false end -- Syntax: #invoke:params|coins|[first coin = value 1]|[second coin = value -- 2]|[...]|[last coin = value N] --[[ library.coins = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! local opts, tbl = ctx.pipe, ctx.params for key, val in pairs(tbl) do tbl[key] = opts[get_parameter_name(val)] end return library.list_values(ctx) end ]]-- -- Syntax: #invoke:params|unique_coins|[first coin = value 1]|[second coin = -- value 2]|[...]|[last coin = value N] --[[ library.unique_coins = function (ctx) local tmp local opts, tbl = ctx.pipe, ctx.params for key, val in pairs(tbl) do tmp = get_parameter_name(val) tbl[key], opts[tmp] = opts[tmp], nil end return library.list_values(ctx) end ]] -- Syntax: #invoke:params|for_each|wikitext library.for_each = function (ctx) -- NOTE: `ctx.pipe` might be the original metatable! local ret, nss, pps, txt = {}, 0, ctx.itersep or '', ctx.pipe[1] or '' local skel, cnv, n_parts = parse_placeholder_string(txt) flush_params(ctx, function (key, val) for idx = 2, n_parts, 2 do if skel[idx] then cnv[idx] = val else cnv[idx] = tostring(key) end end ret[nss + 1], nss = pps, nss + 2 ret[nss] = table.concat(cnv) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|call_for_each|template name|[append 1]|[append 2]| -- [...]|[append n]|[named param 1=value 1]|[...]|[named param -- n=value n]|[...] library.call_for_each = function (ctx) local tname local opts = ctx.pipe if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end if tname == nil then error(modulename .. ', ‘call_for_each’: No template name was provided', 0) end local model = { title = tname, args = opts } local ret, nss, ccs = {}, 0, ctx.itersep or '' table.insert(opts, 1, true) flush_params(ctx, function (key, val) opts[1], opts[2], ret[nss + 1], nss = key, val, ccs, nss + 2 ret[nss] = ctx.frame:expandTemplate(model) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|invoke_for_each|module name|module function|[append -- 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]| -- [named param n=value n]|[...] library.invoke_for_each = function (ctx) local mname, fname local opts = ctx.pipe if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end if mname == nil then error(modulename .. ', ‘invoke_for_each’: No module name was provided', 0) end if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end if fname == nil then error(modulename .. ', ‘invoke_for_each’: No function name was provided', 0) end local model = { title = 'Module:' .. mname, args = opts } local mfunc = require(model.title)[fname] local ret, nss, ccs = {}, 0, ctx.itersep or '' flush_params(ctx, function (key, val) opts[1], opts[2], ret[nss + 1], nss = key, val, ccs, nss + 2 ret[nss] = mfunc(ctx.frame:newChild(model)) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|magic_for_each|parser function|[append 1]|[append -- 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param -- n=value n]|[...] library.magic_for_each = function (ctx) local magic local opts = ctx.pipe if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end if magic == nil then error(modulename .. ', ‘magic_for_each’: No parser function was provided', 0) end local ret, nss, ccs = {}, 0, ctx.itersep or '' table.insert(opts, 1, true) flush_params(ctx, function (key, val) opts[1], opts[2], ret[nss + 1], nss = key, val, ccs, nss + 2 ret[nss] = ctx.frame:callParserFunction(magic, opts) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|call_for_each_value|template name|[append 1]|[append -- 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param -- n=value n]|[...] library.call_for_each_value = function (ctx) local tname local opts = ctx.pipe if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end if tname == nil then error(modulename .. ', ‘call_for_each_value’: No template name was provided', 0) end local model = { title = tname, args = opts } local ret, nss, ccs = {}, 0, ctx.itersep or '' flush_params(ctx, function (key, val) opts[1], ret[nss + 1], nss = val, ccs, nss + 2 ret[nss] = ctx.frame:expandTemplate(model) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|invoke_for_each_value|module name|[append 1]|[append -- 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param -- n=value n]|[...] library.invoke_for_each_value = function (ctx) local opts = ctx.pipe local mname, fname if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end if mname == nil then error(modulename .. ', ‘invoke_for_each_value’: No module name was provided', 0) end if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end if fname == nil then error(modulename .. ', ‘invoke_for_each_value’: No function name was provided', 0) end local model = { title = 'Module:' .. mname, args = opts } local mfunc = require(model.title)[fname] local ret, nss, ccs = {}, 0, ctx.itersep or '' remove_numeric_keys(opts, 1, 1) flush_params(ctx, function (key, val) opts[1], ret[nss + 1], nss = val, ccs, nss + 2 ret[nss] = mfunc(ctx.frame:newChild(model)) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|magic_for_each_value|parser function|[append 1]| -- [append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named -- param n=value n]|[...] library.magic_for_each_value = function (ctx) local opts = ctx.pipe local magic if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end if magic == nil then error(modulename .. ', ‘magic_for_each_value’: No parser function was provided', 0) end local ret, nss, ccs = {}, 0, ctx.itersep or '' flush_params(ctx, function (key, val) opts[1], ret[nss + 1], nss = val, ccs, nss + 2 ret[nss] = ctx.frame:callParserFunction(magic, opts) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end -- Syntax: #invoke:params|call_for_each_group|template name|[append 1]|[append -- 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param -- n=value n]|[...] library.call_for_each_group = function (ctx) -- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables! local tmp if ctx.pipe[1] ~= nil then tmp = ctx.pipe[1]:match'^%s*(.*%S)' end if tmp == nil then error(modulename .. ', ‘call_for_each_group’: No template name was provided', 0) end local model = { title = tmp } local opts, ret, nss, ccs = {}, {}, 0, ctx.itersep or '' for key, val in pairs(ctx.pipe) do if type(key) == 'number' then opts[key - 1] = val else opts[key] = val end end ctx.pipe = opts ctx.params = make_groups(ctx.params) flush_params(ctx, function (gid, group) for key, val in pairs(opts) do group[key] = val end group[0], model.args, ret[nss + 1], nss = gid, group, ccs, nss + 2 ret[nss] = ctx.frame:expandTemplate(model) end) finalize_and_return_concatenated_list(ctx, ret, nss, 2) return false end --[[ First-position-only modifiers ]]-- --------------------------------------- -- Syntax: #invoke:params|new|pipe to static_iface.new = function (child_frame) local ctx = context_new(child_frame) ctx.pipe = copy_or_ref_table(ctx.opipe, false) ctx.params = {} main_loop(ctx, context_iterate(ctx, 1)) return ctx.text end --[[ First-position-only functions ]]-- --------------------------------------- -- Syntax: #invoke:params|self static_iface.self = function (frame) return frame:getParent():getTitle() end --[[ Public metatable of functions ]]-- --------------------------------------- return setmetatable({}, { __index = function (_, query) local fname = query:match'^%s*(.*%S)' if fname == nil then error(modulename .. ': You must specify a function to call', 0) end local func = static_iface[fname] if func ~= nil then return func end func = library[fname] if func == nil then error(modulename .. ': The function ‘' .. fname .. '’ does not exist', 0) end return function (child_frame) local ctx = context_new(child_frame) ctx.pipe = copy_or_ref_table(ctx.opipe, refpipe[fname]) ctx.params = copy_or_ref_table(ctx.oparams, refparams[fname]) main_loop(ctx, func) return ctx.text end end }) jd4jhydnyce3tw9c50qwx3yd53quopx