7

In the luadraw documentation

numericFormat={0,0}. Cette option précise le type d’affiche numérique (non encore implémenté).

numericFormat={0,0}. This option specifies the type of numeric display (not yet implemented). (google traduction)

In the meantime, I used siunitx to get the decimal point in the number display.

Wouldn't there be a more efficient way by globally changing the point to comma in Lua?

enter image description here

With siunitx and

for k = 0, 2.8 , 0.4 do
  g:Dlabel("$\\num{"..k.."}$",k,{pos="S",dist=0.08})
end

enter image description here

Code

% !TeX TS-program = lualatex
\documentclass{standalone}
\usepackage{luadraw}%https://github.com/pfradin/luadraw/
\usepackage[locale=FR]{siunitx}% pour avoir la virgule
\begin{document}
\begin{luadraw}{name=virgule}
local g = graph:new{
  window={-1,4,-1,8,1,0.4},
  size={10,10}
  }
--
defaultlabelshift = 0
g:Labelsize("scriptsize")
--
g:Daxes({0,0.4,1},
    {
        arrows="->",
        limits={{0,3.2},{0,8}},
        nbsubdiv={1,1},
        legend={"Temps (en seconde)","Hauteur (en mètre)"},
        legendpos={0.8,0.975},
        legendsep={0.4,0.},
        labelpos={"none","left"},-- pour ne pas mettre les graduations x
        grid=true,
        gridcolor="lightgray"
    })
--    
-- bricolage pour avoir la virgule
--
for k = 0, 2.8 , 0.4 do
  g:Dlabel("$\\num{"..k.."}$",k,{pos="S",dist=0.08})
end
--
g:Show()
\end{luadraw}
\end{document}

3 Answers 3

7

This is a very French problem :) that might have been more appropriate in the luadraw discussions on GitHub. This isn't currently planned, but it's easy to implement (for the next version). In the meantime, you can use the myxlabels option, which allows you to add your own labels to the Ox axis, but it's not very practical...

% !TeX TS-program = lualatex
\documentclass{standalone}
\usepackage{luadraw}%https://github.com/pfradin/luadraw/
\usepackage[locale=FR]{siunitx}% pour avoir la virgule
\begin{document}
\begin{luadraw}{name=virgule}
local g = graph:new{
  window={-1,4,-1,8,1,0.4},
  size={10,10}
  }
--
defaultlabelshift = 0
g:Labelsize("scriptsize")
--
local mygrad = function(grad1,grad2,unit)
    local rep = {}
    for x = grad1, grad2 do
        table.insert(rep,x); table.insert(rep,"$\\num{"..x*unit.."}$")
    end
    return rep
end
--
g:Daxes({0,0.4,1},
    {
        arrows="->",
        limits={{0,3.2},{0,8}},
        nbsubdiv={1,1},
        legend={"Temps (en seconde)","Hauteur (en mètre)"},
        legendpos={0.8,0.975},
        legendsep={0.4,0.},
        grid=true,
        gridcolor="lightgray",
        myxlabels = mygrad(0,7,0.4) -- from graduation 0 to graduation 7 with a step of 0.4
    })
--    
g:Show()
\end{luadraw}
\end{document}

enter image description here

2
  • Maybe, the possibility to apply a macro to each label could be useful. Can you open an issue for this on github? Commented Sep 6, 2025 at 13:38
  • 1
    This is already done in version 2.1 Commented Sep 6, 2025 at 14:25
5

It seems that switching the decimal point to a comma on the Lua side in LuaTeX isn’t safe. And I don’t think it’s necessary either. You can use the following approach: print numbers with a comma, as in the following code.

\documentclass{article}
\usepackage{luacode}
\usepackage{siunitx}
\sisetup{output-decimal-marker = {,}} % global: decimal comma

% Lua helper for printing numbers via \num{...}
\begin{luacode*}
-- print number using siunitx \num{...}; precision can be adjusted
local function fmt_number(x, prec)
  prec = prec or 15
  local s = string.format("%." .. prec .. "g", x)  -- stable numeric -> string
  tex.sprint("\\num{" .. s .. "}")
end

-- Export short name: num( <number>[, <precision>] )
num = fmt_number
\end{luacode*}

\begin{document}

Plain Lua -> TeX:
\directlua{num(3.14159)}
\par
With precision:
\directlua{num(math.pi, 4)} % 3,142

\end{document}

enter image description here

1

Wouldn't there be a more efficient way by globally changing the point to comma in Lua?

We can globally replace any periods between numbers with commas in text by adding a new font feature and in math by manually walking the node list:

\documentclass{article}

