Module:Convert: Difference between revisions

Content deleted Content added
fix some rounding problems; fix span to match current expected output; implement range aliases and add a couple more ranges
implement composite input units like "|2|ft|6|in"
Line 267:
-- Parameter 'what' determines whether combination units are accepted:
-- 'no_combination' : single unit only
-- 'any_combination' : single unit or combination or output multiple
-- 'only_multiple' : single unit or output multiple only
-- Parameter unitcode is a symbol (like 'g'), with an optional SI prefix (like 'kg').
-- If, for example, 'kg' is in this table, that entry is used;
-- otherwise the prefix ('k') is applied to the base unit ('g').
-- If unitcode is a known combination code (and if allowed by what),
-- a table of output multiple unit tables is included in the result.
-- For compatibility with the old template, underscores in unitcode are replaced
-- with spaces so {{convert|350|board_feet}} --> 350 board feet (0.83 m³).
Line 727:
local invalid = { 'cvt_bad_num', 'cvt_bad_num2' }
 
local function extract_number(args, indextext, which)
-- Return true, info if can extract a number from the text in args[index],
-- where info is a table with the result,
-- or return false, t where t is an error message table.
Line 750:
-- TODO Think about fact that the input value might be like 1.23e+123.
-- Will the exponent break anything?
local text = strip(args[index]text)
if text == nil or text == '' then return false, { missing[which] } end
local clean, sign
Line 848:
args[k] = v
end
success, info1 = extract_number(args, [1], 1)
if not success then return false, info1 end
local in_unit, precision
Line 859:
args.range = range
args.is_range_x = range.is_range_x
success, info2 = extract_number(args, [3], 2)
if not success then return false, info2 end
in_unit = strip(args[4])
Line 879:
in_unit_table.valinfo = { info1, info2 } -- info2 is nil if no range
in_unit_table.inout = 'in' -- this is an input unit
if not range then
local subdivs = in_unit_table.subdivs -- nil or a table of allowed subdivisions
if subdivs then
-- Look for a composite input unit like "|2|ft|6|in".
local subcode = strip(args[i + 1])
local subdiv = subdivs[subcode]
if subdiv then
-- subcode = unit code of a valid subdivision of main unit,
-- but it can be replaced by the optional subdiv[3].
local success, subunit, subinfo
success, subunit = lookup(subdiv[3] or subcode, args.sp, 'no_combination')
if not success then return false, subunit end -- should never occur
success, subinfo = extract_number(args[i], 1)
if not success then return false, subinfo end
i = i + 2
subunit.inout = 'in'
subunit.valinfo = { subinfo }
-- Calculate total value as a number of subdivisions.
-- subdiv[1] = number of subdivisions per main unit (integer > 1).
local total = info1.value * subdiv[1] + subinfo.value
in_unit_table = {
utype = in_unit_table.utype,
scale = subunit.scale,
default = subdiv[2] or in_unit_table.default,
valinfo = { { value = total, clean = subinfo.clean } },
composite = { in_unit_table, subunit },
}
end
end
end
next = strip(args[i])
i = i + 1
Line 1,417 ⟶ 1,447:
-- Processing required once per conversion.
-- Return block of text to represent input (value/unit).
local id1, want_name = make_id(parms, 1, in_current)
local extra = ''
local result
local adj = parms.adj
local disp = parms.disp
if disp == 'output only' or
disp == 'output number only' or disp == 'number' or
disp == 'u2' or disp == 'unit2' then
result = ''
parms.joins = { '', '' }
elseif disp == 'unit' then
if adj == 'on' then
result = hyphenated(id1)
else
result = id1
end
parms.joins = { '', '' }
return ''
end
local first_unit, second_unit
local composite = in_current.composite -- nil or table of units
if composite then
first_unit = composite[1]
second_unit = composite[2]
else
local sepfirst_unit = in_current.sep
end
local abbr = parms.abbr
local id1, local moswant_name = make_id(abbrparms, ==1, 'mos'first_unit)
if disp == 'unit' then
local range = parms.range
parms.joins = { '', '' }
local id = (range == nil) and id1 or make_id(parms, 2, in_current)
if id ~= ''composite then
if adjid1 == id1 .. 'on ' then.. make_id(parms, 1, second_unit)
end
mos = false -- if hyphenated, suppress repeat of unit in a range
if extraparms.adj == '-on' .. hyphenated(id) .. parms.midthen
return hyphenated(id1)
end
return id1
end
local abbr = parms.abbr
if disp == nil then -- special case for the most common setting
parms.joins = disp_joins['b']
elseif disp ~= 'x' then
-- Old template does this.
if disp == 'slash' then
if parms.abbr_org == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
extradisp = sep .. id'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
parms.joins = disp_joins[disp] or disp_joins['b']
local valinfo = in_current.valinfo
end
if range == nil then
if composite then
decorate_value(parms, in_current, 1)
-- Simplify: assume that adj is off, and there is no range, and no decoration.
result = valinfo[1].show
return first_unit.valinfo[1].show .. ' ' .. id1 .. ' ' ..
second_unit.valinfo[1].show .. ' ' .. (make_id(parms, 1, second_unit))
end
local result
local extra = ''
local sep = first_unit.sep
local mos = (abbr == 'mos')
local range = parms.range
local id = (range == nil) and id1 or make_id(parms, 2, first_unit)
if id ~= '' then
if parms.adj == 'on' then
mos = false -- if hyphenated, suppress repeat of unit in a range
extra = '-' .. hyphenated(id) .. parms.mid
else
local rtextextra = range[1]sep .. id
end
if type(rtext) == 'table' then
end
rtext = rtext[abbr] or rtext['off']
local valinfo = first_unit.valinfo
end
if range == if mosnil then
decorate_value(parms, first_unit, 1)
result = valinfo[1].show
else
local rtext = range[1]
if type(rtext) == 'table' then
rtext = rtext[abbr] or rtext['off']
end
if mos then
decorate_value(parms, in_current, 1)
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. sep .. id1 .. rtext .. valinfo[2].show
elseif parms.is_range_x and not want_name then
if abbr == 'in' or abbr == 'on' then
decorate_value(parms, in_current, 1)
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. sep .. id1 .. rtext .. valinfo[2].show
elseif parms.is_range_x and not want_name then
if abbr == 'in' or abbr == 'on' then
decorate_value(parms, in_current, 1)
end
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. sep .. id .. rtext .. valinfo[2].show
else
if abbr == 'in' or abbr == 'on' then
decorate_value(parms, in_current, 1)
end
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. rtext .. valinfo[2].show
end
decorate_value(parms, in_current, 2)
end
if disp == nil thenresult = valinfo[1].show --.. specialsep case.. forid the.. mostrtext common.. settingvalinfo[2].show
else
parms.joins = disp_joins['b']
elseif disp ~ if abbr == 'in' or abbr == 'xon' then
-- Old template does this.decorate_value(parms, in_current, 1)
if disp == 'slash' then
if parms.abbr_org == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
disp = 'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
decorate_value(parms.joins, =in_current, disp_joins[disp] or disp_joins['b']2)
result = valinfo[1].show .. rtext .. valinfo[2].show
end
end
Line 1,549 ⟶ 1,593:
end
 
