User:BrownHairedGirl/Module:FooBarHumMigNav

-- v 10  subpages renamed  testing  - we have output  - portal checking done, but output not working  - full country-checking list is working  - data moved to sub-modules  Now working on fixing countries prefixed by "the"  ToDo in further versions:  * Tracking categories  * error messages  * Tidyup code

-- config local textSize = '90%' local tableClass="toc" local tableFallbackMaxWidth="auto" local tableMaxWidth="calc(100% - 25em)" -- Template:GeoGroup has width: 23em< local tableStyle="margin-left:0; margin-right:auto; clear:left !important; margin-top:0 !important; width:auto; font-weight:normal; " local basicRowStyle="padding:0.3em 0.7em 0.3em 0.3em; vertical-align:top; text-align:left; border-top:1px solid darkgray; " local headerRowStyle="font-weight:normal; text-align:center; background-color:#f3f3f3" local headerCellStyle = "text-align:center; background-color:#f3f3f3;" local evenRowStyle = "" --background-color:#f3f3f3;" local oddRowStyle = "" local footerRowStyle="text-align:center; background-color:#f3f3f3; border-top:1px solid darkgray; " local footerCellStyle = "text-align:center; border-top:1px solid darkgray; background-color:#f3f3f3; " local labelStyle = "text-align:right; font-weight: bold; padding: 0.25em 0.5em 0.25em 0.5em;" local listStyle = "text-align:left; font-weight: normal; padding: 0.25em 0.5em 0.25em 0.5em;" local greyLinkColor = "#888" local defaultPortals = {	"Human migration" }

-- Behaviour switches local portalsEnabled = true local debuggingEnabled = false -- local debuggingEnabled = true

-- globals for this module local debugmsg = "" local tableRowNum = 0 local greyLinkCount = 0 local blueLinkCount = 0 local parentname = "" local templateName local countryName1 = nil local countryName2 = nil local myTrackingCategories = ""

local countryAdjectivesToNounsTable = { } local countryNounstoAdjectivesTable = { }

local countriesPrefixedByThe = { }

-- if the country name is prefixed by "the" in running text, -- then return that prefix -- Otherwise just return an empty string function countryPrefixThe(s) if (countriesPrefixedByThe[s] == true) then return "the " end return "" end

-- other modules local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local p = {}

-- converts first character of a string to uppercase -- while leaving the rest unchanged function firstToUpper(str) return (str:gsub("^%l", string.upper)) end

function makeTrackingCategory -- discount this page, which will always be coded as a blue link, but rendered as bold un-navigable blueLinkCount = blueLinkCount - 1 if greyLinkCount == 0 then return "" end if blueLinkCount == 0 then return "" end if greyLinkCount > 5 then return "" elseif greyLinkCount > 3 then return "" elseif greyLinkCount < 3 then return "" end return "" end

