Module:Archive list

local dts = require('Module:User:Anomie/deepToString').deepToString -- for debugging

local p = {}

-- Checks whether a page exists, going through pcall -- in case we are over the expensive function limit. local function checkPageExists( title ) if not title then error('No title passed to checkArchiveExists', 2) end local noError, titleObject = pcall(mw.title.new, title) if not noError then -- If we are over the expensive function limit then assume -- that the page doesn't exist. return false else return titleObject.exists end end

-- Checks every nth archive to see if it exists, and returns the -- number of the first archive that *doesn't* exist. It is -- necessary to do this in batches because each check is an -- expensive function call, and we want to avoid making too many -- of them so as not to go over the expensive function limit. local function checkArchives( prefix, n, start ) local i = start local exists = true while exists do       exists = checkPageExists( prefix .. tostring( i ) ) if exists then i = i + n       end end return i end

-- Return the biggest archive number, using checkArchives -- and starting in intervals of 1000. This should get us a -- maximum of 500,000 possible archives before we hit the -- expensive function limit. local function getBiggestArchiveNum( prefix ) local check1000 = checkArchives( prefix, 1000, 1 ) if check1000 == 1 then return false -- Return false if no archives were found. end local check200 = checkArchives( prefix, 200, check1000 - 1000 ) local check50 = checkArchives( prefix, 50, check200 - 200 ) local check10 = checkArchives( prefix, 10, check50 - 50 ) local check1 = checkArchives( prefix, 1, check10 - 10 ) -- check1 is the first page that doesn't exist, so we want to   -- subtract it by one to find the biggest existing archive. return check1 - 1 end

local function _main( args ) -- Use current page if no root value root = args.root or mw.title.getCurrentTitle.prefixedText local prefix = root .. '/Archive ' local archiveMax = getBiggestArchiveNum( prefix ) -- Get the number of archives to put on one line. False -- if there should be no line breaks. local links = tonumber( args.links ) local lineNum if args.nobr == 'yes' then lineNum = false elseif type(links) == 'number' and links > 0 and math.floor(links) == links then lineNum = links else lineNum = 10 end -- If there are no archives yet, return a message and a   -- link to create Archive one. if not lineNum then return 'no archives yet (create)' end -- Generate the archive links. local lineCounter = 1 -- The counter to see whether we need a line break or not. local ret = '' -- The string to return. for archiveNum = 1, archiveMax do       ret = ret ..  .. tostring(archiveNum) ..  -- If we don't need a new line, output a comma. We don't need -- a comma after the last link. if lineCounter < lineNum and archiveNum < archiveMax then ret = ret .. ', '           lineCounter = lineCounter + 1 -- Output new lines if needed. We don't need a new line after -- the last link. elseif lineCounter >= lineNum and archiveNum < archiveMax then ret = ret .. ' '           lineCounter = 1 end end return ret end

function p.main( frame ) -- If we are being called from #invoke, get the args from #invoke -- if they exist, or else get the arguments passed to the parent -- frame. Otherwise, assume the arguments are being passed directly -- in from another module or from the debug console. local origArgs if frame == mw.getCurrentFrame then origArgs = frame:getParent.args for k, v in pairs( frame.args ) do           origArgs = frame.args break end else origArgs = frame end -- Trim whitespace from all arguments, and ignore blank values for -- parameters other than "links", which functions differently -- depending on whether it is blank or absent. local args = {} for k, v in pairs( origArgs ) do       v = mw.text.trim(v) -- Trim whitespace. if k == 'links' or v ~= '' then args[k] = v       end end return _main( args ) end

return p