if not modules then modules = { } end modules ['cldf-int'] = { version = 1.001, comment = "companion to cldf-int.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- another experiment -- needs upgrading -- needs checking -- todo: multilingual local byte = string.byte local insert, remove, concat = table.insert, table.remove, table.concat local unpack, type = unpack or table.unpack, type local ctxcatcodes = catcodes.numbers.ctxcatcodes local context = context local contextsprint = context.sprint local trace_define = false trackers.register("context.define", function(v) trace_define = v end) interfaces = interfaces or { } local implement = interfaces.implement local estart = interfaces.elements.start local estop = interfaces.elements.stop local scanners = tokens.scanners local shortcuts = tokens.shortcuts local peekchar = scanners.peekchar local scankey = scanners.key local scanvalue = scanners.value local scanskip = scanners.skip local open = byte('[') local close = byte(']') local equal = byte('=') local comma = byte(',') local function scanhash(scanners) if peekchar() == open then local data = { } scanskip() while true do local c = peekchar() if c == comma then scanskip() elseif c == close then scanskip() break else local key = scankey(equal) if key then if peekchar() == equal then scanskip() if scanners then local scanner = scanners[key] if scanner then data[key] = scanner() else data[key] = scanvalue(comma,close) or "" end else data[key] = scanvalue(comma,close) or "" end else break end else break end end end return data end end local function scanarray() if peekchar() == open then local data = { } local d = 0 scanskip() while true do local c = peekchar() 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 shortcuts.scanhash = scanhash shortcuts.scanarray = scanarray scanners.hash = scanhash scanners.array = scanarray 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 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 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 local macro = specification.macro if macro then implement { name = name, arguments = arguments, public = true, protected = true, actions = macro, } else -- message end end else -- message end end function interfaces.tolist(t) if t then local r = { } for i=1,#t do r[i] = t[i] end local n = #r for k,v in table.sortedhash(t) do if type(k) ~= "number" then n = n + 1 r[n] = k .. "=" .. v end end return concat(r,", ") else return "" end end -- \startluacode -- function test(opt_1, opt_2, arg_1) -- context.startnarrower() -- context("options 1: %s",interfaces.tolist(opt_1)) -- context.par() -- context("options 2: %s",interfaces.tolist(opt_2)) -- context.par() -- context("argument 1: %s",arg_1) -- context.stopnarrower() -- end -- -- interfaces.definecommand { -- name = "test", -- arguments = { -- { "option", "list" }, -- { "option", "hash" }, -- { "content", "string" }, -- }, -- macro = test, -- } -- \stopluacode -- -- test: \test[1][a=3]{whatever} -- -- \startluacode -- local function startmore(opt_1) -- context.startnarrower() -- context("start more, options: %s",interfaces.tolist(opt_1)) -- context.startnarrower() -- end -- -- local function stopmore() -- context.stopnarrower() -- context("stop more") -- context.stopnarrower() -- end -- -- interfaces.definecommand ( "more", { -- environment = true, -- arguments = { -- { "option", "list" }, -- }, -- starter = startmore, -- stopper = stopmore, -- } ) -- \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 --