# automatic number formatting with ConTeXt

I would like to have calculated numbers automatically formatted, so that my pupils can easily read long numbers in my presentations. I figured out that setupunits combined with units, are quite convenient, but they work only if the digits are already formatted with points, and you can't pass a call to tex.print within this macro, as seen in this MWE

\setcharacterspacing[frenchpunctuation]
\mainlanguage[fr]
\language[fr]

\setupunits [method=3,order=reverse]

\starttext
\unit{1.000.333}

\unit{1000333}

{\directlua{tex.print(333*999)}}

\unit{\directlua{tex.print(333*999)}}

\stoptext


What I would like is having a fourth line looking like 332 667 (eventually 332.667, which is also correct in French typography).

After a quick search on the web, I found this lua function that could be assigned as a variable and then passed to units

function comma_value(n) -- credit http://richard.warburton.it
local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$') return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right end  The trouble is my lua skills are none. As far as I understand, such a function should be declared in a \startluacode \stopluacode environment, but even then I still have the issue that \unit{\directlua(comma_value(tex.print(333*999))}  does not have any output. So, • Is there a way to get this unit, comma_value and tex.print working together? • How could I tweak the comma_value function to have an French output, something like 332.667 instead of 333,667 (I understand (num:reverse():gsub('(%d%d%d)','%1.') should do the job for integers, but what if decimals are involved?) • Last but not least, I suppose there is already a lua function doing the job in ConTeXt internal. Do you know it? • You need to call comma_value inside tex.print: \directlua{tex.print(comma_value(333*999))} – DG' Aug 31 at 12:26 • @DG' it is a very good first step: \directlua{tex.print(comma_value(333*999))} output is indeed 332,667 but \unit{\directlua{tex.print(comma_value(333*999))}}has still no output. How can I turn it to be properly processed by unit or, without \unit, to have an output like 332.667 even for digits? – sztruks Aug 31 at 14:27 • I don't now why, but \unit doesn't take the output. But you can call unit from lua with context.unit. I'll add an example in a minute. – DG' Aug 31 at 14:32 ## 2 Answers You can call \unit from within lua with context.unit and do all the formatting there: \setcharacterspacing[frenchpunctuation] \mainlanguage[fr] \language[fr] \startluacode userdata = userdata or { } function userdata.comma_value(n) -- credit http://richard.warburton.it local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end

function userdata.formatted_number(n)
context.unit(userdata.comma_value(n))
end
\stopluacode

\setupunits [method=3]

\starttext

A formatted number: \directlua{userdata.formatted_number(333.3*999.9)}

\stoptext


You can also make a ConTeXt-command that wraps around your lua-code:

\def\formattednumber#1%
{\directlua{userdata.formatted_number(#1)}}


Now you can just use it like this: \formattednumber{333.3*999.9}

• This is really great. Could you explain the meaning of userdata = userdata or { } and why tex.print is not needed? – sztruks Aug 31 at 14:54
• userdata is the namespace for your own functions, using it is a precaution against accidentally messing with the lua internals. tex.print is not needed since context.unit already produces the output. – DG' Aug 31 at 15:00

If you want to do it using \unit, you have to expand the call to \directlua first. I'm using \cldcontext which is essentially a shortcut for \directlua{tex.sprint(...)} (with extra bells and whistles). To expand \cldcontext before \unit I use \expanded.

\setcharacterspacing[frenchpunctuation]
\mainlanguage[fr]
\language[fr]

\setupunits [method=3]

\startluacode

function userdata.comma_value(n) -- credit http://richard.warburton.it
local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)\$')
return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end

\stopluacode

\starttext

\expanded{\unit{\cldcontext{userdata.comma_value(333.3*999.9)}}}

\stoptext