if not modules then modules = { } end modules ['toks-ini'] = { version = 1.001, author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local utfbyte, utfchar, utfvalues = utf.byte, utf.char, utf.values local format, gsub = string.format, string.gsub --[[ldx--
This code is experimental and needs a cleanup. The visualizers will move to a module.
--ldx]]-- -- 1 = command, 2 = modifier (char), 3 = controlsequence id -- -- callback.register('token_filter', token.get_next) -- -- token.get_next() -- token.expand() -- token.create() -- token.csname_id() -- token.csname_name(v) -- token.command_id() -- token.command_name(v) -- token.is_expandable() -- token.is_activechar() -- token.lookup(v) -- actually, we can use token registers to store tokens local token, tex = token, tex local createtoken = token.create local csname_id = token.csname_id local command_id = token.command_id local command_name = token.command_name local get_next = token.get_next local expand = token.expand local is_activechar = token.is_activechar local csname_name = token.csname_name tokens = tokens or { } local tokens = tokens tokens.vbox = createtoken("vbox") tokens.hbox = createtoken("hbox") tokens.vtop = createtoken("vtop") tokens.bgroup = createtoken(utfbyte("{"), 1) tokens.egroup = createtoken(utfbyte("}"), 2) tokens.letter = function(chr) return createtoken(utfbyte(chr), 11) end tokens.other = function(chr) return createtoken(utfbyte(chr), 12) end tokens.letters = function(str) local t, n = { }, 0 for chr in utfvalues(str) do n = n + 1 t[n] = createtoken(chr, 11) end return t end tokens.collectors = tokens.collectors or { } local collectors = tokens.collectors collectors.data = collectors.data or { } local collectordata = collectors.data collectors.registered = collectors.registered or { } local registered = collectors.registered local function printlist(data) callbacks.push('token_filter', function () callbacks.pop('token_filter') -- tricky but the nil assignment helps return data end) end tex.printlist = printlist -- will change to another namespace function collectors.flush(tag) printlist(collectordata[tag]) end function collectors.test(tag) printlist(collectordata[tag]) end function collectors.register(name) registered[csname_id(name)] = name end local call = command_id("call") local letter = command_id("letter") local other = command_id("other_char") function collectors.install(tag,end_cs) local data, d = { }, 0 collectordata[tag] = data local endcs = csname_id(end_cs) while true do local t = get_next() local a, b = t[1], t[3] if b == endcs then context["end_cs"]() return elseif a == call and registered[b] then expand() else d = d + 1 data[d] = t end end end function collectors.handle(tag,handle,flush) collectordata[tag] = handle(collectordata[tag]) if flush then collectors.flush(tag) end end local show_methods = { } collectors.show_methods = show_methods function collectors.show(tag, method) if type(tag) == "table" then show_methods[method or 'a'](tag) else show_methods[method or 'a'](collectordata[tag]) end end function collectors.defaultwords(t,str) local n = #t n = n + 1 t[n] = tokens.bgroup n = n + 1 t[n] = createtoken("red") for i=1,#str do n = n + 1 t[n] = tokens.other('*') end n = n + 1 t[n] = tokens.egroup end function collectors.dowithwords(tag,handle) local t, w, tn, wn = { }, { }, 0, 0 handle = handle or collectors.defaultwords local tagdata = collectordata[tag] for k=1,#tagdata do local v = tagdata[k] if v[1] == letter then wn = wn + 1 w[wn] = v[2] else if wn > 0 then handle(t,w) wn = 0 end tn = tn + 1 t[tn] = v end end if wn > 0 then handle(t,w) end collectordata[tag] = t end local function showtoken(t) if t then local cmd, chr, id, cs, name = t[1], t[2], t[3], nil, command_name(t) or "" if cmd == letter or cmd == other then return format("%s-> %s -> %s", name, chr, utfchar(chr)) elseif id > 0 then cs = csname_name(t) or nil if cs then return format("%s-> %s", name, cs) elseif tonumber(chr) < 0 then return format("%s-> %s", name, id) else return format("%s-> (%s,%s)", name, chr, id) end else return format("%s", name) end else return "no node" end end collectors.showtoken = showtoken function collectors.trace() local t = get_next() logs.report("tokenlist",showtoken(t)) return t end -- these might move to a runtime module show_methods.a = function(data) -- no need to store the table, just pass directly local function row(one,two,three,four,five) context.NC() context(one) context.NC() context(two) context.NC() context(three) context.NC() context(four) context.NC() context(five) context.NC() context.NR() end context.starttabulate { "|T|Tr|cT|Tr|T|" } row("cmd","chr","","id","name") context.HL() for _,v in next, data do local cmd, chr, id, cs, sym = v[1], v[2], v[3], "", "" local name = gsub(command_name(v) or "","_","\\_") if id > 0 then cs = csname_name(v) or "" if cs ~= "" then cs = "\\string " .. cs end else id = "" end if cmd == letter or cmd == other then sym = "\\char " .. chr end if tonumber(chr) < 0 then row(name,"",sym,id,cs) else row(name,chr,sym,id,cs) end end context.stoptabulate() end local function show_b_c(data,swap) -- no need to store the table, just pass directly local function row(one,two,three) context.NC() context(one) context.NC() context(two) context.NC() context(three) context.NC() context.NR() end if swap then context.starttabulate { "|Tl|Tl|Tr|" } else context.starttabulate { "|Tl|Tr|Tl|" } end row("cmd","chr","name") context.HL() for _,v in next, data do local cmd, chr, id, cs, sym = v[1], v[2], v[3], "", "" local name = gsub(command_name(v) or "","_","\\_") if id > 0 then cs = csname_name(v) or "" end if cmd == letter or cmd == other then sym = "\\char " .. chr elseif cs == "" then -- okay elseif is_activechar(v) then sym = "\\string " .. cs else sym = "\\string\\" .. cs end if swap then row(name,sym,chr) elseif tonumber(chr) < 0 then row(name,"",sym) else row(name,chr,sym) end end context.stoptabulate() end -- Even more experimental ... show_methods.b = function(data) show_b_c(data,false) end show_methods.c = function(data) show_b_c(data,true ) end local remapper = { } -- namespace collectors.remapper = remapper local remapperdata = { } -- user mappings remapper.data = remapperdata function remapper.store(tag,class,key) local s = remapperdata[class] if not s then s = { } remapperdata[class] = s end s[key] = collectordata[tag] collectordata[tag] = nil end function remapper.convert(tag,toks) local data = remapperdata[tag] local leftbracket, rightbracket = utfbyte('['), utfbyte(']') local skipping = 0 -- todo: math if data then local t, n = { }, 0 for s=1,#toks do local tok = toks[s] local one, two = tok[1], tok[2] if one == 11 or one == 12 then if two == leftbracket then skipping = skipping + 1 n = n + 1 ; t[n] = tok elseif two == rightbracket then skipping = skipping - 1 n = n + 1 ; t[n] = tok elseif skipping == 0 then local new = data[two] if new then if #new > 1 then for n=1,#new do n = n + 1 ; t[n] = new[n] end else n = n + 1 ; t[n] = new[1] end else n = n + 1 ; t[n] = tok end else n = n + 1 ; t[n] = tok end else n = n + 1 ; t[n] = tok end end return t else return toks end end