local function make_output_single(parms, info, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for a single output (which is not a combination or a multiple);
-- or return false, t where t is an error message table.
local success, info1, info2
success,local info1valinfo = cvtround(parms, info[1], in_unit_table, out_unit_table).valinfo
success, info1 = cvtround(parms, valinfo[1], in_unit_table, out_unit_table)
if not success then return false, info1 end
success, info2 = cvtround(parms, infovalinfo[2], in_unit_table, out_unit_table)
if not success then return false, info2 end
out_unit_table.valinfo = { info1, info2 }
Line 1,562 ⟶ 1,607:
end
 
local function make_output_multiple(parms, info, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for an output which is a multiple (like 'ftin');
Line 1,624 ⟶ 1,669:
return sign .. table.concat(reversed, ' ')
end
local resultvalinfo = make_result(info[1])in_unit_table.valinfo
local result = make_result(valinfo[1])
local range = parms.range
if range then
Line 1,631 ⟶ 1,677:
rtext = rtext[abbr] or rtext['on']
end
result = result .. rtext .. make_result(infovalinfo[2])
end
return true, result
Line 1,640 ⟶ 1,686:
-- or return false, t where t is an error message table.
local success, out_unit_table
local infoinvalue1 = in_unit_table.valinfo[1].value
local invalue1 = info[1].value
local out_unit = parms.out_unit
if out_unit == nil or out_unit == '' then
Line 1,663 ⟶ 1,708:
out_current.inout = 'out'
if out_current.multiple == nil then
success, item = make_output_single(parms, info, in_unit_table, out_current)
else
success, item = make_output_multiple(parms, info, in_unit_table, out_current)
end
if not success then return false, item end