Editing Module:Convert
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 136: | Line 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 function set_config(args) | local function set_config(args) | ||
Line 149: | Line 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 | ||
− | |||
− | |||
spell_module = "Module:ConvertNumeric" | spell_module = "Module:ConvertNumeric" | ||
data_code = mw.loadData(data_module) | data_code = mw.loadData(data_module) | ||
Line 259: | Line 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. |
− | |||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
if title then | if title then | ||
Line 269: | Line 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 | ||
− | cat | + | return cat |
− | |||
− | |||
− | |||
− | |||
end | end | ||
end | end | ||
end | end | ||
− | |||
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 | + | local msg = text_code.all_messages[mcode[1]] |
− | + | local nowiki = mw.text.nowiki | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | local | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
if msg then | if msg then | ||
local parts = {} | local parts = {} | ||
Line 330: | Line 305: | ||
append = '...' | append = '...' | ||
end | end | ||
− | s = | + | s = nowiki(s) .. (append or '') |
else | else | ||
s = '?' | s = '?' | ||
end | end | ||
− | parts[ | + | parts[i] = s |
end | end | ||
− | + | local title = format(msg[1] or 'Missing message', parts[1], parts[2], parts[3]) | |
− | + | local text = msg[2] or 'Missing message' | |
− | + | local cat = wanted_category(text_code.all_categories[msg[3]]) or '' | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | local title = | ||
− | local text = | ||
− | local cat = wanted_category(msg[3] | ||
local anchor = msg[4] or '' | local anchor = msg[4] or '' | ||
− | local | + | local fmt = text_code.all_messages[msg.format or 'cvt_format'] or 'convert: bug' |
− | + | title = title:gsub('"', '"') | |
− | + | return format(fmt, anchor, title, text, cat) | |
− | |||
end | end | ||
return 'Convert internal error: unknown message' | return 'Convert internal error: unknown message' | ||
Line 364: | Line 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. | ||
− | |||
-- To reduce output noise, only the first warning is displayed. | -- To reduce output noise, only the first warning is displayed. | ||
− | if level <= (tonumber(config.warnings) or 1) then | + | if config.warnings or level < 0 then |
− | + | if level <= (tonumber(config.warnings) or 1) then | |
− | + | if parms.warnings == nil then | |
+ | parms.warnings = message({ key, text1, text2 }) | ||
+ | end | ||
end | end | ||
end | end | ||
Line 389: | Line 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 | ||
Line 590: | Line 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. |
− | |||
__index = function (self, key) | __index = function (self, key) | ||
local value | local value | ||
Line 616: | Line 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 = {} } |
− | |||
− | |||
− | |||
− | |||
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 | ||
Line 676: | Line 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 | ||
Line 689: | Line 645: | ||
end | end | ||
unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ') | unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ') | ||
− | |||
− | |||
− | |||
− | |||
− | |||
local t = utable[unitcode] | local t = utable[unitcode] | ||
if t then | if t then | ||
Line 715: | Line 666: | ||
end | end | ||
if t.per then | if t.per then | ||
− | return | + | return make_per(t, function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end) |
end | end | ||
local combo = t.combination -- nil or a table of unitcodes | local combo = t.combination -- nil or a table of unitcodes | ||
Line 735: | Line 686: | ||
end | end | ||
local result = shallow_copy(t) | local result = shallow_copy(t) | ||
− | |||
if result.prefixes then | if result.prefixes then | ||
result.si_name = '' | result.si_name = '' | ||
Line 754: | Line 704: | ||
if t and t.prefixes then | if t and t.prefixes then | ||
local result = shallow_copy(t) | local result = shallow_copy(t) | ||
− | |||
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 | ||
result.scale = t.scale * 10 ^ (si.exponent * t.prefixes) | result.scale = t.scale * 10 ^ (si.exponent * t.prefixes) | ||
return true, setmetatable(result, unit_prefixed_mt) | return true, setmetatable(result, unit_prefixed_mt) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | -- Accept any unit with an engineering notation prefix like "e6cuft" | ||
+ | -- (million cubic feet), but not chained prefixes like "e3e6cuft", | ||
+ | -- and not if the unit is a combination or multiple, | ||
+ | -- and not if the unit has an offset or is a built-in. | ||
+ | -- Only en digits are accepted. | ||
+ | local has_plus = unitcode:find('+', 1, true) | ||
+ | if not has_plus then | ||
+ | local exponent, baseunit = unitcode:match('^e(%d+)(.*)') | ||
+ | if exponent then | ||
+ | local engscale = text_code.eng_scales[exponent] | ||
+ | if engscale then | ||
+ | local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth) | ||
+ | if success and not (result.offset or result.builtin or result.engscale) then | ||
+ | result.defkey = unitcode -- key to lookup default exception | ||
+ | result.engscale = engscale | ||
+ | result.scale = result.scale * 10 ^ tonumber(exponent) | ||
+ | return true, result | ||
+ | end | ||
end | end | ||
end | end | ||
Line 768: | Line 738: | ||
local err_is_fatal | local err_is_fatal | ||
local combo = collection() | local combo = collection() | ||
− | if | + | if has_plus then |
err_is_fatal = true | err_is_fatal = true | ||
for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do | for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do | ||
Line 805: | Line 775: | ||
if success or err_is_fatal then | if success or err_is_fatal then | ||
return success, result | return success, result | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
end | end | ||
Line 833: | Line 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 | ||
Line 960: | Line 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 | ||
Line 1,043: | Line 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. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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) | ||
Line 1,327: | Line 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*$') | ||
Line 1,340: | Line 1,293: | ||
return nil | return nil | ||
end | end | ||
− | local | + | local wholestr |
if prefix == '' then | if prefix == '' then | ||
wholestr = '' | wholestr = '' | ||
Line 1,379: | Line 1,332: | ||
-- Before processing, the input text is cleaned: | -- Before processing, the input text is cleaned: | ||
-- * Any thousand separators (valid or not) are removed. | -- * Any thousand separators (valid or not) are removed. | ||
− | -- * Any sign is replaced with '-' (if negative) or '' (otherwise). | + | -- * Any sign (and optional following whitespace) is replaced with |
+ | -- '-' (if negative) or '' (otherwise). | ||
-- That replaces Unicode minus with '-'. | -- That replaces Unicode minus with '-'. | ||
-- If successful, the returned info table contains named fields: | -- If successful, the returned info table contains named fields: | ||
Line 1,405: | Line 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) | ||
Line 1,439: | Line 1,393: | ||
local valstr | local valstr | ||
for _, prefix in ipairs({ '-', MINUS, '−' }) do | for _, prefix in ipairs({ '-', MINUS, '−' }) do | ||
− | -- Including '-' sets isnegative in case input is a fraction like '-2-3/4'. | + | -- Including '-' means inputs like '- 2' (with space) are accepted as -2. |
+ | -- It also sets isnegative in case input is a fraction like '-2-3/4'. | ||
local plen = #prefix | local plen = #prefix | ||
if clean:sub(1, plen) == prefix then | if clean:sub(1, plen) == prefix then | ||
valstr = clean:sub(plen + 1) | valstr = clean:sub(plen + 1) | ||
− | |||
− | |||
− | |||
break | break | ||
end | end | ||
Line 1,508: | Line 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, | ||
Line 1,533: | Line 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 | ||
Line 1,611: | Line 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 space | + | -- 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 ' ' |
− | + | -- or '-' at that position ('-' is for adjectival text). | |
− | + | local current = text:sub(i, i) | |
− | + | if current == ' ' or current == '-' then | |
− | local | + | return text |
− | if | ||
− | return text | ||
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 | |
− | + | end | |
− | + | if i == 1 then | |
− | + | return ' ' .. text | |
end | end | ||
− | return text | + | return text .. ' ' |
end | end | ||
− | |||
preunit1 = preunit1 or '' | preunit1 = preunit1 or '' | ||
local trim1 = strip(preunit1) | local trim1 = strip(preunit1) | ||
Line 1,640: | Line 1,592: | ||
return nil | return nil | ||
end | end | ||
− | + | return withspace(withspace(preunit1, 1), -1) | |
− | |||
− | |||
− | return withspace(preunit1, | ||
end | end | ||
− | |||
preunit2 = preunit2 or '' | preunit2 = preunit2 or '' | ||
local trim2 = strip(preunit2) | local trim2 = strip(preunit2) | ||
− | if trim1 == ' | + | if trim1 == '' and trim2 == '' then |
− | + | return nil, nil | |
− | + | end | |
− | + | if trim1 ~= '+' then | |
− | preunit1 = | + | preunit1 = withspace(preunit1, 1) |
end | end | ||
− | if trim2 == '' then | + | if trim2 == ' ' then -- trick to make preunit2 empty |
− | + | preunit2 = nil | |
− | + | elseif trim2 == '' then | |
− | |||
preunit2 = preunit1 | preunit2 = preunit1 | ||
− | elseif trim2 | + | elseif trim2 ~= '+' then |
− | + | preunit2 = withspace(preunit2, 1) | |
− | |||
− | |||
− | |||
− | preunit2 = withspace(preunit2) | ||
end | end | ||
return preunit1, preunit2 | return preunit1, preunit2 | ||
Line 1,696: | Line 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) | ||
Line 1,767: | Line 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 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 | ||
Line 1,783: | Line 1,718: | ||
kv_pairs.sing = nil | kv_pairs.sing = nil | ||
end | end | ||
− | |||
for loc_name, loc_value in pairs(kv_pairs) do | for loc_name, loc_value in pairs(kv_pairs) do | ||
local en_name = text_code.en_option_name[loc_name] | local en_name = text_code.en_option_name[loc_name] | ||
Line 1,809: | Line 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 -- accept user text with no validation | |
− | |||
− | |||
− | |||
− | |||
− | |||
else | else | ||
en_value = text_code.en_option_value[en_name][loc_value] | en_value = text_code.en_option_value[en_name][loc_value] | ||
Line 1,867: | Line 1,796: | ||
end | end | ||
if parms.abbr then | if parms.abbr then | ||
− | |||
− | |||
− | |||
− | |||
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 | ||
Line 1,877: | Line 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 | end | ||
if parms.opt_spell_out and not abbr_entered then | if parms.opt_spell_out and not abbr_entered then | ||
Line 2,045: | Line 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 | ||
local clean = to_en(strip(parms[1] or ''), parms) | local clean = to_en(strip(parms[1] or ''), parms) | ||
− | if | + | if #clean > 10 or not clean:match('^[0-9.]+$') then return end |
− | |||
− | |||
local value = tonumber(clean) | local value = tonumber(clean) | ||
if not value then return end | if not value then return end | ||
Line 2,072: | Line 1,989: | ||
end | end | ||
− | + | local function get_parms(args) | |
− | + | -- If successful, return true, parms, unit where | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | local function get_parms( | ||
− | -- If successful, | ||
-- 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. | ||
− | |||
− | |||
-- 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. | ||
Line 2,105: | Line 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 | ||
Line 2,112: | Line 2,009: | ||
kv_pairs[k] = v | kv_pairs[k] = v | ||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 | ||
− | |||
− | |||
− | |||
− | |||
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 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
local valinfo | local valinfo | ||
success, valinfo, i = get_values(parms) | success, valinfo, i = get_values(parms) | ||
Line 2,140: | Line 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 = 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 | ||
Line 2,182: | Line 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 | ||
Line 2,197: | Line 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 | ||
Line 2,204: | Line 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 | ||
Line 2,250: | Line 2,132: | ||
parms.precision = precision | parms.precision = precision | ||
end | end | ||
− | + | return true, parms, in_unit_table | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
Line 2,293: | Line 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" | ||
Line 2,530: | Line 2,406: | ||
end | end | ||
local sortspan | local sortspan | ||
− | if sortkey and not parms.table_align then | + | if sortkey and (parms.opt_sortable_debug or not parms.table_align) then |
sortspan = parms.opt_sortable_debug and | sortspan = parms.opt_sortable_debug and | ||
− | ' | + | '<span style="border:1px solid;display:inline;" class="sortkey">' .. sortkey .. '♠</span>' or |
− | '<span | + | '<span style="display:none" class="sortkey">' .. sortkey .. '♠</span>' |
parms.join_before = sortspan | parms.join_before = sortspan | ||
end | end | ||
if parms.table_align then | if parms.table_align then | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
local style = 'style="text-align:' .. parms.table_align .. ';' | local style = 'style="text-align:' .. parms.table_align .. ';' | ||
+ | local sort = sortkey and ' data-sort-value="' .. sortkey .. '"' or '' | ||
local joins = {} | local joins = {} | ||
for i = 1, 2 do | for i = 1, 2 do | ||
Line 2,565: | Line 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 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 | ||
Line 2,590: | Line 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 | ||
Line 2,842: | Line 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 make_link(link, id, link_key) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | local function make_link(link, id, | ||
-- Return wikilink "[[link|id]]", possibly abbreviated as in examples: | -- Return wikilink "[[link|id]]", possibly abbreviated as in examples: | ||
-- [[Mile|mile]] --> [[mile]] | -- [[Mile|mile]] --> [[mile]] | ||
Line 2,857: | Line 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 | |
− | + | -- overlinking for conversions like the following (each links "mile" twice): | |
− | + | -- {{convert|1|impgal/mi|USgal/mi|lk=on}} | |
− | + | -- {{convert|1|l/km|impgal/mi USgal/mi|lk=on}} | |
− | + | 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) | |
− | |||
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 | ||
Line 2,906: | Line 2,775: | ||
else | else | ||
i = 3 | i = 3 | ||
− | |||
− | |||
− | |||
end | end | ||
vname = split(unit_table.varname, '!')[i] | vname = split(unit_table.varname, '!')[i] | ||
Line 2,939: | Line 2,805: | ||
local per = unit_table.per | local per = unit_table.per | ||
if per then | if per then | ||
− | |||
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 | ||
Line 2,951: | Line 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 | end | ||
end | end | ||
Line 2,993: | Line 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 | ||
Line 3,074: | Line 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) | ||
Line 3,158: | Line 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">' .. | |
− | + | from_en('10') .. | |
− | + | '</span></span><s style="display:none">^</s><sup>' .. | |
− | + | from_en(tostring(engscale.exponent)) .. '</sup>' | |
elseif number_word then | elseif number_word then | ||
local number_id | local number_id | ||
Line 3,220: | Line 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 | ||
Line 3,265: | Line 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 | |
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 | ||
Line 3,302: | Line 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 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 | ||
Line 3,324: | Line 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 | ||
Line 3,333: | Line 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 | |
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 | ||
Line 3,357: | Line 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 | ||
Line 3,374: | Line 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() | |
− | + | local range = parms.range | |
− | + | for i = 1, (range and (range.n + 1) or 1) do | |
− | + | local success, info = cvtround(parms, in_unit_table.valinfo[i], in_unit_table, out_unit_table) | |
− | + | if not success then return false, info end | |
− | + | out_unit_table.valinfo:add(info) | |
− | |||
− | |||
− | |||
end | end | ||
return true, process_one_output(parms, out_unit_table) | return true, process_one_output(parms, out_unit_table) | ||
Line 3,391: | Line 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 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) | ||
Line 3,398: | Line 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 = ' ' | ||
Line 3,415: | Line 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') | ||
Line 3,497: | Line 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 | ||
Line 3,503: | Line 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 | ||
Line 3,530: | Line 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 | ||
Line 3,537: | Line 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) | |
− | success, out_unit = | ||
parms.out_unit = out_unit | parms.out_unit = out_unit | ||
if not success then | if not success then | ||
Line 3,566: | Line 3,424: | ||
end | end | ||
end | end | ||
− | |||
local flipped = parms.opt_flip and not bad_input_mcode | local flipped = parms.opt_flip and not bad_input_mcode | ||
− | if bad_output then | + | local parts = {} |
− | + | for part = 1, 2 do | |
− | + | -- The LHS (parts[1]) is normally the input, but is the output if flipped. | |
− | + | -- Process LHS first so it will be linked, if wanted. | |
− | + | -- Linking to the same item is suppressed in the RHS to avoid overlinking. | |
− | + | if (part == 1 and not flipped) or (part == 2 and flipped) then | |
− | + | parts[part] = process_input(parms, in_unit_table) | |
− | + | elseif bad_output then | |
− | + | parts[part] = (bad_output == '') and '' or message(bad_output) | |
− | + | else | |
− | + | local outputs = {} | |
− | + | 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') | |
− | + | combos = out_unit_table.combination | |
− | + | end | |
− | + | local frac = parms.frac -- nil or denominator of fraction for output values | |
− | + | if frac then | |
− | + | -- Apply fraction to the unit (if only one), or to non-SI units (if a combination), | |
− | + | -- except that if a precision is also specified, the fraction only applies to | |
− | + | -- the hand unit; that allows the following result: | |
− | + | -- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands) | |
− | + | -- However, the following is handled elsewhere as a special case: | |
+ | -- {{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 | ||
− | |||
− | |||
end | end | ||
− | + | local out_first | |
− | + | local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables | |
− | + | 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 | |
− | + | out_first = out_current | |
− | + | 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 | end | ||
− | if | + | if out_current.multiple then |
− | out_current | + | success, item = make_output_multiple(parms, in_unit_table, out_current) |
+ | 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] = '' | |
else | else | ||
− | + | local sep = parms.table_joins and parms.table_joins[2] or parms.join_between | |
+ | parts[part] = table.concat(outputs, sep) | ||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 | ||
Line 3,665: | Line 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. | ||
− | |||
set_config(frame.args) | set_config(frame.args) | ||
− | local success, | + | 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 | |
− | |||
− | |||
− | |||
− | |||
− | for | ||
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 | ||
Line 3,682: | Line 3,522: | ||
end | end | ||
end | end | ||
+ | else | ||
+ | result = parms | ||
end | end | ||
− | + | if success then | |
− | + | return result | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | return | + | return message(result) |
end | end | ||
Line 3,742: | Line 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, | ||
Line 3,757: | Line 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 = 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 |