Module:Convert/show

From blackwiki
< Module:Convert
Revision as of 08:00, 28 October 2013 by blackwiki>Johnuniq (restore: problem is obviously that need)
Jump to navigation Jump to search

This module can be used to prepare tables of wikitext to display simple documentation for specified units. Data is obtained by calling Module:Convert. In addition, the module can be used to show {{convert}} usage examples.

Listing links

See Module talk:Convert/show for a list of unique links for units. The list is shorter and easier to check than the full list of units.

Displaying unit information

The module contains a built-in list of commonly used units. The information at Help:Convert units#Units is the output from:

  • {{#invoke:convert/show|units}}

When no units are specified, the full built-in list of unit codes is used. In addition, the headings and examples defined in the module are displayed.

Units may be specified by entering section names or individual unit codes. No headings or examples are included if units are specified.

For example, one or more sections from the full list can be displayed as in the following examples:

  • {{#invoke:convert/show|units|length}}
  • {{#invoke:convert/show|units|length|mass|area}}

Any "input" unit codes can be specified individually, for example, the following line:

  • {{#invoke:convert/show|units|um|cm|ug|kg}}

gives the result:

Unit code Unit symbol Unit name US name, if different
um μm micrometre micrometer
cm cm centimetre centimeter
ug μg microgram
kg kg kilogram

Only units suitable for use as a conversion input can be used. For example, ftin cannot be used as it is an output unit which displays the result in feet and inches.

Displaying usage examples

The module can display examples of {{convert}} usage in a list or a table. The required parameters must be separated with ! (exclamation mark) rather than the normal | (pipe), and a parameter that includes an equals sign must be prefixed with 1= (for the first parameter), or 2= (for the second), etc.

For example, the following line:

  • {{#invoke:convert/show|list|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}

gives the result:

  • {{convert/sandboxlua|123|cm|in|abbr=on}} → 123 cm (48 in)
  • {{convert/sandboxlua|125|sqft|m2|abbr=off|sp=us}} → 125 square feet (11.6 square meters)

The same information can be displayed in a table.

  • {{#invoke:convert/show|table|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}

gives the result:

{{convert/sandboxlua|123|cm|in|abbr=on}} 123 cm (48 in)
{{convert/sandboxlua|125|sqft|m2|abbr=off|sp=us}} 125 square feet (11.6 square meters)

Substitution

Results from invoking the module can be substituted into the current page, for example:

  • {{subst:#invoke:convert/show|units|length}}
  • {{subst:#invoke:convert/show|table|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}

Substitution may be useful if editing of the resulting wikitext is required.


-- 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 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(frame, 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), frame:preprocess(item)))
    end
    if want_table then
        results:add('|}')
    end
end

local function _show_units(frame, 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(frame, 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, frame, results, frame.args, want_table)
    if ok then
        return results:join('\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, frame, results, frame.args)
    if ok then
        return results:join('\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,
}