Module:Convert/show

-- Prepare tables of wikitext to display simple documentation about -- specified units. Data is obtained by calling Module:Convert. -- Also provides a function to show convert usage examples.

local Collection -- a table to hold items Collection = { add = function (self, item) if item ~= nil then self.n = self.n + 1 self[self.n] = item end end, join = function (self, sep) return table.concat(self, sep) end, remove = function (self, pos) if self.n > 0 and (pos == nil or (0 < pos and pos <= self.n)) then self.n = self.n - 1 return table.remove(self, pos) end end, sort = function (self, comp) table.sort(self, comp) end, new = function return setmetatable({n = 0}, Collection) end } Collection.__index = Collection

local function strip(text) -- Return text with no leading/trailing whitespace. return text:match("^%s*(.-)%s*$") end

local function fakeFrame(selfArgs, parentArgs) -- Simulate enough of a MediaWiki module frame for convert. -- This is a cheap way to call convert with specified arguments. return { args = selfArgs, parent = parentArgs and fakeFrame(parentArgs, nil), getParent = function (self) return self.parent end, } end

local cvtFunction local function callConvert(args) if not cvtFunction then cvtFunction = require('Module:Convert').convert end return cvtFunction(fakeFrame({}, args)) end

local function makeTable(frame, results, units) results:add('{| class="wikitable"') results:add('! Unit code !! Unit symbol !! Unit name !! US name, if different') for i, ucode in ipairs(units) do		local row = Collection.new row:add(ucode) local args = { '1', ucode, abbr = 'on', disp = 'unit' } row:add(callConvert(args)) args.abbr = 'off' local name1 = callConvert(args) row:add(name1) args.sp = 'us' local name1_us = callConvert(args) if name1_us == name1 then row:add('') else row:add(name1_us) end results:add('|-') results:add(strip('| ' .. row:join(' || '))) end results:add('|}') results:add('') end

-- Commonly used units for main documentation. -- Can only be input units (not combinations or multiples). local commonUnits = { ["Area"] = { heading = "Area", examples = { "1.5|sqmi|km2", "1.5|sqmi|km2|abbr=off", "1.5|sqmi|km2|abbr=on" }, "acre", "ha", "m2", "cm2", "km2", "sqin", "sqft", "sqyd", "sqmi", },	["Fuel efficiency"] = { heading = "Fuel efficiency", examples = { "12|mpgus|km/L", "12|mpgus|km/L|abbr=off", "12|mpgus|km/L|abbr=off|sp=us", "12|mpgus|km/L|abbr=on" }, "km/L", "mpgimp", "mpgus", "L/km", "L/100 km", },	["Length"] = { heading = "Length", examples = { "123|cm|in", "123|cm|in|abbr=off|sp=us", "123|cm|in|abbr=on" }, "uin", "in", "ft", "yd", "mi", "nmi", "m", "cm", "mm", "km", "angstrom", },	["Mass"] = { heading = "Mass", examples = { "72.3|kg|lb", "72.3|kg|lb|abbr=off", "72.3|kg|lb|abbr=on" }, "g", "kg", "oz", "lb", "st", "LT", "MT", "ST", },	["Pressure"] = { heading = "Pressure", examples = { "28|psi|Pa", "28|psi|Pa|abbr=off", "28|psi|Pa|abbr=on" }, "atm", "mbar", "psi", "Pa", },	["Speed"] = { heading = "Speed", examples = { "60|mph|km/h", "60|mph|km/h|abbr=off", "60|mph|km/h|abbr=on" }, "km/h", "km/s", "kn", "mph", },	["Temperature"] = { heading = "Temperature", examples = { "100|C|F", "100|C|F|abbr=off", "100|C-change|F-change", "100|C-change|F-change|abbr=out" }, "C", "F", "K", "C-change", "F-change", "K-change", },	["Torque"] = { heading = "Torque", examples = { "12.5|Nm|lb.in", "12.5|Nm|lb.in|abbr=off", "12.5|Nm|lb.in|abbr=on|lk=on" }, "lb.in", "lb.ft", "Nm", },	["Volume"] = { heading = "Volume", examples = { "125|cuin|l", "125|cuin|l|abbr=off", "125|cuin|l|abbr=on" }, "cuin", "cuft", "cuyd", "cumi", "impgal", "impoz", "usgal", "usoz", "L", "l", "m3", "cc", "mm3", }, }

