meta-tex.lua /size: 5242 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['meta-tex'] = {
2    version   = 1.001,
3    comment   = "companion to meta-tex.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local tostring, tonumber = tostring, tonumber
10local format, find, gsub = string.format, string.find, string.gsub
11local formatters = string.formatters
12local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
13
14metapost        = metapost or { }
15local metapost  = metapost
16local context   = context
17
18local implement = interfaces.implement
19
20do
21
22    local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0) -- or \char
23
24    function metapost.escaped(str)
25        context(lpegmatch(pattern,str))
26    end
27
28    implement {
29        name      = "metapostescaped",
30        actions   = metapost.escaped,
31        arguments = "string"
32    }
33
34end
35
36do
37
38    local simplify = true
39    local number   = C((S("+-")^0 * R("09","..")^1))
40    local enumber  = number * S("eE") * number
41    local cleaner  = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0)
42
43    local function format_string(fmt,...)
44        context(lpegmatch(cleaner,fmt),...)
45    end
46
47    local function format_number(fmt,num)
48        if not num then
49            num = fmt
50            fmt = "%e"
51        end
52        local number = tonumber(num)
53        if number then
54            if find(fmt,"[mMfFgG]$") then
55                local clean = gsub(fmt,"@","%%")
56                context(formatters[clean](number))
57            elseif find(fmt,"[dD]$") then
58                local clean = gsub(fmt,"[dD]$","")
59                clean = gsub(clean,"@","%%")
60                context.digits(formatters[clean](number))
61            else
62                local clean = lpegmatch(cleaner,fmt)
63                local base, exponent = lpegmatch(enumber,formatters[clean](number))
64                if base and exponent then
65                    context.MPexponent(base,exponent)
66                else
67                    context(number)
68                end
69            end
70        else
71            context(tostring(num))
72        end
73    end
74
75    -- This is experimental and will change!
76
77    metapost.format_string = format_string
78    metapost.format_number = format_number
79
80    function metapost.svformat(fmt,str)
81        format_string(fmt,metapost.untagvariable(str,false))
82    end
83
84    function metapost.nvformat(fmt,str)
85        format_number(fmt,metapost.untagvariable(str,false))
86    end
87
88    local f_exponent = formatters["\\MPexponent{%s}{%s}"]
89
90    -- can be a weak one: mpformatters
91
92    local mpformatters = table.setmetatableindex(function(t,k)
93        local v = formatters[lpegmatch(cleaner,k)]
94        t[k] = v
95        return v
96    end)
97
98    function metapost.texexp(num,bfmt,efmt)
99        local number = tonumber(num)
100        if number then
101            local base, exponent = lpegmatch(enumber,format("%e",number))
102            if base and exponent then
103                if bfmt then
104                 -- base = formatters[lpegmatch(cleaner,bfmt)](base)
105                    base = mpformatters[bfmt](base)
106                else
107                    base = format("%f",base)
108                end
109                if efmt then
110                 -- exponent = formatters[lpegmatch(cleaner,efmt)](exponent)
111                    exponent = mpformatters[efmt](exponent)
112                else
113                    exponent = format("%i",exponent)
114                end
115                return f_exponent(base,exponent)
116            elseif bfmt then
117             -- return formatters[lpegmatch(cleaner,bfmt)](number)
118                return mpformatters[bfmt](number)
119            else
120                return number
121            end
122        else
123            return num
124        end
125    end
126
127    implement {
128        name      = "metapostformatted",
129        actions   = metapost.svformat,
130        arguments = "2 strings",
131    }
132
133    implement {
134        name      = "metapostgraphformat",
135        actions   = metapost.nvformat,
136        arguments = "2 strings",
137    }
138
139    utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], { texexp = metapost.texexp })
140
141    local f_textext = formatters[ [[textext("%s")]] ]
142    local f_mthtext = formatters[ [[textext("\mathematics{%s}")]] ]
143    local f_exptext = formatters[ [[textext("\mathematics{%s\times10^{%s}}")]] ]
144
145    local mpprint   = mp.print
146
147    function mp.format(fmt,str) -- bah, this overloads mp.format in mlib-lua.lua
148        fmt = lpegmatch(cleaner,fmt)
149        mpprint(f_textext(formatters[fmt](metapost.untagvariable(str,false))))
150    end
151
152    function mp.formatted(fmt,...) -- svformat
153        fmt = lpegmatch(cleaner,fmt)
154        mpprint(f_textext(formatters[fmt](...)))
155    end
156
157    function mp.graphformat(fmt,num) -- nvformat
158        fmt = lpegmatch(cleaner,fmt)
159        local number = tonumber(num)
160        if number then
161            local base, exponent = lpegmatch(enumber,number)
162            if base and exponent then
163                mpprint(f_exptext(base,exponent))
164            else
165                mpprint(f_mthtext(num))
166            end
167        else
168            mpprint(f_textext(tostring(num)))
169        end
170    end
171
172end
173