Module:GHS phrases explained

---------------------------------------------------------------------------------- Module:GHS phrases-- -- main: reads GHS parameters (arguments like "H301", "P401")-- and returns for each (listtype='abbr'):-- phraseID visible; formal phrase text as -- setID = "H" or "P"-- phraseID = e.g. "H201", "P231+P234"-- phrase text read from array tables in ---- Implements: -- Helppage: -- Error category:, (mainspace pages only)---- Also: -- listAll, numberOfPhrases, listOmitRules,-- listtype, omit--------------------------------------------------------------------------------require('strict')local r = -- "r" for return, so no confusion with setID Plocal GHSdata = mw.loadData('Module:GHS phrases/data')local getArgs = require('Module:Arguments').getArgslocal tTools = require('Module:TableTools')local yesno = require('Module:Yesno')local tArgName = -- named parameters (setid, omit, listtype)local tMessagesToShow = -- the tail: Preview, Categories

---------------------------------------------------------------------------------- wlHelpPage---- Formats page as Label-- by default, sLabel

sSection--------------------------------------------------------------------------------local function wlHelpPage(sSection, sLabel)local sHelpPage = 'Template:GHS phrases' if sLabel

nil then sLabel = sSection end if (sLabel or )

then sLabel = else sLabel = '|' .. sLabel end if (sSection or )

then sSection = else sSection = '#' .. sSection end return '' .. sHelpPage .. sSection .. sLabel .. ''end

---------------------------------------------------------------------------------- addErrorCategory---- Formats as -- or when in other namespace.-- sCatsort option using: H, P, _--------------------------------------------------------------------------------local function addErrorCategory(sCatsort)local pagetype = require('Module:Pagetype').main local wlErrCat = if pagetype

'article' then -- mainspace only if sCatsort

nil then sCatsort = tArgName['setID'] end if sCatsort

then wlErrCat = '' else wlErrCat = '' end else return end

table.insert(tMessagesToShow, wlErrCat) returnend

---------------------------------------------------------------------------------- addWarningCategory---- Formats as -- mainspace only, or when in other namespace.-- sCatsort option using: H, P, U, ?, D, O--------------------------------------------------------------------------------local function addWarningCategory(sCatsort)local pagetype = require('Module:Pagetype').mainif sCatsort

nil then sCatsort = tArgName['setID'] end local wlWarnCat = if pagetype

'article' then -- mainspace only if sCatsort

then wlWarnCat = '' else wlWarnCat = '' end else return end

table.insert(tMessagesToShow, wlWarnCat) returnend

---------------------------------------------------------------------------------- addPreviewMsg--------------------------------------------------------------------------------local function addPreviewMsg(sMsg)local previewWarn = require('Module:If preview')._warning table.insert(tMessagesToShow, previewWarn) returnend

---------------------------------------------------------------------------------- showPreviewMsg---- show table tMessagesToShow-- preview-messages and errorcat-- all namespaces--------------------------------------------------------------------------------local function showPreviewMsg if tTools.size(tMessagesToShow) > 0 then return table.concat(tMessagesToShow, ) else return endend

---------------------------------------------------------------------------------- applyRemoveDuplicates---- returns edited table, with double Codes removed-- adds warning with codes.-- base table tArgs is walked through by a iwalker that reads a singel code,-- then a ikiller checks the upward part of the same table to delete all copies-- ikiller starts at end of table, walks towards iwalker; then tArgs is compressed-- iwalker steps 1 up in the freshly compressed table-- Used: iArgs is sorted, and order stays same. compress does not change that.--------------------------------------------------------------------------------local function applyRemoveDuplicates(tArgs)local iR, iK -- iR = reader, iK = killerlocal hit = false

iR = 1 while iR < #tArgs do iK = #tArgs -- will be counting downwards while iK > iR do if tArgs[iK]

tArgs[iR] then hit = true addPreviewMsg('Duplicate removed: ' .. tArgs[iR]) table.remove(tArgs, iK) tTools.compressSparseArray(tArgs) end iK = iK - 1 end tTools.compressSparseArray(tArgs) iR = iR + 1 end

if hit then addWarningCategory('D') end return tArgsend

---------------------------------------------------------------------------------- applyOmitRules---- returns edited table, with Omit phraseID's removed-- Omit rule is per GHS_Rev9E_0.pdf (2021)--------------------------------------------------------------------------------local function applyOmitRules(tArgs)local tRules = GHSdata['tOmitRules'] local hit = false for keep, omit in pairs(tRules) do if tTools.inArray(tArgs, omit) then if tTools.inArray(tArgs, keep) then hit = true for i, k in pairs(tArgs) do if k

omit then table.remove(tArgs, i) end end addPreviewMsg(wlHelpPage('Omit Rules') .. ': keep ' .. keep .. ', omit ' .. omit) end end end if hit then tTools.compressSparseArray(tArgs) addWarningCategory('O') end return tArgsend