-- Order in which sections are wanted when doing all common units. local commonSections = { "Area", "Fuel efficiency", "Length", "Mass", "Pressure", "Speed", "Temperature", "Torque", "Volume", }

local function _showExamples(frame, results, examples, wantTable) local fmt if wantTable then results:add('{|') fmt = '| || → ||%s' else fmt = '* → %s' end for i, item in ipairs(examples) do		if wantTable and i > 1 then results:add('|-') end item = item:gsub('!', '|') item = '' results:add(fmt:format(mw.text.nowiki(item), frame:preprocess(item))) end if wantTable then results:add('|}') end end

local function _showLinks(frame, results, args) local sandbox = args[1] == 'sandbox' and '/sandbox' or '' local dataModule = 'Module:Convert/data' .. sandbox local textModule = 'Module:Convert/text' .. sandbox local dataCode = require(dataModule) local textCode = require(textModule) local uniqueLinks = {} local links = Collection.new local function addLink(link) if link and link ~= '' then -- Some items (alias symlink, chainlk symbol) are already linked. -- Therefore, add link syntax if not present, before testing for uniqueness. -- There will be some duplicate targets such as chain + ch. if link:sub(1, 2) ~=  then				link = '[[' .. link .. 			end			if not uniqueLinks[link] then				uniqueLinks[link] = true				links:add(link)			end		end	end	for _, v in ipairs(textCode.customary_units) do		addLink(v.link)	end	for _, v in pairs(dataCode.all_units) do		-- This does not add anything for automatic per units (assuming they do not define a link).		-- That is ok because per unit x/y has link LINK(x)/LINK(y).		if v.symbol and v.symbol:sub(1, 2) == '[[' then			addLink(v.symbol)		end		if v.name1 and v.name1:sub(1, 2) == '[[' then			addLink(v.name1)		end		addLink(v.symlink)		addLink(v.link or v.name1 or (not v.per and not v.target) and v.symbol)	end	for _, v in pairs(dataCode.link_exceptions) do		addLink(v)	end	for _, v in pairs(dataCode.per_unit_fixups) do		if type(v) == 'table' then			addLink(v.link)		end	end	local function comp(a, b)		local la = a:lower(a)		local lb = b:lower(b)		if la == lb then			return a < b		end		return la < lb	end	links:sort(comp)	for _, v in ipairs(links) do		results:add('*' .. v)	end end

local function _showUnits(frame, results, args) local doFull if args[1] == nil then doFull = true args = commonSections end local group = Collection.new for _, item in ipairs(args) do local units = commonUnits[item] or commonUnits[item:sub(1, 1):upper .. item:sub(2)] if units then if group.n > 0 then makeTable(frame, results, group) group = Collection.new end if doFull then if units.heading then results:add('===' .. units.heading .. '===') end if units.examples then results:add('Examples:') _showExamples(frame, results, units.examples) end end makeTable(frame, results, units) else group:add(item) end end if group.n > 0 then makeTable(frame, results, group) end end

local function showExamples(frame, wantTable) local results = Collection.new local ok, msg = pcall(_showExamples, frame, results, frame.args, wantTable) if ok then return results:join('\n') end return ' Error \n' .. msg end

local function showLinks(frame) local results = Collection.new local ok, msg = pcall(_showLinks, frame, results, frame.args) if ok then return results:join('\n') end return ' Error \n' .. msg end

local function showUnits(frame) local results = Collection.new local ok, msg = pcall(_showUnits, frame, results, frame.args) if ok then return results:join('\n') end return ' Error \n' .. msg end

return { links = showLinks, unit = showUnits, units = showUnits, ['list'] = function (frame) return showExamples(frame, false) end, ['table'] = function (frame) return showExamples(frame, true) end, }