Modul:Convert und Modul:Convert/sandbox: Unterschied zwischen den Seiten
Erscheinungsbild
(Unterschied zwischen Seiten)
Inhalt gelöscht Inhalt hinzugefügt
aus engl. Wikipedia, benötigt für Modul Val |
italienische Version als Zwischenschritt zur Übertragung ins Deutsche |
||
Zeile 136: | Zeile 136: | ||
local spell_module -- name of module that can spell numbers |
local spell_module -- name of module that can spell numbers |
||
local speller -- function from that module to handle spelling (set if |
local speller -- function from that module to handle spelling (set if spelling is wanted) |
||
local wikidata_module, wikidata_data_module -- names of Wikidata modules |
|||
local wikidata_code, wikidata_data -- exported tables from those modules (set if needed) |
|||
local function set_config(args) |
local function set_config(args) |
||
Zeile 149: | Zeile 147: | ||
text_module = "Module:Convert/text" .. sandbox |
text_module = "Module:Convert/text" .. sandbox |
||
extra_module = "Module:Convert/extra" .. sandbox |
extra_module = "Module:Convert/extra" .. sandbox |
||
wikidata_module = "Module:Convert/wikidata" .. sandbox |
|||
wikidata_data_module = "Module:Convert/wikidata/data" .. sandbox |
|||
spell_module = "Module:ConvertNumeric" |
spell_module = "Module:ConvertNumeric" |
||
data_code = mw.loadData(data_module) |
data_code = mw.loadData(data_module) |
||
Zeile 259: | Zeile 255: | ||
end |
end |
||
local function wanted_category( |
local function wanted_category(cat) |
||
-- Return |
-- Return cat if it is wanted in current namespace, otherwise return nil. |
||
-- This is so tracking categories only include pages that need correction. |
|||
-- otherwise return ''. |
|||
local cat |
|||
local title = mw.title.getCurrentTitle() |
local title = mw.title.getCurrentTitle() |
||
if title then |
if title then |
||
Zeile 269: | Zeile 264: | ||
for _, v in ipairs(split(config.nscat or nsdefault, ',')) do |
for _, v in ipairs(split(config.nscat or nsdefault, ',')) do |
||
if namespace == tonumber(v) then |
if namespace == tonumber(v) then |
||
return cat |
|||
cat = text_code.all_categories[want_warning and 'warning' or catkey] |
|||
if catsort and catsort ~= '' and cat:sub(-2) == ']]' then |
|||
cat = cat:sub(1, -3) .. '|' .. mw.text.nowiki(usub(catsort, 1, 20)) .. ']]' |
|||
end |
|||
break |
|||
end |
end |
||
end |
end |
||
end |
end |
||
return cat or '' |
|||
end |
end |
||
local function message( |
local function message(mcode) |
||
-- Return wikitext for an error message, including category if specified |
-- Return wikitext for an error message, including category if specified |
||
-- for the message type. |
-- for the message type. |
||
-- mcode = numbered table specifying the message: |
-- mcode = numbered table specifying the message: |
||
-- mcode[1] = 'cvt_xxx' (string used as a key to get message info) |
-- mcode[1] = 'cvt_xxx' (string used as a key to get message info) |
||
-- mcode[2] = 'parm1' (string to replace |
-- mcode[2] = 'parm1' (string to replace first %s if any in message) |
||
-- mcode[3] = 'parm2' (string to replace |
-- mcode[3] = 'parm2' (string to replace second %s if any in message) |
||
-- mcode[4] = 'parm3' (string to replace |
-- mcode[4] = 'parm3' (string to replace third %s if any in message) |
||
local msg |
local msg = text_code.all_messages[mcode[1]] |
||
local nowiki = mw.text.nowiki |
|||
if type(mcode) == 'table' then |
|||
if mcode[1] == 'cvt_no_output' then |
|||
-- Some errors should cause convert to output an empty string, |
|||
-- for example, for an optional field in an infobox. |
|||
return '' |
|||
end |
|||
msg = text_code.all_messages[mcode[1]] |
|||
end |
|||
parms.have_problem = true |
|||
local function subparm(fmt, ...) |
|||
local rep = {} |
|||
for i, v in ipairs({...}) do |
|||
rep['$' .. i] = v |
|||
end |
|||
return (fmt:gsub('$%d+', rep)) |
|||
end |
|||
if msg then |
if msg then |
||
local parts = {} |
local parts = {} |
||
Zeile 330: | Zeile 305: | ||
append = '...' |
append = '...' |
||
end |
end |
||
s = |
s = nowiki(s) .. (append or '') |
||
else |
else |
||
s = '?' |
s = '?' |
||
end |
end |
||
parts[ |
parts[i] = s |
||
end |
|||
local function ispreview() |
|||
-- Return true if a prominent message should be shown. |
|||
if parms.test == 'preview' or parms.test == 'nopreview' then |
|||
-- For testing, can preview a real message or simulate a preview |
|||
-- when running automated tests. |
|||
return parms.test == 'preview' |
|||
end |
|||
local success, revid = pcall(function () |
|||
return (parms.frame):preprocess('{{REVISIONID}}') end) |
|||
return success and (revid == '') |
|||
end |
end |
||
local title = format(msg[1] or 'Missing message', parts[1], parts[2], parts[3]) |
|||
local want_warning = is_warning and |
|||
local text = msg[2] or 'Missing message' |
|||
not config.warnings and -- show unobtrusive warnings if config.warnings not configured |
|||
local cat = wanted_category(text_code.all_categories[msg[3]]) or '' |
|||
not msg.nowarn -- but use msg settings, not standard warning, if specified |
|||
local title = string.gsub(msg[1] or 'Missing message', '$%d+', parts) |
|||
local text = want_warning and '*' or msg[2] or 'Missing message' |
|||
local cat = wanted_category(msg[3], mcode[2], want_warning) |
|||
local anchor = msg[4] or '' |
local anchor = msg[4] or '' |
||
local fmt = text_code.all_messages[msg.format or 'cvt_format'] or 'convert: bug' |
|||
local fmtkey = ispreview() and 'cvt_format_preview' or |
|||
title = title:gsub('"', '"') |
|||
(want_warning and 'cvt_format2' or msg.format or 'cvt_format') |
|||
return format(fmt, anchor, title, text, cat) |
|||
local fmt = text_code.all_messages[fmtkey] or 'convert: bug' |
|||
return subparm(fmt, title:gsub('"', '"'), text, cat, anchor) |
|||
end |
end |
||
return 'Convert internal error: unknown message' |
return 'Convert internal error: unknown message' |
||
Zeile 364: | Zeile 324: | ||
function add_warning(parms, level, key, text1, text2) -- for forward declaration above |
function add_warning(parms, level, key, text1, text2) -- for forward declaration above |
||
-- If enabled, add a warning that will be displayed after the convert result. |
-- If enabled, add a warning that will be displayed after the convert result. |
||
-- A higher level is more verbose: more kinds of warnings are displayed. |
|||
-- To reduce output noise, only the first warning is displayed. |
-- To reduce output noise, only the first warning is displayed. |
||
if |
if config.warnings or level < 0 then |
||
if |
if level <= (tonumber(config.warnings) or 1) then |
||
parms.warnings = |
if parms.warnings == nil then |
||
parms.warnings = message({ key, text1, text2 }) |
|||
end |
|||
end |
end |
||
end |
end |
||
Zeile 389: | Zeile 350: | ||
success, speller = pcall(get_speller, spell_module) |
success, speller = pcall(get_speller, spell_module) |
||
if not success or type(speller) ~= 'function' then |
if not success or type(speller) ~= 'function' then |
||
add_warning(parms, 1, 'cvt_no_spell |
add_warning(parms, 1, 'cvt_no_spell') |
||
return nil |
return nil |
||
end |
end |
||
Zeile 590: | Zeile 551: | ||
-- This is never called to determine a unit name or link because per units |
-- This is never called to determine a unit name or link because per units |
||
-- are handled as a special case. |
-- are handled as a special case. |
||
-- Similarly, the default output is handled elsewhere |
-- Similarly, the default output is handled elsewhere. |
||
-- this is only called from get_default() for default_exceptions. |
|||
__index = function (self, key) |
__index = function (self, key) |
||
local value |
local value |
||
Zeile 616: | Zeile 576: | ||
} |
} |
||
local function make_per( |
local function make_per(unit_table, ulookup) |
||
-- Return true, t where t is a per unit with unit codes expanded to unit tables, |
-- Return true, t where t is a per unit with unit codes expanded to unit tables, |
||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
local result = { |
local result = { utype = unit_table.utype, per = {} } |
||
unitcode = unitcode, |
|||
utype = unit_table.utype, |
|||
per = {} |
|||
} |
|||
override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' }) |
override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' }) |
||
result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation |
result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation |
||
Zeile 676: | Zeile 632: | ||
-- Wikignomes may also put two spaces or " " in combinations, so |
-- Wikignomes may also put two spaces or " " in combinations, so |
||
-- replace underscore, " ", and multiple spaces with a single space. |
-- replace underscore, " ", and multiple spaces with a single space. |
||
utable = utable |
utable = utable or all_units |
||
fails = fails or {} |
fails = fails or {} |
||
depth = depth and depth + 1 or 1 |
depth = depth and depth + 1 or 1 |
||
Zeile 689: | Zeile 645: | ||
end |
end |
||
unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ') |
unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ') |
||
local function call_make_per(t) |
|||
return make_per(unitcode, t, |
|||
function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end |
|||
) |
|||
end |
|||
local t = utable[unitcode] |
local t = utable[unitcode] |
||
if t then |
if t then |
||
Zeile 715: | Zeile 666: | ||
end |
end |
||
if t.per then |
if t.per then |
||
return make_per(t, function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end) |
|||
return call_make_per(t) |
|||
end |
end |
||
local combo = t.combination -- nil or a table of unitcodes |
local combo = t.combination -- nil or a table of unitcodes |
||
Zeile 735: | Zeile 686: | ||
end |
end |
||
local result = shallow_copy(t) |
local result = shallow_copy(t) |
||
result.unitcode = unitcode |
|||
if result.prefixes then |
if result.prefixes then |
||
result.si_name = '' |
result.si_name = '' |
||
Zeile 754: | Zeile 704: | ||
if t and t.prefixes then |
if t and t.prefixes then |
||
local result = shallow_copy(t) |
local result = shallow_copy(t) |
||
result.unitcode = unitcode |
|||
result.si_name = parms.opt_sp_us and si.name_us or si.name |
result.si_name = parms.opt_sp_us and si.name_us or si.name |
||
result.si_prefix = si.prefix or prefix |
result.si_prefix = si.prefix or prefix |
||
Zeile 775: | Zeile 724: | ||
local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth) |
local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth) |
||
if success and not (result.offset or result.builtin or result.engscale) then |
if success and not (result.offset or result.builtin or result.engscale) then |
||
result.unitcode = unitcode -- 'e6cuft' not 'cuft' |
|||
result.defkey = unitcode -- key to lookup default exception |
result.defkey = unitcode -- key to lookup default exception |
||
result.engscale = engscale |
result.engscale = engscale |
||
Zeile 836: | Zeile 784: | ||
-- Engineering notation (apart from at start and which has been stripped before here), |
-- Engineering notation (apart from at start and which has been stripped before here), |
||
-- is not supported so do not make a per unit if find text like 'e3' in unitcode. |
-- is not supported so do not make a per unit if find text like 'e3' in unitcode. |
||
local success, result = |
local success, result = make_per({ per = {top, bottom} }, function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end) |
||
if success then |
if success then |
||
return true, result |
return true, result |
||
Zeile 963: | Zeile 911: | ||
end |
end |
||
return sep .. id .. mid |
return sep .. id .. mid |
||
end |
|||
local function change_sign(text) |
|||
-- Change sign of text for correct appearance because it is negated. |
|||
if text:sub(1, 1) == '-' then |
|||
return text:sub(2) |
|||
end |
|||
return '-' .. text |
|||
end |
end |
||
Zeile 1.046: | Zeile 1.002: | ||
-- When using gaps, they are inserted before and after the decimal mark. |
-- When using gaps, they are inserted before and after the decimal mark. |
||
-- Separators are inserted only before the decimal mark. |
-- Separators are inserted only before the decimal mark. |
||
-- A trailing dot (as in '123.') is removed because their use appears to |
|||
-- be accidental, and such a number should be shown as '123' or '123.0'. |
|||
-- It is useful for convert to suppress the dot so, for example, '4000.' |
|||
-- is a simple way of indicating that all the digits are significant. |
|||
if text:sub(-1) == '.' then |
|||
text = text:sub(1, -2) |
|||
end |
|||
if #text < 4 or parms.opt_nocomma or numsep == '' then |
if #text < 4 or parms.opt_nocomma or numsep == '' then |
||
return from_en(text) |
return from_en(text) |
||
Zeile 1.330: | Zeile 1.279: | ||
-- with the hands unit (not worth adding code to enforce that). |
-- with the hands unit (not worth adding code to enforce that). |
||
------------------------------------------------------------------------ |
------------------------------------------------------------------------ |
||
local numstr, whole |
|||
local leading_plus, prefix, numstr, slashes, denstr = |
local leading_plus, prefix, numstr, slashes, denstr = |
||
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$') |
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$') |
||
Zeile 1.343: | Zeile 1.293: | ||
return nil |
return nil |
||
end |
end |
||
local |
local wholestr |
||
if prefix == '' then |
if prefix == '' then |
||
wholestr = '' |
wholestr = '' |
||
Zeile 1.409: | Zeile 1.359: | ||
while #remainder > 0 do |
while #remainder > 0 do |
||
local ref, spaces |
local ref, spaces |
||
ref, spaces, remainder = remainder:match('^(\ |
ref, spaces, remainder = remainder:match('^(\127UNIQ[^\127]*%-ref%-%x+%-QINU\127)(%s*)(.*)') |
||
if ref then |
if ref then |
||
table.insert(refs, ref) |
table.insert(refs, ref) |
||
Zeile 1.510: | Zeile 1.460: | ||
end |
end |
||
end |
end |
||
local altvalue = altvalue or value |
|||
if isnegative and (value ~= 0) then |
if isnegative and (value ~= 0) then |
||
value = -value |
value = -value |
||
altvalue = - |
altvalue = -altvalue |
||
end |
end |
||
return true, { |
return true, { |
||
value = value, |
value = value, |
||
altvalue = altvalue |
altvalue = altvalue, |
||
singular = singular, |
singular = singular, |
||
clean = clean, |
clean = clean, |
||
Zeile 1.535: | Zeile 1.486: | ||
local number = tonumber(to_en(text)) |
local number = tonumber(to_en(text)) |
||
if number then |
if number then |
||
local |
local integer, fracpart = math.modf(number) |
||
return number, (fracpart == 0) |
return number, (fracpart == 0) |
||
end |
end |
||
Zeile 1.613: | Zeile 1.564: | ||
-- p2 is text to insert before the output unit |
-- p2 is text to insert before the output unit |
||
-- p1 or p2 may be nil to mean "no preunit" |
-- p1 or p2 may be nil to mean "no preunit" |
||
-- Using '+' gives output like "5+ feet" (no |
-- Using '+ ' gives output like "5+ feet" (no preceding space). |
||
local function withspace(text, |
local function withspace(text, i) |
||
-- |
-- Insert space at beginning if i == 1, or at end if i == -1. |
||
-- However, no space is |
-- However, no space is inserted if there is a space or ' ' |
||
-- at that position ('-' is for adjectival text). |
-- or '-' at that position ('-' is for adjectival text). |
||
local current = text:sub(i, i) |
|||
-- There is also no space if text starts with '&' |
|||
if current == ' ' or current == '-' then |
|||
-- (e.g. '°' would display a degree symbol with no preceding space). |
|||
return text |
|||
if char == '&' then |
|||
return text -- an html entity can be used to specify the exact display |
|||
end |
end |
||
if |
if i == 1 then |
||
current = text:sub(1, 6) |
|||
else |
|||
current = text:sub(-6, -1) |
|||
end |
end |
||
if |
if current == ' ' then |
||
return text |
|||
if not (char == ' ' or char == '-' or text:sub(-6, -1) == ' ') then |
|||
text = text .. ' ' |
|||
end |
|||
end |
end |
||
if i == 1 then |
|||
return text |
|||
return ' ' .. text |
|||
end |
|||
return text .. ' ' |
|||
end |
end |
||
local PLUS = '+ ' |
|||
preunit1 = preunit1 or '' |
preunit1 = preunit1 or '' |
||
local trim1 = strip(preunit1) |
local trim1 = strip(preunit1) |
||
Zeile 1.642: | Zeile 1.592: | ||
return nil |
return nil |
||
end |
end |
||
return withspace(withspace(preunit1, 1), -1) |
|||
if trim1 == '+' then |
|||
return PLUS |
|||
end |
|||
return withspace(preunit1, true) |
|||
end |
end |
||
preunit1 = withspace(preunit1) |
|||
preunit2 = preunit2 or '' |
preunit2 = preunit2 or '' |
||
local trim2 = strip(preunit2) |
local trim2 = strip(preunit2) |
||
if trim1 == ' |
if trim1 == '' and trim2 == '' then |
||
return nil, nil |
|||
if trim2 == '' or trim2 == '+' then |
|||
end |
|||
return PLUS, PLUS |
|||
if trim1 ~= '+' then |
|||
end |
|||
preunit1 = |
preunit1 = withspace(preunit1, 1) |
||
end |
end |
||
if trim2 == '' then |
if trim2 == ' ' then -- trick to make preunit2 empty |
||
preunit2 = nil |
|||
elseif trim2 == '' then |
|||
return nil, nil |
|||
end |
|||
preunit2 = preunit1 |
preunit2 = preunit1 |
||
elseif trim2 |
elseif trim2 ~= '+' then |
||
preunit2 = |
preunit2 = withspace(preunit2, 1) |
||
elseif trim2 == ' ' then -- trick to make preunit2 empty |
|||
preunit2 = nil |
|||
else |
|||
preunit2 = withspace(preunit2) |
|||
end |
end |
||
return preunit1, preunit2 |
return preunit1, preunit2 |
||
Zeile 1.698: | Zeile 1.639: | ||
local function get_composite(parms, iparm, in_unit_table) |
local function get_composite(parms, iparm, in_unit_table) |
||
-- Look for a composite input unit. For example, {{convert|1|yd|2|ft|3|in}} |
-- Look for a composite input unit. For example, "{{convert|1|yd|2|ft|3|in}}" |
||
-- would result in a call to this function with |
-- would result in a call to this function with |
||
-- iparm = 3 (parms[iparm] = "2", just after the first unit) |
-- iparm = 3 (parms[iparm] = "2", just after the first unit) |
||
Zeile 1.769: | Zeile 1.710: | ||
-- Return true if successful or return false, t where t is an error message table. |
-- Return true if successful or return false, t where t is an error message table. |
||
currency_text = nil -- local testing can hold module in memory; must clear globals |
currency_text = nil -- local testing can hold module in memory; must clear globals |
||
local accept_any_text = { |
|||
input = true, |
|||
qid = true, |
|||
qual = true, |
|||
stylein = true, |
|||
styleout = true, |
|||
tracking = true, |
|||
} |
|||
if kv_pairs.adj and kv_pairs.sing then |
if kv_pairs.adj and kv_pairs.sing then |
||
-- For enwiki (before translation), warn if attempt to use adj and sing |
-- For enwiki (before translation), warn if attempt to use adj and sing |
||
Zeile 1.810: | Zeile 1.743: | ||
en_value = number |
en_value = number |
||
else |
else |
||
add_warning(parms, 1, (en_name == 'frac' and 'cvt_bad_frac' or 'cvt_bad_sigfig'), |
add_warning(parms, 1, (en_name == 'frac' and 'cvt_bad_frac' or 'cvt_bad_sigfig'), loc_value) |
||
end |
end |
||
end |
end |
||
elseif |
elseif en_name == 'stylein' or en_name == 'styleout' then |
||
en_value = loc_value |
en_value = loc_value -- accept user text with no validation |
||
if en_name == 'input' then |
|||
-- May have something like {{convert|input=}} (empty input) if source is an infobox |
|||
-- with optional fields. In that case, want to output nothing rather than an error. |
|||
parms.input_text = loc_value -- keep input because parms.input is nil if loc_value == '' |
|||
end |
|||
else |
else |
||
en_value = text_code.en_option_value[en_name][loc_value] |
en_value = text_code.en_option_value[en_name][loc_value] |
||
Zeile 1.868: | Zeile 1.796: | ||
end |
end |
||
if parms.abbr then |
if parms.abbr then |
||
if parms.abbr == 'unit' then |
|||
parms.abbr = 'on' |
|||
parms.number_word = true |
|||
end |
|||
parms.abbr_org = parms.abbr -- original abbr, before any flip |
parms.abbr_org = parms.abbr -- original abbr, before any flip |
||
elseif parms.opt_hand_hh then |
elseif parms.opt_hand_hh then |
||
Zeile 1.878: | Zeile 1.802: | ||
else |
else |
||
parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name) |
parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name) |
||
end |
|||
if parms.opt_order_out then |
|||
-- Disable options that do not work in a useful way with order=out. |
|||
parms.opt_flip = nil -- override adj=flip |
|||
parms.opt_spell_in = nil |
|||
parms.opt_spell_out = nil |
|||
parms.opt_spell_upper = nil |
|||
end |
end |
||
if parms.opt_spell_out and not abbr_entered then |
if parms.opt_spell_out and not abbr_entered then |
||
Zeile 2.046: | Zeile 1.963: | ||
local function simple_get_values(parms) |
local function simple_get_values(parms) |
||
-- If input is like "{{convert|valid_value|valid_unit|...}}", |
-- If input is like "{{convert|valid_value|valid_unit|...}}", |
||
-- return true, |
-- return true, 3, in_unit, in_unit_table |
||
-- |
-- 3 = index in parms of whatever follows valid_unit, if anything). |
||
-- The valid_value is not negative and does not use a fraction, and |
-- The valid_value is not negative and does not use a fraction, and |
||
-- no options requiring further processing of the input are used. |
-- no options requiring further processing of the input are used. |
||
-- Otherwise, return nothing |
-- Otherwise, return nothing and caller will reparse the input. |
||
-- Testing shows this function is successful for 96% of converts in articles, |
-- Testing shows this function is successful for 96% of converts in articles, |
||
-- and that on average it speeds up converts by 8%. |
-- and that on average it speeds up converts by 8%. |
||
if parms.opt_ri or parms.opt_spell_in then return end |
if parms.opt_ri or parms.opt_spell_in then return end |
||
local clean = to_en(strip(parms[1] or ''), parms) |
local clean = to_en(strip(parms[1] or ''), parms) |
||
if #clean > 10 or not clean:match('^[0-9.]+$') then |
if #clean > 10 or not clean:match('^[0-9.]+$') then return end |
||
return false, clean |
|||
end |
|||
local value = tonumber(clean) |
local value = tonumber(clean) |
||
if not value then return end |
if not value then return end |
||
Zeile 2.074: | Zeile 1.989: | ||
end |
end |
||
local function |
local function get_parms(args) |
||
-- If successful, return true, parms, unit where |
|||
-- Return true, s where s is the result of a Wikidata operation, |
|||
-- or return false, t where t is an error message table. |
|||
local function worker(...) |
|||
wikidata_code = wikidata_code or require(wikidata_module) |
|||
wikidata_data = wikidata_data or mw.loadData(wikidata_data_module) |
|||
return wikidata_code[operation](wikidata_data, ...) |
|||
end |
|||
local success, status, result = pcall(worker, ...) |
|||
if success then |
|||
return status, result |
|||
end |
|||
if parms.opt_sortable_debug then |
|||
-- Use debug=yes to crash if an error while accessing Wikidata. |
|||
error('Error accessing Wikidata: ' .. status, 0) |
|||
end |
|||
return false, { 'cvt_wd_fail' } |
|||
end |
|||
local function get_parms(parms, args) |
|||
-- If successful, update parms and return true, unit where |
|||
-- parms is a table of all arguments passed to the template |
-- parms is a table of all arguments passed to the template |
||
-- converted to named arguments, and |
-- converted to named arguments, and |
||
-- unit is the input unit table; |
-- unit is the input unit table; |
||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
-- For special processing (not a convert), can also return |
|||
-- true, wikitext where wikitext is the final result. |
|||
-- The returned input unit table may be for a fake unit using the specified |
-- The returned input unit table may be for a fake unit using the specified |
||
-- unit code as the symbol and name, and with bad_mcode = message code table. |
-- unit code as the symbol and name, and with bad_mcode = message code table. |
||
Zeile 2.107: | Zeile 2.001: | ||
-- whitespace entered in the template, and whitespace is used by some |
-- whitespace entered in the template, and whitespace is used by some |
||
-- parameters (example: the numbered parameters associated with "disp=x"). |
-- parameters (example: the numbered parameters associated with "disp=x"). |
||
local parms = {} -- arguments passed to template, after translation |
|||
local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it |
local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it |
||
for k, v in pairs(args) do |
for k, v in pairs(args) do |
||
Zeile 2.114: | Zeile 2.009: | ||
kv_pairs[k] = v |
kv_pairs[k] = v |
||
end |
end |
||
end |
|||
if parms.test == 'wikidata' then |
|||
local ulookup = function (ucode) |
|||
-- Use empty table for parms so it does not accumulate results when used repeatedly. |
|||
return lookup({}, ucode, 'no_combination') |
|||
end |
|||
return wikidata_call(parms, '_listunits', ulookup) |
|||
end |
end |
||
local success, msg = translate_parms(parms, kv_pairs) |
local success, msg = translate_parms(parms, kv_pairs) |
||
if not success then return false, msg end |
if not success then return false, msg end |
||
if parms.input then |
|||
success, msg = wikidata_call(parms, '_adjustparameters', parms, 1) |
|||
if not success then return false, msg end |
|||
end |
|||
local success, i, in_unit, in_unit_table = simple_get_values(parms) |
local success, i, in_unit, in_unit_table = simple_get_values(parms) |
||
if not success then |
if not success then |
||
if type(i) == 'string' and i:match('^NNN+$') then |
|||
-- Some infoboxes have examples like {{convert|NNN|m}} (3 or more "N"). |
|||
-- Output an empty string for these. |
|||
return false, { 'cvt_no_output' } |
|||
end |
|||
local valinfo |
local valinfo |
||
success, valinfo, i = get_values(parms) |
success, valinfo, i = get_values(parms) |
||
Zeile 2.142: | Zeile 2.021: | ||
success, in_unit_table = lookup(parms, in_unit, 'no_combination') |
success, in_unit_table = lookup(parms, in_unit, 'no_combination') |
||
if not success then |
if not success then |
||
in_unit = |
if in_unit == nil then |
||
in_unit = '' |
|||
end |
|||
if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}}) |
if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}}) |
||
in_unit_table = '' -- suppress error message and prevent processing of output unit |
in_unit_table = '' -- suppress error message and prevent processing of output unit |
||
end |
end |
||
in_unit_table = setmetatable({ |
in_unit_table = setmetatable({ symbol = in_unit, name2 = in_unit, |
||
default = "m", defkey = "m", linkey = "m", |
|||
utype = "length", scale = 1, bad_mcode = in_unit_table }, unit_mt) |
|||
bad_mcode = in_unit_table }, unit_mt) |
|||
end |
end |
||
in_unit_table.valinfo = valinfo |
in_unit_table.valinfo = valinfo |
||
Zeile 2.184: | Zeile 2.064: | ||
end |
end |
||
end |
end |
||
local |
local next = strip(parms[i]) |
||
i = i + 1 |
i = i + 1 |
||
local precision, is_bad_precision |
local precision, is_bad_precision |
||
Zeile 2.199: | Zeile 2.079: | ||
end |
end |
||
end |
end |
||
if |
if not set_precision(next) then |
||
parms.out_unit = |
parms.out_unit = next |
||
if set_precision(strip(parms[i])) then |
if set_precision(strip(parms[i])) then |
||
i = i + 1 |
i = i + 1 |
||
Zeile 2.206: | Zeile 2.086: | ||
end |
end |
||
if parms.opt_adj_mid then |
if parms.opt_adj_mid then |
||
next = parms[i] |
|||
i = i + 1 |
i = i + 1 |
||
if |
if next then -- mid-text words |
||
if |
if next:sub(1, 1) == '-' then |
||
parms.mid = |
parms.mid = next |
||
else |
else |
||
parms.mid = ' ' .. |
parms.mid = ' ' .. next |
||
end |
end |
||
end |
end |
||
Zeile 2.252: | Zeile 2.132: | ||
parms.precision = precision |
parms.precision = precision |
||
end |
end |
||
return true, parms, in_unit_table |
|||
for j = i, i + 3 do |
|||
local parm = parms[j] -- warn if find a non-empty extraneous parameter |
|||
if parm and parm:match('%S') then |
|||
add_warning(parms, 1, 'cvt_unknown_option', parm) |
|||
break |
|||
end |
|||
end |
|||
return true, in_unit_table |
|||
end |
end |
||
Zeile 2.295: | Zeile 2.168: | ||
local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too |
local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too |
||
local prec, minprec, adjust |
local prec, minprec, adjust |
||
local utype = out_current.utype |
|||
local subunit_ignore_trailing_zero |
local subunit_ignore_trailing_zero |
||
local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in" |
local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in" |
||
Zeile 2.559: | Zeile 2.433: | ||
-- is "1", or like "1.00", or is a fraction with value < 1; |
-- is "1", or like "1.00", or is a fraction with value < 1; |
||
-- (and more fields shown below, and a calculated 'absvalue' field). |
-- (and more fields shown below, and a calculated 'absvalue' field). |
||
-- or return true, nil if no value specified; |
|||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
-- Input info.clean uses en digits (it has been translated, if necessary). |
-- Input info.clean uses en digits (it has been translated, if necessary). |
||
-- Output show uses en or non-en digits as appropriate, or can be spelled. |
-- Output show uses en or non-en digits as appropriate, or can be spelled. |
||
local invalue |
|||
if info then |
|||
invalue = info.value |
|||
if in_current.builtin == 'hand' then |
|||
invalue = info.altvalue |
|||
end |
|||
end |
|||
if invalue == nil or invalue == '' then |
|||
return true, nil |
|||
end |
|||
if out_current.builtin == 'hand' then |
if out_current.builtin == 'hand' then |
||
return cvt_to_hand(parms, info, in_current, out_current) |
return cvt_to_hand(parms, info, in_current, out_current) |
||
end |
end |
||
local invalue = in_current.builtin == 'hand' and info.altvalue or info.value |
|||
local outvalue, extra = convert(parms, invalue, info, in_current, out_current) |
local outvalue, extra = convert(parms, invalue, info, in_current, out_current) |
||
if parms.need_table_or_sort then |
if parms.need_table_or_sort then |
||
Zeile 2.584: | Zeile 2.468: | ||
outvalue = -outvalue |
outvalue = -outvalue |
||
end |
end |
||
local precision, show, exponent |
local numerator, precision, success, show, exponent |
||
local denominator = out_current.frac |
local denominator = out_current.frac |
||
if denominator then |
if denominator then |
||
Zeile 2.836: | Zeile 2.720: | ||
local linked_pages -- to record linked pages so will not link to the same page more than once |
local linked_pages -- to record linked pages so will not link to the same page more than once |
||
local function |
local function make_link(link, id, link_key) |
||
-- Forget that the given unit has previously been linked (if it has). |
|||
-- That is needed when processing a range of inputs or outputs when an id |
|||
-- for the first range value may have been evaluated, but only an id for |
|||
-- the last value is displayed, and that id may need to be linked. |
|||
linked_pages[unit_table.unitcode or unit_table] = nil |
|||
end |
|||
local function make_link(link, id, unit_table) |
|||
-- Return wikilink "[[link|id]]", possibly abbreviated as in examples: |
-- Return wikilink "[[link|id]]", possibly abbreviated as in examples: |
||
-- [[Mile|mile]] --> [[mile]] |
-- [[Mile|mile]] --> [[mile]] |
||
Zeile 2.851: | Zeile 2.727: | ||
-- * no link given (so caller does not need to check if a link was defined); or |
-- * no link given (so caller does not need to check if a link was defined); or |
||
-- * link has previously been used during the current convert (to avoid overlinking). |
-- * link has previously been used during the current convert (to avoid overlinking). |
||
-- Linking with a unit uses the unit table as the link key, which fails to detect |
|||
local link_key |
|||
-- overlinking for conversions like the following (each links "mile" twice): |
|||
if unit_table then |
|||
-- {{convert|1|impgal/mi|USgal/mi|lk=on}} |
|||
link_key = unit_table.unitcode or unit_table |
|||
-- {{convert|1|l/km|impgal/mi USgal/mi|lk=on}} |
|||
else |
|||
link_key = link_key or link -- use key if given (the key, but not the link, may be known when need to cancel a link record) |
|||
link_key = link |
|||
end |
|||
if not link or link == '' or linked_pages[link_key] then |
if not link or link == '' or linked_pages[link_key] then |
||
return id |
return id |
||
Zeile 2.900: | Zeile 2.775: | ||
else |
else |
||
i = 3 |
i = 3 |
||
end |
|||
if i > 1 and varname == 'pl' then |
|||
i = i - 1 |
|||
end |
end |
||
vname = split(unit_table.varname, '!')[i] |
vname = split(unit_table.varname, '!')[i] |
||
Zeile 2.933: | Zeile 2.805: | ||
local per = unit_table.per |
local per = unit_table.per |
||
if per then |
if per then |
||
local paren1, paren2 = '', '' -- possible parentheses around bottom unit |
|||
local unit1 = per[1] -- top unit_table, or nil |
local unit1 = per[1] -- top unit_table, or nil |
||
local unit2 = per[2] -- bottom unit_table |
local unit2 = per[2] -- bottom unit_table |
||
Zeile 2.945: | Zeile 2.816: | ||
return symbol -- for exceptions that have the symbol built-in |
return symbol -- for exceptions that have the symbol built-in |
||
end |
end |
||
end |
|||
if (unit2.symbol):find('⋅', 1, true) then |
|||
paren1, paren2 = '(', ')' |
|||
end |
end |
||
end |
end |
||
Zeile 2.987: | Zeile 2.855: | ||
unit_table.sep = '' |
unit_table.sep = '' |
||
end |
end |
||
return result |
return result .. linked_id(parms, unit2, key_id2, want_link, '1') |
||
end |
end |
||
if multiplier then |
if multiplier then |
||
Zeile 3.068: | Zeile 2.936: | ||
local abbr_org = parms.abbr_org |
local abbr_org = parms.abbr_org |
||
local adjectival = parms.opt_adjectival |
local adjectival = parms.opt_adjectival |
||
local disp = parms.disp |
|||
local lk = parms.lk |
local lk = parms.lk |
||
local want_link = (lk == 'on' or lk == inout) |
local want_link = (lk == 'on' or lk == inout) |
||
Zeile 3.152: | Zeile 3.021: | ||
local inout = unit_table.inout |
local inout = unit_table.inout |
||
local abbr = parms.abbr |
local abbr = parms.abbr |
||
if |
if abbr == 'on' or abbr == inout then |
||
info.show = info.show .. |
info.show = info.show .. |
||
'<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' .. |
'<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' .. |
||
Zeile 3.214: | Zeile 3.083: | ||
return preunit .. id1 |
return preunit .. id1 |
||
end |
end |
||
if parms.opt_also_symbol and not composite |
if parms.opt_also_symbol and not composite then |
||
local join1 = parms.joins[1] |
local join1 = parms.joins[1] |
||
if join1 == ' (' or join1 == ' [' then |
if join1 == ' (' or join1 == ' [' then |
||
Zeile 3.259: | Zeile 3.128: | ||
local range = parms.range |
local range = parms.range |
||
if range and not add_unit then |
if range and not add_unit then |
||
linked_pages[first_unit] = nil -- so the final and only id will be linked, if wanted |
|||
unlink(first_unit) |
|||
end |
end |
||
local id = range and make_id(parms, range.n + 1, first_unit) or id1 |
local id = range and make_id(parms, range.n + 1, first_unit) or id1 |
||
Zeile 3.296: | Zeile 3.165: | ||
-- Processing required for each output unit. |
-- Processing required for each output unit. |
||
-- Return block of text to represent output (value/unit). |
-- Return block of text to represent output (value/unit). |
||
local inout = out_current.inout -- normally 'out' but can be 'in' for order=out |
|||
local id1, want_name = make_id(parms, 1, out_current) |
local id1, want_name = make_id(parms, 1, out_current) |
||
local sep = out_current.sep -- set by make_id |
local sep = out_current.sep -- set by make_id |
||
Zeile 3.318: | Zeile 3.186: | ||
if range then |
if range then |
||
-- For simplicity and because more not needed, handle one range item only. |
-- For simplicity and because more not needed, handle one range item only. |
||
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, |
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, 'out') |
||
end |
end |
||
return preunit .. result |
return preunit .. result |
||
Zeile 3.327: | Zeile 3.195: | ||
local range = parms.range |
local range = parms.range |
||
if range and not add_unit then |
if range and not add_unit then |
||
linked_pages[out_current] = nil -- so the final and only id will be linked, if wanted |
|||
unlink(out_current) |
|||
end |
end |
||
local id = range and make_id(parms, range.n + 1, out_current) or id1 |
local id = range and make_id(parms, range.n + 1, out_current) or id1 |
||
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, |
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, 'out') |
||
if was_hyphenated then |
if was_hyphenated then |
||
add_unit = false |
add_unit = false |
||
Zeile 3.351: | Zeile 3.219: | ||
result = show |
result = show |
||
else |
else |
||
result = range_text(range[i], want_name, parms, result, show, |
result = range_text(range[i], want_name, parms, result, show, 'out') |
||
end |
end |
||
end |
end |
||
Zeile 3.368: | Zeile 3.236: | ||
-- for a single output (which is not a combination or a multiple); |
-- for a single output (which is not a combination or a multiple); |
||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
out_unit_table.valinfo = collection() |
|||
if parms.opt_order_out and in_unit_table.unitcode == out_unit_table.unitcode then |
|||
local range = parms.range |
|||
out_unit_table.valinfo = in_unit_table.valinfo |
|||
for i = 1, (range and (range.n + 1) or 1) do |
|||
else |
|||
local success, info = cvtround(parms, in_unit_table.valinfo[i], in_unit_table, out_unit_table) |
|||
out_unit_table.valinfo = collection() |
|||
if not success then return false, info end |
|||
for _, v in ipairs(in_unit_table.valinfo) do |
|||
out_unit_table.valinfo:add(info) |
|||
local success, info = cvtround(parms, v, in_unit_table, out_unit_table) |
|||
if not success then return false, info end |
|||
out_unit_table.valinfo:add(info) |
|||
end |
|||
end |
end |
||
return true, process_one_output(parms, out_unit_table) |
return true, process_one_output(parms, out_unit_table) |
||
Zeile 3.385: | Zeile 3.250: | ||
-- for an output which is a multiple (like 'ftin'); |
-- for an output which is a multiple (like 'ftin'); |
||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
local inout = out_unit_table.inout -- normally 'out' but can be 'in' for order=out |
|||
local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil) |
local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil) |
||
local combos = out_unit_table.combination -- table of unit tables (will not be nil) |
local combos = out_unit_table.combination -- table of unit tables (will not be nil) |
||
Zeile 3.392: | Zeile 3.256: | ||
local disp = parms.disp |
local disp = parms.disp |
||
local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or |
local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or |
||
not (abbr == 'on' or abbr == |
not (abbr == 'on' or abbr == 'out' or abbr == 'mos') |
||
local want_link = (parms.lk == 'on' or parms.lk == |
local want_link = (parms.lk == 'on' or parms.lk == 'out') |
||
local mid = parms.opt_flip and parms.mid or '' |
local mid = parms.opt_flip and parms.mid or '' |
||
local sep1 = ' ' |
local sep1 = ' ' |
||
Zeile 3.409: | Zeile 3.273: | ||
local tfrac, thisvalue, strforce |
local tfrac, thisvalue, strforce |
||
local out_current = combos[i] |
local out_current = combos[i] |
||
out_current.inout = |
out_current.inout = 'out' |
||
local scale = multiple[i] |
local scale = multiple[i] |
||
if i == 1 then -- least significant unit ('in' from 'ftin') |
if i == 1 then -- least significant unit ('in' from 'ftin') |
||
Zeile 3.491: | Zeile 3.355: | ||
end |
end |
||
local strval |
local strval |
||
local |
local inout = (i == #combos or outvalue == 0) and 'out' or '' -- trick so the last value processed (first displayed) has uppercase, if requested |
||
if strforce and outvalue == 0 then |
if strforce and outvalue == 0 then |
||
sign = '' -- any sign is in strforce |
sign = '' -- any sign is in strforce |
||
Zeile 3.497: | Zeile 3.361: | ||
elseif tfrac then |
elseif tfrac then |
||
local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil |
local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil |
||
strval = format_fraction(parms, |
strval = format_fraction(parms, inout, false, wholestr, tfrac.numstr, tfrac.denstr, do_spell) |
||
else |
else |
||
strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue)) |
strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue)) |
||
if do_spell then |
if do_spell then |
||
strval = spell_number(parms, |
strval = spell_number(parms, inout, strval) or strval |
||
end |
end |
||
end |
end |
||
Zeile 3.524: | Zeile 3.388: | ||
local success, result2 = make_result(valinfo[i+1]) |
local success, result2 = make_result(valinfo[i+1]) |
||
if not success then return false, result2 end |
if not success then return false, result2 end |
||
result = range_text(range[i], want_name, parms, result, result2, |
result = range_text(range[i], want_name, parms, result, result2, 'out') |
||
end |
end |
||
end |
end |
||
Zeile 3.531: | Zeile 3.395: | ||
local function process(parms, in_unit_table, out_unit_table) |
local function process(parms, in_unit_table, out_unit_table) |
||
-- Return true, s |
-- Return true, s where s = final wikitext result, |
||
-- or return false, t where t is an error message table. |
-- or return false, t where t is an error message table. |
||
linked_pages = {} |
linked_pages = {} |
||
local success, bad_output |
local success, bad_output |
||
local bad_input_mcode = in_unit_table.bad_mcode -- |
local bad_input_mcode = in_unit_table.bad_mcode -- false if input unit is valid |
||
local invalue1 = in_unit_table.valinfo[1].value |
|||
local out_unit = parms.out_unit |
local out_unit = parms.out_unit |
||
if out_unit == nil or out_unit == ' |
if out_unit == nil or out_unit == '' then |
||
if bad_input_mcode or parms.opt_input_unit_only then |
if bad_input_mcode or parms.opt_input_unit_only then |
||
bad_output = '' |
bad_output = '' |
||
else |
else |
||
success, out_unit = get_default(invalue1, in_unit_table) |
|||
local getdef = type(out_unit) == 'function' and out_unit or get_default |
|||
success, out_unit = getdef(in_unit_table.valinfo[1].value, in_unit_table) |
|||
parms.out_unit = out_unit |
parms.out_unit = out_unit |
||
if not success then |
if not success then |
||
Zeile 3.560: | Zeile 3.424: | ||
end |
end |
||
end |
end |
||
local lhs, rhs |
|||
local flipped = parms.opt_flip and not bad_input_mcode |
local flipped = parms.opt_flip and not bad_input_mcode |
||
local parts = {} |
|||
if bad_output then |
|||
for part = 1, 2 do |
|||
rhs = (bad_output == '') and '' or message(parms, bad_output) |
|||
-- The LHS (parts[1]) is normally the input, but is the output if flipped. |
|||
elseif parms.opt_input_unit_only then |
|||
-- Process LHS first so it will be linked, if wanted. |
|||
rhs = '' |
|||
-- Linking to the same item is suppressed in the RHS to avoid overlinking. |
|||
else |
|||
if (part == 1 and not flipped) or (part == 2 and flipped) then |
|||
parts[part] = process_input(parms, in_unit_table) |
|||
if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin') |
|||
elseif bad_output then |
|||
combos = out_unit_table.combination |
|||
parts[part] = (bad_output == '') and '' or message(bad_output) |
|||
end |
|||
else |
|||
local frac = parms.frac -- nil or denominator of fraction for output values |
|||
local outputs = {} |
|||
if frac then |
|||
local combos -- nil (for 'ft' or 'ftin'), or table of unit tables (for 'm ft') |
|||
if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin') |
|||
-- except that if a precision is also specified, the fraction only applies to |
|||
combos = out_unit_table.combination |
|||
-- the hand unit; that allows the following result: |
|||
end |
|||
-- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands) |
|||
local frac = parms.frac -- nil or denominator of fraction for output values |
|||
-- However, the following is handled elsewhere as a special case: |
|||
if frac then |
|||
-- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in) |
|||
-- Apply fraction to the unit (if only one), or to non-SI units (if a combination), |
|||
if combos then |
|||
-- except that if a precision is also specified, the fraction only applies to |
|||
local precision = parms.precision |
|||
-- the hand unit; that allows the following result: |
|||
-- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands) |
|||
if unit.builtin == 'hand' or (not precision and not unit.prefixes) then |
|||
-- However, the following is handled elsewhere as a special case: |
|||
unit.frac = frac |
|||
-- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in) |
|||
if combos then |
|||
local precision = parms.precision |
|||
for _, unit in ipairs(combos) do |
|||
if unit.builtin == 'hand' or (not precision and not unit.prefixes) then |
|||
unit.frac = frac |
|||
end |
|||
end |
end |
||
else |
|||
out_unit_table.frac = frac |
|||
end |
end |
||
else |
|||
out_unit_table.frac = frac |
|||
end |
end |
||
local out_first |
|||
end |
|||
local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables |
|||
local outputs = {} |
|||
for i = 1, imax do |
|||
local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables |
|||
local success, item |
|||
if imax == 1 then |
|||
local out_current = combos and combos[i] or out_unit_table |
|||
parms.opt_order_out = nil -- only useful with an output combination |
|||
out_current.inout = 'out' |
|||
end |
|||
if |
if i == 1 then |
||
out_first = out_current |
|||
-- Process left side first so any duplicate links (from lk=on) are suppressed |
|||
if imax > 1 and out_current.builtin == 'hand' then |
|||
-- on right. Example: {{convert|28|e9pc|e9ly|abbr=off|lk=on}} |
|||
out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination |
|||
lhs = process_input(parms, in_unit_table) |
|||
end |
end |
||
for i = 1, imax do |
|||
local success, item |
|||
local out_current = combos and combos[i] or out_unit_table |
|||
out_current.inout = 'out' |
|||
if i == 1 then |
|||
if imax > 1 and out_current.builtin == 'hand' then |
|||
out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination |
|||
end |
end |
||
if |
if out_current.multiple then |
||
success, item = make_output_multiple(parms, in_unit_table, out_current) |
|||
out_current.inout = 'in' |
|||
else |
|||
success, item = make_output_single(parms, in_unit_table, out_current) |
|||
end |
end |
||
if not success then return false, item end |
|||
table.insert(outputs, item) |
|||
end |
end |
||
if |
if parms.opt_input_unit_only then |
||
parts[part] = '' |
|||
success, item = make_output_multiple(parms, in_unit_table, out_current) |
|||
else |
else |
||
local sep = parms.table_joins and parms.table_joins[2] or parms.join_between |
|||
success, item = make_output_single(parms, in_unit_table, out_current) |
|||
parts[part] = table.concat(outputs, sep) |
|||
end |
end |
||
if not success then return false, item end |
|||
outputs[i] = item |
|||
end |
|||
if parms.opt_order_out then |
|||
lhs = outputs[1] |
|||
table.remove(outputs, 1) |
|||
end |
|||
local sep = parms.table_joins and parms.table_joins[2] or parms.join_between |
|||
rhs = table.concat(outputs, sep) |
|||
end |
|||
if flipped or not lhs then |
|||
local input = process_input(parms, in_unit_table) |
|||
if flipped then |
|||
lhs = rhs |
|||
rhs = input |
|||
else |
|||
lhs = input |
|||
end |
end |
||
end |
end |
||
if parms.join_before then |
if parms.join_before then |
||
parts[1] = parms.join_before .. parts[1] |
|||
end |
end |
||
local wikitext |
local wikitext |
||
if bad_input_mcode then |
if bad_input_mcode then |
||
if bad_input_mcode == '' then |
if bad_input_mcode == '' then |
||
wikitext = |
wikitext = parts[1] |
||
else |
else |
||
wikitext = |
wikitext = parts[1] .. message(bad_input_mcode) |
||
end |
end |
||
elseif parms.table_joins then |
elseif parms.table_joins then |
||
wikitext = parms.table_joins[1] .. |
wikitext = parms.table_joins[1] .. parts[1] .. parms.table_joins[2] .. parts[2] |
||
else |
else |
||
wikitext = |
wikitext = parts[1] .. parms.joins[1] .. parts[2] .. parms.joins[2] |
||
end |
end |
||
if parms.warnings and not bad_input_mcode then |
if parms.warnings and not bad_input_mcode then |
||
Zeile 3.659: | Zeile 3.510: | ||
local function main_convert(frame) |
local function main_convert(frame) |
||
-- Do convert, and if needed, do it again with higher default precision. |
-- Do convert, and if needed, do it again with higher default precision. |
||
local parms = { frame = frame } -- will hold template arguments, after translation |
|||
set_config(frame.args) |
set_config(frame.args) |
||
local |
local result, out_unit_table |
||
local success, parms, in_unit_table = get_parms(frame:getParent().args) |
|||
if success then |
if success then |
||
for i = 1, 2 do -- use counter so cannot get stuck repeating convert |
|||
if type(result) ~= 'table' then |
|||
return tostring(result) |
|||
end |
|||
local in_unit_table = result |
|||
local out_unit_table |
|||
for _ = 1, 2 do -- use counter so cannot get stuck repeating convert |
|||
success, result, out_unit_table = process(parms, in_unit_table, out_unit_table) |
success, result, out_unit_table = process(parms, in_unit_table, out_unit_table) |
||
if success and parms.do_convert_again then |
if success and parms.do_convert_again then |
||
Zeile 3.676: | Zeile 3.522: | ||
end |
end |
||
end |
end |
||
else |
|||
result = parms |
|||
end |
end |
||
if success then |
|||
-- If input=x gives a problem, the result should be just the user input |
|||
return result |
|||
-- (if x is a property like P123 it has been replaced with ''). |
|||
-- An unknown input unit would display the input and an error message |
|||
-- with success == true at this point. |
|||
-- Also, can have success == false with a message that outputs an empty string. |
|||
if parms.input_text then |
|||
if success and not parms.have_problem then |
|||
return result |
|||
end |
|||
local cat |
|||
if parms.tracking then |
|||
-- Add a tracking category using the given text as the category sort key. |
|||
-- There is currently only one type of tracking, but in principle multiple |
|||
-- items could be tracked, using different sort keys for convenience. |
|||
cat = wanted_category('tracking', parms.tracking) |
|||
end |
|||
return parms.input_text .. (cat or '') |
|||
end |
end |
||
return |
return message(result) |
||
end |
end |
||
Zeile 3.736: | Zeile 3.569: | ||
opt_sortable_debug = options.sort == 'debug', |
opt_sortable_debug = options.sort == 'debug', |
||
} |
} |
||
local utable |
|||
if options.si then |
if options.si then |
||
-- Make a dummy table of units (just one unit) for lookup to use. |
-- Make a dummy table of units (just one unit) for lookup to use. |
||
-- This makes lookup recognize any SI prefix in the unitcode. |
-- This makes lookup recognize any SI prefix in the unitcode. |
||
local symbol = options.si[1] or '?' |
local symbol = options.si[1] or '?' |
||
utable = { [symbol] = { |
|||
_name1 = symbol, |
_name1 = symbol, |
||
_name2 = symbol, |
_name2 = symbol, |
||
Zeile 3.751: | Zeile 3.585: | ||
}} |
}} |
||
end |
end |
||
local success, unit_table = lookup(parms, unitcode, 'no_combination') |
local success, unit_table = lookup(parms, unitcode, 'no_combination', utable) |
||
if not success then |
if not success then |
||
unit_table = setmetatable({ |
unit_table = setmetatable({ |
||
symbol = unitcode, name2 |
symbol = unitcode, name2 = unitcode, |
||
default = "m", defkey = "m", linkey = "m", |
|||
utype = "length", scale = 1 }, unit_mt) |
|||
end |
end |
||
local value = tonumber(options.value) or 1 |
local value = tonumber(options.value) or 1 |