---------------------------------------------------------------------------------- label H-phrases or P-phrases--------------------------------------------------------------------------------local function PHlabel if tArgName['setID']

'GHS' then return 'GHS phrases' else return tArgName['setID'] .. '-phrases' endend

---------------------------------------------------------------------------------- inMono---- Use mono font-family (from: Template:Mono)--------------------------------------------------------------------------------local function inMono(s) if s

nil then s = end return '

' .. s .. ''end

---------------------------------------------------------------------------------- wlInlineTag---- Returns [?] with wikilink to errormessage--------------------------------------------------------------------------------local function wlInlineTag(phraseID) local sMsg sMsg = '

[' .. wlHelpPage(PHlabel, '?') .. ']' return sMsgend

---------------------------------------------------------------------------------- errorPhraseIDnotFound---- Returns single value when error (not found in list):-- plain value + inline warning [?] (linked) + error cat (mainsp) + preview warning--------------------------------------------------------------------------------local function errorPhraseIDnotFound(phraseID) if phraseID

nil then phraseID = end local inlineTag = wlInlineTag(phraseID) local previewMsg = wlHelpPage(PHlabel) .. ': \"' .. phraseID .. '\" not found' addPreviewMsg(previewMsg) addErrorCategory return phraseID .. inlineTagend

---------------------------------------------------------------------------------- errorHPsetIDnotFound---- setID H or P could not be found--------------------------------------------------------------------------------local function errorHPsetIDnotFound local sMsg sMsg = wlHelpPage(, PHlabel) .. ': "H" or "P" set id not found' .. ' (please use form like "|H200" or "|P300+P301")' addPreviewMsg(sMsg) addErrorCategory('?') return showPreviewMsgend

---------------------------------------------------------------------------------- errorHPsetIDmissing---- parameter |setid= to be used--------------------------------------------------------------------------------local function errorHPsetIDmissing local sMsg sMsg = wlHelpPage(, PHlabel) .. ': "H" or "P" set id not found,' .. ' please use |setid=... (H or P)' addPreviewMsg(sMsg) returnend

---------------------------------------------------------------------------------- formatPhraseAbbr---- format phraseID and text, for abbr-form (infobox list form)--------------------------------------------------------------------------------local function formatPhraseAbbr(phraseID, sPhrase) return '' .. phraseID .. ''end

---------------------------------------------------------------------------------- formatPhraseInline---- format phraseID and text, for inline form (in sentence)-- adds "quotes"--------------------------------------------------------------------------------local function formatPhraseInline(phraseID, sPhrase) return inMono(phraseID) .. ': \"' .. sPhrase .. '\"'end

---------------------------------------------------------------------------------- formatPhraseList---- as inline, but no "quotes" added.--------------------------------------------------------------------------------local function formatPhraseList(phraseID, sPhrase) return inMono(phraseID) .. ': ' .. sPhraseend

---------------------------------------------------------------------------------- getSetID---- Determines setID (expected either 'H' or 'P')-- First route is: read |setid=-- When |setid= is not set, -- it looks for a first parameter that has an H of P prefix (in |P201|P202|...)-- when not found, 'GHS' is retured-- In one call, P and H numbers can *not* be mixed-- so "|H201|P202|" will cause error "P202 not found" (... in H-list)--------------------------------------------------------------------------------local function getSetID(tArgs) local setIDfound = 'GHS' local paramsetID = tArgs['setid'] or nil if (paramsetID ~= nil) and (paramsetID

'P' or paramsetID

'H') then setIDfound = paramsetID else local initial = nil for i, v in ipairs(tArgs) do initial = mw.ustring.match(v, '^[PH]') if initial ~=nil then setIDfound = initial break end end end return setIDfoundend

---------------------------------------------------------------------------------- getListType---- Checks list format, including those from Module:List--------------------------------------------------------------------------------local function getListType(tArgs) local listTypes = local sListType = tArgs['listtype'] or 'abbr'

if sListType

or sListType

'abbr' then return 'abbr' elseif listTypes[sListType]

true then if sListType

'horizontal ordered' then sListType = 'horizontal_ordered' end return sListType else sListType = 'abbr' end return sListTypeend

---------------------------------------------------------------------------------- getDoOmitRules--------------------------------------------------------------------------------local function getDoOmitRules(tArgs) local b = yesno(tArgs['omit'], true) if b

nil then b = true end

return yesno(b, true)end

---------------------------------------------------------------------------------- prepareArgs---- First: determine setID (from |setID= OR from prefixes in parameters)-- Then: clean up & format phrase IDs (=unnamed parameters)-- remove bad characters, create H/P pattern "H201", "P310+P302"-- straight array, no nil's, sorted--------------------------------------------------------------------------------local function prepareArgs(tArgs)

tArgName['setID'] = getSetID(tArgs) tArgName['listtype'] = getListType(tArgs) tArgName['omit'] = getDoOmitRules(tArgs)

