Module:Soundtrack

-- Functions for Template:Infobox music --

local p = {}; -- Soundtrack Package

-- --[==[ Modules ]==]-- local getArgs = require("Dev:Arguments").getArgs; local ostList = mw.loadData "Module:Soundtrack/OST List"; -- read-only, psuedo-table, use pairs and *not* next local userError = require "Dev:User error";

--[==[ Global Functions ]==]-- -- A wrapper function that will catch uny uncaught errors in func and will display the error to the editor function nag_wrap(func) return function(...) local results = { pcall(func, ...) }; local success = results[1]; table.remove(results, 1); -- remove success arg from results if success then return unpack(results); else return userError(results[1], "Pages with script errors"); end end end

-- Returns whether the % (force article name) sentinel is appended to the name, and returns the real article name -- For cases such as "Home (Music box)" function isNameForced(name, onlyFrm) local frmName,forced = name:gsub("%%$",''); forced = forced > 0; if onlyFrm then -- Returns only the formatted name return frmName; else return forced, frmName; end end

-- Creates a MediaWiki link function formatLink(name, link) local nameForced,name = isNameForced(name); local link = nameForced and name or link; return (link == name or (not link)) and "" .. name .. "" or "' .. name .. ""; end

-- "Shorthand" function to check all OSTs -- May ultimately diminish readability by running loop in another func, but... function chkOST(func) for ost,list in pairs(ostList) do       func(ost, list); end end

--[==[ Module Functions ]==]-- -- Gets track name from raw article name -- e.g. "Alphys (track)" -> "Alphys" function p.getFrmTrack(articleName) return articleName:gsub("%s*%b$", ""); end

-- Gets track's index in track list from frame function p.getListing(frame) local rTrack = getArgs(frame)[1]; -- Raw track name (article) assert(type(rTrack) == "string", "The first positional argument is a " .. type(rTrack) .. ". (Expected string)"); -- error local trackNum = {}; -- to hold the track number(s) local multiOST = 0; -- a counter of the number of OSTs the soundtrack is present in    chkOST(function(ost, list)        -- Perform a linear search        for i,name in pairs(list) do            if isNameForced(name, true):lower == rTrack:lower then                -- Track found                trackNum[ost] = i;                multiOST = multiOST + 1;                break; -- only breaks the inner-most loop            end        end    end) assert(next(trackNum), "This article is not a valid soundtrack page"); -- error return trackNum, multiOST > 1; end

-- wrapper function p.incr_track_wrapper = function(incr) return function(frame) local str = "";        -- hold the sequential track info local trackPresent = {} -- holds keys of tracks and string vals regarding which OST lists the track as present local trackCount = 0;  -- counter for number of tracks to be returned local indices,multiOST = p.getListing(frame); -- Get sequential track information chkOST(function(ost, list)           local rTrack = indices[ost] and list[indices[ost]+ incr]; -- raw track name            if rTrack then                trackCount = trackCount + (trackPresent[rTrack] and 0 or 1); -- increment                trackPresent[rTrack] = (trackPresent[rTrack] or "") .. ost .. " + ";            end        end) -- Generate string for rTrack,info in pairs(trackPresent) do           str = str .. formatLink(p.getFrmTrack(rTrack), rTrack) .. " (" .. info:sub(1, -4) .. ")\n"; end return trackCount == 1 and p.getFrmTrack(str:sub(1, -2)) or str:sub(1, -2); end end

p.next_track = nag_wrap(p.incr_track_wrapper( 1)); p.prev_track = nag_wrap(p.incr_track_wrapper(-1));

-- Returns the names of the albums that the current track (current article) belongs in p.get_albums = function(frame) local albums = p.getListing(frame); local str = ""; for ost in pairs(albums) do       str = str .. formatLink(ost) .. '\n'; end return str; end

-- Changes the title of articles (do not implement, goes against canonicalization) -- e.g. "Alphys (track)" -> "Alphys" p.frm_article_title = function(frame) --[[   local title = getArgs(frame)[1]; -- article's title    local whitelisted = false; -- flag to indicate article's "whitelist" status    assert(type(title) == "string", "The first positional argument is a " .. type(title) .. ". (Expected string)"); -- error    local trackName,frm = p.getFrmTrack(title);    if frm == 0 then return''; end; -- title is already formatted    -- Check if article is "whitelisted" (w/ sentinel)    chkOST(function(_,list)        for _,articleName in pairs(list) do            local forced,frmName = isNameForced(articleName);            if forced and frmName == title then                whitelisted = true;                return; -- terminate all loops            end        end    end)

if whitelisted then return''; end; -- whitelisted from title formatting return ""; -- this does not work in the parser, find a different solution --]] end

return p;