cldf-int.lua /size: 7341 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['cldf-int'] = {
2    version   = 1.001,
3    comment   = "companion to cldf-int.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-- another experiment, won't change etc ... mkiv stuff .. used?
10
11local insert, remove, concat = table.insert, table.remove, table.concat
12local unpack, type = unpack or table.unpack, type
13
14local ctxcatcodes    = catcodes.numbers.ctxcatcodes
15local context        = context
16local contextsprint  = context.sprint
17
18local trace_define   = false  trackers.register("context.define", function(v) trace_define = v end)
19
20interfaces           = interfaces or { }
21local estart         = interfaces.elements.start
22local estop          = interfaces.elements.stop
23
24_clmh_ = utilities.parsers.settings_to_hash
25_clma_ = utilities.parsers.settings_to_array
26_clmn_ = tonumber
27
28local starters, stoppers, macros, stack = { }, { }, { }, { }
29
30local checkers = {
31    [0] = "",
32    "\\dosingleempty",
33    "\\dodoubleempty",
34    "\\dotripleempty",
35    "\\doquadrupleempty",
36    "\\doquintupleempty",
37    "\\dosixtupleempty",
38}
39
40function _clmm_(name,...)
41    macros[name](...)
42end
43
44function _clmb_(name,...)
45    local sn = stack[name]
46    insert(sn,{...})
47    starters[name](...)
48end
49
50function _clme_(name)
51    local sn = stack[name]
52    local sv = remove(sn)
53    if sv then
54        stoppers[name](unpack(sv))
55    else
56        -- nesting error
57    end
58end
59
60-- this is a bit old definition ... needs to be modernized
61
62function interfaces.definecommand(name,specification) -- name is optional
63    if type(name) == "table" then
64        specification = name
65        name = specification.name
66    end
67    if name and specification then
68        local arguments = specification.arguments
69        local na = (arguments and #arguments) or 0
70        local environment = specification.environment
71        if na == 0 then
72            if environment then
73                contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}")
74                contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
75            end
76            if not environment or environment == "both" then
77                contextsprint(ctxcatcodes,"\\setuvalue{",       name,"}{\\ctxlua{_clmm_('",name,"')}}")
78            end
79        else
80            -- we could flush immediate but tracing is bad then
81            stack[name] = { }
82            local opt      = 0
83            local done     = false
84            local snippets = { } -- we can reuse it
85            local mkivdo   = "\\mkivdo" .. name -- maybe clddo
86            snippets[#snippets+1] = "\\def"
87            snippets[#snippets+1] = mkivdo
88            for i=1,na do
89                local a = arguments[i]
90                local variant = a[1]
91                if variant == "option" then
92                    snippets[#snippets+1] = "[#"
93                    snippets[#snippets+1] = i
94                    snippets[#snippets+1] = "]"
95                    if not done then
96                        opt = opt + 1
97                    end
98                else
99                    done = true -- no more optional checking after this
100                    snippets[#snippets+1] = "#"
101                    snippets[#snippets+1] = i
102                end
103            end
104            if environment then
105                snippets[#snippets+1] = "{\\ctxlua{_clmb_('"
106                snippets[#snippets+1] = name
107                snippets[#snippets+1] = "'"
108            else
109                snippets[#snippets+1] = "{\\ctxlua{_clmm_('"
110                snippets[#snippets+1] = name
111                snippets[#snippets+1] = "'"
112            end
113            for i=1,na do
114                local a = arguments[i]
115                local variant = a[2]
116                if variant == "list" then
117                    snippets[#snippets+1] = ",_clma_([==[#"
118                    snippets[#snippets+1] = i
119                    snippets[#snippets+1] = "]==])"
120                elseif variant == "hash" then
121                    snippets[#snippets+1] = ",_clmh_([==[#"
122                    snippets[#snippets+1] = i
123                    snippets[#snippets+1] = "]==])"
124                elseif variant == "number" then
125                    snippets[#snippets+1] = ",_clmn_([==[#"
126                    snippets[#snippets+1] = i
127                    snippets[#snippets+1] = "]==])"
128                else
129                    snippets[#snippets+1] = ",[==[#"
130                    snippets[#snippets+1] = i
131                    snippets[#snippets+1] = "]==]"
132                end
133            end
134            snippets[#snippets+1] = ")}}"
135            contextsprint(ctxcatcodes,unpack(snippets))
136            if environment then
137                -- needs checking
138                contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}")
139                contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
140            end
141            if not environment or environment == "both" then
142                contextsprint(ctxcatcodes,"\\setuvalue{",       name,"}{",checkers[opt],mkivdo,"}")
143            end
144        end
145        if environment then
146            starters[name] = specification.starter
147            stoppers[name] = specification.stopper
148        else
149            macros[name] = specification.macro
150        end
151    end
152end
153
154function interfaces.tolist(t)
155    if t then
156        local r = { }
157        for i=1,#t do
158            r[i] = t[i]
159        end
160        local n = #r
161        for k,v in table.sortedhash(t) do
162            if type(k) ~= "number" then
163                n = n + 1
164                r[n] = k .. "=" .. v
165            end
166        end
167        return concat(r,", ")
168    else
169        return ""
170    end
171end
172
173-- \startluacode
174-- function test(opt_1, opt_2, arg_1)
175--     context.startnarrower()
176--     context("options 1: %s",interfaces.tolist(opt_1))
177--     context.par()
178--     context("options 2: %s",interfaces.tolist(opt_2))
179--     context.par()
180--     context("argument 1: %s",arg_1)
181--     context.stopnarrower()
182-- end
183--
184-- interfaces.definecommand {
185--     name = "test",
186--     arguments = {
187--         { "option", "list" },
188--         { "option", "hash" },
189--         { "content", "string" },
190--     },
191--     macro = test,
192-- }
193-- \stopluacode
194--
195-- test: \test[1][a=3]{whatever}
196--
197-- \startluacode
198-- local function startmore(opt_1)
199--     context.startnarrower()
200--     context("start more, options: %s",interfaces.tolist(opt_1))
201--     context.startnarrower()
202-- end
203--
204-- local function stopmore()
205--     context.stopnarrower()
206--     context("stop more")
207--     context.stopnarrower()
208-- end
209--
210-- interfaces.definecommand ( "more", {
211--     environment = true,
212--     arguments = {
213--         { "option", "list" },
214--     },
215--     starter = startmore,
216--     stopper = stopmore,
217-- } )
218-- \stopluacode
219--
220-- more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
221--
222-- More modern (no need for option or content):
223--
224-- \startluacode
225-- interfaces.definecommand {
226--     name = "test",
227--     arguments = {
228--         "array", -- or list
229--         "hash",
230--         "string",
231--         "number",
232--     },
233--     macro = test,
234-- }
235-- \stopluacode
236--
237
238