Módulo:Testes/Gkiyoshinishimoto/Hatnote list
Aspeto
Este módulo não apresenta nenhuma documentação. Por favor, documente-o caso o saiba usar ou tenha conhecimentos para tal. |
--------------------------------------------------------------------------------
-- Módulo:Testes/Gkiyoshinishimoto/Hatnote list --
-- --
-- Este módulo produz e formata listas para uso em notas de cabeçalho --
-- ('hatnotes'). Em particular, ele implementa a lista "for-see", ou seja, --
-- listas de declarações "Para X, consulte Y", conforme usado em --
-- {{Teste/Gkiyoshinishimoto/About}}, {{Teste/Gkiyoshinishimoto/Redirect}} e --
-- suas variantes. Também são introduzidas as auxiliares "andList" e "orList" --
-- para formatar listas com essas conjunções ("e"/"ou"). --
--------------------------------------------------------------------------------
local mArguments -- inicializa lentamente
local mFormatLink = require('Módulo:Testes/Gkiyoshinishimoto/Format link')
local mHatnote = require('Módulo:Testes/Gkiyoshinishimoto/Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
--------------------------------------------------------------------------------
-- Funções auxiliares de sequenciamento ("'string'ificação") de lista
--
-- Essas funções são usadas para transformar listas e sequências ('strings'),
-- geralmente listas de páginas dentro da parte "Y" de "Para X, ver Y" de
-- itens para ver.
--------------------------------------------------------------------------------
-- tabela de opções padrão usada nas funções de sequenciamento
-- ("'string'ificação") de listas
local stringifyListDefaultOptions = {
conjunction = "e",
separator = ",",
altSeparator = ";",
space = " ",
formatted = false
}
-- Pesquisa somente texto a ser mostrado
local function searchDisp(haystack, needle)
return string.find(
string.sub(haystack, (string.find(haystack, '|') or 0) + 1), needle
)
end
-- Sequencia ("'string'ifica") uma lista genericamente; provavelmente
-- não deve ser usada diretamente
local function stringifyList(list, options)
-- Verificações de tipo, padrões e um atalho
checkType("stringifyList", 1, list, "table")
if #list == 0 then return nil end
checkType("stringifyList", 2, options, "table", true)
options = options or {}
for k, v in pairs(stringifyListDefaultOptions) do
if options[k] == nil then options[k] = v end
end
local s = options.space
-- Formata a lista se solicitado
if options.formatted then
list = mFormatLink.formatPages(
{categorizeMissing = mHatnote.missingTargetCat}, list
)
end
-- Define o separador; se algum item contiver, usa o separador alternativo
local separator = options.separator
for k, v in pairs(list) do
if searchDisp(v, separator) then
separator = options.altSeparator
break
end
end
-- Define a conjunção, aplica a vírgula de Oxford e força uma vírgula se #1 tiver "§"
local conjunction = s .. options.conjunction .. s
if #list == 2 and searchDisp(list[1], "§") or #list > 2 then
conjunction = separator .. conjunction
end
-- Retorna a sequência ('string') formatada
return mw.text.listToText(list, separator .. s, conjunction)
end
-- Função "'DRY'"
function p.conjList (conj, list, fmt)
return stringifyList(list, {conjunction = conj, formatted = fmt})
end
-- Sequencia ("'string'ifica") listas com "e" ou "ou"
function p.andList (...) return p.conjList("e", ...) end
function p.orList (...) return p.conjList("ou", ...) end
--------------------------------------------------------------------------------
-- Para ver
--
-- Faz uma lista "Para X, ver [[Y]]." a partir de parâmetros brutos. Destinada
-- às predefinições {{Teste/Gkiyoshinishimoto/About}} e
-- {{Teste/Gkiyoshinishimoto/Redirect}} e suas variantes.
--------------------------------------------------------------------------------
-- tabela de opções padrão usada na família de funções "forSee"
local forSeeDefaultOptions = {
andKeyword = 'e',
title = mw.title.getCurrentTitle().text,
otherText = 'outros usos',
forSeeForm = 'Para %s, ver %s.',
}
-- Recolhe a pontuação duplicada no final da sequência ('string'), ignorando
-- itálico e ligações ('links')
local function punctuationCollapse (text)
return text:match("[.?!]('?)%1(%]?)%2%.$") and text:sub(1, -2) or text
end
-- Estrutura argumentos em uma tabela para sequenciamento ("'string'ificação")
-- e opções
function p.forSeeArgsToTable (args, from, options)
-- Verificações de tipo e padrões
checkType("forSeeArgsToTable", 1, args, 'table')
checkType("forSeeArgsToTable", 2, from, 'number', true)
from = from or 1
checkType("forSeeArgsToTable", 3, options, 'table', true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- de "maxArg" é obtido manualmente porque "getArgs()" e "table.maxn"
-- não são amigos
local maxArg = 0
for k, v in pairs(args) do
if type(k) == 'number' and k > maxArg then maxArg = k end
end
-- Estrutura os dados a partir da lista de parâmetros:
-- * "forTable" é a tabela "'wrapper'", com linhas de "forRow"
-- As linhas são tabelas de uma sequência ('string') de "usos" e uma tabela
-- de "páginas" de sequências ('strings') de nomes de páginas
-- * Os espaços em branco são deixados em branco para padronizar em outro lugar,
-- mas podem terminar a lista
local forTable = {}
local i = from
local terminated = false
-- Se houver texto extra e nenhum argumento for fornecido, fornece o valor
-- nulo ('nil') para não produzir o padrão de "Para outros usos, ver
-- algo (desambiguação)"
if options.extratext and i > maxArg then return nil end
-- Retorno ('loop') para geração de linhas
repeat
-- Nova linha vazia
local forRow = {}
-- No uso em branco, assume que a lista terminou e quebra no final deste
-- retorno ('loop')
forRow.use = args[i]
if not args[i] then terminated = true end
-- Nova lista vazia de páginas
forRow.pages = {}
-- Insere o primeiro item de páginas se presente
table.insert(forRow.pages, args[i + 1])
-- Se o parâmetro após o próximo for "e", faz um retorno ('loop') interno
-- para coletar parâmetros
-- até que os "e"s acabem. Os espaços em branco são ignorados:
-- "1|e||e|3" → {1, 3}
while args[i + 2] == options.andKeyword do
if args[i + 3] then
table.insert(forRow.pages, args[i + 3])
end
-- Incrementa para o próximo "e"
i = i + 2
end
-- Incrementa para o próximo uso
i = i + 2
-- Acrescenta a linha
table.insert(forTable, forRow)
until terminated or i > maxArg
return forTable
end
-- Sequencia ("'string'ifica") uma tabela conforme formatada por "forSeeArgsToTable"
function p.forSeeTableToString (forSeeTable, options)
-- Verificações de tipo e padrões
checkType("forSeeTableToString", 1, forSeeTable, "table", true)
checkType("forSeeTableToString", 2, options, "table", true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Sequencia ("'string'ifica") cada item de para ver em uma lista
local strList = {}
if forSeeTable then
for k, v in pairs(forSeeTable) do
local useStr = v.use or options.otherText
local pagesStr =
p.andList(v.pages, true) or
mFormatLink._formatLink{
categorizeMissing = mHatnote.missingTargetCat,
link = mHatnote.disambiguate(options.title)
}
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)
forSeeStr = punctuationCollapse(forSeeStr)
table.insert(strList, forSeeStr)
end
end
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'.')) end
-- Retorna a lista concatenada
return table.concat(strList, ' ')
end
-- Produz uma sequência ('string') "Para X, ver [[Y]]" de argumentos. Espera lacunas
-- no índice mas não valores em branco/espaço em branco. Ignora argumentos ('args')
-- nomeados e argumentos ('args') menores que ("<") "from".
function p._forSee (args, from, options)
local forSeeTable = p.forSeeArgsToTable(args, from, options)
return p.forSeeTableToString(forSeeTable, options)
end
-- Assim como "_forSee", mas usa o quadro ('frame').
function p.forSee (frame, from, options)
mArguments = require('Módulo:Testes/Gkiyoshinishimoto/Arguments')
return p._forSee(mArguments.getArgs(frame), from, options)
end
return p