tArgs = tTools.compressSparseArray(tArgs) -- removes all named args if string.len(tArgName['setID'])

1 and #tArgs > 0 then for i, v in ipairs(tArgs) do v = mw.text.decode(v) v = mw.ustring.gsub(v, '[^%d%+A-Za-z]', ) v = mw.ustring.gsub(v, '^(%d)', tArgName['setID'] .. '%1') v = mw.ustring.gsub(v, '%+(%d)', '+' .. tArgName['setID'] .. '%1') tArgs[i] = v end table.sort(tArgs) end return tArgsend

---------------------------------------------------------------------------------- listAll---- Returns wikitable rows for each phrase id.-- requires |setID=P/H-- returns full list, all phrases, for a setID-- 2-columns wikitable, sorted, sortable, anchor like "H201" for each--------------------------------------------------------------------------------function r.listAll(frame)local newArgs = getArgs(frame)local tL =

prepareArgs(newArgs) local tRead if tArgName['setID']

'H' then tRead = GHSdata['Hphrases'] elseif tArgName['setID']

'P' then tRead = GHSdata['Pphrases'] else errorHPsetIDmissing return showPreviewMsg end

-- Intermediate table t2 to maintain order; read from original table (/data) local t2 = local iPh for s, v in pairs(tRead) do iPh = tonumber(mw.ustring.match(s, '[PH](%d%d%d)')) if string.len(s) > 4 then iPh = tTools.size(t2) + 1 end table.insert(t2, iPh, s) end t2 = tTools.compressSparseArray(t2) table.sort(t2)

local sTR, v, sAnchor -- i = array index, s = phraseID, v = phrase text for i, s in ipairs(t2) do v = tRead[s] sAnchor = '

' sTR = '|- ' .. sAnchor .. '\n| datasortvalue="' .. i .. '" | ' .. s .. ' || ' .. v table.insert(tL, sTR) end

return table.concat(tL, '\n')end

---------------------------------------------------------------------------------- numberOfPhrases---- Documentation-- requires |setID=H/P-- Returns number of phrases, in format-- "GHS H-phrases (123)"--------------------------------------------------------------------------------function r.numberOfPhrases(frame) local newArgs = getArgs(frame)

prepareArgs(newArgs)

local iT if tArgName['setID']

'H' then iT = tTools.size(GHSdata['Hphrases']) elseif tArgName['setID']

'P' then iT = tTools.size(GHSdata['Pphrases']) else errorHPsetIDmissing return showPreviewMsg end

return 'GHS ' .. PHlabel .. '

(' .. tostring(iT) .. ')'end

---------------------------------------------------------------------------------- listOmitRules---- self-documentation--------------------------------------------------------------------------------function r.listOmitRuleslocal tRules = GHSdata['tOmitRules']local tL = local s

s = wlHelpPage('Omit Rules') .. ': when the keep ID is present, do not show the omit ID phrase' table.insert(tL, s) for keep, omit in pairs (tRules) do s = '• keep ' .. inMono(keep) .. ', omit ' .. inMono(omit) table.insert(tL, s) end return table.concat(tL, '
')end

---------------------------------------------------------------------------------- _main---- processes setID (H, P) and phrase codes-- error: setID not P, H-- code not found-- cannot mix H and P phrases-- reads phrases from /data H or P phrases tables-- formats phrase (abbreviation, abbr-title, phraseID)--------------------------------------------------------------------------------function r._main(tArgs)

tArgs = prepareArgs(tArgs) if #tArgs

0 then return showPreviewMsg -- no content elseif tArgName['setID']

'GHS' then return errorHPsetIDnotFound end

tArgs = applyRemoveDuplicates(tArgs) if tArgName['omit'] then tArgs = applyOmitRules(tArgs) end

local formatterF if tArgName['listtype']

'abbr' then formatterF = formatPhraseAbbr elseif tArgName['listtype']

'inline' then formatterF = formatPhraseInline else --- Module:List options formatterF = formatPhraseList end local tReadD = if tArgName['setID']

'H' then tReadD = GHSdata['Hphrases'] elseif tArgName['setID']

'P' then tReadD = GHSdata['Pphrases'] else return showPreviewMsg end

local sPhrase local tR = for i, v in ipairs(tArgs) do sPhrase = tReadD[v] if sPhrase

nil then table.insert(tR, errorPhraseIDnotFound(tostring(v))) else table.insert(tR, formatterF(v, sPhrase)) end end

if tArgName['listtype']

'abbr' then return table.concat(tR, ', ') .. showPreviewMsg elseif tArgName['listtype']

'inline' then return table.concat(tR, ', ') .. showPreviewMsg else local mList = require('Module:List') return mList[tArgName['listtype']](tR) .. showPreviewMsg endend

---------------------------------------------------------------------------------- main---- handles template input frame, then calls generic _main function-- To be invoked from --------------------------------------------------------------------------------function r.main(frame)local newArgs = getArgs(frame) return r._main(newArgs) end

return r