Module:ConvertIB
Appearance
![]() | This Lua module is used on approximately 222,000 pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
A Lua module that implements {{convinfobox}}: a wrapper around {{convert}} designed for infoboxes.
Usage
{{#invoke:ConvertIB|convert}}
- Like {{convinfobox}}, accepts alternating series of pairs of [blank|value], unit . When a unit has a non-blank value, it will get converted to all other units that do have blank values
- Accepts all named parameters that {{convert}} does
- Accepts groups of multiple units (e.g., "5 ft 6 in") that {{convert}} does
require('strict')localp={}localgetArgs=require('Module:Arguments').getArgs-- Units accepted by {{convert}} that come in groups (e.g., "5 ft 6 in")localmultiple={'mich','michlk','michainlk','miyd','miydftin','mift','ydftin','ydft','ftin','footin','handin','lboz','stlb','stlboz','stlb'}-- Convert unit list to hashlocalmult_table={}for_,vinipairs(multiple)domult_table[v]=trueend-- Function to pull out values and units from numeric args-- Returns:-- values: list of numeric values, or "false" if no numeric argument is given-- units: list of units (str)-- value: if there is a last numeric value unpaired with a unit, it becomes the precision-- anyValue: whether there is a non-false value in the values listlocalfunctionparseValuesUnits(args)localvalues={}localunits={}localindx=1localvalue=nillocalanyValue=false-- loop through numeric arguments in pairswhileargs[indx]orargs[indx+1]dovalue=args[indx]anyValue=anyValueorvalue-- if there is a unit, save in output listsifargs[indx+1]thentable.insert(values,valueorfalse)table.insert(units,args[indx+1])value=nilendindx=indx+2endreturnvalues,units,value,anyValueend-- Function to identify multiple units and rewrite them as new input or output groups-- Args:-- values, units: numeric values and units, as lists with same length-- Returns:-- newValues, newUnits: same lists rewrittenlocalfunctionparseMultiples(values,units)localnewValues={}localnewUnits={}locali=1-- we will search for multiples with up to 4 entries (depending on length)localmaxMultiple=math.min(4,#units-1)localvalueFound=false-- flag to suppress second (and later) input values--- Hack for handling "stone": check if only value supplied is "lb"localonlyPounds=truefori=1,#unitsdoifvalues[i]andunits[i]~='lb'thenonlyPounds=falsebreakendend-- sweep through unitswhilei<=#unitsdo-- determine index of last possible unit that could contain a multiplelocallast_unit=math.min(i+maxMultiple-1,#units)localmultipleFound=false-- try from longest multiple down to double multiple (prefer longest ones)forj=last_unit,i+1,-1dolocalkey=table.concat({unpack(units,i,j)},'')ifmult_table[key]then-- we found a multiple unitmultipleFound=true-- Hack for "stone": add either 'lb' or multiple unit string to output units-- depending on whether 'lb' was the only unit string with a valueifmw.ustring.sub(key,1,2)=='st'thentable.insert(newValues,false)table.insert(newUnits,onlyPoundsandkeyor'lb')end-- if there are any value in the span of the multiple,-- then the multiple is an input-- assume all missing values after the first are zerolocalfirstValueFound=falsefork=i,jdofirstValueFound=notvalueFoundand(firstValueFoundorvalues[k])iffirstValueFoundthentable.insert(newValues,values[k]or0)table.insert(newUnits,units[k])endendvalueFound=valueFoundorfirstValueFound-- if no values in the span of the multiple,-- then the multiple is an output. Insert combined string as output unitifnotfirstValueFoundthentable.insert(newValues,false)table.insert(newUnits,key)endi=j+1breakendend--- If no multiple unit was found, insert value[i] and unit[i] into rewritten listsifnotmultipleFoundthenifvalueFoundthentable.insert(newValues,false)-- skip writing value if it is a duplicateelsetable.insert(newValues,values[i])valueFound=values[i]endtable.insert(newUnits,units[i])i=i+1endendreturnnewValues,newUnitsend-- Implement {{convinfobox}}functionp._convert(args)-- find all values and units in numeric args (and the precision, if it exists)localvalues,units,precision,anyValue=parseValuesUnits(args)-- bail if no values at allifnotanyValuethenreturnnilend-- rewrite values and units if multiple units are foundvalues,units=parseMultiples(values,units)-- sort input and outputs into different bucketslocalinput_values={}localinput_units={}localoutput_units={}fori=1,#unitsdoifvalues[i]thentable.insert(input_values,values[i])table.insert(input_units,units[i])elsetable.insert(output_units,units[i])endend-- bail if nothing to convertif#input_values==0or#output_units==0thenreturnnilend-- assemble argument list to {{convert}}localinnerArgs={}-- First, pass all input unit(s)fori,vinipairs(input_values)dotable.insert(innerArgs,v)table.insert(innerArgs,input_units[i])end-- Then the output unit(s) [concatenated as single argument]table.insert(innerArgs,table.concat(output_units,"+"))ifprecisionthentable.insert(innerArgs,precision)-- last non-nil value contains precisionend-- now handle all non-numeric arguments, passing to {{convert}}innerArgs.abbr='on'-- abbr=on by defaultfork,vinpairs(args)doifnottonumber(k)theninnerArgs[k]=vendend-- Call {{convert}} with innerArgslocalframe=mw.getCurrentFrame()returnframe:expandTemplate{title='Convert',args=innerArgs}endfunctionp.convert(frame)localargs=getArgs(frame)returnp._convert(args)or""endreturnp