function makeTableRow(rowLabel, countryA, countryB) tableRowNum = tableRowNum + 1 debugLog(3, string.format("makeTableRow #%d", tableRowNum)) local rowLabel = string.format("%s in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB) debugLog(4, "rowLabel=" .. rowLabel) local thisRow if (tableRowNum % 2) == 0 then debugLog(4, "Even-numbered") thisRow = '\n' else debugLog(4, "Odd-numbered") thisRow = '\n' end thisRow = thisRow .. '' .. rowLabel .. ' \n' thisRow = thisRow .. ' \n' -- now begin making the row contents thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s expatriates in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "Expatriates") .. '\n' thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s expatriate sportspeople in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "(sportspeople)") .. ' \n' thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s emigrants to %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "Emigrants") .. '\n' thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s people of %s descent", getAdjectiveFromCountry(countryB), getAdjectiveFromCountry(countryA)), "Descent") .. '\n' local diasporaCatName = string.format("%s diaspora in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB) if (doesPageExist(diasporaCatName, "Category")) then thisRow = thisRow .. '* ' .. makeCatLink(diasporaCatName, "Diaspora") .. '\n' end thisRow = thisRow .. ' \n ' debugLog(4, "Made the row") return thisRow end

function makeTable debugLog(1, "makeTable") debugLog(2, "countryName1=") if (countryName1 == nil) then debugLog(nil, "nil") else debugLog(nil, countryName1) end debugLog(2, "countryName2=") if (countryName2 == nil) then debugLog(nil, "nil") else debugLog(nil, countryName2) end -- sort country names debugLog(2, "checking sort order: ") if (countryName1 <= countryName2) then debugLog(nil, "checking sort order: OK") else debugLog(nil, "checking sort order: need to be swapped") local swapSpace = countryName1 countryName1 = countryName2 countryName2 = swapSpace debugLog(3, "Swapped.: Now countryName1=[%s], and countryName2=[%s]", countryName1, countryName2) end

tableRowNum = 0 local myTable = ' \n"	return myTable end

-- Make a piped link to a category, if it exists -- If it doesn't exist, just display the greyed the link title without linking function makeCatLink(catname, disp) local displaytext if (disp ~= "") and (disp ~= nil) then -- use 'disp' parameter, but strip any trailing disambiguator displaytext = mw.ustring.gsub(disp, "%s+%(.+$", "");	else		displaytext = catname	end	local fmtlink	if (doesPageExist(catname, "Category")) then		fmtlink = "" .. displaytext .. ""		blueLinkCount = blueLinkCount + 1	else		fmtlink = ' ' .. displaytext .. " "		greyLinkCount = greyLinkCount + 1	end

return fmtlink end

function doesPageExist(s, myNamespace) local myTestPage = mw.title.new(s, myNamespace) if (myTestPage.exists) then return true else return false end end

-- ##################### New stuff starts here ################

function getCountryFromAdjective(s) return countryAdjectivesToNounsTable[s] end

function getAdjectiveFromCountry(s) return countryNounstoAdjectivesTable[s] end

function stripThe(s) if s == nil then debugLog(2, string.format("cannot strip a nil value")) return nil end if mw.ustring.match( s, "^[T]he Gambia") ~= nil then return "the Gambia" end debugLog(2, string.format("stripping [%s]", s)) local stripped = mw.ustring.gsub(s, "^[tT]he ", "") if stripped == nil then debugLog(nil, " &rarr; nil") else debugLog(nil, string.format(" &rarr; [%s]", stripped)) end return stripped end

-- semi-patterns -- add explanation local categoryMasks = { ["Fooian people of Barian descent"] = {false, "(.+) people of (.+) descent"}, ["Fooian emigrants to Bar"] = {true, "(.+) emigrants to (.+)"}, ["Fooian expatriates in Bar"] = {true, "(.+) expatriates in (.+)"}, ["Fooian expatriate sportspeople in Bar"] = {true, "(.+) expatriate sportspeople in (.+)"}, ["Fooian diaspora in Bar"] = {true, "(.+) diaspora in (.+)$"} }

-- parse the pagename to find two countyName/countryAdjective pairs -- looks for one of 5 different types of category, -- as defined in categoryMasks{} -- Each of the 5 formats is tested in turn, until a format is found which -- matches the current pagename -- The return value is a string: --   "//success//" = matched a pattern, and built two countyName/countryAdjective pairs --   "//nomatch//" = did not match any pattern --   "//unknown//:sometext" = one of the countrynames or adjectives found in the title --                             was not found in the lookup table --   "//error//" function parsePagename(pn) local splitResult = nil local nmasks = 0 debugLog(1, "parsePagename") debugLog(2, " pn = [" .. pn .."]") for catDescription, maskData in pairs(categoryMasks) do		nmasks = nmasks + 1 debugLog(3, string.format("Mask #%d: catDescription=[%s], isNoun=[%s]  pattern=[%s]", nmasks, catDescription, tostring(maskData[1]), maskData[2])) splitResult = splitPagename(pn, maskData[1], "^" .. maskData[2] .. "$") if splitResult == "//success//" then return splitResult elseif splitResult == "//nomatch//" then -- do nothing. We'l just loop again and try the next mask elseif mw.ustring.match(splitResult, "^//unknown//") then return splitResult else return "//error//unexpected result from splitPagename" end end debugLog(2, "nmasks = ", tonumber(nmasks)) if splitResult == nil then splitResult = "splitResult=nil. Why????" end return splitResult end

function splitPagename(pname, isNoun, pattern) debugLog(4, string.format("splitPagename: pname=[%s], isNoun=[%s], pattern=[%s]", pname, tostring(isNoun), pattern))

if not mw.ustring.match(pname, pattern) then debugLog(5, "no match") return "//nomatch//" end local v1 = mw.ustring.gsub(pname, pattern, "%1") -- extract the "Fooian" athe start of the cat name local v2 = mw.ustring.gsub(pname, pattern, "%2") -- extract the "Foo" or "Fooian" athe start of the cat name debugLog(5, string.format("v1=[%s], v2=[%s]", v1, v2)) countryName1 = getCountryFromAdjective(v1) if countryName1 == nil then return "//unknown//adjective: " .. v1	end if isNoun then countryName2 = v2		countryName2 = stripThe(countryName2) if getAdjectiveFromCountry(countryName2) == nil then return "//unknown//noun: " .. v2		end else countryName2 = getCountryFromAdjective(v2) if countryName2 == nil then return "//unknown//adjective:" .. v2		end end return "//success//" end

-- ###################### END NEWSTUFF ############################################### function publishDebugLog if not debuggingEnabled then return "" end return "==Debugging ==\n\n" .. debugmsg .. "\n== Output ==\n" end

-- debugLog builds a log which can be output if debuging is enabled -- each log entry is given a level, so that the output is not simply a flat list -- a debug msg may be appended to the previous msg by setting the level to nil function debugLog(level, msg)

if (debugmsg == nil) then debugmsg = "" end

if (level ~= nil) then -- not appending, so make a new line debugmsg = debugmsg .. "\n" -- then add the level local i		for i = 1, level do			if (i % 2) == 1 then debugmsg = debugmsg .. "#"			else debugmsg = debugmsg .. "*"			end end end debugmsg = debugmsg .. " " .. msg return true end

function getYesNoParam(args, thisParamName, defaultVal) local paramVal = args[thisParamName] if paramVal == nil then paramVal = "" end

debugLog(2, "Evaluate yes/no parameter: [" .. thisParamName .. "] = [" .. paramVal .. "]") debugLog(3, "default = " .. ((defaultVal and "Yes") or "No")) debugLog(3, "Evaluate as: ") local returnValue if paramVal == "" then returnValue = defaultVal else returnValue = yesno(args[thisParamName], defaultVal) end if (returnValue) then debugLog(nil, "Yes") else debugLog(nil, "No") end return returnValue end

function makeErrorMsg(s) return ' ' .. parentname .. ' Error: ' .. s .. ' \n' end

function p.main(frame) local parent = frame:getParent if parent then parentname = parent:getTitle:gsub('/sandbox$', '') end templateName = mw.ustring.gsub(parentname, "^Template:", "")

-- get the page title debugLog(1, "mw.title.getCurrentTitle") thispage = mw.title.getCurrentTitle thispagename = thispage.text; debugLog(2, "thispage.text = [" .. thispage.text .."]") debugLog(2, "thispage.namespace = [" .. thispage.namespace .."]") debugLog(2, "thispage.nsText = [" .. thispage.nsText .."]") debugLog(2, "is it a cat? using (thispage:inNamespace(14)): ") if not (thispage:inNamespace(14)) then debugLog(nil, "No, this is not a category") debugLog(1, "Not a category, so no output") return makeErrorMsg("only for use on a category page") .. publishDebugLog end debugLog(nil, "Yes, this is a category") debugLog(2, "list categoryMasks") for x, y in ipairs(categoryMasks) do debugLog(3, "[" .. x .. "] = [" .. y .."]") end

debugLog(1, "makeAdjectivesToNounsTable") local nMade = makeAdjectivesToNounsTable debugLog(2, string.format("makeAdjectivesToNounsTable done: %d", nMade)) debugLog(1, "next call parsePagename")

local parseResult = parsePagename(thispagename) debugLog(1, "Parsed"); debugLog(2, string.format("parseResult=%s", parseResult)) debugLog(2, "countries found:") debugLog(3, "countryName1=") if (countryName1 == nil) then debugLog(nil, "nil") parseResult = parseResult .. " but countryName1 is nil" else debugLog(nil, string.format("[%s] .. and adjective = [%s]", countryName1, getAdjectiveFromCountry(countryName1))) end debugLog(3, "countryName2=") if countryName2 == nil then debugLog(nil, "nil") parseResult = parseResult .. " but countryName2 is nil" else debugLog(nil, string.format("[%s] .. and adjective = [%s]", countryName2, getAdjectiveFromCountry(countryName2))) end local myNavTable = ""; local myPortalsBox = "" if (parseResult ~= "//success//") then debugLog(1, "Not a success, so no makeTable") else debugLog(1, "Calling makeTable") myNavTable = makeTable debugLog(1, "Table made") debugLog(2, string.format("Greylinks: %d", greyLinkCount)) debugLog(1, "Making portals") --		myPortalsBox = makePortalBox myPortalsBox = frame:expandTemplate{ title = 'Portal', args = {countryName1, countryName2} } debugLog(2, "Portals done") myTrackingCategories = makeTrackingCategory end return publishDebugLog .. myPortalsBox .. myNavTable .. myTrackingCategories end

function makePortalBox local myPortalsList = "" --" .. countryName1		myPortalsArray[#myPortalsArray + 1] = countryName1	end	if (doesPageExist(countryName2, "Portal")) then		myPortalsList = myPortalsList .. "|" .. countryName2		myPortalsArray[#myPortalsArray + 1] = countryName2	end	local i, v	for i, v in ipairs(defaultPortals) do		if (doesPageExist(v, "Portal")) then			myPortalsList = myPortalsList .. "|" .. v			myPortalsArray[#myPortalsArray + 1] = countryName1		end	end	debugLog(2, string.format("Portal made. myPortalsList = [%s]", myPortalsList))	-- showMyPortals(countryName1, countryName2)	-- showMyPortals(myPortalsArray) myPortalsList = frame:expandTemplate{ title = 'Portal', args = {countryName1, countryName2} } return myPortalsList end

function makeAdjectivesToNounsTable countriesPrefixedByThe = mw.loadData( 'Module:CountryNameDemonym/the' ) countryNounstoAdjectivesTable = mw.loadData( 'Module:CountryNameDemonym/adjectives' ) local myCounter = 0 local myNoun, myAdj for myNoun, myAdj in pairs(countryNounstoAdjectivesTable) do		countryAdjectivesToNounsTable[myAdj] = myNoun myCounter = myCounter + 1 end return myCounter end

return p