s-system-macros.mkxl /size: 15 Kb    last modification: 2023-12-21 09:45
1%D \module
2%D   [      file=s-system-tokens.mkxl,
3%D        version=2020.06.02,
4%D          title=\CONTEXT\ Style File,
5%D       subtitle=System Tokens Checking,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14%D This file is for Wolfgang and Hans and it's used in the transition from \MKIV\
15%D to the more robust \LMTX.
16
17% todo:  \permanent\protected\let\select\directselect : same value (add ref)
18%
19% todo: when mutable, remove immutable, decide on how immutable it really is
20%
21% todo: just for the fun of it we can compare the table generated here to mkiv but it
22% needs the same hash exposure as we use in luametatex so i'll do that after all lmtx
23% macros are checked (maybe i need to backport some more but it has a low priority)
24%
25% todo: do we need something similar for lua functions etc (problem: performance hit)
26%
27% todo: and how about metapost ... i need a mp.hashtokens in order to do that and I also
28% need to think about protection there (tricky as we use an avl hash there)
29%
30% todo:  when possible replace \p_whatever_key by \p_key
31%
32% public undefined : SmallCaps scitebuffer sciteinlinebuffer
33% single todos     : \ \- \\ \_
34
35\enablemode[texmacros]
36\enablemode[metapostmacros]
37% \enablemode[notmarked]
38\enablemode[everything]
39
40\startmodule[system-macros]
41
42\continueifinputfile{s-system-macros.mkxl}
43
44% \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt]
45\usemodule[article-basic] \setuplayout[tight] \setupbodyfont[5pt,tt]
46
47\setupbackgrounds[page][background=color,backgroundcolor=darkgray] \setupcolors[textcolor=white]
48
49\setuppapersize
50  [A4,landscape]
51  [A4,landscape]
52
53\bitwiseflip \normalizelinemode \discardzerotabskipsnormalizecode
54
55\starttext
56
57\startluacode
58
59    if tex.modes.texmacros then
60
61        local context     = context
62        local ctx_NC      = context.NC
63        local ctx_NR      = context.NR
64        local ctx_bold    = context.bold
65        local ctx_verb    = context.verbatim
66        local ctx_escaped = context.escaped
67
68        local find     = string.find
69        local gsub     = string.gsub
70        local gmatch   = string.gmatch
71        local create   = tokens.create
72
73        local crap     = "[$>%|%&%#" .. string.char(0xEF) .. "]"
74
75        local basefile  = resolvers.findfile("context.mkxl")
76        local swapnames = { }
77
78        local pattern   = file.join(file.pathpart(basefile),"/*.mk*")
79        local filenames = dir.glob(pattern)
80        for i=1,#filenames do
81            swapnames[file.basename(filenames[i])] = true
82        end
83
84        local pattern   = file.join(file.pathpart(basefile),"/*.l**")
85        local filenames = dir.glob(pattern)
86        for i=1,#filenames do
87            swapnames[file.basename(filenames[i])] = true
88        end
89
90        local hashnames = table.setmetatableindex(function(t,k)
91            local s = file.suffix(k)
92            local v = k
93            if s == "mkiv" then
94                local n = file.replacesuffix(k,"mkxl")
95                if swapnames[n] then
96                    v = n
97                end
98            elseif s == "mkvi" then
99                local n = file.replacesuffix(k,"mklx")
100                if swapnames[n] then
101                    v = n
102                end
103            elseif s == "lua" then
104                local n = file.replacesuffix(k,"lmt")
105                if swapnames[n] then
106                    v = n
107                end
108            end
109            t[k] = v
110            return v
111        end)
112
113        require("mtx-interface")
114
115        local data       = scripts.interface.editor("data")
116        local files      = data and data.common and data.common.filenames or { }
117        local macros     = { }
118        local registers  = { }
119        local implements = { }
120        local flagged    = 0
121        local total      = 0
122        local list       = tex.hashtokens()
123        local all        = not tex.modes.notmarked
124        local everything = tex.modes.everything
125        local getmacro   = token.getmacro
126
127        local fmtname = resolvers.locateformat("cont-en.fmt")
128        if fmtname then
129            local logname = file.replacesuffix(fmtname,"log")
130            for filename in gmatch(io.loaddata(logname),"fullname=(%S+)") do
131                local s = file.suffix(filename)
132                local b = file.basename(filename)
133                if s ~= "lua" and s ~= "lmt" then
134-- todo: newfloat etc
135                    local d = io.loaddata(filename)
136                    -- we could make a nice lpeg
137                    for m in gmatch(d,"\n[\\a-z]*[exg]*def\\([a-zA-Z_]+)") do
138                        macros[m] = b
139                    end
140                    for m in gmatch(d,"\n[\\a-z]*[g]*let\\([a-zA-Z_]+)") do
141                        macros[m] = b
142                    end
143                    for m in gmatch(d,"\n\\lettonothing\\([a-zA-Z_]+)") do
144                        macros[m] = b
145                    end
146                    for m in gmatch(d,"\n\\integerdef\\([a-zA-Z_]+)") do
147                        macros[m] = b
148                    end
149                    for m in gmatch(d,"\n\\dimensiondef\\([a-zA-Z_]+)") do
150                        macros[m] = b
151                    end
152                    for m in gmatch(d,"\n\\gluespecdef\\([a-zA-Z_]+)") do
153                        macros[m] = b
154                    end
155                    for m in gmatch(d,"\n\\mugluespecdef\\([a-zA-Z_]+)") do
156                        macros[m] = b
157                    end
158                    for m in gmatch(d,"\n\\newinteger\\([a-zA-Z_]+)") do
159                        registers[m] = b
160                    end
161                    for m in gmatch(d,"\n\\newdimension\\([a-zA-Z_]+)") do
162                        registers[m] = b
163                    end
164                    for m in gmatch(d,"\n\\newgluespec\\([a-zA-Z_]+)") do
165                        registers[m] = b
166                    end
167                    for m in gmatch(d,"\n\\newmugluespec\\([a-zA-Z_]+)") do
168                        registers[m] = b
169                    end
170                    for m in gmatch(d,"\n\\newconditional\\([a-zA-Z_]+)") do
171                        registers[m] = b
172                    end
173                    for m in gmatch(d,"\n\\newtoks\\([a-zA-Z_]+)") do
174                        registers[m] = b
175                    end
176                    for m in gmatch(d,"\n\\newcount\\([a-zA-Z_]+)") do
177                        registers[m] = b
178                    end
179                    for m in gmatch(d,"\n\\newdimen\\([a-zA-Z_]+)") do
180                        registers[m] = b
181                    end
182                    for m in gmatch(d,"\n\\newskip\\([a-zA-Z_]+)") do
183                        registers[m] = b
184                    end
185                    for m in gmatch(d,"\n\\newmuskip\\([a-zA-Z_]+)") do
186                        registers[m] = b
187                    end
188                elseif b ~= "char-def.lua" then
189                    local d = io.loaddata(filename)
190                    -- maybe inside implement { }
191                    -- maybe get file from debug interface
192                    for m in gmatch(d,'\n +name += +"([a-zA-Z_]+)",') do
193                        implements[m] = b
194                    end
195                end
196            end
197        end
198
199        table.sort(list)
200
201        local function show(visible, check)
202            context.starttabulate { "|l|l|l|lj2|l|l|l|l|l|l|l|l|l|l|l|" }
203            for i=1,#list do
204                local k = list[i]
205                if check(k) then
206                    local v = create(k)
207                    local mutable    = v.mutable    and "mutable"
208                    local immutable  = v.immutable  and "immutable"
209                    local frozen     = v.frozen     and "frozen"
210                    local permanent  = v.permanent  and "permanent"
211                    local primitive  = v.primitive  and "primitive"
212                    local instance   = v.instance   and "instance"
213                    local constant   = v.constant   and "constant"
214                    local untraced   = v.untraced   and "untraced"
215                    local dealtwith  = mutable or immutable or mutable or frozen or permanent or primitive -- beware: we can have combinations
216                    local whatever   = find(k,"^[a-z][a-z][a-z]+_")
217                    local cscommand  = gsub(v.cmdname or "","_"," ")
218                    local undefined  = cscommand == "undefined cs"
219                    local marked     = (dealtwith and "+") or (whatever and "-") or (instance and "!")
220                    if everything or ((all or not marked) and not find(k,"^[pvm]_") and not find(k,"^![tT]")) then
221                        local parameters = v.parameters
222                        local noaligned  = v.noaligned  and "noaligned"
223                        local filename   = files[k] or macros[k] or implements[k] or registers[k] or implements[gsub(k,"^clf_","")]
224                        local csname     = context.escape(k)
225                        if undefined then
226                            marked = "?"
227                        end
228                        ctx_NC() if marked     then context(marked)     end
229                        ctx_NC() if primitive  then ctx_bold(csname)    else
230                                                    ctx_verb(csname)    end
231                        ctx_NC() if parameters then context(parameters > 0 and parameters or "-") end
232                        ctx_NC() if undefined  then context.red(false)  end
233                                                    context(cscommand)
234                        ctx_NC() if primitive  then context(primitive)  end
235                        ctx_NC() if permanent  then context(permanent)  end
236                        ctx_NC() if immutable  then context(immutable)  end
237                        ctx_NC() if frozen     then context(frozen)     end
238                        ctx_NC() if mutable    then context(mutable)    end
239                        ctx_NC() if instance   then context(instance)   end
240                        ctx_NC() if noaligned  then context(noaligned)  end
241                        ctx_NC() if constant   then context(constant)   end
242                        ctx_NC() if untraced   then context(untraced)   end
243                        ctx_NC() if filename   then context(hashnames[filename]) end
244                        ctx_NC() if parameters then if parameters > 0 then ctx_escaped(getmacro(csname,false,true)) end end
245                        ctx_NC() ctx_NR()
246                    end
247                    if visible then
248                        total = total + 1
249                        if dealtwith then
250                            flagged = flagged + 1
251                        end
252                    end
253                end
254            end
255            context.stoptabulate()
256        end
257
258        context.starttitle { title = "Public \\TEX\\ commands" }
259            show(true, function(k) return find(k,"^[a-zA-Z]+$") end)
260        context.stoptitle()
261
262        context.starttitle { title = "Private \\TEX\\ commands" }
263            show(false, function(k) return not find(k,"^[a-zA-Z]+$") and not find(k,crap) end)
264        context.stoptitle()
265
266        tokens.setters.macro("NumberOfVisible", total)
267        tokens.setters.macro("NumberOfFlagged", flagged)
268
269    end
270
271\stopluacode
272
273\startmode[texmacros]
274
275    \page
276
277    \starttabulate[|c|l|]
278    \HL
279    \NC \type {+}   \NC mutable, immutable, frozen, permanent, primitive \NC \NR
280    \NC \type {-}   \NC protected by obscurity (underscores) \NC \NR
281    \NC \type {!}   \NC instance (can be frozen) \NC \NR
282    \NC \type {0-9} \NC the number of arguments (argument grabbing can be delegated) \NC \NR
283    \HL
284    \stoptabulate
285
286    \start \hsize 15cm \veryraggedright
287    Often frozen commands are redefined on demand and they can be overloaded. Mutable
288    doesn't mean that a user can change it without consequences, for instance the
289    \type {\current...} ones. Primitives come with the engine, permanent macros are
290    the core of \CONTEXT. Noaligned macros are special and dealt deep down when
291    scanning for alignment specific primitives.
292    \par \stop
293
294    \starttabulate[||r|]
295    \BC number of visible macros  \NC \NumberOfVisible \NC \NR
296    \BC number of flagged macros  \NC \NumberOfFlagged \NC \NR
297    \stoptabulate
298
299\stopmode
300
301\page
302
303\startluacode
304
305    if tex.modes.metapostmacros then
306
307        local context  = context
308     -- local ctx_NC   = context.NC
309     -- local ctx_NR   = context.NR
310     -- local ctx_bold = context.bold
311
312        local find     = string.find
313        local gsub     = string.gsub
314        local create   = tokens.create
315
316        context.starttitle { title = "\\METAFUN\\ commands" }
317
318            metapost.simple("prestine")
319
320            local mptotal    = 0
321            local codes      = metapost.codes
322            local types      = metapost.types
323            local parameters = metapost.knownparameters
324            local procodes   = mplib.propertycodes
325            local everything = tex.modes.everything
326
327            context.startcolumns { n = 5, distance = "1em" }
328                context.nohyphens(false)
329                context.obeyspaces(false)
330                local t = metapost.gethashentries("prestine",true) -- prestine:1
331                if t then
332                    table.sort(t,function(a,b) return a[3] < b[3] end)
333                    mptotal = #t
334                    for i=1,mptotal do
335                        local ti       = t[i]
336                        local code     = codes[ti[1]]
337                        local property = procodes[ti[2]]
338                        local name     = ti[3]
339                        local vtype    = ti[4]
340                        local vardef   = vtype and types[vtype] == "unsuffixedmacro"
341                        context.bgroup()
342                     -- context("%-15s\\quad",vardef and "(vardef) tag" or code)
343                        context("%s %-15s\\quad",parameters[name] and "+" or "\\nbsp",vardef and "(vardef) tag" or code)
344                        if property == "primitive" then
345                            context.bf(false)
346                            context.blue(false)
347                        elseif property == "permanent"  then
348                            context.bf(false)
349                            context.lightgreen(false)
350                        elseif property == "immutable"  then
351                            context.bf(false)
352                            context.lightcyan(false)
353                        elseif property == "mutable"  then
354                            context.bf(false)
355                            context.lightmagenta(false)
356                        elseif everything or not find(name,"^%a+_") then
357                            -- todo:
358                            if vardef then
359                                context.bf(false)
360                                context.lightred(false)
361                            end
362                        end
363                        context.verbatim(name)
364                        context.egroup()
365                        context.par()
366                    end
367                end
368            context.stopcolumns()
369
370        context.stoptitle()
371
372        tokens.setters.macro("NumberOfMetafun", mptotal)
373
374    end
375\stopluacode
376
377\startmode [metapostmacros]
378
379    \page
380
381    \starttabulate[|c|l|]
382    \HL
383    \NC \type {-3} \NC \bf \lightmagenta mutable   \NC \NR
384    \NC \type  {1} \NC \bf \blue         primitive \NC \NR
385    \NC \type  {2} \NC \bf \lightgreen   permanent \NC \NR
386    \NC \type  {3} \NC \bf \lightcyan    immutable \NC \NR
387    \NC \type  {+} \NC \bf (also) used as key      \NC \NR
388    \HL
389    \stoptabulate
390
391    \starttabulate[||r|]
392    \BC number of metafun entries \NC \NumberOfMetafun \NC \NR
393    \stoptabulate
394
395\stopmode
396
397\stopmodule
398