local token_create = token.create local parse_token = token_create'__luakeyval_parse:n' local parse_clist_token = token_create'__luakeyval_clist_parse:n' local parse_clist_token_e = token_create'__luakeyval_clist_parse:e' local scan_stop = token_create'scan_stop:' local put_next = token.put_next local scan_token = token.scan_token local scan_argument = token.scan_argument local functions = lua.get_functions_table() local current_clist_handler local current_handlers, current_context local exp_helpers = setmetatable({}, {__index = function(t, kind) local exp_token = token.create('exp_args:N' .. kind) local helper = {exp_token, scan_stop} t[kind] = helper return helper end}) do local noop_helper = {scan_stop} exp_helpers.n, exp_helpers.N = noop_helper, noop_helper end local func_single = luatexbase.new_luafunction'__luakeyval_pair:n' token.set_lua('__luakeyval_pair:n', func_single) functions[func_single] = function() local name = scan_argument() local handler = current_handlers[name] if not handler then return tex.error(string.format("Unsupported keyval key %q", name)) end return handler(false, current_context, name) end local func_pair = luatexbase.new_luafunction'__luakeyval_pair:nn' token.set_lua('__luakeyval_pair:nn', func_pair) functions[func_pair] = function() local name = scan_argument() local handler = current_handlers[name] if not handler then local base, exp_qualifier = string.match(name, '^(.*):([noVveNc])$') if base then put_next(exp_helpers[exp_qualifier]) local scanned = scan_token() assert(scanned == scan_stop) name = base handler = current_handlers[name] end if not handler then scan_argument() return tex.error(string.format("Unsupported keyval key %q", name)) end end return handler(true, current_context, name) end local func_item = luatexbase.new_luafunction'__luakeyval_item:n' token.set_lua('__luakeyval_item:n', func_item) functions[func_item] = function() current_clist_handler(current_context) end return { clist = function(handler, context, expand) local saved_handler, saved_context = current_clist_handler, current_context current_clist_handler, current_context = handler, context put_next(expand and parse_clist_token_e or parse_clist_token) local scanned = scan_token() if scanned.csname ~= 'scan_stop:' then print(scanned, scanned.cmdname) error'???' end current_clist_handler, current_context = saved_handlers, saved_context end, keyval = function(handlers, context) local saved_handlers, saved_context = current_handlers, current_context current_handlers, current_context = handlers, context put_next(parse_token) local scanned = scan_token() if scanned.csname ~= 'scan_stop:' then print(scanned, scanned.cmdname) error'???' end current_handler, current_context = saved_handler, saved_context end, }