From a92a8d40ce567ecf5b0baacd9a93a94aac9a4a2d Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Tue, 16 Jul 2019 22:42:53 +0200 Subject: 2019-07-16 18:30:00 --- tex/context/base/mkiv/cldf-int.lua | 382 ++++++++++++++++++++++++++----------- 1 file changed, 271 insertions(+), 111 deletions(-) (limited to 'tex/context/base/mkiv/cldf-int.lua') diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua index 52cfea8d0..937e1da60 100644 --- a/tex/context/base/mkiv/cldf-int.lua +++ b/tex/context/base/mkiv/cldf-int.lua @@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['cldf-int'] = { -- needs checking -- todo: multilingual -local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat -local unpack = unpack or table.unpack +local format, byte = string.format, string.byte +local insert, remove, concat = table.insert, table.remove, table.concat +local unpack, type = unpack or table.unpack, type local catcodenumbers = catcodes.numbers @@ -24,140 +25,282 @@ local contextsprint = context.sprint local trace_define = false trackers.register("context.define", function(v) trace_define = v end) -interfaces = interfaces or { } +interfaces = interfaces or { } +local implement = interfaces.implement +local estart = interfaces.elements.start +local estop = interfaces.elements.stop -_clmh_ = utilities.parsers.settings_to_hash -_clma_ = utilities.parsers.settings_to_array +if CONTEXTLMTXMODE > 0 then -local starters, stoppers, macros, stack = { }, { }, { }, { } + local scanners = tokens.scanners + local shortcuts = tokens.shortcuts -local checkers = { - [0] = "", - "\\dosingleempty", - "\\dodoubleempty", - "\\dotripleempty", - "\\doquadrupleempty", - "\\doquintupleempty", - "\\dosixtupleempty", -} + local scanpeek = scanners.peek + local scankey = scanners.key + local scanvalue = scanners.value + local scanskip = scanners.skip -function _clmm_(name,...) - macros[name](...) -end + local open = byte('[') + local close = byte(']') + local equal = byte('=') + local comma = byte(',') -function _clmb_(name,...) - local sn = stack[name] - insert(sn,{...}) - starters[name](...) -end - -function _clme_(name) - local sn = stack[name] - local sv = remove(sn) - if sv then - stoppers[name](unpack(sv)) - else - -- nesting error + function scanhash(t) + if scanpeek() == open then + local data = { } + scanskip() + while true do + local c = scanpeek() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local key = scankey(equal) + if key then + if scanpeek() == equal then + scanskip() + data[key] = scanvalue(comma,close) or "" + else + break + end + else + break + end + end + end + return data + end end -end -_clmn_ = tonumber + function scanarray(t) + if scanpeek() == open then + local data = { } + local d = 0 + scanskip() + while true do + local c = scanpeek() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local v = scanvalue(comma,close) or "" + d = d + 1 + data[d] = v + end + end + return data + end + end -local estart = interfaces.elements.start -local estop = interfaces.elements.stop + shortcuts.scanhash = scanhash + shortcuts.scanarray = scanarray --- this is a bit old definition ... needs to be modernized + scanners.hash = scanhash + scanners.array = scanarray -function interfaces.definecommand(name,specification) -- name is optional - if type(name) == "table" then - specification = name - name = specification.name + local function remap(arguments) + -- backward compatibility + if type(arguments) == "table" then + for i=1,#arguments do + local a = arguments[i] + if type(a) == "table" then + local t = a[2] + arguments[i] = t == "list" and "array" or t + end + end + return arguments + end end - if name and specification then - local arguments = specification.arguments - local na = (arguments and #arguments) or 0 - local environment = specification.environment - if na == 0 then + + function interfaces.definecommand(name,specification) -- name is optional + if type(name) == "table" then + specification = name + name = specification.name + end + if name and specification then + local environment = specification.environment + local arguments = remap(specification.arguments) if environment then - contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}") - contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") + local starter = specification.starter + local stopper = specification.stopper + if starter and stopper then + implement { + name = estart .. name, + arguments = arguments, + public = true, + protected = true, + actions = starter, + } + implement { + name = estop .. name, + public = true, + protected = true, + actions = stopper, + } + else + -- message + end end if not environment or environment == "both" then - contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}") - end - else - -- we could flush immediate but tracing is bad then - stack[name] = { } - local opt = 0 - local done = false - local snippets = { } -- we can reuse it - local mkivdo = "\\mkivdo" .. name -- maybe clddo - snippets[#snippets+1] = "\\def" - snippets[#snippets+1] = mkivdo - for i=1,na do - local a = arguments[i] - local variant = a[1] - if variant == "option" then - snippets[#snippets+1] = "[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]" - if not done then - opt = opt + 1 - end + local macro = specification.macro + if macro then + implement { + name = name, + arguments = arguments, + public = true, + protected = true, + actions = macro, + } else - done = true -- no more optional checking after this - snippets[#snippets+1] = "#" - snippets[#snippets+1] = i + -- message end end - if environment then - snippets[#snippets+1] = "{\\ctxlua{_clmb_('" - snippets[#snippets+1] = name - snippets[#snippets+1] = "'" + else + -- message + end + end + + +else + + _clmh_ = utilities.parsers.settings_to_hash + _clma_ = utilities.parsers.settings_to_array + + local starters, stoppers, macros, stack = { }, { }, { }, { } + + local checkers = { + [0] = "", + "\\dosingleempty", + "\\dodoubleempty", + "\\dotripleempty", + "\\doquadrupleempty", + "\\doquintupleempty", + "\\dosixtupleempty", + } + + function _clmm_(name,...) + macros[name](...) + end + + function _clmb_(name,...) + local sn = stack[name] + insert(sn,{...}) + starters[name](...) + end + + function _clme_(name) + local sn = stack[name] + local sv = remove(sn) + if sv then + stoppers[name](unpack(sv)) + else + -- nesting error + end + end + + _clmn_ = tonumber + + local estart = interfaces.elements.start + local estop = interfaces.elements.stop + + -- this is a bit old definition ... needs to be modernized + + function interfaces.definecommand(name,specification) -- name is optional + if type(name) == "table" then + specification = name + name = specification.name + end + if name and specification then + local arguments = specification.arguments + local na = (arguments and #arguments) or 0 + local environment = specification.environment + if na == 0 then + if environment then + contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}") + contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") + end + if not environment or environment == "both" then + contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}") + end else - snippets[#snippets+1] = "{\\ctxlua{_clmm_('" - snippets[#snippets+1] = name - snippets[#snippets+1] = "'" - end - for i=1,na do - local a = arguments[i] - local variant = a[2] - if variant == "list" then - snippets[#snippets+1] = ",_clma_([[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]])" - elseif variant == "hash" then - snippets[#snippets+1] = ",_clmh_([[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]])" - elseif variant == "number" then - snippets[#snippets+1] = ",_clmn_([[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]])" + -- we could flush immediate but tracing is bad then + stack[name] = { } + local opt = 0 + local done = false + local snippets = { } -- we can reuse it + local mkivdo = "\\mkivdo" .. name -- maybe clddo + snippets[#snippets+1] = "\\def" + snippets[#snippets+1] = mkivdo + for i=1,na do + local a = arguments[i] + local variant = a[1] + if variant == "option" then + snippets[#snippets+1] = "[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]" + if not done then + opt = opt + 1 + end + else + done = true -- no more optional checking after this + snippets[#snippets+1] = "#" + snippets[#snippets+1] = i + end + end + if environment then + snippets[#snippets+1] = "{\\ctxlua{_clmb_('" + snippets[#snippets+1] = name + snippets[#snippets+1] = "'" else - snippets[#snippets+1] = ",[[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]]" + snippets[#snippets+1] = "{\\ctxlua{_clmm_('" + snippets[#snippets+1] = name + snippets[#snippets+1] = "'" + end + for i=1,na do + local a = arguments[i] + local variant = a[2] + if variant == "list" then + snippets[#snippets+1] = ",_clma_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + elseif variant == "hash" then + snippets[#snippets+1] = ",_clmh_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + elseif variant == "number" then + snippets[#snippets+1] = ",_clmn_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + else + snippets[#snippets+1] = ",[==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==]" + end + end + snippets[#snippets+1] = ")}}" + contextsprint(ctxcatcodes,unpack(snippets)) + if environment then + -- needs checking + contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}") + contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") + end + if not environment or environment == "both" then + contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}") end end - snippets[#snippets+1] = ")}}" - contextsprint(ctxcatcodes,unpack(snippets)) if environment then - -- needs checking - contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}") - contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") - end - if not environment or environment == "both" then - contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}") + starters[name] = specification.starter + stoppers[name] = specification.stopper + else + macros[name] = specification.macro end end - if environment then - starters[name] = specification.starter - stoppers[name] = specification.stopper - else - macros[name] = specification.macro - end end + end function interfaces.tolist(t) @@ -223,3 +366,20 @@ end -- \stopluacode -- -- more: \startmore[1] one \startmore[2] two \stopmore one \stopmore +-- +-- More modern (no need for option or content): +-- +-- \startluacode +-- interfaces.definecommand { +-- name = "test", +-- arguments = { +-- "array", -- or list +-- "hash", +-- "string", +-- "number", +-- }, +-- macro = test, +-- } +-- \stopluacode +-- + -- cgit v1.2.3