core-env.lmt /size: 7413 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['core-env'] = {
2    version   = 1.001,
3    comment   = "companion to core-env.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
9-- maybe this will move to the context name space although the
10-- plurals are unlikely to clash with future tex primitives
11--
12-- if tex.modes['xxxx'] then .... else .... end
13
14local rawset = rawset
15
16local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns
17
18local context              = context
19local ctxcore              = context.core
20
21local texgetcount          = tex.getcount
22local texgetintegervalue   = token.getinteger -- todo
23
24local allocate             = utilities.storage.allocate
25local setmetatableindex    = table.setmetatableindex
26local setmetatablenewindex = table.setmetatablenewindex
27local setmetatablecall     = table.setmetatablecall
28
29local createtoken          = token.create
30local isdefined            = tokens.isdefined
31
32texmodes                   = allocate { }  tex.modes        = texmodes
33texsystemmodes             = allocate { }  tex.systemmodes  = texsystemmodes
34texconstants               = allocate { }  tex.constants    = texconstants
35texconditionals            = allocate { }  tex.conditionals = texconditionals
36texifs                     = allocate { }  tex.ifs          = texifs
37texisdefined               = allocate { }  tex.isdefined    = texisdefined
38
39local modes                = { }
40local systemmodes          = { }
41
42-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching
43-- at the lua end is not that bad (and we need more anyway)
44
45local cache = tokens.cache
46
47-- we can have a modes cache too
48
49local commandcodes  = tokens.commands
50local iftrue        = cache["iftrue"].index
51
52-- local dimencode     = cache["scratchdimen"]  .command -- tokens.commands.register_dimen
53-- local countcode     = cache["scratchcounter"].command -- tokens.commands.register_int
54-- local tokencode     = cache["scratchtoks"]   .command -- tokens.commands.register_toks
55-- local skipcode      = cache["scratchskip"]   .command -- tokens.commands.register_glue
56-- local muskipcode    = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue
57-- local conditioncode = cache["iftrue"]        .command -- tokens.commands.if_test
58
59-- local types = {
60--     [dimencode]     = "dimen",
61--     [countcode]     = "count",
62--     [tokencode]     = "token",
63--     [skipcode]      = "skip",
64--     [muskipcode]    = "muskip",
65--  -- [attributecode] = "attribute",
66--     [conditioncode] = "condition"
67-- }
68
69local dimencode     = commandcodes.register_dimen   -- cache["scratchdimen"]  .command -- tokens.commands.register_dimen
70local countcode     = commandcodes.register_int     -- cache["scratchcounter"].command -- tokens.commands.register_int
71local tokencode     = commandcodes.register_toks    -- ["scratchtoks"]   .command -- tokens.commands.register_toks
72local skipcode      = commandcodes.register_glue    -- cache["scratchskip"]   .command -- tokens.commands.register_glue
73local muskipcode    = commandcodes.register_mu_glue -- cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue
74local conditioncode = commandcodes.if_test          -- cache["iftrue"]        .command -- tokens.commands.if_test
75local integercode   = commandcodes.integer
76
77local types = {
78    [dimencode]     = "dimen",
79    [countcode]     = "count",
80    [tokencode]     = "token",
81    [skipcode]      = "skip",
82    [muskipcode]    = "muskip",
83 -- [attributecode] = "attribute",
84    [conditioncode] = "condition",
85    [integercode]   = "integer",
86}
87
88setmetatableindex(texmodes, function(t,k)
89    local m = systemmodes[k]
90    if not m then
91        local n = "mode>" .. k
92        m = function() return texgetintegervalue(n) == 1 end
93        rawset(modes,k,m)
94    end
95    return m()
96end)
97
98setmetatableindex(texsystemmodes, function(t,k)
99    local m = systemmodes[k]
100    if not m then
101        local n = "mode>*" .. k
102        m = function() return texgetintegervalue(n) == 1 end
103        rawset(modes,k,m)
104    end
105    return m()
106end)
107
108-- also a call method
109
110context.settrialtypesettingmethod(function() return texsystemmodes.trialtypesetting end)
111
112setmetatablenewindex(texmodes,        function(t,k) report_mode("you cannot set the %s named %a this way","mode",       k) end)
113setmetatablenewindex(texsystemmodes,  function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end)
114setmetatablenewindex(texconstants,    function(t,k) report_mode("you cannot set the %s named %a this way","constant",   k) end)
115setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end)
116setmetatablenewindex(texifs,          function(t,k) end)
117
118-- if we really need performance we can have a dedicated cache for each
119-- kind of variable ... maybe we no longer have to cache anyway (in lmtx)
120
121setmetatableindex(texconstants, function(t,k)
122 -- return cache[k].command == countcode and texgetcount(k) or 0
123    return cache[k].command == integercode and texgetintegervalue(k) or 0
124end)
125
126setmetatableindex(texconditionals, function(t,k) -- 0 == true
127 -- return cache[k].command == countcode and texgetcount(k) == 0
128    return cache[k].command == integercode and texgetintegervalue(k) == 0
129end)
130
131setmetatableindex(texifs, function(t,k)
132    local c = cache[k]
133    return c.command == conditioncode and c.index == iftrue
134end)
135
136tex.isdefined = isdefined
137
138function tex.isdimen(name)
139    local hit = cache[name]
140    return hit.command == dimencode and hit.index or true
141end
142
143function tex.iscount(name)
144    local hit = cache[name]
145    return hit.command == countcode and hit.index or true
146end
147
148function tex.istoken(name)
149    local hit = cache[name]
150    return hit.command == tokencode and hit.index or true
151end
152
153function tex.isskip(name)
154    local hit = cache[name]
155    return hit.command == skipcode and hit.index or true
156end
157
158function tex.ismuskip(name)
159    local hit = cache[name]
160    return hit.command == muskipcode and hit.index or true
161end
162
163function tex.type(name)
164    return types[cache[name].command] or "macro"
165end
166
167function context.setconditional(name,value)
168    if value then
169        ctxcore.settruevalue(name)
170    else
171        ctxcore.setfalsevalue(name)
172    end
173end
174
175function context.setmode(name,value)
176    if value then
177        ctxcore.setmode(name)
178    else
179        ctxcore.resetmode(name)
180    end
181end
182
183function context.setsystemmode(name,value)
184    if value then
185        ctxcore.setsystemmode(name)
186    else
187        ctxcore.resetsystemmode(name)
188    end
189end
190
191context.modes        = texmodes
192context.systemmodes  = texsystemmodes
193context.conditionals = texconditionals
194-------.constants    = texconstants
195-------.ifs          = texifs
196
197local sep = S("), ")
198local str = C((1-sep)^1)
199local tag = P("(") * C((1-S(")" ))^1) * P(")")
200local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")")
201
202local pattern = (
203     P("lua") * tag        / ctxcore.luasetup
204  +  P("xml") * arg        / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments
205  + (P("tex") * tag + str) / ctxcore.texsetup
206  +             sep^1
207)^1
208
209interfaces.implement {
210    name      = "autosetups",
211    actions   = function(str) lpegmatch(pattern,str) end,
212    arguments = "string"
213}
214