\usepackage{luacode}
\begin{luacode*}
    -- Constants
    local comma      = utf8.codepoint(",")
    local digits     = { utf8.codepoint("0123456789", 1, -1)}
    local digits_set = table.tohash(digits)
    local glyph_id   = node.id("glyph")
    local period     = utf8.codepoint(".")

    -- Cache the results of a function as a table.
    local function memoized(func)
        return setmetatable({}, { __index = function(cache, key)
            local ret = func(key, cache)
            cache[key] = ret
            return ret
        end })
    end

    -- Convert a font ID and character index to Unicode characters.
    local font_to_unicode = memoized(function(font_id)
        local font = font.getfont(font_id)

        return memoized(function(char)
            local codes = (font.characters[char] or {}).unicode
            if type(codes) == "table" then
                return utf8.char(unpack(codes))
            elseif type(codes) == "number" then
                return utf8.char(codes)
            else
                return utf8.char(char)
            end
        end)
    end)

    -- Text mode: Add a new font feature that replaces periods surrounded by
    -- digits with commas.
    fonts.handlers.otf.addfeature {
        name = "periodtocomma",
        type = "chainsubstitution",
        lookups = {
            {
                type = "multiple",
                data = {
                    [period] = { comma },
                }
            },
        },
        data = {
            rules = {
                {
                    before = { digits },
                    current = { { period } },
                    after = { digits },
                    lookups = { 1 },
                },
            },
        },
    }

    -- Enable this feature for all fonts by default.
    luaotfload.features.global["periodtocomma"] = true

    -- Math mode: Manually iterate over all glyph nodes, and replace periods
    -- surrounded by digits with commas.
    local function recurse(head)
        for n in node.traverse(head) do
            if n.id == glyph_id then
                local char = font_to_unicode[n.font][n.char]
                if char == "." then
                    local prev = n.prev
                    local next = n.next
                    if  prev and
                        next and
                        prev.id == glyph_id and
                        next.id == glyph_id
                    then
                        local prev_char = font_to_unicode[prev.font][prev.char]
                        local next_char = font_to_unicode[next.font][next.char]
                        if digits_set[utf8.codepoint(prev_char)] and
                           digits_set[utf8.codepoint(next_char)]
                        then
                            n.char = comma
                        end
                    end
                end
            end
            if n.list then
                n.list = recurse(n.list)
            end
        end
        return head
    end

    luatexbase.add_to_callback("post_mlist_to_hlist_filter", recurse, "periodtocomma-math")
\end{luacode*}

\usepackage{fontspec}
\setmainfont{Latin Modern Roman}

\usepackage{unicode-math}
\setmathfont{Latin Modern Math}

\pagestyle{empty}

\begin{document}
    1.2 123.34 $1.2$ $123.34$
\end{document}

output

This also works as expected with luadraw:

\documentclass{standalone}

\usepackage{luacode}
\begin{luacode*}
    -- Constants
    local comma      = utf8.codepoint(",")
    local digits     = { utf8.codepoint("0123456789", 1, -1)}
    local digits_set = table.tohash(digits)
    local glyph_id   = node.id("glyph")
    local period     = utf8.codepoint(".")

    -- Cache the results of a function as a table.
    local function memoized(func)
        return setmetatable({}, { __index = function(cache, key)
            local ret = func(key, cache)
            cache[key] = ret
            return ret
        end })
    end

    -- Convert a font ID and character index to Unicode characters.
    local font_to_unicode = memoized(function(font_id)
        local font = font.getfont(font_id)

        return memoized(function(char)
            local codes = (font.characters[char] or {}).unicode
            if type(codes) == "table" then
                return utf8.char(unpack(codes))
            elseif type(codes) == "number" then
                return utf8.char(codes)
            else
                return utf8.char(char)
            end
        end)
    end)

    -- Text mode: Add a new font feature that replaces periods surrounded by
    -- digits with commas.
    fonts.handlers.otf.addfeature {
        name = "periodtocomma",
        type = "chainsubstitution",
        lookups = {
            {
                type = "multiple",
                data = {
                    [period] = { comma },
                }
            },
        },
        data = {
            rules = {
                {
                    before = { digits },
                    current = { { period } },
                    after = { digits },
                    lookups = { 1 },
                },
            },
        },
    }

    -- Enable this feature for all fonts by default.
    luaotfload.features.global["periodtocomma"] = true

    -- Math mode: Manually iterate over all glyph nodes, and replace periods
    -- surrounded by digits with commas.
    local function recurse(head)
        for n in node.traverse(head) do
            if n.id == glyph_id then
                local char = font_to_unicode[n.font][n.char]
                if char == "." then
                    local prev = n.prev
                    local next = n.next
                    if  prev and
                        next and
                        prev.id == glyph_id and
                        next.id == glyph_id
                    then
                        local prev_char = font_to_unicode[prev.font][prev.char]
                        local next_char = font_to_unicode[next.font][next.char]
                        if digits_set[utf8.codepoint(prev_char)] and
                           digits_set[utf8.codepoint(next_char)]
                        then
                            n.char = comma
                        end
                    end
                end
            end
            if n.list then
                n.list = recurse(n.list)
            end
        end
        return head
    end

    luatexbase.add_to_callback("post_mlist_to_hlist_filter", recurse, "periodtocomma-math")
\end{luacode*}

\usepackage{luadraw}%https://github.com/pfradin/luadraw/
\usepackage[locale=FR]{siunitx}% pour avoir la virgule
\begin{document}
\begin{luadraw}{name=virgule}
local g = graph:new{
  window={-1,4,-1,8,1,0.4},
  size={10,10}
  }
--
defaultlabelshift = 0
g:Labelsize("scriptsize")
--
g:Daxes({0,0.4,1},
    {
        arrows="->",
        limits={{0,3.2},{0,8}},
        nbsubdiv={1,1},
        legend={"Temps (en seconde)","Hauteur (en mètre)"},
        legendpos={0.8,0.975},
        legendsep={0.4,0.},
        labelpos={"none","left"},-- pour ne pas mettre les graduations x
        grid=true,
        gridcolor="lightgray"
    })
--
-- bricolage pour avoir la virgule
--
for k = 0, 2.8 , 0.4 do
  g:Dlabel("$\\num{"..k.."}$",k,{pos="S",dist=0.08})
end
--
g:Show()
\end{luadraw}
\end{document}

output

1
  • 1
    The luadraw example you took already adds commas by itself. I tested with an other example, and I confirm that your code adds the commas even in luadraw. Thanks Commented Sep 10, 2025 at 8:01

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.