Jump to content

Module:Convert/show

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Johnuniq (talk | contribs) at 03:53, 28 October 2013 (nowiki tags need fiddling). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

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

local function collection()
    -- Return a table to hold items.
    return {
        n = 0,
        add = function (self, item)
            self.n = self.n + 1
            self[self.n] = item
        end,
        join = function (self, sep)
            return table.concat(self, sep)
        end,
    }
end

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

local function frame(self_args, parent_args)
    -- Simulate enough of a MediaWiki module frame for convert.
     return {
        args = self_args,
        parent = parent_args and frame(parent_args, nil),
        getParent = function (self) return self.parent end,
    }
end

local cvt_function
local function call_convert(args)
    if not cvt_function then
        -- A testing program can set the global variable 'is_test_run'.
        cvt_function = require(is_test_run and 'convert' or 'Module:Convert').convert
    end
    return cvt_function(frame({}, args))
end

local function maketable(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()
        row:add(ucode)
        local args = { '1', ucode, abbr = 'on', disp = 'unit' }
        row:add(call_convert(args))
        args.abbr = 'off'
        local name1 = call_convert(args)
        row:add(name1)
        args.sp = 'us'
        local name1_us = call_convert(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 common_units = {
    ["Area"] = {
        heading = "Area",
	examples = { "1.5|sqmi|km2", "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=on" },
        "km/L",
        "mpgimp",
        "mpgus",
        "L/km",
        "L/100 km",
    },
    ["Length"] = {
        heading = "Length",
	examples = { "123|cm|in", "123|cm|in|sp=us|abbr=off", "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=on" },
        "g",
        "kg",
        "oz",
        "lb",
        "st",
        "LT",
        "MT",
        "ST",
    },
    ["Pressure"] = {
        heading = "Pressure",
	examples = { "28|psi|Pa", "28|psi|Pa|abbr=on" },
        "atm",
        "mbar",
        "psi",
        "Pa",
    },
    ["Speed"] = {
        heading = "Speed",
	examples = { "60|mph|km/h", "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=on", "12.5|Nm|lb.in|abbr=on|lk=on" },
        "lb.in",
        "lb.ft",
        "Nm",
    },
    ["Volume"] = {
        heading = "Volume",
	examples = { "125|cuin|l", "125|cuin|l", "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 common_sections = {
    "Area",
    "Fuel efficiency",
    "Length",
    "Mass",
    "Pressure",
    "Speed",
    "Temperature",
    "Torque",
    "Volume",
}

local function _show_examples(results, examples, want_table)
    local fmt
    if want_table then
        results:add('{|')
        fmt = '|<code>%s</code>|| → ||%s'
    else
        fmt = '*<code>%s</code> → %s'
    end
    for i, item in ipairs(examples) do
        if want_table and i > 1 then
            results:add('|-')
        end
        item = item:gsub('!', '|')
        item = '{{convert/sandboxlua' .. (item:sub(1, 1) == '|' and '' or '|') .. item .. '}}'
        results:add(fmt:format(mw.text.nowiki(item), item))
    end
    if want_table then
        results:add('|}')
    end
end

local function _show_units(results, args)
    local do_full
    if args[1] == nil then
        do_full = true
        args = common_sections
    end
    local group = collection()
    for _, item in ipairs(args) do
        local units = common_units[item] or common_units[item:sub(1, 1):upper() .. item:sub(2)]
        if units then
            if group.n > 0 then
                maketable(results, group)
                group = collection()
            end
            if do_full then
                if units.heading then
                    results:add('===' .. units.heading .. '===')
                end
                if units.examples then
                    results:add('Examples:')
                    _show_examples(results, units.examples)
                end
            end
            maketable(results, units)
        else
            group:add(item)
        end
    end
    if group.n > 0 then
        maketable(results, group)
    end
end

local function show_examples(frame, want_table)
    local results = collection()
    local ok, msg = pcall(_show_examples, results, frame.args, want_table)
    if ok then
        return results:join('\n') .. '\n'
    end
    return '<strong class="error">Error</strong>\n' .. msg
end

local function show_units(frame)
    local results = collection()
    local ok, msg = pcall(_show_units, results, frame.args)
    if ok then
        return results:join('\n') .. '\n'
    end
    return '<strong class="error">Error</strong>\n' .. msg
end

return {
    unit = show_units,
    units = show_units,
    ['list'] = function (frame) return show_examples(frame, false) end,
    ['table'] = function (frame) return show_examples(frame, true) end,
}