Module:Wp/bgn/Gapnum

From Wikimedia Incubator

Documentation for this module may be created at Module:Wp/bgn/Gapnum/doc

local p = {}

local getArgs

function p.main(frame)
	if not getArgs then
		getArgs = require('Module:Wp/bg/Arguments').getArgs
	end
	local args = getArgs(frame, {wrappers = 'Template:Wp/bgn/Gapnum'})
	local gap =  args.gap or '0.25em'

	local ret_string = '<span style="white-space:nowrap">'

	if not args[1] then
		error('Parameter 1 is required')
	end
	local n = args[1]
	if not tonumber(n) then
		error('Unable to convert "' .. args[1] .. '" to a number')
	end
	
	local nstr = tostring(n)
	local decimalloc = nstr:find('.', 1, true)
	local int_part, frac_part
	if decimalloc == nil then
		int_part = nstr
	else
		int_part = nstr:sub(1, decimalloc-1)
		frac_part = nstr:sub(decimalloc + 1)
	end
	
	local int_string = ''
	-- Loop to handle most of the groupings; from right to left, so that if a group has
	-- less than 3 members, it will be the first group
	while int_part:len() > 3 do
		int_string = '<span style="margin-left:'..gap..';">'..int_part:sub(-3)..'</span>'..int_string
		int_part = int_part:sub(1,-4)
	end
	
	-- handle any left over numbers
	int_string = int_part..int_string
	
	ret_string = ret_string..int_string
	
	local precision = tonumber(args.prec) or -1
	if precision ~= 0 and frac_part then
		local frac_string = '.'
		if precision == -1 then
			precision = frac_part:len()
		end
		-- Reduce the length of the string if required precision is less than actual precision
		-- OR
		-- Increase it (by adding 0s) if the required precision is more than actual
		local offset = precision - frac_part:len()
		if offset < 0 then
			frac_part = frac_part:sub(1,precision)
		elseif offset > 0 then
			frac_part = frac_part .. string.rep('0', offset)
		end
		
		-- The first group after the decimal shouldn't have a gap between the decimal
		if frac_part:len() >= 3 then
			frac_string = frac_string..frac_part:sub(1,3)
			frac_part = frac_part:sub(4)
		else
			frac_string = frac_string..frac_part
			frac_part = ''
		end
		
	-- Loop to handle most of the groupings; from left to right, so that if a group has
	-- less than 3 members, it will be the last group
		while frac_part:len() >= 3 do
			frac_string = frac_string..'<span style="margin-left:'..gap..';">'..frac_part:sub(1,3)..'</span>'
			frac_part = frac_part:sub(4)
		end
	
		-- Handle any left over numbers
		if frac_part:len() > 0 then
			frac_string = frac_string..'<span style="margin-left:'..gap..';">'..frac_part..'</span>'
		end
		
		if frac_string:len() > 1 then
			ret_string = ret_string..frac_string
		end
	end
	
	-- Closing span tag
	ret_string = ret_string..'</span>'

	return ret_string
end

return p