summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2012-12-24 21:40:31 +0200
committerMarius <mariausol@gmail.com>2012-12-24 21:40:31 +0200
commit31c8bf0930a6d3e353a552d6bab71f62bc25f34e (patch)
treef9fd41e91d4751cdddd2bdfc15ae69f78b61f73f
parent1c36d2cc9c25d74a806ee74c0ee28da32d5e84ba (diff)
downloadcontext-31c8bf0930a6d3e353a552d6bab71f62bc25f34e.tar.gz
beta 2012.12.24 20:08
-rw-r--r--context/data/scite/lexers/data/scite-context-data-context.lua4
-rw-r--r--context/data/scite/lexers/data/scite-context-data-interfaces.lua4
-rw-r--r--context/data/scite/lexers/scite-context-lexer-lua.lua77
-rw-r--r--context/data/scite/lexers/scite-context-lexer-mps.lua11
-rw-r--r--context/data/scite/lexers/scite-context-lexer-tex.lua7
-rw-r--r--context/data/scite/lexers/scite-context-lexer.lua9
-rw-r--r--context/data/scite/scite-context-data-context.properties108
-rw-r--r--context/data/scite/scite-context-data-interfaces.properties1254
-rw-r--r--context/data/scite/scite-context-data-metapost.properties20
-rw-r--r--context/data/scite/scite-context-data-tex.properties132
-rw-r--r--metapost/context/base/mp-chem.mpiv780
-rw-r--r--metapost/context/base/mp-mlib.mpiv2
-rw-r--r--metapost/context/base/mp-tool.mpiv14
-rw-r--r--scripts/context/lua/mtx-context.lua70
-rw-r--r--scripts/context/lua/mtxrun.lua3736
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua3736
-rw-r--r--scripts/context/stubs/unix/mtxrun3736
-rw-r--r--tex/context/base/anch-pos.lua2
-rw-r--r--tex/context/base/attr-lay.lua2
-rw-r--r--tex/context/base/back-exp.lua3
-rw-r--r--tex/context/base/bibl-bib.lua1
-rw-r--r--tex/context/base/buff-ini.lua90
-rw-r--r--tex/context/base/char-ini.lua86
-rw-r--r--tex/context/base/char-tex.lua13
-rw-r--r--tex/context/base/char-utf.lua23
-rw-r--r--tex/context/base/chem-ini.lua58
-rw-r--r--tex/context/base/chem-str.lua448
-rw-r--r--tex/context/base/chem-str.mkiv83
-rw-r--r--tex/context/base/cldf-bas.mkiv1
-rw-r--r--tex/context/base/cldf-com.lua5
-rw-r--r--tex/context/base/cldf-ini.lua30
-rw-r--r--tex/context/base/cldf-prs.lua52
-rw-r--r--tex/context/base/colo-ini.lua11
-rw-r--r--tex/context/base/cont-new.mkii2
-rw-r--r--tex/context/base/cont-new.mkiv2
-rw-r--r--tex/context/base/cont-yes.mkiv11
-rw-r--r--tex/context/base/context-version.pdfbin4089 -> 4112 bytes
-rw-r--r--tex/context/base/context-version.pngbin40551 -> 40425 bytes
-rw-r--r--tex/context/base/context.mkii2
-rw-r--r--tex/context/base/context.mkiv2
-rw-r--r--tex/context/base/core-con.lua2
-rw-r--r--tex/context/base/core-uti.lua1
-rw-r--r--tex/context/base/data-env.lua4
-rw-r--r--tex/context/base/data-ini.lua18
-rw-r--r--tex/context/base/data-lua.lua18
-rw-r--r--tex/context/base/data-pre.lua27
-rw-r--r--tex/context/base/data-res.lua13
-rw-r--r--tex/context/base/data-sch.lua4
-rw-r--r--tex/context/base/data-tex.lua10
-rw-r--r--tex/context/base/data-tmp.lua48
-rw-r--r--tex/context/base/data-use.lua8
-rw-r--r--tex/context/base/file-job.lua2
-rw-r--r--tex/context/base/font-con.lua3
-rw-r--r--tex/context/base/font-def.lua1
-rw-r--r--tex/context/base/font-ext.lua1
-rw-r--r--tex/context/base/font-ota.lua2
-rw-r--r--tex/context/base/font-otf.lua26
-rw-r--r--tex/context/base/font-otn.lua2
-rw-r--r--tex/context/base/font-otp.lua226
-rw-r--r--tex/context/base/font-syn.lua1
-rw-r--r--tex/context/base/font-vf.lua7
-rw-r--r--tex/context/base/l-dir.lua26
-rw-r--r--tex/context/base/l-file.lua133
-rw-r--r--tex/context/base/l-io.lua2
-rw-r--r--tex/context/base/l-lpeg.lua323
-rw-r--r--tex/context/base/l-lua.lua107
-rw-r--r--tex/context/base/l-number.lua238
-rw-r--r--tex/context/base/l-string.lua194
-rw-r--r--tex/context/base/l-table.lua238
-rw-r--r--tex/context/base/l-unicode.lua693
-rw-r--r--tex/context/base/lang-ini.lua1
-rw-r--r--tex/context/base/lang-url.lua5
-rw-r--r--tex/context/base/lang-wrd.lua4
-rw-r--r--tex/context/base/lpdf-epa.lua141
-rw-r--r--tex/context/base/lpdf-epd.lua28
-rw-r--r--tex/context/base/lpdf-ini.lua3
-rw-r--r--tex/context/base/lpdf-swf.lua2
-rw-r--r--tex/context/base/luat-bas.mkiv3
-rw-r--r--tex/context/base/luat-cnf.lua77
-rw-r--r--tex/context/base/luat-cod.mkiv2
-rw-r--r--tex/context/base/luat-env.lua71
-rw-r--r--tex/context/base/luat-exe.lua15
-rw-r--r--tex/context/base/luat-fio.lua3
-rw-r--r--tex/context/base/luat-fmt.lua25
-rw-r--r--tex/context/base/luat-ini.lua232
-rw-r--r--tex/context/base/luat-ini.mkiv100
-rw-r--r--tex/context/base/lxml-ent.lua3
-rw-r--r--tex/context/base/lxml-inf.lua2
-rw-r--r--tex/context/base/lxml-lpt.lua30
-rw-r--r--tex/context/base/lxml-tab.lua1
-rw-r--r--tex/context/base/lxml-tex.lua36
-rw-r--r--tex/context/base/m-database.lua16
-rw-r--r--tex/context/base/m-morse.mkvi23
-rw-r--r--tex/context/base/m-timing.mkiv10
-rw-r--r--tex/context/base/math-ini.lua3
-rw-r--r--tex/context/base/math-ini.mkiv12
-rw-r--r--tex/context/base/math-noa.lua2
-rw-r--r--tex/context/base/meta-fun.lua4
-rw-r--r--tex/context/base/meta-imp-dum.mkiv1
-rw-r--r--tex/context/base/meta-ini.lua117
-rw-r--r--tex/context/base/meta-ini.mkiv13
-rw-r--r--tex/context/base/meta-pag.mkiv2
-rw-r--r--tex/context/base/meta-pdf.lua1
-rw-r--r--tex/context/base/mlib-pdf.lua4
-rw-r--r--tex/context/base/mlib-run.lua2
-rw-r--r--tex/context/base/mtx-context-copy.tex151
-rw-r--r--tex/context/base/mtx-context-select.tex3
-rw-r--r--tex/context/base/mtx-context-timing.tex6
-rw-r--r--tex/context/base/mult-de.mkii1
-rw-r--r--tex/context/base/mult-def.lua4
-rw-r--r--tex/context/base/mult-en.mkii1
-rw-r--r--tex/context/base/mult-fr.mkii1
-rw-r--r--tex/context/base/mult-it.mkii1
-rw-r--r--tex/context/base/mult-low.lua22
-rw-r--r--tex/context/base/mult-nl.mkii1
-rw-r--r--tex/context/base/mult-pe.mkii1
-rw-r--r--tex/context/base/mult-ro.mkii1
-rw-r--r--tex/context/base/node-aux.lua2
-rw-r--r--tex/context/base/node-fnt.lua161
-rw-r--r--tex/context/base/node-ini.lua1
-rw-r--r--tex/context/base/node-inj.lua2
-rw-r--r--tex/context/base/node-pro.lua1
-rw-r--r--tex/context/base/node-typ.lua2
-rw-r--r--tex/context/base/phys-dim.mkiv4
-rw-r--r--tex/context/base/s-abr-01.tex1
-rw-r--r--tex/context/base/s-abr-04.tex1
-rw-r--r--tex/context/base/s-inf-03.mkiv33
-rw-r--r--tex/context/base/s-mod-01.mkiv3
-rw-r--r--tex/context/base/sort-ini.lua7
-rw-r--r--tex/context/base/spac-ver.mkiv16
-rw-r--r--tex/context/base/status-files.pdfbin24378 -> 24410 bytes
-rw-r--r--tex/context/base/status-lua.pdfbin199955 -> 203150 bytes
-rw-r--r--tex/context/base/status-mkiv.tex9
-rw-r--r--tex/context/base/strc-bkm.lua2
-rw-r--r--tex/context/base/strc-doc.lua7
-rw-r--r--tex/context/base/strc-ini.lua10
-rw-r--r--tex/context/base/strc-ref.lua2
-rw-r--r--tex/context/base/strc-ref.mkvi4
-rw-r--r--tex/context/base/syst-aux.lua1
-rw-r--r--tex/context/base/syst-con.lua2
-rw-r--r--tex/context/base/syst-lua.mkiv12
-rw-r--r--tex/context/base/toks-ini.lua5
-rw-r--r--tex/context/base/trac-log.lua14
-rw-r--r--tex/context/base/trac-set.lua35
-rw-r--r--tex/context/base/trac-tim.lua6
-rw-r--r--tex/context/base/typo-dir.lua2
-rw-r--r--tex/context/base/typo-krn.lua2
-rw-r--r--tex/context/base/typo-spa.lua2
-rw-r--r--tex/context/base/util-lua.lua161
-rw-r--r--tex/context/base/util-pck.lua29
-rw-r--r--tex/context/base/util-prs.lua40
-rw-r--r--tex/context/base/util-seq.lua4
-rw-r--r--tex/context/base/util-sql-users.lua4
-rw-r--r--tex/context/base/util-sql.lua4
-rw-r--r--tex/context/base/util-sta.lua6
-rw-r--r--tex/context/base/util-sto.lua66
-rw-r--r--tex/context/base/util-tab.lua28
-rw-r--r--tex/context/base/x-mathml.lua4
-rw-r--r--tex/context/interface/keys-cs.xml1
-rw-r--r--tex/context/interface/keys-de.xml1
-rw-r--r--tex/context/interface/keys-en.xml1
-rw-r--r--tex/context/interface/keys-fr.xml1
-rw-r--r--tex/context/interface/keys-it.xml1
-rw-r--r--tex/context/interface/keys-nl.xml1
-rw-r--r--tex/context/interface/keys-pe.xml1
-rw-r--r--tex/context/interface/keys-ro.xml1
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2260
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua4
168 files changed, 12651 insertions, 8508 deletions
diff --git a/context/data/scite/lexers/data/scite-context-data-context.lua b/context/data/scite/lexers/data/scite-context-data-context.lua
index acc65770a..bd7d94492 100644
--- a/context/data/scite/lexers/data/scite-context-data-context.lua
+++ b/context/data/scite/lexers/data/scite-context-data-context.lua
@@ -1,4 +1,4 @@
return {
- ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startnotext", "stopnotext", "startdocument", "stopdocument", "documentvariable", "startmodule", "stopmodule", "usemodule", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "globalenablemode", "globaldisablemode", "globalpreventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile" },
- ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing", "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing", "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing", "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", "normalreqno", "startimath", "stopimath", "normalstartimath", "normalstopimath", "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathstyleface" },
+ ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startnotext", "stopnotext", "startdocument", "stopdocument", "documentvariable", "startmodule", "stopmodule", "usemodule", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "globalenablemode", "globaldisablemode", "globalpreventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile", "luastringsep", "!!bs", "!!es" },
+ ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "obeyedspace", "obeyedline", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "installcorenamespace", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing", "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing", "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing", "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", "normalreqno", "startimath", "stopimath", "normalstartimath", "normalstopimath", "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathstyleface", "mathstylecommand", "luaexpr", "expdoifelse", "expdoif", "expdoifnot", "expdoifcommonelse", "expdoifinsetelse", "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport", "ctxlua", "luacode", "lateluacode", "directluacode", "registerctxluafile", "ctxloadluafile", "luaversion", "luamajorversion", "luaminorversion", "ctxluacode", "luaconditional", "luaexpanded", "startluaparameterset", "stopluaparameterset", "luaparameterset", "definenamedlua", "obeylualines", "obeyluatokens", "startluacode", "stopluacode", "startlua", "stoplua" },
} \ No newline at end of file
diff --git a/context/data/scite/lexers/data/scite-context-data-interfaces.lua b/context/data/scite/lexers/data/scite-context-data-interfaces.lua
index ee7b75718..b2c09b62a 100644
--- a/context/data/scite/lexers/data/scite-context-data-interfaces.lua
+++ b/context/data/scite/lexers/data/scite-context-data-interfaces.lua
@@ -1,10 +1,10 @@
return {
["cs"]={ "CAP", "Cap", "Caps", "Cisla", "KAP", "Kap", "Kaps", "MESIC", "Rimskecislice", "SLOVA", "SLOVO", "Slova", "Slovo", "VSEDNIDEN", "Znak", "Znaky", "aktualnicislonadpisu", "aktualnidatum", "appendix", "arg", "atleftmargin", "atrightmargin", "barevnalista", "barva", "bilemisto", "bottomspace", "bublinkovanapoveda", "bydliste", "bypassblocks", "cap", "celkovypocetstran", "cernalinka", "cernelinky", "chapter", "chem", "cisla", "cislonadpisu", "cislopodrovnice", "cislorovnice", "cislostrany", "citace", "citovat", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "definerawfont", "definerule", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definuj", "definujakcent", "definujbarvu", "definujblok", "definujbloksekce", "definujbuffer", "definujfont", "definujformatodkazu", "definujhbox", "definujhlavnipole", "definujinterakcnimenu", "definujkombinovanyseznam", "definujkonverzi", "definujlogo", "definujnadpis", "definujobrazeksymbol", "definujodkaz", "definujodstavce", "definujopis", "definujoramovani", "definujoramovanytext", "definujpaletu", "definujplvouciobjekt", "definujpodpole", "definujpole", "definujpopis", "definujpopisek", "definujprekryv", "definujpreskok", "definujprikaz", "definujprofil", "definujprogram", "definujprostredizakladnihofontu", "definujrejstrik", "definujsablonutabulky", "definujsekci", "definujseznam", "definujseznamodkazu", "definujskupinubarev", "definujstartstop", "definujstyl", "definujstylfontu", "definujsymbol", "definujsynonumumfontu", "definujsynonyma", "definujtabelaci", "definujtext", "definujtrideni", "definujupravu", "definujvelikostpapiru", "definujverzi", "definujvycet", "definujvystup", "definujzakladnifont", "definujzasobnikpoli", "definujznaceni", "definujznak", "delkaseznamu", "description", "dodrzujprofil", "dodrzujverzi", "dodrzujverziprofilu", "dvoustrannypapir", "emptylines", "enumeration", "externiobraz", "fakt", "footnotetext", "forceblocks", "framedtext", "getnumber", "headsym", "hl", "hlavnijazyk", "hlavniuroven", "hodnotabarvy", "hodnotasedi", "immediatebetweenlist", "immediatetolist", "indentation", "ininner", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "instalacejazyka", "interakcnilista", "interakcnitlacitka", "interaktivnimenu", "jazyk", "jdidolu", "jdina", "jdinabox", "jdinastranu", "jmeno", "kap", "klonujpole", "komponenta", "konvertujcislo", "kopirujpole", "korekcebilehomista", "labeling", "leg", "listsymbol", "loadsorts", "loadsynonyms", "maoramovani", "mapfontsize", "marginalnilinka", "marginalninadpis", "marginalnislovo", "marginalnitext", "matematika", "mazaramovani", "mediaeval", "meritko", "mesic", "mezera", "moveformula", "movesidefloat", "mrizka", "nadpis", "nadruhyokraj", "nalevo", "nalevyokraj", "name", "naokraj", "napravo", "napravyokraj", "nastavbarvu", "nastavbarvy", "nastavbilamista", "nastavblok", "nastavbloksekce", "nastavbuffer", "nastavcernelinky", "nastavcislonadpisu", "nastavcislostrany", "nastavcislovani", "nastavcislovaniodstavcu", "nastavcislovaniradku", "nastavcislovanistran", "nastavcitaci", "nastavdefinicipoznamekpodcarou", "nastavdeleniplvoucichobjektu", "nastavdelitko", "nastavdolnitexty", "nastaveni", "nastavexterniobrazy", "nastavhorejsek", "nastavhornitexty", "nastavinterakci", "nastavinterakcnilistu", "nastavinterakcnimenu", "nastavinterakcniobrazovku", "nastavjazyk", "nastavkapitalky", "nastavkombinovanyseznam", "nastavkomentar", "nastavkomentarstrany", "nastavlegendu", "nastavmarginalie", "nastavmarginalniblok", "nastavmarginalnilinky", "nastavmeziradkovoumezeru", "nastavnadpis", "nastavnadpisy", "nastavodkazovani", "nastavodsazovani", "nastavodstavce", "nastavopis", "nastavoramovanetexty", "nastavoramovani", "nastavorez", "nastavotoceni", "nastavpaletu", "nastavplvouciobjekt", "nastavplvouciobjekty", "nastavpodcislostrany", "nastavpodtrzeni", "nastavpole", "nastavpolozky", "nastavpopisek", "nastavpopisky", "nastavpopisy", "nastavpozadi", "nastavpoznamkypodcarou", "nastavprechodstrany", "nastavpreskok", "nastavprofily", "nastavprogramy", "nastavprostredizakladnihofontu", "nastavpublikace", "nastavradkovani", "nastavradky", "nastavrastr", "nastavrejstrik", "nastavrovnice", "nastavsadusymbolu", "nastavsekci", "nastavseznam", "nastavseznamodkazu", "nastavsirkucary", "nastavsloupce", "nastavspodek", "nastavspojeni", "nastavsynchronizaci", "nastavsynchronizacnilistu", "nastavsynonyma", "nastavsystem", "nastavtab", "nastavtabelaci", "nastavtabulky", "nastavtenkelinky", "nastavtext", "nastavtexthlavicky", "nastavtextovelinky", "nastavtextpopisku", "nastavtexttexty", "nastavtextyupati", "nastavtextyzahlavi", "nastavtlacitka", "nastavtoleranci", "nastavtrideni", "nastavtype", "nastavumisteniprotejsku", "nastavumistovani", "nastavupati", "nastavupravu", "nastavurl", "nastavusporadani", "nastavvelikostpapiru", "nastavverze", "nastavvsechnapole", "nastavvycty", "nastavvyplnovelinky", "nastavvyplnoveradky", "nastavvystup", "nastavvzhled", "nastavzahlavi", "nastavzakladnifont", "nastavzarovnani", "nastavznaceni", "nastavzuzeni", "nastrane", "navigating", "nejakyradek", "nekde", "nextsection", "neznamo", "nivy", "nizky", "nocap", "nokap", "nop", "numberofsubpages", "obrazovka", "odkaz", "odkaznadatum", "odkaznastranu", "odkaznatext", "odkazujici", "odsazenishora", "odsazenizleva", "odsazovani", "okr", "opakovat", "opis", "opissoubor", "oramovani", "oref", "orez", "otocit", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "oznaceni", "oznacverzi", "pagedepth", "pageoffset", "paragraph", "parovastrana", "part", "pis", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "plnezneni", "pol", "pole", "polozka", "polozky", "popisky", "poppisek", "porovnejpaletu", "porovnejskupinubarev", "positiontext", "pozadi", "pozice", "poznamka", "poznamkapodcarou", "pref", "prelozit", "premistinamrizku", "prepninazakladnifont", "preskoc", "prizpusobivepole", "prizpusobvzhled", "produkt", "program", "projekt", "propojeneznaceni", "propojenydokument", "propojenyrejstrik", "prostredi", "publikace", "ran", "ref", "register", "reservefloat", "reset", "resetnumber", "resettextcontent", "resetznaceni", "rimskecislice", "rozdelplvouciobjekt", "rozmer", "rozpojeneznaceni", "roztazene", "schovejbloky", "section", "sedabarva", "seeregister", "setnumber", "settextcontent", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "sirkalevehookraje", "sirkalevemarginalie", "sirkamarginalie", "sirkaokraje", "sirkapapiru", "sirkapravehookraje", "sirkapravemarginalie", "sirkasazby", "sirkaseznamu", "sirkatextu", "sirkatiskpapiru", "sloupec", "slovovpravo", "sort", "spodek", "stanovcharakteristickuseznamu", "stanovcislonadpisu", "startalignment", "startbarva", "startbuffer", "startcislovaniradku", "startcitace", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenumeration", "startfakt", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobalni", "starthiding", "startinteraktivnimenu", "startitemgroup", "startkodovani", "startkomponenta", "startkorekceradku", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokalni", "startlokalnipoznamkypodcarou", "startmakeup", "startmarginalniblok", "startmarginalnilinka", "startmarginblock", "startnamemakeup", "startnarrower", "startnezhustene", "startobraz", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozadi", "startprehled", "startprekryv", "startprodukt", "startprofil", "startprofile", "startprojekt", "startprostredi", "startprotejsek", "startradek", "startradky", "startrastr", "startregister", "startsadasymbolu", "startsloupce", "startspojeni", "startsymbolset", "startsynchronizace", "startsynchronization", "starttable", "starttables", "starttabulate", "starttabulka", "starttabulky", "starttext", "starttextovalinka", "starttyping", "startumistovani", "startunpacked", "startuprava", "startverze", "startzarovnavani", "startzhustene", "startzuzeni", "stopalignment", "stopbarva", "stopbuffer", "stopcislovaniradku", "stopcitace", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenumeration", "stopfakt", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobalni", "stophiding", "stopinteraktivnimenu", "stopitemgroup", "stopkodovani", "stopkomponenta", "stopkorekceradku", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokalni", "stoplokalnipoznamkypodcarou", "stopmakeup", "stopmarginalniblok", "stopmarginalnilinka", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopnezhustene", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozadi", "stopprehled", "stopprekryv", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopprostredi", "stopprotejsek", "stopradek", "stopradky", "stoprastr", "stopsloupce", "stopspojeni", "stopsymbolset", "stopsynchronizace", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptabulka", "stoptabulky", "stoptext", "stoptextovalinka", "stoptyping", "stopumistovani", "stopunpacked", "stopuprava", "stopverze", "stopzarovnavani", "stopzhustene", "stopzuzeni", "strana", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronizacnilista", "synchronizovat", "synonym", "tab", "tecky", "tenkalinka", "tenkelinky", "testcolumn", "testpage", "tex", "texthlavicky", "textovalinka", "textpopisku", "textvariable", "title", "tlacitko", "tlacitkomenu", "tloustkacary", "tref", "tvrdamezera", "tvrdemezery", "txt", "typebuffer", "ukazbarvu", "ukazexterniobrazy", "ukazmrizku", "ukaznastaveni", "ukazpaletu", "ukazpodpery", "ukazpole", "ukazpostredizakladnihofontu", "ukazramecek", "ukazsadusymbolu", "ukazskupinubarev", "ukazupravu", "ukazvytisk", "ukazvzhled", "ukazzakladnifont", "umistikombinovanyseznam", "umistilegendu", "umistiloga", "umistilokalnipoznamkypodcarou", "umistinadsebe", "umistinamrizku", "umistipodrovnici", "umistipoznamkypodcarou", "umistirejstrik", "umistirovnici", "umistiseznam", "umistivedlesebe", "umistizalozky", "underbar", "underbars", "urcicharakteristikurejstriku", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "uzijJSscripts", "uzijURL", "uzijadresar", "uzijbloky", "uzijexternidokument", "uzijexterniobraz", "uzijexternisoubor", "uzijexternisoubory", "uzijexternizvuk", "uzijkodovani", "uzijmodul", "uzijmoduly", "uzijodkazy", "uzijprikazy", "uzijspeciality", "uzijsymbol", "uzijurl", "verze", "vl", "vlasovalinka", "vlevo", "vpravo", "vradku", "vsedniden", "vyberbloky", "vyberpapir", "vyberverzi", "vyplnenytext", "vyplnovelinky", "vyplnovepole", "vyplnovyradek", "vyskahorejsku", "vyskapapiru", "vyskasazby", "vyskaseznamu", "vyskaspodku", "vyskatextu", "vyskatiskpapiru", "vyskaupati", "vyskazahlavi", "vysoky", "vyznam", "vzdalenosthorejsku", "vzdalenostlevehookraje", "vzdalenostlevemarginalie", "vzdalenostmarginalie", "vzdalenostokraje", "vzdalenostpravehookraje", "vzdalenostpravemarginalie", "vzdalenostspodku", "vzdalenostupati", "vzdalenostzahlavi", "zablokujinterakcnimenu", "zachovejbloky", "zadnamezera", "zadnebilemisto", "zadnedalsibloky", "zadnedalsisoubory", "zadnehorniadolniradky", "zadneodsazovani", "zadnezahlaviaupati", "zadneznaceni", "zadnyrozmer", "zadnyseznam", "zadnytest", "zalozka", "zapisdorejstriku", "zapisdoseznamu", "zapisdoseznamuodkazu", "zapismeziseznam", "zaramovani", "zarovnanonastred", "zarovnanovlevo", "zarovnanovpravo", "zasobnikpoli", "zaznamovepole", "zhustene", "ziskejbuffer", "ziskejznaceni", "zlomek", "znaceni", "znak", "znaky", "zpracujbloky", "zpracujstranu", "zrcadlit", "zref", "zvysujicicislo" },
["de"]={ "Buchstabe", "Buchstaben", "CAP", "Cap", "Caps", "KAP", "Kap", "Kaps", "MONAT", "Roemischezahlen", "WOCHENTAG", "WOERTER", "WORT", "Woerter", "Wort", "Ziffern", "abstandlinkerrand", "abstandoben", "abstandrechterrand", "abstandunten", "amgitterausrichten", "amgitterneuausrichten", "appendix", "arg", "atleftmargin", "atrightmargin", "aufseite", "ausfuellfeld", "ausfuelltext", "ausschnitt", "bearbeitebloecke", "bearbeiteseite", "bedeutung", "behaltebloecke", "bei", "bemerkung", "benutzekodierung", "benutzespezielles", "benutzeverzeichnis", "beschrifteversion", "beschriftung", "bestimmekopfnummer", "bestimmelistencharakeristika", "bestimmeregistercharakteristika", "bildschirm", "blanko", "bookmark", "bottomspace", "breitelinkerrand", "breiterechterrand", "bruch", "buchstabe", "buchstaben", "but", "bypassblocks", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "defineoutput", "definepagebreak", "defineplacement", "definerawfont", "definerule", "defineschriftsynonym", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definiereabbsymbol", "definiereabsaetze", "definiereabschnitt", "definiereabschnittsblock", "definiereakzent", "definierebefehl", "definierebeschreibung", "definierebeschreibungen", "definierebeschriftung", "definiereblanko", "definiereblock", "definierefarbe", "definierefarbengruppe", "definierefeld", "definierefeldstapel", "definierefliesstext", "definierefliesstextumgebung", "definieregleitobjekt", "definierehauptfeld", "definierehbox", "definiereinteraktionsmenue", "definierekonversion", "definierelabel", "definiereliste", "definierelogo", "definieren", "definierenummerierung", "definiereoverlay", "definierepalette", "definierepapierformat", "definiereprofil", "definiereprogramme", "definierepuffer", "definierereferenz", "definierereferenzformat", "definierereferenzliste", "definiereregister", "definiereschrift", "definiereschriftstil", "definieresortieren", "definierestartstop", "definierestil", "definieresubfeld", "definieresymbol", "definieresynonyme", "definieretabellenvorlage", "definieretabulator", "definieretext", "definieretippen", "definiereueberschrift", "definiereumbruch", "definiereumrahmt", "definiereumrahmtertext", "definiereversion", "definierezeichen", "definierezusammengestellteliste", "description", "dimension", "doppelseite", "doppelseitigespapier", "drehen", "duennelinie", "duennerumriss", "einezeile", "einstellungen", "einziehen", "emptylines", "entknuepfebeschriftung", "enumeration", "externeabbildung", "farbbalken", "farbe", "farbewert", "feld", "feldstapel", "festesspatium", "folgeprofil", "folgeprofilversion", "folgeversion", "footnotetext", "forceblocks", "format", "formelnummer", "framedtext", "fussnote", "fusszeileabstand", "fusszeilenhoehe", "gefuelltesrechteck", "gefuelltezeile", "geg", "gesamtseitenanzahl", "gestreckt", "getnumber", "gitter", "graufarbe", "grauwert", "haarlinie", "hauptsprache", "headsym", "heutigesdatum", "heutigeskopfnummer", "hintergrund", "hl", "hoch", "hoeheoben", "hoeheunten", "holebeschriftung", "holepuffer", "imlinken", "imlinkenrand", "immaumrise", "immediatebetweenlist", "immediatetolist", "imrechten", "imrechtenrand", "imumriss", "in", "inaktiviereinteraktionsmenue", "inanderermarginale", "indentation", "ininner", "inlinkermarginale", "inmarginalie", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inrechtermarginale", "installieresprache", "interaktionsbalken", "interaktionsknopfe", "interaktionsmenue", "inzeile", "irgendwo", "its", "kap", "keindimension", "keinebeschriftung", "keinebloeckemehr", "keinedateienmehr", "keinekopfundfusszeilen", "keineliste", "keinspatium", "keintest", "keinzeilenobenundunten", "keinzwischenraum", "kleinerdurchschuss", "klonierefeld", "knopf", "komponente", "konvertierezahl", "kopf", "kopfniveau", "kopfnummer", "kopfweite", "kopfzeilenabstand", "kopfzeilenhoehe", "kopierefeld", "korrigierezwischenraum", "label", "labeling", "labels", "labeltext", "leg", "liniendicke", "linkemarginalafstand", "linkemarginalbreite", "linksbuendig", "listenbreite", "listenhoehe", "listenlaenge", "listsymbol", "loadsorts", "loadsynonyms", "mapfontsize", "mar", "marginalafstand", "marginalbreite", "marginallinie", "marginaltext", "marginaltitel", "marginalwort", "mathematik", "maumrise", "mediaeval", "menueknopf", "monat", "moveformula", "movesidefloat", "nachunten", "name", "navigating", "nextsection", "nichteinziehen", "nocap", "nokap", "nop", "notiz", "numberofsubpages", "nummererhoehen", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "papierbreite", "papierhoehe", "paragraph", "part", "passelayoutan", "passendfeld", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "platzierebookmarks", "platziereformel", "platzierefussnoten", "platzierelegende", "platziereliste", "platzierelogo", "platzierelokalefussnoten", "platzierenebeneinander", "platziereregister", "platziereuntereinander", "platziereunterformel", "platzierezusammengestellteliste", "pos", "position", "positiontext", "posten", "printpapierbreite", "printpapierhoehe", "produkt", "programm", "projekt", "publikation", "punkt", "ran", "randabstand", "randbreite", "rechteck", "rechtecke", "rechtemarginalafstand", "rechtemarginalbreite", "rechtsbuendig", "ref", "referenz", "referieren", "register", "registrierefelder", "reservefloat", "resetnumber", "resettextcontent", "roemischezahlen", "ruecksetzten", "ruecksetztenbeschriftung", "rumpfweite", "satzbreite", "satzhoehe", "schreibezumregister", "schreibezurliste", "schreibezurreferenzliste", "schreibezwischenliste", "section", "seeregister", "seite", "seitenreferenz", "seitenummer", "setnumber", "settext", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "showsymbolset", "sort", "spalte", "spatium", "spiegeln", "sprache", "startabbildung", "startalignment", "startausrichtung", "startbuffer", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenger", "startenumeration", "startfarbe", "startfigure", "startfloattext", "startformula", "startframedtext", "startgeg", "startgegenueber", "startglobal", "startgrosserdurchschuss", "starthiding", "starthintergrund", "startinteraktionsmenue", "startitemgroup", "startkleinerdurchschuss", "startkodierung", "startkombination", "startkomponente", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokal", "startlokalefussnoten", "startmakeup", "startmarginalblock", "startmarginallinie", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositionieren", "startpositioning", "startpostponing", "startprodukt", "startprofil", "startprofile", "startprojekt", "startraster", "startregister", "startspalten", "startsymbolset", "startsynchronisation", "startsynchronization", "starttabelle", "starttabellen", "starttable", "starttables", "starttabulate", "starttext", "starttextlinie", "starttyping", "startueberblick", "startumbruch", "startumgebung", "startunpacked", "startversion", "startzeile", "startzeilen", "startzeilenkorrektur", "startzeilennumerierung", "startzitat", "stelleabsaetzeein", "stelleabsatznummerierungein", "stelleabschnittein", "stelleabschnittsblockein", "stelleanordnenein", "stelleaufzaehlungenein", "stelleausgabeein", "stelleausrichtungein", "stelleausschnittein", "stellebeschreibungein", "stellebeschriftungein", "stellebilderunterschriftein", "stellebildunterschriftein", "stellebindestrichein", "stelleblankoein", "stelleblockein", "stelledrehenein", "stelleduennerumrissein", "stelleeinziehenein", "stelleengerein", "stelleexterneabbildungenein", "stellefarbeein", "stellefarbenein", "stellefeldein", "stellefelderin", "stellefliesstextein", "stellefliesstextumgebungein", "stelleformelnein", "stellefussnotendefinitionein", "stellefussnotenein", "stellefusszeileein", "stellefusszeilentextein", "stellegefuelltesrechteckein", "stellegefuelltezeileein", "stellegegenueberplatzierenein", "stellegleitobjekteein", "stellegleitobjektein", "stellehintergruendeein", "stellehintergrundein", "stelleinmarginalieein", "stelleinteraktionein", "stelleinteraktionsbalkenein", "stelleinteraktionsbildschirmein", "stelleinteraktionsmenueein", "stelleknopfein", "stellekombinationein", "stellekommentarein", "stellekopfzahlein", "stellekopfzeileein", "stellekopfzeilentextein", "stellelabeltextein", "stellelayoutein", "stellelegendeein", "stellelinienbreiteein", "stellelisteein", "stellemarginalblockein", "stellemarginallinieein", "stellenobenein", "stellenummerierungein", "stellepaletteein", "stellepapierformatein", "stelleplatziegeteiltegleitobjekt", "stellepositionierenein", "stellepostenein", "stelleprofilein", "stelleprogrammein", "stellepublikationein", "stellepufferein", "stellerasterein", "stellerechteckein", "stellereferenzierenein", "stellereferenzlisteein", "stelleregisterein", "stelleseitenkommentarein", "stelleseitennummerein", "stelleseitennummeriernungein", "stelleseitenuebergangein", "stellesortierenein", "stellespaltenein", "stellespatiumein", "stellespracheein", "stellesymbolsetein", "stellesynchronisationein", "stellesynchronisationsbalkenein", "stellesynonymein", "stellesystemein", "stelletabein", "stelletabellenein", "stelletabulatorein", "stelletextein", "stelletextobenein", "stelletexttexteein", "stelletextumrissein", "stelletextuntenein", "stelletipein", "stelletippenein", "stelletoleranzein", "stelleueberschriftein", "stelleueberschriftenein", "stelleueberschrifttextein", "stelleumbruchein", "stelleumrahmtein", "stelleumrahmtetexteein", "stelleuntenein", "stelleunterseitennummerein", "stelleunterstreichenein", "stelleurlein", "stelleversalienein", "stelleversionein", "stellezeilenabstandein", "stellezeilenein", "stellezeilennumerierungein", "stellezitierenein", "stellezusammengestelltelisteein", "stellezwischenraumein", "stopalignment", "stopausrichtung", "stopbuffer", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenger", "stopenumeration", "stopfarbe", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopgegenueber", "stopglobal", "stopgrosserdurchschuss", "stophiding", "stophintergrund", "stopinteraktionsmenue", "stopitemgroup", "stopkleinerdurchschuss", "stopkodierung", "stopkombination", "stopkomponente", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokal", "stoplokalefussnoten", "stopmakeup", "stopmarginalblock", "stopmarginallinie", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositionieren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopraster", "stopspalten", "stopsymbolset", "stopsynchronisation", "stopsynchronization", "stoptabelle", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextlinie", "stoptyping", "stopueberblick", "stopumbruch", "stopumgebung", "stopunpacked", "stopversion", "stopzeile", "stopzeilen", "stopzeilenkorrektur", "stopzeilennumerierung", "stopzitat", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronisationsbalken", "synchronisieren", "synonym", "tab", "teilegleitobjekt", "testcolumn", "testpage", "tex", "textbreite", "texthoehe", "textlinie", "textreferenz", "textvariable", "tief", "tiho", "tip", "tippedatei", "tippen", "tippepuffer", "title", "tooltip", "txt", "ueber", "ueberschrifttext", "uebersetzten", "umgebung", "umrahmt", "unbekant", "underbar", "underbars", "unterformelnummer", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "verbergebloecke", "vergleichefarbengruppe", "vergleichepalette", "verknuepfebeschriftung", "verknuepfedokument", "verknuepfregister", "version", "verweis", "verweisdatum", "verwendeJSscript", "verwendeURL", "verwendebefehl", "verwendebloecke", "verwendeexteresdokument", "verwendeexterneabbildung", "verwendeexternedatei", "verwendeexternedateien", "verwendeexternestonstueck", "verwendemodul", "verwendemodule", "verwendereferenzen", "verwendesymbole", "verwendeurl", "vl", "volleswort", "von", "waehlebloeckeaus", "waehlepapieraus", "waehleversionaus", "wechselezumfliesstext", "wiederholen", "wochentag", "wohnort", "wortrechts", "zeigedruck", "zeigeeinstellungen", "zeigeexterneabbildungen", "zeigefarbe", "zeigefarbengruppe", "zeigefelder", "zeigefliesstext", "zeigefliesstextumgebung", "zeigegitter", "zeigelayout", "zeigepalette", "zeigerahmen", "zeigestruts", "zeigeumbruch", "zentriert", "ziffern", "zitat", "zitieren", "zu", "zurbox", "zurseite", "zwischenraum" },
- ["en"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "about", "adaptlayout", "adding", "appendix", "arg", "at", "atleftmargin", "atpage", "atrightmargin", "background", "backspace", "blackrule", "blackrules", "blank", "bookmark", "bottomdistance", "bottomheight", "bottomspace", "but", "button", "bypassblocks", "cap", "chapter", "character", "characters", "chem", "clip", "clonefield", "color", "colorbar", "colorvalue", "column", "comment", "comparecolorgroup", "comparepalet", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "component", "convertnumber", "copyfield", "correctwhitespace", "coupledocument", "coupledregister", "couplemarking", "couplepage", "couplepaper", "coupleregister", "crlf", "currentdate", "currentheadnumber", "cutspace", "date", "decouplemarking", "decrementnumber", "define", "defineaccent", "defineblank", "defineblock", "definebodyfont", "definebodyfontDEF", "definebodyfontREF", "definebodyfontenvironment", "definebuffer", "definecharacter", "definecolor", "definecolorgroup", "definecolumnbreak", "definecolumnset", "definecombination", "definecombinedlist", "definecommand", "defineconversion", "definedescription", "definedfont", "defineenumeration", "definefield", "definefieldstack", "definefiguresymbol", "definefloat", "definefont", "definefontfeature", "definefonthandling", "definefontstyle", "definefontsynonym", "defineframed", "defineframedtext", "definehbox", "definehead", "defineindentedtext", "defineinmargin", "defineinteractionmenu", "defineitemgroup", "definelabel", "definelayer", "definelayout", "definelist", "definelogo", "definemainfield", "definemakeup", "definemarking", "definemathalignment", "defineoutput", "defineoverlay", "definepagebreak", "definepalet", "definepapersize", "defineparagraphs", "defineplacement", "defineprofile", "defineprogram", "definerawfont", "definereference", "definereferenceformat", "definereferencelist", "defineregister", "definerule", "definesection", "definesectionblock", "definesorting", "definestartstop", "definestyle", "definesubfield", "definesymbol", "definesynonyms", "definetabletemplate", "definetabulate", "definetext", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definetyping", "defineversion", "description", "determineheadnumber", "determinelistcharacteristics", "determineregistercharacteristics", "dimension", "disableinteractionmenu", "domicile", "donttest", "edgedistance", "edgewidth", "emptylines", "enumeration", "environment", "externalfigure", "fact", "field", "fieldstack", "fillinfield", "fillinline", "fillinrules", "fillintext", "fitfield", "fixedspace", "fixedspaces", "followprofile", "followprofileversion", "followversion", "footerdistance", "footerheight", "footnote", "footnotetext", "forceblocks", "formulanumber", "fraction", "framed", "framedtext", "from", "getbuffer", "getmarking", "getnumber", "godown", "goto", "gotobox", "gotopage", "graycolor", "greyvalue", "grid", "hairline", "head", "headerdistance", "headerheight", "headlevel", "headnumber", "headsym", "headtext", "hideblocks", "high", "hl", "immediatebetweenlist", "immediatetolist", "in", "incrementnumber", "indentation", "indenting", "inframed", "infull", "ininner", "inleft", "inleftedge", "inleftmargin", "inline", "inmaframed", "inmargin", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inothermargin", "inouter", "inright", "inrightedge", "inrightmargin", "installlanguage", "interactionbar", "interactionbuttons", "interactionmenu", "item", "items", "its", "keepblocks", "label", "labeling", "labels", "labeltext", "language", "leftaligned", "leftedgedistance", "leftedgewidth", "leftmargindistance", "leftmarginwidth", "leg", "linethickness", "listheight", "listlength", "listsymbol", "listwidth", "loadsorts", "loadsynonyms", "logfields", "lohi", "low", "maframed", "mainlanguage", "makeupheight", "makeupwidth", "mapfontsize", "mar", "margindistance", "marginrule", "margintext", "margintitle", "marginwidth", "marginword", "marking", "markversion", "mathematics", "mediaeval", "menubutton", "midaligned", "mirror", "month", "moveformula", "moveongrid", "movesidefloat", "name", "navigating", "nextsection", "nocap", "nodimension", "noheaderandfooterlines", "noindenting", "nolist", "nomarking", "nomoreblocks", "nomorefiles", "nop", "nospace", "note", "notopandbottomlines", "nowhitespace", "numberofsubpages", "numbers", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "packed", "page", "pagedepth", "pagenumber", "pageoffset", "pagereference", "paperheight", "paperwidth", "paragraph", "part", "periods", "placebookmarks", "placecombinedlist", "placefloat", "placefootnotes", "placeformula", "placeheadnumber", "placeheadtext", "placelegend", "placelist", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelocalfootnotes", "placelogos", "placeongrid", "placeontopofeachother", "placepagenumber", "placerawlist", "placereferencelist", "placeregister", "placerule", "placesidebyside", "placesubformula", "placetextvariable", "position", "positiontext", "printpaperheight", "printpaperwidth", "processblocks", "processpage", "product", "program", "project", "publication", "quotation", "quote", "ran", "redo", "ref", "reference", "referral", "referraldate", "referring", "register", "remark", "reservefloat", "reset", "resetmarking", "resetnumber", "resettextcontent", "rightaligned", "rightedgedistance", "rightedgewidth", "rightmargindistance", "rightmarginwidth", "romannumerals", "rotate", "scale", "screen", "section", "seeregister", "selectblocks", "selectpaper", "selectversion", "setnumber", "settextcontent", "settextvariable", "setupalign", "setupanswerarea", "setuparranging", "setupbackground", "setupbackgrounds", "setupblackrules", "setupblank", "setupblock", "setupbodyfont", "setupbodyfontenvironment", "setupbottom", "setupbottomtexts", "setupbuffer", "setupbuttons", "setupcapitals", "setupcaption", "setupcaptions", "setupclipping", "setupcolor", "setupcolors", "setupcolumns", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupcombinations", "setupcombinedlist", "setupcomment", "setupdescriptions", "setupenumerations", "setupexternalfigures", "setupfield", "setupfields", "setupfillinlines", "setupfillinrules", "setupfloat", "setupfloats", "setupfloatsplitting", "setupfonthandling", "setupfontsynonym", "setupfooter", "setupfootertexts", "setupfootnotedefinition", "setupfootnotes", "setupforms", "setupformulae", "setupframed", "setupframedtexts", "setuphead", "setupheader", "setupheadertexts", "setupheadnumber", "setupheads", "setupheadtext", "setuphyphenmark", "setupindentedtext", "setupindenting", "setupinmargin", "setupinteraction", "setupinteractionbar", "setupinteractionmenu", "setupinteractionscreen", "setupinterlinespace", "setupinterlinespace2", "setupitemgroup", "setupitemizations", "setupitems", "setuplabeltext", "setuplanguage", "setuplayout", "setuplegend", "setuplinenumbering", "setuplines", "setuplinewidth", "setuplist", "setuplistalternative", "setupmakeup", "setupmarginblocks", "setupmarginrules", "setupmarking", "setupmathalignment", "setupnarrower", "setupnumber", "setupnumbering", "setupoppositeplacing", "setupoutput", "setuppagecomment", "setuppagenumber", "setuppagenumbering", "setuppagetransitions", "setuppalet", "setuppaper", "setuppapersize", "setupparagraphnumbering", "setupparagraphs", "setupplacement", "setuppositioning", "setupprofiles", "setupprograms", "setuppublications", "setupquote", "setupreferencelist", "setupreferencing", "setupregister", "setuprotate", "setuprule", "setups", "setupscreens", "setupsection", "setupsectionblock", "setupsorting", "setupspacing", "setupstartstop", "setupstrut", "setupsubpagenumber", "setupsymbolset", "setupsynchronization", "setupsynchronizationbar", "setupsynonyms", "setupsystem", "setuptab", "setuptables", "setuptabulate", "setuptext", "setuptextposition", "setuptextrules", "setuptexttexts", "setuptextvariable", "setupthinrules", "setuptolerance", "setuptop", "setuptoptexts", "setuptype", "setuptyping", "setupunderbar", "setupurl", "setupversions", "setupwhitespace", "showbodyfont", "showbodyfontenvironment", "showcolor", "showcolorgroup", "showexternalfigures", "showfields", "showframe", "showgrid", "showlayout", "showmakeup", "showpalet", "showprint", "showsetups", "showstruts", "showsymbolset", "someline", "somewhere", "sort", "space", "splitfloat", "startalignment", "startbackground", "startbuffer", "startcoding", "startcolor", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startcomponent", "startdescription", "startdocument", "startenumeration", "startenvironment", "startfact", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobal", "starthiding", "startinteractionmenu", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmarginrule", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startpacked", "startparagraph", "startpositioning", "startpostponing", "startproduct", "startprofile", "startproject", "startquotation", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttext", "starttextrule", "starttyping", "startunpacked", "startversion", "stopalignment", "stopbackground", "stopbuffer", "stopcoding", "stopcolor", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopcomponent", "stopdescription", "stopdocument", "stopenumeration", "stopenvironment", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobal", "stophiding", "stopinteractionmenu", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmarginrule", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stoppacked", "stopparagraph", "stoppositioning", "stoppostponing", "stopproduct", "stopprofile", "stopproject", "stopquotation", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextrule", "stoptyping", "stopunpacked", "stopversion", "stretched", "sub", "subformulanumber", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtobodyfont", "switchtorawfont", "sym", "symbol", "synchronizationbar", "synchronize", "synonym", "tab", "testcolumn", "testpage", "tex", "textheight", "textreference", "textrule", "textvariable", "textwidth", "thinrule", "thinrules", "title", "tooltip", "topdistance", "topheight", "topspace", "totalnumberofpages", "translate", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "unitmeaning", "unknown", "useJSscripts", "useURL", "useXMLfilter", "useblocks", "usecommands", "usedirectory", "useencoding", "useexternaldocument", "useexternalfigure", "useexternalfile", "useexternalfiles", "useexternalsoundtrack", "usemodule", "usemodules", "usereferences", "usespecials", "usesymbols", "usetypescript", "usetypescriptfile", "useurl", "version", "vl", "weekday", "whitespace", "wordright", "writebetweenlist", "writetolist", "writetoreferencelist", "writetoregister" },
+ ["en"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "about", "adaptlayout", "adding", "appendix", "arg", "at", "atleftmargin", "atpage", "atrightmargin", "background", "backspace", "blackrule", "blackrules", "blank", "bookmark", "bottomdistance", "bottomheight", "bottomspace", "but", "button", "bypassblocks", "cap", "chapter", "character", "characters", "chem", "clip", "clonefield", "color", "colorbar", "colorvalue", "column", "comment", "comparecolorgroup", "comparepalet", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "component", "convertnumber", "copyfield", "correctwhitespace", "coupledocument", "coupledregister", "couplemarking", "couplepage", "couplepaper", "coupleregister", "crlf", "currentdate", "currentheadnumber", "cutspace", "date", "decouplemarking", "decrementnumber", "define", "defineaccent", "defineblank", "defineblock", "definebodyfont", "definebodyfontDEF", "definebodyfontREF", "definebodyfontenvironment", "definebuffer", "definecharacter", "definecolor", "definecolorgroup", "definecolumnbreak", "definecolumnset", "definecombination", "definecombinedlist", "definecommand", "defineconversion", "definedescription", "definedfont", "defineenumeration", "definefield", "definefieldstack", "definefiguresymbol", "definefloat", "definefont", "definefontfeature", "definefonthandling", "definefontstyle", "definefontsynonym", "defineframed", "defineframedtext", "definehbox", "definehead", "defineindentedtext", "defineinmargin", "defineinteractionmenu", "defineitemgroup", "definelabel", "definelayer", "definelayout", "definelist", "definelogo", "definemainfield", "definemakeup", "definemarking", "definemathalignment", "defineoutput", "defineoverlay", "definepagebreak", "definepalet", "definepapersize", "defineparagraphs", "defineplacement", "defineprofile", "defineprogram", "definerawfont", "definereference", "definereferenceformat", "definereferencelist", "defineregister", "definerule", "definesection", "definesectionblock", "definesorting", "definestartstop", "definestyle", "definesubfield", "definesymbol", "definesynonyms", "definetabletemplate", "definetabulate", "definetext", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definetyping", "defineversion", "description", "determineheadnumber", "determinelistcharacteristics", "determineregistercharacteristics", "dimension", "disableinteractionmenu", "domicile", "donttest", "edgedistance", "edgewidth", "emptylines", "enumeration", "environment", "externalfigure", "fact", "field", "fieldstack", "fillinfield", "fillinline", "fillinrules", "fillintext", "fitfield", "fixedspace", "fixedspaces", "followprofile", "followprofileversion", "followversion", "footerdistance", "footerheight", "footnote", "footnotetext", "forceblocks", "formulanumber", "fraction", "framed", "framedtext", "from", "getbuffer", "getmarking", "getnumber", "godown", "goto", "gotobox", "gotopage", "graycolor", "greyvalue", "grid", "hairline", "head", "headerdistance", "headerheight", "headlevel", "headnumber", "headsym", "headtext", "hideblocks", "high", "hl", "immediatebetweenlist", "immediatetolist", "in", "incrementnumber", "indentation", "indenting", "inframed", "infull", "ininner", "inleft", "inleftedge", "inleftmargin", "inline", "inmaframed", "inmargin", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inothermargin", "inouter", "inright", "inrightedge", "inrightmargin", "installlanguage", "interactionbar", "interactionbuttons", "interactionmenu", "item", "items", "its", "keepblocks", "label", "labeling", "labels", "labeltext", "language", "leftaligned", "leftedgedistance", "leftedgewidth", "leftmargindistance", "leftmarginwidth", "leg", "linethickness", "listheight", "listlength", "listsymbol", "listwidth", "loadsorts", "loadsynonyms", "logfields", "lohi", "low", "maframed", "mainlanguage", "makeupheight", "makeupwidth", "mapfontsize", "mar", "margindistance", "marginrule", "margintext", "margintitle", "marginwidth", "marginword", "marking", "markversion", "mathematics", "mediaeval", "menubutton", "midaligned", "mirror", "month", "moveformula", "moveongrid", "movesidefloat", "name", "navigating", "nextsection", "nocap", "nodimension", "noheaderandfooterlines", "noindenting", "nolist", "nomarking", "nomoreblocks", "nomorefiles", "nop", "nospace", "note", "notopandbottomlines", "nowhitespace", "numberofsubpages", "numbers", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "packed", "page", "pagedepth", "pagenumber", "pageoffset", "pagereference", "paperheight", "paperwidth", "paragraph", "part", "periods", "placebookmarks", "placecombinedlist", "placefloat", "placefootnotes", "placeformula", "placeheadnumber", "placeheadtext", "placelegend", "placelist", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelocalfootnotes", "placelogos", "placeongrid", "placeontopofeachother", "placepagenumber", "placerawlist", "placereferencelist", "placeregister", "placerule", "placesidebyside", "placesubformula", "placetextvariable", "position", "positiontext", "printpaperheight", "printpaperwidth", "processblocks", "processpage", "product", "program", "project", "publication", "quotation", "quote", "ran", "redo", "ref", "reference", "referral", "referraldate", "referring", "register", "remark", "reservefloat", "reset", "resetmarking", "resetnumber", "resettextcontent", "rightaligned", "rightedgedistance", "rightedgewidth", "rightmargindistance", "rightmarginwidth", "romannumerals", "rotate", "scale", "screen", "section", "seeregister", "selectblocks", "selectpaper", "selectversion", "setnumber", "settextcontent", "settextvariable", "setupalign", "setupanswerarea", "setuparranging", "setupbackground", "setupbackgrounds", "setupblackrules", "setupblank", "setupblock", "setupbodyfont", "setupbodyfontenvironment", "setupbottom", "setupbottomtexts", "setupbuffer", "setupbuttons", "setupcapitals", "setupcaption", "setupcaptions", "setupclipping", "setupcolor", "setupcolors", "setupcolumns", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupcombinations", "setupcombinedlist", "setupcomment", "setupdescriptions", "setupenumerations", "setupexternalfigures", "setupfield", "setupfields", "setupfillinlines", "setupfillinrules", "setupfloat", "setupfloats", "setupfloatsplitting", "setupfonthandling", "setupfontsynonym", "setupfooter", "setupfootertexts", "setupfootnotedefinition", "setupfootnotes", "setupforms", "setupformulae", "setupframed", "setupframedtexts", "setuphead", "setupheader", "setupheadertexts", "setupheadnumber", "setupheads", "setupheadtext", "setuphyphenmark", "setupindentedtext", "setupindenting", "setupinmargin", "setupinteraction", "setupinteractionbar", "setupinteractionmenu", "setupinteractionscreen", "setupinterlinespace", "setupinterlinespace2", "setupitemgroup", "setupitemizations", "setupitems", "setuplabeltext", "setuplanguage", "setuplayout", "setuplegend", "setuplinenumbering", "setuplines", "setuplinewidth", "setuplist", "setuplistalternative", "setupmakeup", "setupmarginblocks", "setupmarginrules", "setupmarking", "setupmathalignment", "setupnarrower", "setupnumber", "setupnumbering", "setupoppositeplacing", "setupoutput", "setuppagecomment", "setuppagenumber", "setuppagenumbering", "setuppagetransitions", "setuppalet", "setuppaper", "setuppapersize", "setupparagraphnumbering", "setupparagraphs", "setupplacement", "setuppositioning", "setupprofiles", "setupprograms", "setuppublications", "setupquote", "setupreferencelist", "setupreferencing", "setupregister", "setuprotate", "setuprule", "setups", "setupscreens", "setupsection", "setupsectionblock", "setupsorting", "setupspacing", "setupstartstop", "setupstrut", "setupsubpagenumber", "setupsymbolset", "setupsynchronization", "setupsynchronizationbar", "setupsynonyms", "setupsystem", "setuptab", "setuptables", "setuptabulate", "setuptext", "setuptextposition", "setuptextrules", "setuptexttexts", "setuptextvariable", "setupthinrules", "setuptolerance", "setuptop", "setuptoptexts", "setuptype", "setuptyping", "setupunderbar", "setupurl", "setupversions", "setupwhitespace", "showbodyfont", "showbodyfontenvironment", "showcolor", "showcolorgroup", "showexternalfigures", "showfields", "showframe", "showgrid", "showlayout", "showmakeup", "showpalet", "showprint", "showsetups", "showstruts", "showsymbolset", "someline", "somewhere", "sort", "space", "splitfloat", "startalignment", "startbackground", "startbuffer", "startcoding", "startcolor", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startcomponent", "startdescription", "startdocument", "startenumeration", "startenvironment", "startfact", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobal", "starthiding", "startinteractionmenu", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmarginrule", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startpacked", "startparagraph", "startpositioning", "startpostponing", "startproduct", "startprofile", "startproject", "startquotation", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttext", "starttextrule", "starttyping", "startunpacked", "startversion", "stopalignment", "stopbackground", "stopbuffer", "stopcoding", "stopcolor", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopcomponent", "stopdescription", "stopdocument", "stopenumeration", "stopenvironment", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobal", "stophiding", "stopinteractionmenu", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmarginrule", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stoppacked", "stopparagraph", "stoppositioning", "stoppostponing", "stopproduct", "stopprofile", "stopproject", "stopquotation", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextrule", "stoptyping", "stopunpacked", "stopversion", "stretched", "sub", "subformulanumber", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtobodyfont", "switchtorawfont", "sym", "symbol", "symoffset", "synchronizationbar", "synchronize", "synonym", "tab", "testcolumn", "testpage", "tex", "textheight", "textreference", "textrule", "textvariable", "textwidth", "thinrule", "thinrules", "title", "tooltip", "topdistance", "topheight", "topspace", "totalnumberofpages", "translate", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "unitmeaning", "unknown", "useJSscripts", "useURL", "useXMLfilter", "useblocks", "usecommands", "usedirectory", "useencoding", "useexternaldocument", "useexternalfigure", "useexternalfile", "useexternalfiles", "useexternalsoundtrack", "usemodule", "usemodules", "usereferences", "usespecials", "usesymbols", "usetypescript", "usetypescriptfile", "useurl", "version", "vl", "weekday", "whitespace", "wordright", "writebetweenlist", "writetolist", "writetoreferencelist", "writetoregister" },
["fr"]={ "CAP", "Cap", "Caps", "Caractere", "Caracteres", "Chiffresromains", "JOURSEMAINE", "MOIS", "MOT", "MOTS", "Mot", "Mots", "Numeros", "a", "adaptedisposition", "affectenumero", "affectevariabletexte", "ajustechamp", "alaligne", "alapage", "aligneadroite", "aligneagauche", "aligneaumilieu", "appendix", "arg", "arriereplan", "atleftmargin", "atrightmargin", "baha", "barrecouleur", "barreinteraction", "barresynchronisation", "bas", "bouton", "boutonmenu", "boutonsinteraction", "but", "cacheblocs", "cap", "caractere", "caracteres", "champ", "changepolicebrute", "changepolicecorps", "chapter", "chem", "chiffresromains", "citation", "citer", "clip", "clonechamp", "colonne", "comment", "commentaire", "comparegroupecouleur", "comparepalette", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completenumeropage", "completeregistre", "composant", "composeenalinea", "concernant", "convertitnumero", "copitchamp", "corrigeespaceblanc", "couleur", "couleurgrise", "coupledocument", "coupledregister", "couplemarquage", "couplepapier", "coupleregistre", "crlf", "cutspace", "dactylographier", "dans", "dansautremarge", "dansborddroit", "dansbordgauche", "dansdroite", "dansgauche", "dansmarge", "dansmargedroite", "dansmargegauche", "date", "datecourante", "daterecommandation", "de", "decouplemarquage", "decrementenumero", "definebodyfontDEF", "definebodyfontREF", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineframed", "defineframedtext", "defineindentedtext", "defineitemgroup", "definemathalignment", "defineplacement", "definetypeface", "definicaractere", "definit", "definitaccent", "definitbloc", "definitblocsection", "definitbuffer", "definitcalque", "definitchamp", "definitchampprincipal", "definitcommande", "definitconversion", "definitcouleur", "definitdactylo", "definitdansmarge", "definitdemarrestoppe", "definitdescription", "definitdisposition", "definitenumeration", "definitenvironnementpolicecorps", "definitetiquette", "definitflottant", "definitformatreference", "definitgroupecouleur", "definithbox", "definitjeucolonne", "definitliste", "definitlisteimbriquee", "definitlistereference", "definitlogo", "definitmakeup", "definitmarquage", "definitmenuinteraction", "definitnotepdp", "definitpalette", "definitparagraphes", "definitpilechamp", "definitpolice", "definitpolicebrute", "definitpolicecorps", "definitpositiontexte", "definitprofil", "definitprogramme", "definitreference", "definitregistre", "definitregle", "definitrevetement", "definitsautdecolonne", "definitsautdepage", "definitsection", "definitsortie", "definitsouschamp", "definitstyle", "definitstylepolice", "definitsymbole", "definitsymbolefigure", "definitsynonymepolice", "definitsynonymes", "definittabulation", "definittaillepapier", "definittete", "definittexte", "definittrametableau", "definittri", "definittype", "definitvariabletexte", "definitversion", "definitvide", "demarrealignement", "demarrearriereplan", "demarreblocmarge", "demarrecitation", "demarreciter", "demarrecodage", "demarrecolonnes", "demarrecombinaison", "demarrecompoetroite", "demarrecomposant", "demarrecorrectionligne", "demarrecouleur", "demarredegroupe", "demarredocument", "demarreenvironement", "demarrefigure", "demarreglobal", "demarregroupe", "demarrejeucolonne", "demarrejeusymboles", "demarreligne", "demarreligneregleetexte", "demarrelignes", "demarrelocal", "demarremakeup", "demarremargereglee", "demarrenotespdplocales", "demarrenumerotationligne", "demarreopposition", "demarrepositionnement", "demarreproduit", "demarreprofil", "demarreprojet", "demarreraster", "demarrerevetement", "demarresynchronisation", "demarretableau", "demarretableaux", "demarretexte", "demarreversion", "demarrevuedensemble", "deplaceformule", "deplacesurgrille", "description", "determinecaracteristiqueliste", "determinecaracteristiquesregistre", "determinenumerotete", "dimension", "distancebord", "distanceborddroit", "distancebordgauche", "distanceentete", "distanceinf", "distancemarge", "distancemargedroite", "distancemargegauche", "distancepdp", "distancesup", "domicile", "echelle", "ecran", "ecritdansliste", "ecritdanslistereference", "ecritentreliste", "ecritregistre", "el", "element", "elements", "emptylines", "enumeration", "environement", "espace", "espaceblanc", "espacefixe", "espaceinf", "espacesfixes", "espacesup", "etiquette", "etiquettes", "etire", "fait", "faitreference", "fichierdactylo", "figureexterne", "forceblocs", "fraction", "framed", "framedtext", "gardeblocs", "getnumber", "grille", "groupe", "haut", "hauteureditionpapier", "hauteurentete", "hauteurinf", "hauteurliste", "hauteurmakeup", "hauteurpapier", "hauteurpdp", "hauteursup", "hauteurtexte", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "inconnu", "incrementenumero", "indentation", "inframed", "infull", "inhibemenuinteraction", "ininner", "inmframed", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "installelangue", "joursemaine", "labeling", "labeltexte", "langue", "langueprincipale", "largeurbord", "largeurborddroit", "largeurbordgauche", "largeureditionpapier", "largeurligne", "largeurliste", "largeurmakeup", "largeurmarge", "largeurmargedroite", "largeurmargegauche", "largeurpapier", "largeurtexte", "leg", "ligneh", "lignenoire", "ligneregleetexte", "lignesnoires", "listesymbole", "llongueurliste", "loadsorts", "loadsynonyms", "logchamp", "mapfontsize", "mar", "margereglee", "marquage", "marquageversion", "marquepage", "mathematique", "mediaeval", "menuinteraction", "mframed", "mois", "montrecadre", "montrechamps", "montrecouleur", "montredisposition", "montreedition", "montreenvironnementpolicecorps", "montrefiguresexternes", "montregrille", "montregroupecouleur", "montrejeusymboles", "montremakeup", "montrepalette", "montrepolicecorps", "montrereglages", "montrestruts", "motdroit", "motmarge", "movesidefloat", "name", "navigating", "nextsection", "niveautete", "nocap", "nombredesouspages", "nombretotaldepages", "nommacro", "nop", "note", "notepdp", "numeroformule", "numeropage", "numeros", "numerosousformule", "numerotete", "numerotetecourant", "obtientmarquage", "oriente", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "page", "pagedepth", "pagedouble", "pageoffset", "paragraph", "part", "pasplusdeblocs", "pasplusdefichiers", "periodes", "pilechamp", "placecoteacote", "placeflottant", "placeformule", "placelegende", "placelesunsaudessusdesautres", "placeliste", "placelisteinmbriquee", "placelistereference", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelogos", "placemarquespages", "placenotespdp", "placenotespdplocales", "placenumeropage", "placenumerotete", "placerawlist", "placeregistre", "placeregle", "placesousformule", "placesurgrille", "placetextetete", "placevariabletexte", "position", "positionnetexte", "prendbuffer", "produit", "programme", "projet", "publication", "qqpart", "ran", "raz", "razmarquage", "raznumero", "recommandation", "ref", "refait", "reference", "referencepage", "referencetexte", "reflete", "register", "reglages", "reglealignement", "reglearrangement", "reglearriereplan", "reglearriereplans", "reglebarreinteraction", "reglebarresynchronisation", "reglebloc", "regleblocmarge", "regleblocsection", "regleboutons", "reglebuffer", "reglecapitales", "reglechamp", "reglechamps", "regleclipping", "reglecolonnes", "reglecombinaisons", "reglecommentaire", "reglecommentairepage", "reglecompoetroite", "reglecomposeenalinea", "reglecouleur", "reglecouleurs", "regledactylo", "regledansmarge", "regledemarrestoppe", "regledescriptions", "regledisposition", "regleecraninteraction", "regleecrans", "regleelements", "regleencadre", "regleentete", "regleenumerations", "regleenvironnementpolicecorps", "regleepaisseurligne", "regleespaceblanc", "regleespacement", "regleespacementinterligne", "reglefiguresexternes", "regleflottant", "regleflottants", "regleformulaires", "regleformules", "reglegroupeselements", "regleinf", "regleinteraction", "regleintitule", "regleintitules", "reglejeucolonne", "reglejeusymboles", "reglelabeltexte", "reglelangue", "reglelegende", "reglelignes", "reglelignesnoires", "reglelignesreglestexte", "regleliste", "reglelisteimbriquee", "reglelistereference", "reglemakeup", "reglemargereglee", "reglemarquage", "reglemarquagehyphenation", "reglemenuinteraction", "reglenotepdp", "reglenumero", "reglenumeropage", "reglenumerotation", "reglenumerotationligne", "reglenumerotationpage", "reglenumerotationparagraphe", "reglenumerotete", "regleoriente", "reglepalette", "reglepapier", "regleparagraphes", "reglepdp", "regleplacementopposition", "reglepolicecorps", "reglepositionnement", "reglepositiontexte", "regleprofils", "regleprogrammes", "reglepublications", "reglereferencage", "regleregistre", "regleregle", "regleremplitligne", "regleremplitlignesreglees", "reglesection", "regleseparationflottant", "reglesortie", "reglesouslignage", "reglesousnumeropage", "reglestrut", "reglesup", "reglesynchronisation", "reglesynonymes", "reglesysteme", "regletab", "regletableaux", "regletabulation", "regletaillepapier", "regletete", "regletetes", "regletexte", "regletextesentete", "regletextesinf", "regletextespdp", "regletextessup", "regletextestexte", "regletextetete", "regletolerance", "regletraitsfins", "regletransitionspage", "regletri", "regletype", "regleurl", "reglevariabletexte", "regleversions", "remplitchamp", "remplitligne", "remplitlignesreglees", "remplittexte", "reservefloat", "resettextcontent", "retourarriere", "sansalinea", "sansdimension", "sansespace", "sansespaceblanc", "sanslignesenteteetpdp", "sanslignessupetinf", "sansliste", "sansmarquage", "sanstest", "sauteblocs", "section", "seeregister", "selectionneblocs", "selectionnepapier", "selectionneversion", "sensunite", "separeflottant", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupframedtexts", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupplacement", "sort", "sousnumeropage", "startalignment", "startarriereplan", "startbuffer", "startcitation", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomposant", "startcouleur", "startdescription", "startdocument", "startenumeration", "startenvironement", "startfait", "startfigure", "startfloattext", "startformula", "startframedtext", "startgroupe", "starthiding", "startitemgroup", "startlegend", "startligneregleetexte", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmargereglee", "startmarginblock", "startmenuinteraction", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startproduit", "startprofile", "startprojet", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversion", "stopalignment", "stoparriereplan", "stopbuffer", "stopcitation", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcompoetroite", "stopcomposant", "stopcouleur", "stopdescription", "stopdocument", "stopenumeration", "stopenvironement", "stopfait", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgroupe", "stophiding", "stopitemgroup", "stoplegend", "stopligneregleetexte", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmargereglee", "stopmarginblock", "stopmenuinteraction", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppealignement", "stoppearriereplan", "stoppeblocmarge", "stoppecitation", "stoppecodage", "stoppecolonnes", "stoppecombinaison", "stoppecomposant", "stoppecorrectionligne", "stoppecouleur", "stoppedegroupe", "stoppedocument", "stoppeenvironement", "stoppeglobal", "stoppegroupe", "stoppejeucolonne", "stoppeligne", "stoppeligneregleetexte", "stoppelignes", "stoppelocal", "stoppemakeup", "stoppemargereglee", "stoppenotespdplocales", "stoppenumerotationligne", "stoppeopposition", "stoppepositionnement", "stoppeproduit", "stoppeprofil", "stoppeprojet", "stopperaster", "stopperevetement", "stoppesynchronisation", "stoppetableau", "stoppetableaux", "stoppetexte", "stoppeversion", "stoppevuedensemble", "stoppositioning", "stoppostponing", "stopproduit", "stopprofile", "stopprojet", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversion", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestion", "suivantprofil", "suivantversion", "suivantversionprofil", "sym", "symbole", "synchronise", "synonym", "tab", "tapebuffer", "testcolumn", "testpage", "tete", "tex", "textemarge", "textenotepdp", "textetete", "title", "titremarge", "traduire", "traiteblocs", "traitepage", "traitfin", "traitsfins", "txt", "typ", "underbar", "underbars", "uneligne", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "utiliseJSscripts", "utiliseURL", "utiliseblocs", "utilisechemin", "utilisecommandes", "utilisedocumentexterne", "utiliseencodage", "utilisefichierexterne", "utilisefichiersexternes", "utilisefigureexterne", "utilisemodule", "utilisemodules", "utilisepsiteaudioexterne", "utilisereferences", "utilisespecialites", "utilisesymboles", "utiliseurl", "va", "vaalaboite", "vaalapage", "vaenbas", "valeurcouleur", "valeurgris", "variabletexte", "version", "vide", "vl" },
["it"]={ "CAP", "Cap", "Caps", "GIORNOSETTIMANA", "Lettera", "Lettere", "MESE", "Numeri", "Numeriromani", "PAROLA", "PAROLE", "Parola", "Parole", "accoppiacarta", "accoppiadocumento", "accoppiamarcatura", "accoppiapagina", "accoppiaregistro", "adattacampo", "adattalayout", "al", "allineacentro", "allineadestra", "allineasinistra", "altezzacarta", "altezzacartastampa", "altezzacima", "altezzaelenco", "altezzafondo", "altezzaintestazione", "altezzamakeup", "altezzapdp", "altezzatesto", "ambiente", "ampiezzabordo", "ampiezzabordodestro", "ampiezzabordosinistro", "ampiezzacarta", "ampiezzacartastampa", "ampiezzaelenco", "ampiezzamakeup", "ampiezzamargine", "ampiezzamarginedestro", "ampiezzamarginesinistro", "ampiezzatesto", "ap", "apagina", "appendix", "arg", "atleftmargin", "atrightmargin", "barracolori", "barrainterazione", "barrasincronizzazione", "bastablocchi", "bastafile", "cambiaafontdeltesto", "campi", "camporiempimento", "cap", "capello", "chapter", "chim", "circondato", "citazione", "clip", "clonacampo", "colonna", "colore", "coloregrigio", "comment", "commento", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenet", "confrontagruppocolori", "confrontatavolozza", "convertinumero", "copiacampo", "correggispaziobianco", "coupledregister", "crlf", "cutspace", "da", "daqualcheparte", "data", "datadioggi", "datareferral", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definemathalignment", "definepagebreak", "defineplacement", "definetypeface", "definisci", "definisciaccento", "definisciambientefontdeltesto", "definisciblocco", "definiscibloccosezione", "definiscibuffer", "definiscicampo", "definiscicampoprincipale", "definiscicapoversi", "definiscicarattere", "definiscicolore", "definiscicomando", "definisciconversione", "definiscidescrizione", "definiscidimensionicarta", "definiscielenco", "definiscielencocombinato", "definiscienumerazione", "definiscietichetta", "definiscifigurasimbolo", "definiscifont", "definiscifontdeltesto", "definiscifontgrezzo", "definisciformatoriferimento", "definiscigruppocolonne", "definiscigruppocolori", "definiscihbox", "definisciincorniciato", "definisciiniziatermina", "definiscilayout", "definiscilinea", "definiscilistariferimenti", "definiscilogo", "definiscimakeup", "definiscimarcatura", "definiscimenuinterazione", "definiscimodellotabella", "definiscioggettomobile", "definisciordinamento", "definiscioutput", "definisciposizionetesto", "definisciprofilo", "definisciprogramma", "definisciregistro", "definisciriferimento", "definiscirigovuoto", "definiscisezione", "definiscisimbolo", "definiscisinonimi", "definiscisinonimofont", "definiscisottocampo", "definiscisovrapposizione", "definiscistackcampi", "definiscistile", "definiscistilefont", "definiscitabulato", "definiscitavolozza", "definiscitesta", "definiscitesto", "definiscitestoincorniciato", "definiscitype", "definiscityping", "definiscivariabiletesto", "definisciversion", "description", "determinacaratteristicheregistro", "determinacarattersticheelenco", "determinanumerotesta", "dimensione", "disabilitamenuinterazione", "distanzabordo", "distanzabordodestro", "distanzabordosinistro", "distanzacima", "distanzafondo", "distanzaintestazione", "distanzamargine", "distanzamarginedestro", "distanzamarginesinistro", "distanzapdp", "domicilio", "el", "elaborablocchi", "elaborapagina", "elementi", "elemento", "emptylines", "enumeration", "etichetta", "etichette", "fatto", "figuraesterna", "fondo", "forzablocchi", "framedtext", "frazione", "getnumber", "giornosettimana", "griglia", "headsym", "hl", "ignoto", "immediatebetweenlist", "immediatetolist", "impaccato", "impostaallineamento", "impostaambientefontdeltesto", "impostaampiezzariga", "impostabarrainterazione", "impostabarrasincronizzazione", "impostablocchimargine", "impostablocco", "impostabloccosezione", "impostabuffer", "impostacampi", "impostacampo", "impostacapoversi", "impostacaption", "impostacaptions", "impostacima", "impostaclippling", "impostacolonne", "impostacolore", "impostacolori", "impostacombinazioni", "impostacommento", "impostacommentopagina", "impostadefinizionenotepdp", "impostadescrizioni", "impostadimensionicarta", "impostaelementi", "impostaelencazioni", "impostaelenco", "impostaelencocombinato", "impostaenumerazioni", "impostafigureesterne", "impostafondo", "impostafontdeltesto", "impostaforms", "impostaformule", "impostagruppocolonne", "impostaincorniciato", "impostainiziatermina", "impostainmargine", "impostainstestazione", "impostainterazione", "impostainterlinea", "impostalayout", "impostalegenda", "impostalinea", "impostalineemargine", "impostalineenere", "impostalineeriempimento", "impostalineesottili", "impostalineetesto", "impostalingua", "impostalistariferimenti", "impostamaiuscole", "impostamakeup", "impostamarcatura", "impostamenuinterazione", "impostamenzione", "impostanotepdp", "impostanumerazione", "impostanumerazionecapoversi", "impostanumerazionepagina", "impostanumerazionerighe", "impostanumeropagina", "impostanumerosottopagina", "impostanumerotesta", "impostaoggettimobili", "impostaoggettomobile", "impostaordinamento", "impostaoutput", "impostaparranging", "impostapdp", "impostapiustretto", "impostaposizionamento", "impostaposizionamentoopposti", "impostaposizionetesto", "impostaprofili", "impostaprogrammi", "impostapubblicazioni", "impostapulsanti", "impostaregistro", "impostarientro", "impostariferimento", "impostarighe", "impostarigheriempimento", "impostarigovuoto", "impostarotazione", "impostaschermi", "impostaschermointerazione", "impostasegnosillabazione", "impostasetsimboli", "impostasezione", "impostasfondi", "impostasfondo", "impostasincronizzazione", "impostasinonimi", "impostasistema", "impostasottolinea", "impostaspaziatura", "impostaspaziobianco", "impostaspezzamentooggettomobile", "impostastrut", "impostatab", "impostatabelle", "impostatabulato", "impostatavolozza", "impostatesta", "impostateste", "impostatesticima", "impostatestifondo", "impostatestiincorniciati", "impostatestiintestazioni", "impostatestipdp", "impostatesto", "impostatestoetichette", "impostatestointestazioni", "impostatestotesti", "impostatolleranza", "impostatransizionepagina", "impostatype", "impostatyping", "impostaurl", "impostavariabiletesto", "impostaversioni", "impostazioni", "in", "inaltromargine", "incorniciato", "incrementanumero", "indentation", "indestra", "ininner", "iniziaallineamento", "iniziaambiente", "iniziabloccomargine", "iniziacitazione", "iniziacodifica", "iniziacolonne", "iniziacolore", "iniziacombinazione", "iniziacomponente", "iniziacorrezioneriga", "iniziadocumento", "iniziafigura", "iniziaglobale", "iniziagruppocolonne", "iniziaimpaccato", "inizialineamargine", "inizialineatesto", "inizialocale", "iniziamakeup", "inizianotepdplocali", "inizianumerazionerighe", "iniziaopposto", "iniziaoverview", "iniziapiustretto", "iniziaposizionamento", "iniziaprodotto", "iniziaprofilo", "iniziaprogetto", "iniziaraster", "iniziariga", "iniziarighe", "iniziasetsimboli", "iniziasfondo", "iniziasincronizzazione", "iniziasovrapposizione", "iniziatabella", "iniziatabelle", "iniziatesto", "iniziaunpacked", "iniziaversione", "inlatodestro", "inlatosinistro", "inmaframed", "inmargine", "inmarginedestro", "inmarginesinistro", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inriga", "insinistra", "installalingua", "intorno", "labeling", "leg", "lettera", "lettere", "lineamargine", "lineanera", "lineasottile", "lineatesto", "lineenere", "lineeriempimento", "lineesottili", "lingua", "linguaprincipale", "listsymbol", "livellotesta", "loadsorts", "loadsynonyms", "logcampi", "lunghezzaelenco", "maframed", "mapfontsize", "mar", "marcatura", "marcaversione", "matematica", "mediaeval", "menuinterattivo", "menzione", "mese", "mettielenco", "mettielencocombinato", "mettifiancoafianco", "mettiformula", "mettiingriglia", "mettilegenda", "mettilinea", "mettiloghi", "mettinotepdp", "mettinotepdplocali", "mettinumeropagina", "mettiregistro", "mettisegnalibro", "mettisottoformula", "mettiunosullaltro", "mettivariabiletesto", "mostraambientefontdeltesto", "mostracampi", "mostracolore", "mostracornice", "mostrafiguresterne", "mostrafontdeltesto", "mostragriglia", "mostragruppocolori", "mostraimpostazioni", "mostralyout", "mostramakeup", "mostrasetsimboli", "mostrastampa", "mostrastruts", "mostratavolozza", "movesidefloat", "name", "nascondiblocchi", "navigating", "nextsection", "nientedimensioni", "nienteelenco", "nientelineecimafondo", "nientelineintestazionepdp", "nientemarcatura", "nienterientro", "nientespazio", "nientespaziobianco", "nocap", "nome", "nomeunita", "nop", "nota", "notapdp", "notest", "numberofsubpages", "numeri", "numeriromani", "numeroformula", "numeropagina", "numeropaginacompleto", "numerosottoformula", "numerotesta", "numerotestacorrente", "numerototaledipagine", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paragraph", "paroladestra", "parolainmargine", "part", "passaafontgrezzo", "ped", "pedap", "perlungo", "placefloat", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "posizionanumerotesta", "posizionatesto", "posizionatestotesta", "posizione", "prendibuffer", "prendimarcatura", "prodotto", "progetto", "programma", "pubblicazione", "pulsante", "pulsantemenu", "pulsantinterazione", "punti", "qualcheriga", "ran", "referral", "referring", "register", "reimposta", "reimpostamarcatura", "reservefloat", "resetnumber", "resettextcontent", "rientro", "rif", "rifai", "riferimento", "riferimentopagina", "riferimentotesto", "riflessione", "rigariempimento", "rigovuoto", "ruota", "saltablocchi", "scala", "schermo", "scrividentroelenco", "scriviinelenco", "scriviinlistariferimenti", "scriviinregistro", "section", "seeregister", "segnalibro", "seguiprofilo", "seguiversione", "seguiversioneprofilo", "selezionablocchi", "selezionacarta", "selezionaversione", "separamarcatura", "setnumber", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setuppaper", "setupplacement", "setvariabiletesto", "sfondo", "sim", "simbolo", "sincronizza", "sort", "spazifissi", "spazio", "spaziobianco", "spaziocima", "spaziodietro", "spaziofisso", "spaziofondo", "spessoreriga", "spezzaoggettomobile", "spostaagriglia", "spostaformula", "stackcampi", "startalignment", "startambiente", "startbuffer", "startcitazione", "startcolore", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomponenet", "startdescription", "startdocument", "startenumeration", "startfatto", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startimpaccato", "startitemgroup", "startlegend", "startline", "startlineamargine", "startlineatesto", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmenuinterattivo", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprodotto", "startprofile", "startprogetto", "startregister", "startsfondo", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversione", "stirato", "stopalignment", "stopambiente", "stopbuffer", "stopcitazione", "stopcolore", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcomponenet", "stopdescription", "stopdocument", "stopenumeration", "stopfatto", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopimpaccato", "stopitemgroup", "stoplegend", "stopline", "stoplineamargine", "stoplineatesto", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmenuinterattivo", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprodotto", "stopprofile", "stopprogetto", "stopsfondo", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversione", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "terminaallineamento", "terminaambiente", "terminabloccomargine", "terminacitazione", "terminacodifica", "terminacolonne", "terminacolore", "terminacombinazione", "terminacomponente", "terminacorrezioneriga", "terminadocumento", "terminaglobale", "terminagruppocolonne", "terminaimpaccato", "terminalineamargine", "terminalineatesto", "terminalocale", "terminamakeup", "terminanotepdplocali", "terminanumerazionerighe", "terminaopposto", "terminaoverview", "terminapiustretto", "terminaposizionamento", "terminaprodotto", "terminaprofili", "terminaprogetto", "terminaraster", "terminariga", "terminarighe", "terminasfondo", "terminasincronizzazione", "terminasovrapposizione", "terminatabella", "terminatabelle", "terminatesto", "terminaunpacked", "terminaversioni", "testa", "testcolumn", "testoetichetta", "testoinmargine", "testoinstestazioni", "testonotapdp", "testoriempimento", "testpage", "tex", "tieniblocchi", "title", "titoloinmargine", "tooltip", "traduci", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "usaJSscripts", "usaURL", "usablocco", "usacartella", "usacodifica", "usacolonnasonoraesterna", "usacomandi", "usadocumentoesterno", "usafiguraesterna", "usafileesterni", "usafileesterno", "usamoduli", "usamodulo", "usariferimenti", "usasimboli", "usaspecialita", "usaurl", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "vaia", "vaiabox", "vaiapagina", "vaigiu", "valorecolore", "valoregrigio", "variabiletesto", "versione", "vl" },
- ["nl"]={ "CAP", "Cap", "Caps", "Cijfers", "KAP", "Kap", "Kaps", "Letter", "Letters", "MAAND", "Romeins", "WEEKDAG", "WOORD", "WOORDEN", "Woord", "Woorden", "aantalsubpaginas", "about", "achtergrond", "appendix", "arg", "bepaalkopnummer", "bepaallijstkenmerken", "bepaalregisterkenmerken", "betekenis", "binnenmargeafstand", "binnenmargebreedte", "binnenrandafstand", "binnenrandbreedte", "blanko", "blokje", "blokjes", "blokkeerinteractiemenu", "bodemwit", "bookmark", "bovenafstand", "bovenhoogte", "breuk", "buitenmargeafstand", "buitenmargebreedte", "buitenrandafstand", "buitenrandbreedte", "but", "button", "cap", "chapter", "chem", "cijfers", "citaat", "citeer", "clip", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "converteernummer", "copieerveld", "corrigeerwitruimte", "coupledregister", "crlf", "datum", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "definerawfont", "definetypeface", "definieer", "definieeraccent", "definieeralineas", "definieerbeeldmerk", "definieerblanko", "definieerblok", "definieerbuffer", "definieercombinatie", "definieercommando", "definieerconversie", "definieerfiguursymbool", "definieerfont", "definieerfontstijl", "definieerfontsynoniem", "definieerhbox", "definieerhoofdveld", "definieeringesprongentext", "definieerinmarge", "definieerinteractiemenu", "definieeritemgroep", "definieerkadertekst", "definieerkarakter", "definieerkleur", "definieerkleurgroep", "definieerkolomgroep", "definieerkolomovergang", "definieerkop", "definieerkorps", "definieerkorpsomgeving", "definieerlayer", "definieerlayout", "definieerletter", "definieerlijn", "definieerlijst", "definieermarkering", "definieeromlijnd", "definieeropmaak", "definieeroverlay", "definieerpaginaovergang", "definieerpalet", "definieerpapierformaat", "definieerplaats", "definieerplaatsblok", "definieerprofiel", "definieerprogramma", "definieerreferentie", "definieerreferentieformaat", "definieerreferentielijst", "definieerregister", "definieersamengesteldelijst", "definieersectie", "definieersectieblok", "definieersorteren", "definieerstartstop", "definieersubveld", "definieersymbool", "definieersynoniemen", "definieertabelvorm", "definieertabulatie", "definieertekst", "definieertekstpositie", "definieertekstvariabele", "definieertype", "definieertypen", "definieeruitvoer", "definieerveld", "definieerveldstapel", "definieerversie", "definieerwiskundeuitlijnen", "description", "dimensie", "directnaarlijst", "directtussenlijst", "doordefinieren", "doorlabelen", "doornummeren", "dunnelijn", "dunnelijnen", "eenregel", "enumeration", "ergens", "externfiguur", "forceerblokken", "formulenummer", "framedtext", "gebruikJSscripts", "gebruikURL", "gebruikXMLfilter", "gebruikblokken", "gebruikcommandos", "gebruikexterndocument", "gebruikexternefile", "gebruikexternefiles", "gebruikexternfiguur", "gebruikexterngeluidsfragment", "gebruikgebied", "gebruikmodule", "gebruikmodules", "gebruikreferenties", "gebruikspecials", "gebruiksymbolen", "gebruiktypescript", "gebruiktypescriptfile", "gebruikurl", "geenblokkenmeer", "geenbovenenonderregels", "geendimensie", "geenfilesmeer", "geenhoofdenvoetregels", "geenlijst", "geenmarkering", "geenspatie", "geentest", "geenwitruimte", "geg", "grijskleur", "grijswaarde", "haalbuffer", "haalmarkering", "haalnummer", "haarlijn", "handhaafblokken", "herhaal", "hl", "hoofdafstand", "hoofdhoogte", "hoofdtaal", "hoog", "huidigedatum", "huidigekopnummer", "in", "inanderemarge", "inbinnen", "inbuiten", "indentation", "inlijnd", "inlinker", "inlinkermarge", "inlinkerrand", "inmarge", "inrechter", "inrechtermarge", "inrechterrand", "inregel", "inspringen", "installeertaal", "instellingen", "interactiebalk", "interactiebuttons", "interactiemenu", "invullijnen", "invulregel", "invultekst", "invulveld", "inwilijnd", "items", "its", "kantlijn", "kap", "kenmerk", "kenmerkdatum", "kentekstvariabeletoe", "kleur", "kleurenbalk", "kleurwaarde", "kloonveld", "kolom", "kop", "kopniveau", "kopnummer", "koppeldocument", "koppelmarkering", "koppelpagina", "koppelpapier", "koppelregister", "kopsym", "koptekst", "kopwit", "laag", "label", "labeling", "labels", "labeltekst", "laho", "leg", "legeregels", "letter", "letters", "lijndikte", "lijstbreedte", "lijsthoogte", "lijstlengte", "lijstsymbool", "linkermargeafstand", "linkermargebreedte", "linkerrandafstand", "linkerrandbreedte", "loadsorts", "loadsynonyms", "maand", "mapfontsize", "mar", "margeafstand", "margebreedte", "margetekst", "margetitel", "margewoord", "markeer", "markeerversie", "mediaeval", "menubutton", "naam", "naar", "naarbox", "naarpagina", "name", "navigerend", "nextsection", "nietinspringen", "nocap", "nokap", "noot", "nop", "omgeving", "omlaag", "omlijnd", "onbekend", "onderafstand", "onderdeel", "onderhoogte", "ontkoppelmarkering", "op", "opelkaar", "oplinkermarge", "oppagina", "oprechtermarge", "overbar", "overbars", "overstrike", "overstrikes", "pagina", "paginadiepte", "paginanummer", "paginaoffset", "paginareferentie", "papierbreedte", "papierhoogte", "paragraph", "part", "paslayoutaan", "passeerblokken", "passendveld", "plaatsbeeldmerken", "plaatsbookmarks", "plaatsformule", "plaatskopnummer", "plaatskoptekst", "plaatslegenda", "plaatslijn", "plaatslijst", "plaatslokalevoetnoten", "plaatsnaastelkaar", "plaatsonderelkaar", "plaatsopgrid", "plaatspaginanummer", "plaatsplaatsblok", "plaatsreferentielijst", "plaatsregister", "plaatsruwelijst", "plaatssamengesteldelijst", "plaatssubformule", "plaatstekstvariabele", "plaatsvoetnoten", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "positioneer", "positioneertekst", "printpapierbreedte", "printpapierhoogte", "produkt", "programma", "projekt", "publicatie", "punten", "ran", "randafstand", "randbreedte", "rechtermargeafstand", "rechtermargebreedte", "rechterrandafstand", "rechterrandbreedte", "ref", "refereer", "referentie", "regellinks", "regelmidden", "regelrechts", "register", "registreervelden", "reservefloat", "reset", "resetmarkering", "resetnummer", "resettekstinhoud", "resettextcontent", "romeins", "rooster", "roteer", "rugwit", "schaal", "scherm", "schrijfnaarlijst", "schrijfnaarreferentielijst", "schrijfnaarregister", "schrijftussenlijst", "section", "seeregister", "selecteerblokken", "selecteerpapier", "selecteerversie", "setnummer", "setupfonthandling", "setupfontsynonym", "setupinterlinespace2", "setuplistalternative", "snijwit", "som", "sort", "spatie", "spiegel", "splitsplaatsblok", "startachtergrond", "startalignment", "startbuffer", "startcitaat", "startcodering", "startcolumns", "startcombinatie", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfiguur", "startfloattext", "startformula", "startframedtext", "startgeg", "startglobaal", "starthiding", "startinteractiemenu", "startitemgroup", "startkantlijn", "startkleur", "startkolomgroep", "startkolommen", "startkolomopmaak", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokaal", "startlokalevoetnoten", "startmakeup", "startmargeblok", "startmarginblock", "startnaast", "startnamemakeup", "startnarrower", "startomgeving", "startonderdeel", "startopelkaar", "startopmaak", "startopposite", "startoverlay", "startoverview", "startoverzicht", "startparagraph", "startpositioneren", "startpositioning", "startpostponing", "startprodukt", "startprofiel", "startprofile", "startprojekt", "startraster", "startregel", "startregelcorrectie", "startregelnummeren", "startregels", "startregister", "startsmaller", "startsymbolset", "startsymboolset", "startsynchronisatie", "startsynchronization", "starttabel", "starttabellen", "starttable", "starttables", "starttabulate", "starttekst", "starttekstlijn", "starttyping", "startuitlijnen", "startunpacked", "startvanelkaar", "startversie", "stelachtergrondenin", "stelachtergrondin", "stelalineasin", "stelantwoordgebiedin", "stelarrangerenin", "stelblankoin", "stelblokin", "stelblokjesin", "stelblokkopjein", "stelblokkopjesin", "stelbovenin", "stelboventekstenin", "stelbufferin", "stelbuttonsin", "stelciterenin", "stelclipin", "stelcombinatiesin", "stelcommentaarin", "steldoordefinierenin", "steldoornummerenin", "steldunnelijnenin", "stelexternefigurenin", "stelformulesin", "stelformulierenin", "stelhoofdin", "stelhoofdtekstenin", "stelingesprongentextin", "stelinmargein", "stelinspringenin", "stelinteractiebalkin", "stelinteractiein", "stelinteractiemenuin", "stelinteractieschermin", "stelinterliniein", "stelinvullijnenin", "stelinvulregelsin", "stelitemgroepin", "stelitemsin", "stelkadertekstenin", "stelkantlijnin", "stelkapitalenin", "stelkleurenin", "stelkleurin", "stelkolomgroepin", "stelkolomgroepregelsin", "stelkolomgroepstartin", "stelkolommenin", "stelkopin", "stelkopnummerin", "stelkoppeltekenin", "stelkoppenin", "stelkoptekstin", "stelkorpsin", "stelkorpsomgevingin", "stellabeltekstin", "stellayoutin", "stellegendain", "stellijndiktein", "stellijnin", "stellijstin", "stelmargeblokkenin", "stelmarkeringin", "stelnaastplaatsenin", "stelnummerenin", "stelnummerin", "stelomlijndin", "stelonderin", "stelonderstrepenin", "stelondertekstenin", "stelopmaakin", "stelopsommingenin", "stelpaginacommentaarin", "stelpaginanummerin", "stelpaginanummeringin", "stelpaginaovergangenin", "stelpaletin", "stelpapierformaatin", "stelpapierin", "stelparagraafnummerenin", "stelplaatsblokin", "stelplaatsblokkenin", "stelplaatsbloksplitsenin", "stelplaatsin", "stelpositionerenin", "stelprofielenin", "stelprogrammasin", "stelpublicatiesin", "stelrastersin", "stelreferentielijstin", "stelrefererenin", "stelregelnummerenin", "stelregelsin", "stelregisterin", "stelroterenin", "stelsamengesteldelijstin", "stelsectieblokin", "stelsectiein", "stelsmallerin", "stelsorterenin", "stelspatieringin", "stelstartstopin", "stelstrutin", "stelsubpaginanummerin", "stelsymboolsetin", "stelsynchronisatiebalkin", "stelsynchronisatiein", "stelsynoniemenin", "stelsysteemin", "steltaalin", "steltabellenin", "steltabin", "steltabulatiein", "steltekstin", "steltekstinhoudin", "steltekstlijnenin", "steltekstpositiein", "stelteksttekstenin", "steltekstvariabelein", "steltolerantiein", "steltypein", "steltypenin", "steluitlijnenin", "steluitvoerin", "stelurlin", "stelveldenin", "stelveldin", "stelversiesin", "stelvoetin", "stelvoetnootdefinitiein", "stelvoetnotenin", "stelvoettekstenin", "stelwiskundeuitlijnenin", "stelwitruimtein", "stopachtergrond", "stopalignment", "stopbuffer", "stopcitaat", "stopcodering", "stopcolumns", "stopcombinatie", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopglobaal", "stophiding", "stopinteractiemenu", "stopitemgroup", "stopkantlijn", "stopkleur", "stopkolomgroep", "stopkolommen", "stopkolomopmaak", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokaal", "stoplokalevoetnoten", "stopmakeup", "stopmargeblok", "stopmarginblock", "stopnaast", "stopnamemakeup", "stopnarrower", "stopomgeving", "stoponderdeel", "stopopelkaar", "stopopmaak", "stopopposite", "stopoverlay", "stopoverview", "stopoverzicht", "stopparagraph", "stoppositioneren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofiel", "stopprofile", "stopprojekt", "stopraster", "stopregel", "stopregelcorrectie", "stopregelnummeren", "stopregels", "stopsmaller", "stopsymbolset", "stopsynchronisatie", "stopsynchronization", "stoptabel", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptekst", "stoptekstlijn", "stoptyping", "stopuitlijnen", "stopunpacked", "stopvanelkaar", "stopversie", "sub", "subformulenummer", "subject", "subpaginanummer", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestie", "switchnaarkorps", "switchtorawfont", "sym", "symbool", "synchronisatiebalk", "synchroniseer", "synonym", "taal", "tab", "tekstbreedte", "teksthoogte", "tekstlijn", "tekstreferentie", "tekstvariabele", "testkolom", "testpagina", "tex", "title", "toelichting", "toonexternefiguren", "toongrid", "tooninstellingen", "toonkader", "toonkleur", "toonkleurgroep", "toonkorps", "toonkorpsomgeving", "toonlayout", "toonopmaak", "toonpalet", "toonprint", "toonstruts", "toonsymboolset", "toonvelden", "totaalaantalpaginas", "txt", "typ", "type", "typebuffer", "typefile", "uit", "uitgerekt", "underbar", "underbars", "usecodering", "usedirectory", "vastespatie", "vastespaties", "veld", "veldstapel", "verbergblokken", "vergelijkkleurgroep", "vergelijkpalet", "verhoognummer", "verlaagnummer", "verplaatsformule", "verplaatsopgrid", "verplaatszijblok", "versie", "vertaal", "verwerkblokken", "verwerkpagina", "vl", "voetafstand", "voethoogte", "voetnoot", "voetnoottekst", "volgprofiel", "volgprofielversie", "volgversie", "volledigepaginanummer", "volledigregister", "voluit", "weekdag", "wilijnd", "wiskunde", "witruimte", "woonplaats", "woordrechts", "zetbreedte", "zethoogte" },
+ ["nl"]={ "CAP", "Cap", "Caps", "Cijfers", "KAP", "Kap", "Kaps", "Letter", "Letters", "MAAND", "Romeins", "WEEKDAG", "WOORD", "WOORDEN", "Woord", "Woorden", "aantalsubpaginas", "about", "achtergrond", "appendix", "arg", "bepaalkopnummer", "bepaallijstkenmerken", "bepaalregisterkenmerken", "betekenis", "binnenmargeafstand", "binnenmargebreedte", "binnenrandafstand", "binnenrandbreedte", "blanko", "blokje", "blokjes", "blokkeerinteractiemenu", "bodemwit", "bookmark", "bovenafstand", "bovenhoogte", "breuk", "buitenmargeafstand", "buitenmargebreedte", "buitenrandafstand", "buitenrandbreedte", "but", "button", "cap", "chapter", "chem", "cijfers", "citaat", "citeer", "clip", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "converteernummer", "copieerveld", "corrigeerwitruimte", "coupledregister", "crlf", "datum", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "definerawfont", "definetypeface", "definieer", "definieeraccent", "definieeralineas", "definieerbeeldmerk", "definieerblanko", "definieerblok", "definieerbuffer", "definieercombinatie", "definieercommando", "definieerconversie", "definieerfiguursymbool", "definieerfont", "definieerfontstijl", "definieerfontsynoniem", "definieerhbox", "definieerhoofdveld", "definieeringesprongentext", "definieerinmarge", "definieerinteractiemenu", "definieeritemgroep", "definieerkadertekst", "definieerkarakter", "definieerkleur", "definieerkleurgroep", "definieerkolomgroep", "definieerkolomovergang", "definieerkop", "definieerkorps", "definieerkorpsomgeving", "definieerlayer", "definieerlayout", "definieerletter", "definieerlijn", "definieerlijst", "definieermarkering", "definieeromlijnd", "definieeropmaak", "definieeroverlay", "definieerpaginaovergang", "definieerpalet", "definieerpapierformaat", "definieerplaats", "definieerplaatsblok", "definieerprofiel", "definieerprogramma", "definieerreferentie", "definieerreferentieformaat", "definieerreferentielijst", "definieerregister", "definieersamengesteldelijst", "definieersectie", "definieersectieblok", "definieersorteren", "definieerstartstop", "definieersubveld", "definieersymbool", "definieersynoniemen", "definieertabelvorm", "definieertabulatie", "definieertekst", "definieertekstpositie", "definieertekstvariabele", "definieertype", "definieertypen", "definieeruitvoer", "definieerveld", "definieerveldstapel", "definieerversie", "definieerwiskundeuitlijnen", "description", "dimensie", "directnaarlijst", "directtussenlijst", "doordefinieren", "doorlabelen", "doornummeren", "dunnelijn", "dunnelijnen", "eenregel", "enumeration", "ergens", "externfiguur", "forceerblokken", "formulenummer", "framedtext", "gebruikJSscripts", "gebruikURL", "gebruikXMLfilter", "gebruikblokken", "gebruikcommandos", "gebruikexterndocument", "gebruikexternefile", "gebruikexternefiles", "gebruikexternfiguur", "gebruikexterngeluidsfragment", "gebruikgebied", "gebruikmodule", "gebruikmodules", "gebruikreferenties", "gebruikspecials", "gebruiksymbolen", "gebruiktypescript", "gebruiktypescriptfile", "gebruikurl", "geenblokkenmeer", "geenbovenenonderregels", "geendimensie", "geenfilesmeer", "geenhoofdenvoetregels", "geenlijst", "geenmarkering", "geenspatie", "geentest", "geenwitruimte", "geg", "grijskleur", "grijswaarde", "haalbuffer", "haalmarkering", "haalnummer", "haarlijn", "handhaafblokken", "herhaal", "hl", "hoofdafstand", "hoofdhoogte", "hoofdtaal", "hoog", "huidigedatum", "huidigekopnummer", "in", "inanderemarge", "inbinnen", "inbuiten", "indentation", "inlijnd", "inlinker", "inlinkermarge", "inlinkerrand", "inmarge", "inrechter", "inrechtermarge", "inrechterrand", "inregel", "inspringen", "installeertaal", "instellingen", "interactiebalk", "interactiebuttons", "interactiemenu", "invullijnen", "invulregel", "invultekst", "invulveld", "inwilijnd", "items", "its", "kantlijn", "kap", "kenmerk", "kenmerkdatum", "kentekstvariabeletoe", "kleur", "kleurenbalk", "kleurwaarde", "kloonveld", "kolom", "kop", "kopniveau", "kopnummer", "koppeldocument", "koppelmarkering", "koppelpagina", "koppelpapier", "koppelregister", "kopsym", "koptekst", "kopwit", "laag", "label", "labeling", "labels", "labeltekst", "laho", "leg", "legeregels", "letter", "letters", "lijndikte", "lijstbreedte", "lijsthoogte", "lijstlengte", "lijstsymbool", "linkermargeafstand", "linkermargebreedte", "linkerrandafstand", "linkerrandbreedte", "loadsorts", "loadsynonyms", "maand", "mapfontsize", "mar", "margeafstand", "margebreedte", "margetekst", "margetitel", "margewoord", "markeer", "markeerversie", "mediaeval", "menubutton", "naam", "naar", "naarbox", "naarpagina", "name", "navigerend", "nextsection", "nietinspringen", "nocap", "nokap", "noot", "nop", "omgeving", "omlaag", "omlijnd", "onbekend", "onderafstand", "onderdeel", "onderhoogte", "ontkoppelmarkering", "op", "opelkaar", "oplinkermarge", "oppagina", "oprechtermarge", "overbar", "overbars", "overstrike", "overstrikes", "pagina", "paginadiepte", "paginanummer", "paginaoffset", "paginareferentie", "papierbreedte", "papierhoogte", "paragraph", "part", "paslayoutaan", "passeerblokken", "passendveld", "plaatsbeeldmerken", "plaatsbookmarks", "plaatsformule", "plaatskopnummer", "plaatskoptekst", "plaatslegenda", "plaatslijn", "plaatslijst", "plaatslokalevoetnoten", "plaatsnaastelkaar", "plaatsonderelkaar", "plaatsopgrid", "plaatspaginanummer", "plaatsplaatsblok", "plaatsreferentielijst", "plaatsregister", "plaatsruwelijst", "plaatssamengesteldelijst", "plaatssubformule", "plaatstekstvariabele", "plaatsvoetnoten", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "positioneer", "positioneertekst", "printpapierbreedte", "printpapierhoogte", "produkt", "programma", "projekt", "publicatie", "punten", "ran", "randafstand", "randbreedte", "rechtermargeafstand", "rechtermargebreedte", "rechterrandafstand", "rechterrandbreedte", "ref", "refereer", "referentie", "regellinks", "regelmidden", "regelrechts", "register", "registreervelden", "reservefloat", "reset", "resetmarkering", "resetnummer", "resettekstinhoud", "resettextcontent", "romeins", "rooster", "roteer", "rugwit", "schaal", "scherm", "schrijfnaarlijst", "schrijfnaarreferentielijst", "schrijfnaarregister", "schrijftussenlijst", "section", "seeregister", "selecteerblokken", "selecteerpapier", "selecteerversie", "setnummer", "setupfonthandling", "setupfontsynonym", "setupinterlinespace2", "setuplistalternative", "snijwit", "som", "sort", "spatie", "spiegel", "splitsplaatsblok", "startachtergrond", "startalignment", "startbuffer", "startcitaat", "startcodering", "startcolumns", "startcombinatie", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfiguur", "startfloattext", "startformula", "startframedtext", "startgeg", "startglobaal", "starthiding", "startinteractiemenu", "startitemgroup", "startkantlijn", "startkleur", "startkolomgroep", "startkolommen", "startkolomopmaak", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokaal", "startlokalevoetnoten", "startmakeup", "startmargeblok", "startmarginblock", "startnaast", "startnamemakeup", "startnarrower", "startomgeving", "startonderdeel", "startopelkaar", "startopmaak", "startopposite", "startoverlay", "startoverview", "startoverzicht", "startparagraph", "startpositioneren", "startpositioning", "startpostponing", "startprodukt", "startprofiel", "startprofile", "startprojekt", "startraster", "startregel", "startregelcorrectie", "startregelnummeren", "startregels", "startregister", "startsmaller", "startsymbolset", "startsymboolset", "startsynchronisatie", "startsynchronization", "starttabel", "starttabellen", "starttable", "starttables", "starttabulate", "starttekst", "starttekstlijn", "starttyping", "startuitlijnen", "startunpacked", "startvanelkaar", "startversie", "stelachtergrondenin", "stelachtergrondin", "stelalineasin", "stelantwoordgebiedin", "stelarrangerenin", "stelblankoin", "stelblokin", "stelblokjesin", "stelblokkopjein", "stelblokkopjesin", "stelbovenin", "stelboventekstenin", "stelbufferin", "stelbuttonsin", "stelciterenin", "stelclipin", "stelcombinatiesin", "stelcommentaarin", "steldoordefinierenin", "steldoornummerenin", "steldunnelijnenin", "stelexternefigurenin", "stelformulesin", "stelformulierenin", "stelhoofdin", "stelhoofdtekstenin", "stelingesprongentextin", "stelinmargein", "stelinspringenin", "stelinteractiebalkin", "stelinteractiein", "stelinteractiemenuin", "stelinteractieschermin", "stelinterliniein", "stelinvullijnenin", "stelinvulregelsin", "stelitemgroepin", "stelitemsin", "stelkadertekstenin", "stelkantlijnin", "stelkapitalenin", "stelkleurenin", "stelkleurin", "stelkolomgroepin", "stelkolomgroepregelsin", "stelkolomgroepstartin", "stelkolommenin", "stelkopin", "stelkopnummerin", "stelkoppeltekenin", "stelkoppenin", "stelkoptekstin", "stelkorpsin", "stelkorpsomgevingin", "stellabeltekstin", "stellayoutin", "stellegendain", "stellijndiktein", "stellijnin", "stellijstin", "stelmargeblokkenin", "stelmarkeringin", "stelnaastplaatsenin", "stelnummerenin", "stelnummerin", "stelomlijndin", "stelonderin", "stelonderstrepenin", "stelondertekstenin", "stelopmaakin", "stelopsommingenin", "stelpaginacommentaarin", "stelpaginanummerin", "stelpaginanummeringin", "stelpaginaovergangenin", "stelpaletin", "stelpapierformaatin", "stelpapierin", "stelparagraafnummerenin", "stelplaatsblokin", "stelplaatsblokkenin", "stelplaatsbloksplitsenin", "stelplaatsin", "stelpositionerenin", "stelprofielenin", "stelprogrammasin", "stelpublicatiesin", "stelrastersin", "stelreferentielijstin", "stelrefererenin", "stelregelnummerenin", "stelregelsin", "stelregisterin", "stelroterenin", "stelsamengesteldelijstin", "stelsectieblokin", "stelsectiein", "stelsmallerin", "stelsorterenin", "stelspatieringin", "stelstartstopin", "stelstrutin", "stelsubpaginanummerin", "stelsymboolsetin", "stelsynchronisatiebalkin", "stelsynchronisatiein", "stelsynoniemenin", "stelsysteemin", "steltaalin", "steltabellenin", "steltabin", "steltabulatiein", "steltekstin", "steltekstinhoudin", "steltekstlijnenin", "steltekstpositiein", "stelteksttekstenin", "steltekstvariabelein", "steltolerantiein", "steltypein", "steltypenin", "steluitlijnenin", "steluitvoerin", "stelurlin", "stelveldenin", "stelveldin", "stelversiesin", "stelvoetin", "stelvoetnootdefinitiein", "stelvoetnotenin", "stelvoettekstenin", "stelwiskundeuitlijnenin", "stelwitruimtein", "stopachtergrond", "stopalignment", "stopbuffer", "stopcitaat", "stopcodering", "stopcolumns", "stopcombinatie", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopglobaal", "stophiding", "stopinteractiemenu", "stopitemgroup", "stopkantlijn", "stopkleur", "stopkolomgroep", "stopkolommen", "stopkolomopmaak", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokaal", "stoplokalevoetnoten", "stopmakeup", "stopmargeblok", "stopmarginblock", "stopnaast", "stopnamemakeup", "stopnarrower", "stopomgeving", "stoponderdeel", "stopopelkaar", "stopopmaak", "stopopposite", "stopoverlay", "stopoverview", "stopoverzicht", "stopparagraph", "stoppositioneren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofiel", "stopprofile", "stopprojekt", "stopraster", "stopregel", "stopregelcorrectie", "stopregelnummeren", "stopregels", "stopsmaller", "stopsymbolset", "stopsynchronisatie", "stopsynchronization", "stoptabel", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptekst", "stoptekstlijn", "stoptyping", "stopuitlijnen", "stopunpacked", "stopvanelkaar", "stopversie", "sub", "subformulenummer", "subject", "subpaginanummer", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestie", "switchnaarkorps", "switchtorawfont", "sym", "symbool", "symoffset", "synchronisatiebalk", "synchroniseer", "synonym", "taal", "tab", "tekstbreedte", "teksthoogte", "tekstlijn", "tekstreferentie", "tekstvariabele", "testkolom", "testpagina", "tex", "title", "toelichting", "toonexternefiguren", "toongrid", "tooninstellingen", "toonkader", "toonkleur", "toonkleurgroep", "toonkorps", "toonkorpsomgeving", "toonlayout", "toonopmaak", "toonpalet", "toonprint", "toonstruts", "toonsymboolset", "toonvelden", "totaalaantalpaginas", "txt", "typ", "type", "typebuffer", "typefile", "uit", "uitgerekt", "underbar", "underbars", "usecodering", "usedirectory", "vastespatie", "vastespaties", "veld", "veldstapel", "verbergblokken", "vergelijkkleurgroep", "vergelijkpalet", "verhoognummer", "verlaagnummer", "verplaatsformule", "verplaatsopgrid", "verplaatszijblok", "versie", "vertaal", "verwerkblokken", "verwerkpagina", "vl", "voetafstand", "voethoogte", "voetnoot", "voetnoottekst", "volgprofiel", "volgprofielversie", "volgversie", "volledigepaginanummer", "volledigregister", "voluit", "weekdag", "wilijnd", "wiskunde", "witruimte", "woonplaats", "woordrechts", "zetbreedte", "zethoogte" },
["pe"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "appendix", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "coupledregister", "crlf", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "definetypeface", "description", "enumeration", "framedtext", "indentation", "inmframed", "its", "labeling", "loadsorts", "loadsynonyms", "mapfontsize", "mediaeval", "mframed", "name", "nextsection", "nocap", "overbar", "overbars", "overstrike", "overstrikes", "paragraph", "part", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "ran", "register", "reservefloat", "resettextcontent", "section", "seeregister", "setupanswerarea", "setupcapitals", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setuplistalternative", "setupurl", "sort", "startalignment", "startbuffer", "startcolumns", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprofile", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startتولید", "startحقیقت", "startخط‌حاشیه", "startخط‌متن", "startرنگ", "startفشرده", "startمحیط", "startمنوی‌پانل", "startمولفه", "startنسخه", "startنقل‌قول", "startپروژه", "startپس‌زمینه", "stopalignment", "stopbuffer", "stopcolumns", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprofile", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopتولید", "stopحقیقت", "stopخط‌حاشیه", "stopخط‌متن", "stopرنگ", "stopفشرده", "stopمحیط", "stopمنوی‌پانل", "stopمولفه", "stopنسخه", "stopنقل‌قول", "stopپروژه", "stopپس‌زمینه", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "title", "tooltip", "txt", "typ", "underbar", "underbars", "useJSscripts", "useURL", "useXMLfilter", "usedirectory", "useurl", "آفست‌صفحه", "آیتم", "آیتمها", "آینه", "اجباربلوکها", "ارتفاع‌آرایش", "ارتفاع‌بالا", "ارتفاع‌برگ", "ارتفاع‌ته‌برگ", "ارتفاع‌خط", "ارتفاع‌سربرگ", "ارتفاع‌متن", "ارتفاع‌پایین", "از", "ازکارانداختن‌منوی‌پانل", "استفاده‌بلوکها", "استفاده‌دستخط‌تایپ", "استفاده‌رمزینه", "استفاده‌شکل‌خارجی", "استفاده‌فرمانها", "استفاده‌قطعه‌موزیک‌خارجی", "استفاده‌مدول", "استفاده‌مدولها", "استفاده‌مرجعها", "استفاده‌مسیر", "استفاده‌نمادها", "استفاده‌نوشتارخارجی", "استفاده‌ویژگیها", "استفاده‌پرونده‌خارجی", "استفاده‌پرونده‌دستخط‌تایپ", "استفاده‌پرونده‌های‌خارجی", "اعدادلاتین", "افزودن", "اما", "امتحان‌نکن", "انتخاب‌برگ", "انتخاب‌بلوکها", "انتخاب‌نسخه", "انتقال‌به‌توری", "انتقال‌فرمول", "انتقال‌کنار‌شناور", "انجام‌دوباره", "بارگذاریها", "بارگذاری‌آرایش", "بارگذاری‌آیتمها", "بارگذاری‌ارجاع", "بارگذاری‌اندازه‌برگ", "بارگذاری‌باریکتر", "بارگذاری‌بافر", "بارگذاری‌بالا", "بارگذاری‌بخش", "بارگذاری‌بردباری", "بارگذاری‌برنامه‌ها", "بارگذاری‌برگ", "بارگذاری‌بست", "بارگذاری‌بلوک", "بارگذاری‌بلوکهای‌حاشیه", "بارگذاری‌بلوک‌بخش", "بارگذاری‌تایپ", "بارگذاری‌تایپ‌کردن", "بارگذاری‌تب", "بارگذاری‌ترتیب", "بارگذاری‌ترکیب‌ها", "بارگذاری‌تطابق", "بارگذاری‌تعریف‌پانوشت", "بارگذاری‌تنظیم", "بارگذاری‌تنظیم‌ریاضی", "بارگذاری‌ته‌برگ", "بارگذاری‌تورفتگی", "بارگذاری‌توضیح", "بارگذاری‌توضیح‌صفحه", "بارگذاری‌ثبت", "بارگذاری‌جانشانی", "بارگذاری‌جدولها", "بارگذاری‌جدول‌بندی", "بارگذاری‌خالی", "بارگذاری‌خروجی", "بارگذاری‌خط", "بارگذاری‌خطها", "بارگذاری‌خطهای‌حاشیه", "بارگذاری‌خطهای‌سیاه", "بارگذاری‌خطهای‌متن", "بارگذاری‌خطهای‌مجموعه‌ستون", "بارگذاری‌خطها‌ی‌نازک", "بارگذاری‌درج‌درخطها", "بارگذاری‌درج‌مخالف", "بارگذاری‌درون‌حاشیه", "بارگذاری‌دوران", "بارگذاری‌دکمه‌ها", "بارگذاری‌راهنما", "بارگذاری‌رنگ", "بارگذاری‌رنگها", "بارگذاری‌زبان", "بارگذاری‌ستونها", "بارگذاری‌سر", "بارگذاری‌سربرگ", "بارگذاری‌سرها", "بارگذاری‌سیستم", "بارگذاری‌شرح", "بارگذاری‌شرحها", "بارگذاری‌شروع‌مجموعه‌ستون", "بارگذاری‌شروع‌پایان", "بارگذاری‌شماره", "بارگذاری‌شماره‌زیرصفحه", "بارگذاری‌شماره‌سر", "بارگذاری‌شماره‌صفحه", "بارگذاری‌شماره‌گذاری", "بارگذاری‌شماره‌گذاریها", "بارگذاری‌شماره‌گذاری‌صفحه", "بارگذاری‌شماره‌گذاری‌پاراگراف", "بارگذاری‌شماره‌‌گذاری‌خط", "بارگذاری‌شناور", "بارگذاری‌شناورها", "بارگذاری‌شکافتن‌شناورها", "بارگذاری‌شکلهای‌خارجی", "بارگذاری‌طرح", "بارگذاری‌طرح‌بندی", "بارگذاری‌عرض‌خط", "بارگذاری‌فاصله‌بین‌خط", "بارگذاری‌فرمولها", "بارگذاری‌فضای‌سفید", "بارگذاری‌فضا‌گذاری", "بارگذاری‌قالبی", "بارگذاری‌قلم‌متن", "بارگذاری‌لوح", "بارگذاری‌لیست", "بارگذاری‌لیست‌ترکیبی", "بارگذاری‌لیست‌مرجع", "بارگذاری‌مترادفها", "بارگذاری‌متغیر‌متن", "بارگذاری‌متن", "بارگذاری‌متنهای‌بالا", "بارگذاری‌متن‌سر", "بارگذاری‌متن‌سربرگ", "بارگذاری‌متن‌قالبی", "بارگذاری‌متن‌متنها", "بارگذاری‌متن‌پانوشت", "بارگذاری‌متن‌پایین", "بارگذاری‌مجموعه‌ستون", "بارگذاری‌مجموعه‌نماد", "بارگذاری‌محیط‌قلم‌متن", "بارگذاری‌منوی‌پانل", "بارگذاری‌مکان‌متن", "بارگذاری‌مکان‌گذاری", "بارگذاری‌میدان", "بارگذاری‌میدانها", "بارگذاری‌میله‌تطابق", "بارگذاری‌میله‌زیر", "بارگذاری‌میله‌پانل", "بارگذاری‌نسخه‌ها", "بارگذاری‌نشانه‌شکستن", "بارگذاری‌نشانه‌گذاری", "بارگذاری‌نشرها", "بارگذاری‌نقل", "بارگذاری‌پاراگرافها", "بارگذاری‌پانل", "بارگذاری‌پانوشتها", "بارگذاری‌پایین", "بارگذاری‌پرده‌ها", "بارگذاری‌پرده‌پانل", "بارگذاری‌پروفایلها", "بارگذاری‌پرکردن‌خطها", "بارگذاری‌پس‌زمینه", "بارگذاری‌پس‌زمینه‌ها", "بارگذاری‌چیدن", "بارگذاری‌گذارصفحه", "بارگذاری‌گروههای‌آیتم", "بارگذاری‌گروه‌آیتم", "بازنشانی", "بازنشانی‌شماره", "بازنشانی‌متن", "بازنشانی‌نشانه‌گذاری", "باگذاری‌متن‌برچسب", "بدون‌بعد", "بدون‌بلوکهای‌بیشتر", "بدون‌تورفتگی", "بدون‌خط‌بالاوپایین", "بدون‌خط‌سروته‌برگ", "بدون‌فایلهای‌بیشتر", "بدون‌فضا", "بدون‌فضای‌سفید", "بدون‌لیست", "بدون‌نشانه‌گذاری", "برنامه", "بروبه", "بروبه‌جعبه", "بروبه‌صفحه", "بروپایین", "برچسب", "برچسبها", "بعد", "بلند", "بلوکهای‌پردازش", "بلوکها‌پنهان", "بنویس‌بین‌لیست", "بنویس‌درثبت", "بنویس‌درلیست‌مرجع", "بنویس‌در‌لیست", "تاریخ", "تاریخ‌جاری", "تاریخ‌رجوع", "تایپ", "تایپ‌بافر", "تایپ‌پرونده", "تب", "ترجمه", "تطابق", "تعریف", "تعریف‌آرایش", "تعریف‌آرم", "تعریف‌الگوی‌جدول", "تعریف‌اندازه‌برگ", "تعریف‌بافر", "تعریف‌بخش", "تعریف‌برنامه", "تعریف‌برچسب", "تعریف‌بلوک", "تعریف‌بلوک‌بخش", "تعریف‌تایپ", "تعریف‌تایپ‌کردن", "تعریف‌تبدیل", "تعریف‌ترتیب", "تعریف‌ترکیب", "تعریف‌تنظیم‌ریاضی", "تعریف‌توده‌میدان", "تعریف‌ثبت", "تعریف‌جانشانی", "تعریف‌جدول‌بندی", "تعریف‌جعبه‌‌افقی", "تعریف‌حرف", "تعریف‌خالی", "تعریف‌خروجی", "تعریف‌خط‌حائل", "تعریف‌درون‌حاشیه", "تعریف‌رنگ", "تعریف‌زیرمیدان", "تعریف‌سبک", "تعریف‌سبک‌قلم", "تعریف‌سر", "تعریف‌شرح", "تعریف‌شروع‌پایان", "تعریف‌شماره‌بندی", "تعریف‌شمایل‌مرجع", "تعریف‌شناور", "تعریف‌شکستن‌ستون", "تعریف‌شکست‌صفحه", "تعریف‌طرح‌بندی", "تعریف‌فرمان", "تعریف‌قالبی", "تعریف‌قلم", "تعریف‌قلم‌خام", "تعریف‌قلم‌متن", "تعریف‌لایه", "تعریف‌لهجه", "تعریف‌لوح", "تعریف‌لیست", "تعریف‌لیست‌ترکیبی", "تعریف‌لیست‌مرجع", "تعریف‌مترادفها", "تعریف‌مترادف‌قلم", "تعریف‌متغیرمتن", "تعریف‌متن", "تعریف‌متن‌قالبی", "تعریف‌مجموعه‌ستون", "تعریف‌محیط‌قلم‌بدنه", "تعریف‌مرجع", "تعریف‌منوی‌پانل", "تعریف‌مکان‌متن", "تعریف‌میدان", "تعریف‌میدان‌اصلی", "تعریف‌نسخه", "تعریف‌نشانه‌گذاری", "تعریف‌نماد", "تعریف‌نمادشکل", "تعریف‌پاراگرافها", "تعریف‌پروفایل", "تعریف‌پوشش", "تعریف‌گروه‌آیتم", "تعریف‌گروه‌رنگ", "تعیین‌شماره", "تعیین‌شماره‌سر", "تعیین‌متغیر‌متن", "تعیین‌محتوای‌متن", "تعیین‌مشخصات‌ثبت", "تعیین‌مشخصات‌لیست", "تغییربه‌قلم‌بدنه", "تغییربه‌قلم‌خام", "تنظیم‌راست", "تنظیم‌طرح‌بندی", "تنظیم‌وسط", "توجه", "تورفتگی", "توری", "تولید", "تک", "ثبت‌زوج", "ثبت‌کامل", "جداسازی‌نشانه‌گذاری", "حاش", "حرف", "حرفها", "حفظ‌بلوکها", "حقیقت", "خالی", "خطهای‌سیاه", "خطهای‌نازک", "خطها‌خالی", "خط‌حاشیه", "خط‌سیاه", "خط‌متن", "خط‌مو", "خط‌نازک", "خ‌ا", "خ‌ع", "در", "درج‌آرمها", "درج‌ثبت", "درج‌خط", "درج‌درخط", "درج‌درخطها", "درج‌درمتن", "درج‌درمیدان", "درج‌در‌بالای‌یکدیگر", "درج‌در‌توری", "درج‌راهنما", "درج‌زیرفرمول", "درج‌شماره‌سر", "درج‌شماره‌صفحه", "درج‌شناور", "درج‌فرمول", "درج‌لیست", "درج‌لیست‌خام", "درج‌لیست‌مختلط", "درج‌لیست‌مرجع", "درج‌متغیرمتن", "درج‌متن‌سر", "درج‌پانوشتها", "درج‌پانوشتهای‌موضعی", "درج‌چوب‌خط", "درج‌کنار‌به‌کنار", "درحاشیه", "درحاشیه‌دیگر", "درحاشیه‌راست", "درحاشیه‌چپ", "درخارجی", "درخط", "درداخلی", "درراست", "درصفحه", "درقالبی", "درلبه‌راست", "درلبه‌چپ", "درمورد", "درون", "درپر", "درچپ", "دریافت‌بافر", "دریافت‌شماره", "دریافت‌نشانه", "دوران", "دکمه", "دکمه‌منو", "دکمه‌پانل", "رج", "رجوع", "رنگ", "رنگ‌خاکستری", "روزهفته", "ریاضی", "زبان", "زبان‌اصلی", "ستون", "ستون‌امتحان", "سر", "سرپوش‌کوچک‌نه", "شروع‌آرایش", "شروع‌آرایش‌ستون", "شروع‌باریکتر", "شروع‌بازبینی", "شروع‌بلوک‌حاشیه", "شروع‌ترکیب", "شروع‌تصحیح‌خط", "شروع‌تطابق", "شروع‌تنظیم", "شروع‌تولید", "شروع‌جدول", "شروع‌جدولها", "شروع‌خط", "شروع‌خطها", "شروع‌خط‌حاشیه", "شروع‌خط‌متن", "شروع‌رنگ", "شروع‌ستونها", "شروع‌سراسری", "شروع‌شماره‌گذاری‌خط", "شروع‌شکل", "شروع‌غیر‌فشرده", "شروع‌فشرده", "شروع‌متن", "شروع‌مجموعه‌ستون", "شروع‌مجموعه‌نماد", "شروع‌محیط", "شروع‌مخالف", "شروع‌موضعی", "شروع‌مولفه", "شروع‌مکان‌گذاری", "شروع‌نسخه", "شروع‌نقل‌قول", "شروع‌نوشتار", "شروع‌پانوشتهای‌موضعی", "شروع‌پروفایل", "شروع‌پروژه", "شروع‌پس‌زمینه", "شروع‌پوشش", "شروع‌کد", "شماره‌افزایش", "شماره‌زیرصفحه", "شماره‌زیرفرمول", "شماره‌سر", "شماره‌سرجاری", "شماره‌صفحه", "شماره‌صفحه‌کامل", "شماره‌فرمول", "شماره‌مبدل", "شماره‌ها", "شماره‌کاهش", "شماره‌کل‌صفحه‌ها", "شکافتن‌شناور", "شکل‌خارجی", "صفحه", "صفحه‌تست", "صفحه‌زوج", "صفحه‌پردازش", "طول‌لیست", "عبوربلوکها", "عرض‌آرایش", "عرض‌برگ", "عرض‌حاشیه", "عرض‌حاشیه‌خارجی", "عرض‌حاشیه‌داخلی", "عرض‌حاشیه‌راست", "عرض‌حاشیه‌چپ", "عرض‌خط", "عرض‌لبه", "عرض‌لبه‌خارجی", "عرض‌لبه‌داخلی", "عرض‌لبه‌راست", "عرض‌لبه‌چپ", "عرض‌لیست", "عرض‌متن", "عمق‌صفحه", "عنوان‌حاشیه", "فاصله‌بالا", "فاصله‌ته‌برگ", "فاصله‌حاشیه", "فاصله‌حاشیه‌خارجی", "فاصله‌حاشیه‌داخلی", "فاصله‌حاشیه‌راست", "فاصله‌حاشیه‌چپ", "فاصله‌سربرگ", "فاصله‌لبه", "فاصله‌لبه‌خارجی", "فاصله‌لبه‌داخلی", "فاصله‌لبه‌راست", "فاصله‌لبه‌چپ", "فاصله‌پایین", "فاصله‌پشت", "فشرده", "فضا", "فضاهای‌ثابت", "فضای‌بالا", "فضای‌برش", "فضای‌ثابت", "فضای‌سفید", "فضای‌سفیدصحیح", "فضای‌پایین", "فوری‌به‌لیست", "فوری‌بین‌لیست", "قالبی", "لوح‌مقایسه", "ماه", "متغیر متن", "متن‌برچسب", "متن‌حاشیه", "متن‌سر", "متن‌پانوشت", "محیط", "مراجعه", "مرجع", "مرجع‌صفحه", "مرجع‌متن", "مرحله‌سر", "مسکن", "معنی‌واحد", "مقایسه‌گروه‌رنگ", "مقدارخاکستری", "مقداررنگ", "مقیاس", "منفی", "منوی‌پانل", "مولفه", "مکان", "مکان‌متن", "میدان", "میدانهای‌گزارش", "میدان‌شبیه‌سازی", "میدان‌پشته", "میدان‌کپی", "میله‌تطابق", "میله‌رنگ", "میله‌پانل", "ناشناس", "نام‌ماکرو", "نسخه", "نسخه‌نشانه", "نشانه‌گذاری", "نشانه‌گذاری‌زوج", "نشر", "نصب‌زبان", "نقطه‌ها", "نقل", "نقل‌قول", "نم", "نماد", "نمادسر", "نمادلیست", "نمایش‌آرایش", "نمایش‌بارگذاریها", "نمایش‌بستها", "نمایش‌توری", "نمایش‌رنگ", "نمایش‌شکلهای‌خارجی", "نمایش‌طرح‌بندی", "نمایش‌قالب", "نمایش‌قلم‌بدنه", "نمایش‌لوح", "نمایش‌مجموعه‌علامت", "نمایش‌محیط‌قلم‌بدنه", "نمایش‌میدانها", "نمایش‌چاپ", "نمایش‌گروه‌رنگ", "نوشتارزوج", "هدایت", "پا", "پابا", "پانوشت", "پایان‌آرایش", "پایان‌آرایش‌ستون", "پایان‌بازبینی", "پایان‌بلوک‌حاشیه", "پایان‌ترکیب", "پایان‌تصحیح‌خط", "پایان‌تطابق", "پایان‌تنظیم", "پایان‌تولید", "پایان‌جدول", "پایان‌جدولها", "پایان‌خط", "پایان‌خطها", "پایان‌خط‌حاشیه", "پایان‌خط‌متن", "پایان‌رنگ", "پایان‌ستونها", "پایان‌سراسری", "پایان‌شماره‌گذاری‌خط", "پایان‌غیرفشرده", "پایان‌فشرده", "پایان‌متن", "پایان‌مجموعه‌ستون", "پایان‌محیط", "پایان‌مخالف", "پایان‌موضعی", "پایان‌مولفه", "پایان‌مکان‌گذاری", "پایان‌نازکتر", "پایان‌نسخه", "پایان‌نقل‌قول", "پایان‌نوشتار", "پایان‌پانوشتهای‌موضعی", "پایان‌پروفایل", "پایان‌پروژه", "پایان‌پس‌زمینه", "پایان‌پوشش", "پایان‌کد", "پایین", "پرده", "پروژه", "پرکردن‌میدان", "پس‌زمینه", "پیروی‌نسخه", "پیروی‌نسخه‌پروفایل", "پیروی‌پروفایل", "چاپ‌ارتفاع‌برگ", "چاپ‌عرض‌برگ", "چوبخط", "چپ‌چین", "کاغذزوج", "کسر", "کشیده", "کلمه‌حاشیه", "کلمه‌راست", "گیره", "یادداشت", "یک‌جا", "یک‌خط" },
["ro"]={ "CAP", "CUVANT", "CUVINTE", "Cap", "Caps", "Cuvant", "Cuvinte", "KAP", "Kap", "Kaps", "LUNA", "Litera", "Litere", "Numere", "Numereromane", "ZIDINSAPTAMANA", "adapteazaaspect", "adubuffer", "adumarcaje", "afiseazaaspect", "afiseazacampuri", "afiseazaculoare", "afiseazafiguriexterne", "afiseazafonttext", "afiseazagrid", "afiseazagrupculoare", "afiseazamakeup", "afiseazamediufonttext", "afiseazapaleta", "afiseazarama", "afiseazasetari", "afiseazasetsimboluri", "afiseazastruts", "afiseazatiparire", "aliniat", "aliniatcentru", "aliniatdreapta", "aliniatstanga", "appendix", "arg", "ascundeblocuri", "atleftmargin", "atrightmargin", "baraculoare", "barainteractiune", "barasincronizare", "blanc", "but", "butoaneinteractiune", "buton", "butonmeniu", "camp", "campumplere", "cap", "chapter", "chem", "citat", "clip", "cloneazacamp", "coloana", "comment", "comparagrupculoare", "comparapaleta", "completeazanumarpagina", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenta", "convertestenumar", "copiazacamp", "corecteazaspatiualb", "coupledregister", "crlf", "culoare", "culoaregri", "cupleazadocument", "cupleazamarcaje", "cupleazaregistru", "cutspace", "cuvantdreapta", "cuvantmarginal", "data", "datacurenta", "datareferit", "decrementnumber", "decupleazamarcaje", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "defineste", "definesteaccent", "definesteantet", "definesteblanc", "definestebloc", "definesteblocsectiune", "definestebuffer", "definestecamp", "definestecampprincipal", "definestecaracter", "definestecomanda", "definesteconversie", "definesteculoare", "definestedescriere", "definestedimensiunehartie", "definesteenumerare", "definesteeticheta", "definestefloat", "definestefont", "definestefontraw", "definestefonttext", "definesteformatreferinte", "definestegrupculori", "definestehbox", "definesteinconjurare", "definestelista", "definestelistacombinata", "definestelistareferinte", "definestelogo", "definestemakeup", "definestemarcaje", "definestemediulfonttext", "definestemeniuinteractiune", "definesteoutput", "definesteoverlay", "definestepaleta", "definesteparagraf", "definestepozitietext", "definesteprofil", "definesteprogram", "definestereferinte", "definesteregistru", "definesterigla", "definestesablontabel", "definestesectiune", "definestesimbol", "definestesimbolfigura", "definestesinonim", "definestesinonimfont", "definestesortare", "definestestartstop", "definestestil", "definestestilfont", "definestestivacampuri", "definestesubcamp", "definestetabulatori", "definestetext", "definestetexteinconjurate", "definestetextinconjurat", "definestetyping", "definestevariabilatext", "definesteversiune", "definetype", "definetypeface", "description", "despre", "determinacaracteristicilelistei", "determinacaracteristiciregistru", "determinanumartitlu", "dezactiveazameniuinteractiune", "dimensiune", "din", "distantaantet", "distantacolt", "distantacoltdreapta", "distantacoltstanga", "distantajos", "distantamargine", "distantamarginedreapta", "distantamarginestanga", "distantasubsol", "distantasus", "domiciliu", "dute", "dutebox", "dutepagina", "ecran", "el", "element", "emptylines", "enumeration", "eticheta", "etichete", "fact", "faraaliniat", "faradimensiune", "farafisiere", "faraliniiantetsisubsol", "faraliniisussijos", "faralista", "faramarcaje", "faraspatiu", "faraspatiualb", "figuraexterna", "firdepar", "folosesteURL", "folosestebloc", "folosestecodificarea", "folosestecomenzi", "folosestedirector", "folosestedocumentextern", "folosestefiguraexterna", "folosestefisiereexterne", "folosestefisierextern", "folosestemodul", "folosestemodule", "folosestemuzicaexterna", "folosestereferinte", "folosestescriptJS", "folosestesimboluri", "folosestespeciale", "folosesteurl", "footnotetext", "forteazablocuri", "fractie", "framed", "framedtext", "fundal", "gatablocuri", "getnumber", "grid", "grosimelinie", "hartiedubla", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "impachetat", "impartefloat", "in", "inalt", "inaltamargine", "inaltimeantet", "inaltimehartie", "inaltimehartieimprimanta", "inaltimejos", "inaltimelista", "inaltimemakeup", "inaltimesubsol", "inaltimesus", "inaltimetext", "indentation", "indreapta", "inframed", "ininner", "injos", "inlinie", "inmaframed", "inmargineadreapta", "inmargineastanga", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inparteadreapta", "inparteastanga", "instalarelimba", "instanga", "intins", "jos", "jossus", "kap", "la", "labeling", "lapagina", "latimecoltdreapta", "latimecoltstanga", "latimecolturi", "latimehartie", "latimehartieimprimanta", "latimelista", "latimemakeup", "latimemargine", "latimemarginedreapta", "latimemarginestanga", "latimetext", "leg", "limba", "limbaprincipala", "liniemargine", "linieneagra", "liniesubtire", "linieumplere", "liniinegre", "liniisubtiri", "listsymbol", "litera", "litere", "loadsorts", "loadsynonyms", "logcampuri", "luna", "lungimelista", "maframed", "mapfontsize", "mar", "marcaje", "marcheazaversiune", "marginal", "matematica", "mediaeval", "mediu", "meniuinteractiune", "minicitat", "moveformula", "movesidefloat", "mutapegrid", "name", "navigating", "necunoscut", "nextsection", "niveltitlu", "nocap", "nokap", "nop", "nota", "notasubsol", "numarformula", "numarincrement", "numarpagina", "numarsubformula", "numartitlu", "numartitlucurent", "numartotalpagini", "numberofsubpages", "nume", "numere", "numereromane", "numeunitate", "nutesta", "olinie", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paginadubla", "paragraph", "part", "pastreazablocuri", "pelung", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "plaseazapegrid", "plaseazasemnecarte", "potrivestecamp", "pozitie", "pozitietext", "proceseazabloc", "proceseazapagina", "produs", "program", "proiect", "publicatie", "puncte", "punedeasuprafiecareia", "punefatainfata", "puneformula", "punelegenda", "punelista", "punelistacombinata", "punelogouri", "punenotesubsol", "punenotesubsollocale", "punenumarpagina", "puneregistru", "punerigla", "punesubformula", "punevariabilatext", "ran", "ref", "refa", "referinta", "referintapagina", "referintatext", "referit", "referring", "reflexie", "register", "remarca", "reservefloat", "reset", "reseteazamarcaje", "resetnumber", "resettextcontent", "riglatext", "rigleumplere", "roteste", "saripesteblocuri", "scala", "scriebuffer", "scrieinlista", "scrieinlistareferinte", "scrieinregistru", "scrieintreliste", "section", "seeregister", "selecteazablocuri", "selecteazahartie", "selecteazaversiune", "semncarte", "setarebarasincronizare", "setareitemization", "setarelimba", "setareoutput", "setarepozitie", "setaresincronizare", "setari", "seteazaaliniat", "seteazaalinierea", "seteazaantet", "seteazaaranjareapag", "seteazaaspect", "seteazabarainteractiune", "seteazablanc", "seteazabloc", "seteazablocsectiune", "seteazablocurimarginale", "seteazabuffer", "seteazabutoane", "seteazacamp", "seteazacampuri", "seteazaclipping", "seteazacoloane", "seteazacombinari", "seteazacomentariu", "seteazacomentariupagina", "seteazaculoare", "seteazaculori", "seteazadefinireanotasubsol", "seteazadescriere", "seteazadimensiunihartie", "seteazaecrane", "seteazaecraninteractiune", "seteazaelemente", "seteazaenumerare", "seteazafiguriexterne", "seteazafloat", "seteazafloats", "seteazafonttext", "seteazaformulare", "seteazaformule", "seteazafundal", "seteazafundaluri", "seteazagrosimelinie", "seteazaimpartireafloat", "seteazainconjurat", "seteazaingust", "seteazainteractiunea", "seteazajos", "seteazalegenda", "seteazalegendele", "seteazaliniesilabe", "seteazaliniesubtire", "seteazalinii", "seteazaliniimargine", "seteazaliniinegre", "seteazaliniiumplere", "seteazalista", "seteazalistacombinata", "seteazalistareferinte", "seteazamajuscule", "seteazamakeup", "seteazamarcaje", "seteazamarginal", "seteazamediulfonttext", "seteazameniuinteractiune", "seteazaminicitat", "seteazanotasubsol", "seteazanumarpagina", "seteazanumarsubpagina", "seteazanumartitlu", "seteazanumerotare", "seteazanumerotarelinii", "seteazanumerotarepagina", "seteazanumerotareparagrafe", "seteazapaleta", "seteazaparagrafe", "seteazaplasareaopozita", "seteazapozitietext", "seteazaprofile", "seteazaprograme", "seteazapublicatii", "seteazareferinte", "seteazaregistru", "seteazarigla", "seteazarigletext", "seteazarigleumplere", "seteazarotare", "seteazasectiune", "seteazasimbol", "seteazasinonime", "seteazasistem", "seteazasortare", "seteazaspatiu", "seteazaspatiualb", "seteazaspatiuinterliniar", "seteazastrut", "seteazasublinie", "seteazasubsol", "seteazasus", "seteazatab", "seteazatabele", "seteazatabulatori", "seteazatext", "seteazatexteantet", "seteazatextejos", "seteazatextesubsol", "seteazatextesus", "seteazatextetext", "seteazatexteticheta", "seteazatexttitlu", "seteazatitlu", "seteazatitluri", "seteazatoleranta", "seteazatranzitiepagina", "seteazatype", "seteazatyping", "seteazaurl", "seteazavariabilatext", "seteazaversiuni", "setnumber", "settextcontent", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setupstartstop", "setvariabilatext", "sim", "simbol", "sincronizeaza", "sort", "spatiifixate", "spatiu", "spatiualb", "spatiufixat", "spatiujos", "spatiuspate", "spatiusus", "startalignment", "startaliniere", "startblocmarginal", "startbuffer", "startcitat", "startcodificare", "startcoloane", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombinare", "startcombination", "startcomment", "startcomponenta", "startcorectielinie", "startculoare", "startdescription", "startdocument", "startenumeration", "startfact", "startfigura", "startfigure", "startfloattext", "startformula", "startframedtext", "startfundal", "startglobal", "starthiding", "startimpachetat", "startingust", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlinie", "startliniemargine", "startlinii", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmediu", "startmeniuinteractiune", "startnamemakeup", "startnarrower", "startneimpachetat", "startnotesubsollocale", "startnumerotarelinii", "startopozit", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozitionare", "startprodus", "startprofil", "startprofile", "startproiect", "startraster", "startregister", "startriglatext", "startsetsimboluri", "startsincronizare", "startsymbolset", "startsynchronization", "starttabel", "starttabele", "starttable", "starttables", "starttabulate", "starttext", "starttyping", "startunpacked", "startversiune", "stivacampuri", "stopalignment", "stopaliniere", "stopblobal", "stopblocmarginal", "stopbuffer", "stopcitat", "stopcodificare", "stopcoloane", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombinare", "stopcombination", "stopcomment", "stopcomponenta", "stopcorectielinie", "stopculoare", "stopdescription", "stopdocument", "stopenumeration", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopfundal", "stophiding", "stopimpachetat", "stopingust", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplinie", "stopliniemargine", "stoplinii", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmediu", "stopmeniuinteractiune", "stopnamemakeup", "stopnarrower", "stopneimpachetat", "stopnotesubsollocale", "stopnumerotarelinii", "stopopozit", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozitionare", "stopprodus", "stopprofil", "stopprofile", "stopproiect", "stopraster", "stopriglatext", "stopsincronizare", "stopsymbolset", "stopsynchronization", "stoptabel", "stoptabele", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptyping", "stopunpacked", "stopversiune", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "testcolumn", "testpage", "tex", "texteticheta", "textmarginal", "texttitlu", "textumplere", "title", "titlu", "titlumarginal", "tooltip", "traduce", "trecilafontraw", "trecilafonttext", "txt", "typ", "type", "typefile", "underbar", "underbars", "undeva", "urmeazaprofil", "urmeazaversiune", "urmeazaversiuneprofil", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "valoareculoare", "valoaregri", "variabilatext", "versiune", "vl", "zidinsaptamana" },
} \ No newline at end of file
diff --git a/context/data/scite/lexers/scite-context-lexer-lua.lua b/context/data/scite/lexers/scite-context-lexer-lua.lua
index 0ace7afc6..e8a52c991 100644
--- a/context/data/scite/lexers/scite-context-lexer-lua.lua
+++ b/context/data/scite/lexers/scite-context-lexer-lua.lua
@@ -34,18 +34,22 @@ local keywords = {
}
local functions = {
- 'assert', 'collectgarbage', 'dofile', 'error', 'getfenv', 'getmetatable',
- 'ipairs', 'load', 'loadfile', 'loadstring', 'module', 'next', 'pairs',
- 'pcall', 'print', 'rawequal', 'rawget', 'rawset', 'require', 'setfenv',
- 'setmetatable', 'tonumber', 'tostring', 'type', 'unpack', 'xpcall', "select",
+ 'assert', 'collectgarbage', 'dofile', 'error', 'getmetatable',
+ 'ipairs', 'load', 'loadfile', 'module', 'next', 'pairs',
+ 'pcall', 'print', 'rawequal', 'rawget', 'rawset', 'require',
+ 'setmetatable', 'tonumber', 'tostring', 'type', 'unpack', 'xpcall', 'select',
+
+ "string", "table", "coroutine", "debug", "file", "io", "lpeg", "math", "os", "package", "bit32",
}
local constants = {
- '_G', '_VERSION', '_M', "...",
+ '_G', '_VERSION', '_M', "...", '_ENV'
}
local depricated = {
"arg", "arg.n",
+ "loadstring", "setfenv", "getfenv",
+ "pack",
}
local csnames = { -- todo: option
@@ -156,14 +160,21 @@ local gotolabel = token("keyword", P("::"))
* token("grouping",validword)
* token("keyword", P("::"))
-local keyword = token("keyword", exact_match(keywords ))
-local builtin = token("plain", exact_match(functions))
-local constant = token("data", exact_match(constants))
-local csname = token("user", exact_match(csnames ))
+local p_keywords = exact_match(keywords )
+local p_functions = exact_match(functions)
+local p_constants = exact_match(constants)
+local p_csnames = exact_match(csnames )
+
+local keyword = token("keyword", p_keywords)
+local builtin = token("plain", p_functions)
+local constant = token("data", p_constants)
+local csname = token("user", p_csnames)
* (
optionalspace * hasargument
- + ( optionalspace * token("special", P(".")) * optionalspace * token("user", validword) )^1
+ + ( optionalspace * token("special", S(".:")) * optionalspace * token("user", validword) )^1
)
+local identifier = token("default", validword)
+ * ( optionalspace * token("special", S(".:")) * optionalspace * (token("warning", p_keywords) + token("default", validword)) )^0
lualexer._rules = {
{ 'whitespace', spacing },
@@ -184,6 +195,52 @@ lualexer._rules = {
{ 'rest', rest },
}
+-- -- experiment
+--
+-- local idtoken = R("az","AZ","__")
+--
+-- function context.one_of_match(specification)
+-- local pattern = idtoken -- the concat catches _ etc
+-- local list = { }
+-- for i=1,#specification do
+-- local style = specification[i][1]
+-- local words = specification[i][2]
+-- pattern = pattern + S(table.concat(words))
+-- for i=1,#words do
+-- list[words[i]] = style
+-- end
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- local style = list[s]
+-- if style then
+-- return true, { style, i } -- and i or nil
+-- else
+-- -- fail
+-- end
+-- end)
+-- end
+--
+-- local whatever = context.one_of_match {
+-- { "keyword", keywords }, -- keyword
+-- { "plain", functions }, -- builtin
+-- { "data", constants }, -- constant
+-- }
+--
+-- lualexer._rules = {
+-- { 'whitespace', spacing },
+-- { 'whatever', whatever },
+-- { 'csname', csname },
+-- { 'goto', gotokeyword },
+-- { 'identifier', identifier },
+-- { 'string', string },
+-- { 'number', number },
+-- { 'longcomment', longcomment },
+-- { 'shortcomment', shortcomment },
+-- { 'label', gotolabel },
+-- { 'operator', operator },
+-- { 'rest', rest },
+-- }
+
lualexer._tokenstyles = context.styleset
lualexer._foldsymbols = {
diff --git a/context/data/scite/lexers/scite-context-lexer-mps.lua b/context/data/scite/lexers/scite-context-lexer-mps.lua
index 1a2a2571d..27a2e2979 100644
--- a/context/data/scite/lexers/scite-context-lexer-mps.lua
+++ b/context/data/scite/lexers/scite-context-lexer-mps.lua
@@ -70,6 +70,9 @@ local any = lexer.any
local dquote = P('"')
local cstoken = R("az","AZ") + P("_")
+local mptoken = R("az","AZ")
+local leftbrace = P("{")
+local rightbrace = P("}")
local number = context.patterns.real
local cstokentex = R("az","AZ","\127\255") + S("@!?_")
@@ -97,6 +100,14 @@ local special = token('special', S("#()[]{}<>=:\"")) -- or else := <> etc s
local texlike = token('warning', P("\\") * cstokentex^1)
local extra = token('extra', S("`~%^&_-+*/\'|\\"))
+local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace }
+local texlike = token('embedded', P("\\") * (P("MP") + P("mp")) * mptoken^1)
+ * spacing^0
+ * token('grouping', leftbrace)
+ * token('rest', (nested + (1-rightbrace))^0 )
+ * token('grouping', rightbrace)
+ + token('warning', P("\\") * cstokentex^1)
+
metafunlexer._rules = {
{ 'whitespace', spacing },
{ 'comment', comment },
diff --git a/context/data/scite/lexers/scite-context-lexer-tex.lua b/context/data/scite/lexers/scite-context-lexer-tex.lua
index f59624051..1c0e77455 100644
--- a/context/data/scite/lexers/scite-context-lexer-tex.lua
+++ b/context/data/scite/lexers/scite-context-lexer-tex.lua
@@ -344,7 +344,7 @@ local function stopinlinelua_b(_,i,s) -- {
if luastatus == "display" then
return false
elseif luastatus == "inline" then
- lualevel = lualevel + 1
+ lualevel = lualevel + 1 -- ?
return false
else
return true
@@ -373,15 +373,16 @@ contextlexer._reset_parser = function()
lualevel = 0
end
-local luaenvironment = P("luacode")
+local luaenvironment = P("luacode") + P("lua")
local inlinelua = P("\\") * (
P("ctx") * ( P("lua") + P("command") + P("late") * (P("lua") + P("command")) )
+ P("cld") * ( P("command") + P("context") )
+ + P("luaexpr")
)
local startlua = P("\\start") * Cmt(luaenvironment,startdisplaylua)
- + inlinelua * space^0 * Cmt(P("{"),startinlinelua)
+ + inlinelua * space^0 * ( Cmt(P("{"),startinlinelua) )
local stoplua = P("\\stop") * Cmt(luaenvironment,stopdisplaylua)
+ Cmt(P("{"),stopinlinelua_b)
diff --git a/context/data/scite/lexers/scite-context-lexer.lua b/context/data/scite/lexers/scite-context-lexer.lua
index 1c9f2cec0..fa627a836 100644
--- a/context/data/scite/lexers/scite-context-lexer.lua
+++ b/context/data/scite/lexers/scite-context-lexer.lua
@@ -8,6 +8,15 @@ local info = {
}
+-- Starting with SciTE version 3.20 there is an issue with coloring. As we still lack
+-- a connection with scite itself (properties as well as printing to the log pane) we
+-- cannot trace this (on windows). As far as I can see, there are no fundamental
+-- changes in lexer.lua or LexLPeg.cxx so it must be in scintilla itself. So for the
+-- moment I stick to 3.10. Indicators are: no lexing of 'next' and 'goto <label>' in the
+-- Lua lexer and no brace highlighting either. Interesting is that it does work ok in
+-- the cld lexer (so the Lua code is okay). Also the fact that char-def.lua lexes fast
+-- is a signal that the lexer quits somewhere halfway.
+
-- The fold and lex functions are copied and patched from original code by Mitchell (see
-- lexer.lua). All errors are mine.
--
diff --git a/context/data/scite/scite-context-data-context.properties b/context/data/scite/scite-context-data-context.properties
index 6e6a26da9..d2023ea40 100644
--- a/context/data/scite/scite-context-data-context.properties
+++ b/context/data/scite/scite-context-data-context.properties
@@ -50,55 +50,63 @@ tracingnone loggingall removetoks appendtoks prependtoks \
appendtotoks prependtotoks to endgraf endpar \
everyendpar reseteverypar finishpar empty null \
space quad enspace obeyspaces obeylines \
-normalspace executeifdefined singleexpandafter doubleexpandafter tripleexpandafter \
-dontleavehmode removelastspace removeunwantedspaces keepunwantedspaces wait \
-writestatus define redefine setmeasure setemeasure \
-setgmeasure setxmeasure definemeasure freezemeasure measure \
-getvalue setvalue setevalue setgvalue setxvalue \
-letvalue letgvalue resetvalue undefinevalue ignorevalue \
-setuvalue setuevalue setugvalue setuxvalue globallet \
-glet udef ugdef uedef uxdef \
-getparameters geteparameters getgparameters getxparameters forgetparameters \
-copyparameters getdummyparameters dummyparameter directdummyparameter setdummyparameter \
-letdummyparameter usedummystyleandcolor usedummystyleparameter usedummycolorparameter processcommalist \
-processcommacommand quitcommalist quitprevcommalist processaction processallactions \
-processfirstactioninset processallactionsinset unexpanded expanded startexpanded \
-stopexpanded protected protect unprotect firstofoneargument \
-firstoftwoarguments secondoftwoarguments firstofthreearguments secondofthreearguments thirdofthreearguments \
-firstoffourarguments secondoffourarguments thirdoffourarguments fourthoffourarguments firstoffivearguments \
-secondoffivearguments thirdoffivearguments fourthoffivearguments fifthoffivearguments firstofsixarguments \
-secondofsixarguments thirdofsixarguments fourthofsixarguments fifthofsixarguments sixthofsixarguments \
-firstofoneunexpanded gobbleoneargument gobbletwoarguments gobblethreearguments gobblefourarguments \
-gobblefivearguments gobblesixarguments gobblesevenarguments gobbleeightarguments gobbleninearguments \
-gobbletenarguments gobbleoneoptional gobbletwooptionals gobblethreeoptionals gobblefouroptionals \
-gobblefiveoptionals dorecurse doloop exitloop dostepwiserecurse \
-recurselevel recursedepth dofastloopcs newconstant setnewconstant \
-newconditional settrue setfalse setconstant newmacro \
-setnewmacro newfraction newsignal dosingleempty dodoubleempty \
-dotripleempty doquadrupleempty doquintupleempty dosixtupleempty doseventupleempty \
-dosingleargument dodoubleargument dotripleargument doquadrupleargument doquintupleargument \
-dosixtupleargument doseventupleargument dosinglegroupempty dodoublegroupempty dotriplegroupempty \
-doquadruplegroupempty doquintuplegroupempty nopdfcompression maximumpdfcompression normalpdfcompression \
-modulonumber dividenumber getfirstcharacter doiffirstcharelse startnointerference \
-stopnointerference twodigits threedigits strut setstrut \
-strutbox strutht strutdp strutwd struthtdp \
-begstrut endstrut lineheight ordordspacing ordopspacing \
-ordbinspacing ordrelspacing ordopenspacing ordclosespacing ordpunctspacing \
-ordinnerspacing opordspacing opopspacing opbinspacing oprelspacing \
-opopenspacing opclosespacing oppunctspacing opinnerspacing binordspacing \
-binopspacing binbinspacing binrelspacing binopenspacing binclosespacing \
-binpunctspacing bininnerspacing relordspacing relopspacing relbinspacing \
-relrelspacing relopenspacing relclosespacing relpunctspacing relinnerspacing \
-openordspacing openopspacing openbinspacing openrelspacing openopenspacing \
-openclosespacing openpunctspacing openinnerspacing closeordspacing closeopspacing \
-closebinspacing closerelspacing closeopenspacing closeclosespacing closepunctspacing \
-closeinnerspacing punctordspacing punctopspacing punctbinspacing punctrelspacing \
-punctopenspacing punctclosespacing punctpunctspacing punctinnerspacing innerordspacing \
-inneropspacing innerbinspacing innerrelspacing inneropenspacing innerclosespacing \
-innerpunctspacing innerinnerspacing normalreqno startimath stopimath \
-normalstartimath normalstopimath startdmath stopdmath normalstartdmath \
-normalstopdmath uncramped cramped triggermathstyle mathstylefont \
-mathstyleface
+obeyedspace obeyedline normalspace executeifdefined singleexpandafter \
+doubleexpandafter tripleexpandafter dontleavehmode removelastspace removeunwantedspaces \
+keepunwantedspaces wait writestatus define redefine \
+setmeasure setemeasure setgmeasure setxmeasure definemeasure \
+freezemeasure measure installcorenamespace getvalue setvalue \
+setevalue setgvalue setxvalue letvalue letgvalue \
+resetvalue undefinevalue ignorevalue setuvalue setuevalue \
+setugvalue setuxvalue globallet glet udef \
+ugdef uedef uxdef getparameters geteparameters \
+getgparameters getxparameters forgetparameters copyparameters getdummyparameters \
+dummyparameter directdummyparameter setdummyparameter letdummyparameter usedummystyleandcolor \
+usedummystyleparameter usedummycolorparameter processcommalist processcommacommand quitcommalist \
+quitprevcommalist processaction processallactions processfirstactioninset processallactionsinset \
+unexpanded expanded startexpanded stopexpanded protected \
+protect unprotect firstofoneargument firstoftwoarguments secondoftwoarguments \
+firstofthreearguments secondofthreearguments thirdofthreearguments firstoffourarguments secondoffourarguments \
+thirdoffourarguments fourthoffourarguments firstoffivearguments secondoffivearguments thirdoffivearguments \
+fourthoffivearguments fifthoffivearguments firstofsixarguments secondofsixarguments thirdofsixarguments \
+fourthofsixarguments fifthofsixarguments sixthofsixarguments firstofoneunexpanded gobbleoneargument \
+gobbletwoarguments gobblethreearguments gobblefourarguments gobblefivearguments gobblesixarguments \
+gobblesevenarguments gobbleeightarguments gobbleninearguments gobbletenarguments gobbleoneoptional \
+gobbletwooptionals gobblethreeoptionals gobblefouroptionals gobblefiveoptionals dorecurse \
+doloop exitloop dostepwiserecurse recurselevel recursedepth \
+dofastloopcs newconstant setnewconstant newconditional settrue \
+setfalse setconstant newmacro setnewmacro newfraction \
+newsignal dosingleempty dodoubleempty dotripleempty doquadrupleempty \
+doquintupleempty dosixtupleempty doseventupleempty dosingleargument dodoubleargument \
+dotripleargument doquadrupleargument doquintupleargument dosixtupleargument doseventupleargument \
+dosinglegroupempty dodoublegroupempty dotriplegroupempty doquadruplegroupempty doquintuplegroupempty \
+nopdfcompression maximumpdfcompression normalpdfcompression modulonumber dividenumber \
+getfirstcharacter doiffirstcharelse startnointerference stopnointerference twodigits \
+threedigits strut setstrut strutbox strutht \
+strutdp strutwd struthtdp begstrut endstrut \
+lineheight ordordspacing ordopspacing ordbinspacing ordrelspacing \
+ordopenspacing ordclosespacing ordpunctspacing ordinnerspacing opordspacing \
+opopspacing opbinspacing oprelspacing opopenspacing opclosespacing \
+oppunctspacing opinnerspacing binordspacing binopspacing binbinspacing \
+binrelspacing binopenspacing binclosespacing binpunctspacing bininnerspacing \
+relordspacing relopspacing relbinspacing relrelspacing relopenspacing \
+relclosespacing relpunctspacing relinnerspacing openordspacing openopspacing \
+openbinspacing openrelspacing openopenspacing openclosespacing openpunctspacing \
+openinnerspacing closeordspacing closeopspacing closebinspacing closerelspacing \
+closeopenspacing closeclosespacing closepunctspacing closeinnerspacing punctordspacing \
+punctopspacing punctbinspacing punctrelspacing punctopenspacing punctclosespacing \
+punctpunctspacing punctinnerspacing innerordspacing inneropspacing innerbinspacing \
+innerrelspacing inneropenspacing innerclosespacing innerpunctspacing innerinnerspacing \
+normalreqno startimath stopimath normalstartimath normalstopimath \
+startdmath stopdmath normalstartdmath normalstopdmath uncramped \
+cramped triggermathstyle mathstylefont mathstyleface mathstylecommand \
+luaexpr expdoifelse expdoif expdoifnot expdoifcommonelse \
+expdoifinsetelse ctxdirectlua ctxlatelua ctxsprint ctxwrite \
+ctxcommand ctxdirectcommand ctxlatecommand ctxreport ctxlua \
+luacode lateluacode directluacode registerctxluafile ctxloadluafile \
+luaversion luamajorversion luaminorversion ctxluacode luaconditional \
+luaexpanded startluaparameterset stopluaparameterset luaparameterset definenamedlua \
+obeylualines obeyluatokens startluacode stopluacode startlua \
+stoplua
keywordclass.context.constants=\
zerocount minusone minustwo plusone \
@@ -158,5 +166,5 @@ mathordcode mathopcode mathbincode mathrelcode mathopencode \
mathclosecode mathpunctcode mathalphacode mathinnercode mathnothingcode \
mathlimopcode mathnolopcode mathboxcode mathchoicecode mathaccentcode \
mathradicalcode constantnumber constantnumberargument constantdimen constantdimenargument \
-constantemptyargument continueifinputfile
+constantemptyargument continueifinputfile luastringsep !!bs !!es
diff --git a/context/data/scite/scite-context-data-interfaces.properties b/context/data/scite/scite-context-data-interfaces.properties
index 44f315053..30d0ebfa9 100644
--- a/context/data/scite/scite-context-data-interfaces.properties
+++ b/context/data/scite/scite-context-data-interfaces.properties
@@ -1,152 +1,162 @@
-keywordclass.context.en=\
-CAP Cap Caps Character \
-Characters MONTH Numbers Romannumerals WEEKDAY \
-WORD WORDS Word Words about \
-adaptlayout adding appendix arg at \
-atleftmargin atpage atrightmargin background backspace \
-blackrule blackrules blank bookmark bottomdistance \
-bottomheight bottomspace but button bypassblocks \
-cap chapter character characters chem \
-clip clonefield color colorbar colorvalue \
-column comment comparecolorgroup comparepalet completecombinedlist \
+keywordclass.context.cs=\
+CAP Cap Caps Cisla \
+KAP Kap Kaps MESIC Rimskecislice \
+SLOVA SLOVO Slova Slovo VSEDNIDEN \
+Znak Znaky aktualnicislonadpisu aktualnidatum appendix \
+arg atleftmargin atrightmargin barevnalista barva \
+bilemisto bottomspace bublinkovanapoveda bydliste bypassblocks \
+cap celkovypocetstran cernalinka cernelinky chapter \
+chem cisla cislonadpisu cislopodrovnice cislorovnice \
+cislostrany citace citovat comment completecombinedlist \
completelistoffloats completelistofsorts completelistofsynonyms completepagenumber completeregister \
-component convertnumber copyfield correctwhitespace coupledocument \
-coupledregister couplemarking couplepage couplepaper coupleregister \
-crlf currentdate currentheadnumber cutspace date \
-decouplemarking decrementnumber define defineaccent defineblank \
-defineblock definebodyfont definebodyfontDEF definebodyfontREF definebodyfontenvironment \
-definebuffer definecharacter definecolor definecolorgroup definecolumnbreak \
-definecolumnset definecombination definecombinedlist definecommand defineconversion \
-definedescription definedfont defineenumeration definefield definefieldstack \
-definefiguresymbol definefloat definefont definefontfeature definefonthandling \
-definefontstyle definefontsynonym defineframed defineframedtext definehbox \
-definehead defineindentedtext defineinmargin defineinteractionmenu defineitemgroup \
-definelabel definelayer definelayout definelist definelogo \
-definemainfield definemakeup definemarking definemathalignment defineoutput \
-defineoverlay definepagebreak definepalet definepapersize defineparagraphs \
-defineplacement defineprofile defineprogram definerawfont definereference \
-definereferenceformat definereferencelist defineregister definerule definesection \
-definesectionblock definesorting definestartstop definestyle definesubfield \
-definesymbol definesynonyms definetabletemplate definetabulate definetext \
-definetextposition definetextvariable definetype definetypeface definetyping \
-defineversion description determineheadnumber determinelistcharacteristics determineregistercharacteristics \
-dimension disableinteractionmenu domicile donttest edgedistance \
-edgewidth emptylines enumeration environment externalfigure \
-fact field fieldstack fillinfield fillinline \
-fillinrules fillintext fitfield fixedspace fixedspaces \
-followprofile followprofileversion followversion footerdistance footerheight \
-footnote footnotetext forceblocks formulanumber fraction \
-framed framedtext from getbuffer getmarking \
-getnumber godown goto gotobox gotopage \
-graycolor greyvalue grid hairline head \
-headerdistance headerheight headlevel headnumber headsym \
-headtext hideblocks high hl immediatebetweenlist \
-immediatetolist in incrementnumber indentation indenting \
-inframed infull ininner inleft inleftedge \
-inleftmargin inline inmaframed inmargin inneredgedistance \
-inneredgewidth innermargindistance innermarginwidth inothermargin inouter \
-inright inrightedge inrightmargin installlanguage interactionbar \
-interactionbuttons interactionmenu item items its \
-keepblocks label labeling labels labeltext \
-language leftaligned leftedgedistance leftedgewidth leftmargindistance \
-leftmarginwidth leg linethickness listheight listlength \
-listsymbol listwidth loadsorts loadsynonyms logfields \
-lohi low maframed mainlanguage makeupheight \
-makeupwidth mapfontsize mar margindistance marginrule \
-margintext margintitle marginwidth marginword marking \
-markversion mathematics mediaeval menubutton midaligned \
-mirror month moveformula moveongrid movesidefloat \
-name navigating nextsection nocap nodimension \
-noheaderandfooterlines noindenting nolist nomarking nomoreblocks \
-nomorefiles nop nospace note notopandbottomlines \
-nowhitespace numberofsubpages numbers outeredgedistance outeredgewidth \
-outermargindistance outermarginwidth overbar overbars overstrike \
-overstrikes packed page pagedepth pagenumber \
-pageoffset pagereference paperheight paperwidth paragraph \
-part periods placebookmarks placecombinedlist placefloat \
-placefootnotes placeformula placeheadnumber placeheadtext placelegend \
-placelist placelistoffloats placelistofsorts placelistofsynonyms placelocalfootnotes \
-placelogos placeongrid placeontopofeachother placepagenumber placerawlist \
-placereferencelist placeregister placerule placesidebyside placesubformula \
-placetextvariable position positiontext printpaperheight printpaperwidth \
-processblocks processpage product program project \
-publication quotation quote ran redo \
-ref reference referral referraldate referring \
-register remark reservefloat reset resetmarking \
-resetnumber resettextcontent rightaligned rightedgedistance rightedgewidth \
-rightmargindistance rightmarginwidth romannumerals rotate scale \
-screen section seeregister selectblocks selectpaper \
-selectversion setnumber settextcontent settextvariable setupalign \
-setupanswerarea setuparranging setupbackground setupbackgrounds setupblackrules \
-setupblank setupblock setupbodyfont setupbodyfontenvironment setupbottom \
-setupbottomtexts setupbuffer setupbuttons setupcapitals setupcaption \
-setupcaptions setupclipping setupcolor setupcolors setupcolumns \
-setupcolumnset setupcolumnsetlines setupcolumnsetstart setupcombinations setupcombinedlist \
-setupcomment setupdescriptions setupenumerations setupexternalfigures setupfield \
-setupfields setupfillinlines setupfillinrules setupfloat setupfloats \
-setupfloatsplitting setupfonthandling setupfontsynonym setupfooter setupfootertexts \
-setupfootnotedefinition setupfootnotes setupforms setupformulae setupframed \
-setupframedtexts setuphead setupheader setupheadertexts setupheadnumber \
-setupheads setupheadtext setuphyphenmark setupindentedtext setupindenting \
-setupinmargin setupinteraction setupinteractionbar setupinteractionmenu setupinteractionscreen \
-setupinterlinespace setupinterlinespace2 setupitemgroup setupitemizations setupitems \
-setuplabeltext setuplanguage setuplayout setuplegend setuplinenumbering \
-setuplines setuplinewidth setuplist setuplistalternative setupmakeup \
-setupmarginblocks setupmarginrules setupmarking setupmathalignment setupnarrower \
-setupnumber setupnumbering setupoppositeplacing setupoutput setuppagecomment \
-setuppagenumber setuppagenumbering setuppagetransitions setuppalet setuppaper \
-setuppapersize setupparagraphnumbering setupparagraphs setupplacement setuppositioning \
-setupprofiles setupprograms setuppublications setupquote setupreferencelist \
-setupreferencing setupregister setuprotate setuprule setups \
-setupscreens setupsection setupsectionblock setupsorting setupspacing \
-setupstartstop setupstrut setupsubpagenumber setupsymbolset setupsynchronization \
-setupsynchronizationbar setupsynonyms setupsystem setuptab setuptables \
-setuptabulate setuptext setuptextposition setuptextrules setuptexttexts \
-setuptextvariable setupthinrules setuptolerance setuptop setuptoptexts \
-setuptype setuptyping setupunderbar setupurl setupversions \
-setupwhitespace showbodyfont showbodyfontenvironment showcolor showcolorgroup \
-showexternalfigures showfields showframe showgrid showlayout \
-showmakeup showpalet showprint showsetups showstruts \
-showsymbolset someline somewhere sort space \
-splitfloat startalignment startbackground startbuffer startcoding \
-startcolor startcolumnmakeup startcolumns startcolumnset startcombination \
-startcomment startcomponent startdescription startdocument startenumeration \
-startenvironment startfact startfigure startfloattext startformula \
-startframedtext startglobal starthiding startinteractionmenu startitemgroup \
+coupledregister crlf cutspace datum decrementnumber \
+definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset definecombination \
+definedfont definefontfeature definefonthandling defineindentedtext defineinmargin \
+defineitemgroup definelayer definelayout definemathalignment definepagebreak \
+defineplacement definerawfont definerule definetextposition definetextvariable \
+definetype definetypeface definuj definujakcent definujbarvu \
+definujblok definujbloksekce definujbuffer definujfont definujformatodkazu \
+definujhbox definujhlavnipole definujinterakcnimenu definujkombinovanyseznam definujkonverzi \
+definujlogo definujnadpis definujobrazeksymbol definujodkaz definujodstavce \
+definujopis definujoramovani definujoramovanytext definujpaletu definujplvouciobjekt \
+definujpodpole definujpole definujpopis definujpopisek definujprekryv \
+definujpreskok definujprikaz definujprofil definujprogram definujprostredizakladnihofontu \
+definujrejstrik definujsablonutabulky definujsekci definujseznam definujseznamodkazu \
+definujskupinubarev definujstartstop definujstyl definujstylfontu definujsymbol \
+definujsynonumumfontu definujsynonyma definujtabelaci definujtext definujtrideni \
+definujupravu definujvelikostpapiru definujverzi definujvycet definujvystup \
+definujzakladnifont definujzasobnikpoli definujznaceni definujznak delkaseznamu \
+description dodrzujprofil dodrzujverzi dodrzujverziprofilu dvoustrannypapir \
+emptylines enumeration externiobraz fakt footnotetext \
+forceblocks framedtext getnumber headsym hl \
+hlavnijazyk hlavniuroven hodnotabarvy hodnotasedi immediatebetweenlist \
+immediatetolist indentation ininner inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter instalacejazyka interakcnilista \
+interakcnitlacitka interaktivnimenu jazyk jdidolu jdina \
+jdinabox jdinastranu jmeno kap klonujpole \
+komponenta konvertujcislo kopirujpole korekcebilehomista labeling \
+leg listsymbol loadsorts loadsynonyms maoramovani \
+mapfontsize marginalnilinka marginalninadpis marginalnislovo marginalnitext \
+matematika mazaramovani mediaeval meritko mesic \
+mezera moveformula movesidefloat mrizka nadpis \
+nadruhyokraj nalevo nalevyokraj name naokraj \
+napravo napravyokraj nastavbarvu nastavbarvy nastavbilamista \
+nastavblok nastavbloksekce nastavbuffer nastavcernelinky nastavcislonadpisu \
+nastavcislostrany nastavcislovani nastavcislovaniodstavcu nastavcislovaniradku nastavcislovanistran \
+nastavcitaci nastavdefinicipoznamekpodcarou nastavdeleniplvoucichobjektu nastavdelitko nastavdolnitexty \
+nastaveni nastavexterniobrazy nastavhorejsek nastavhornitexty nastavinterakci \
+nastavinterakcnilistu nastavinterakcnimenu nastavinterakcniobrazovku nastavjazyk nastavkapitalky \
+nastavkombinovanyseznam nastavkomentar nastavkomentarstrany nastavlegendu nastavmarginalie \
+nastavmarginalniblok nastavmarginalnilinky nastavmeziradkovoumezeru nastavnadpis nastavnadpisy \
+nastavodkazovani nastavodsazovani nastavodstavce nastavopis nastavoramovanetexty \
+nastavoramovani nastavorez nastavotoceni nastavpaletu nastavplvouciobjekt \
+nastavplvouciobjekty nastavpodcislostrany nastavpodtrzeni nastavpole nastavpolozky \
+nastavpopisek nastavpopisky nastavpopisy nastavpozadi nastavpoznamkypodcarou \
+nastavprechodstrany nastavpreskok nastavprofily nastavprogramy nastavprostredizakladnihofontu \
+nastavpublikace nastavradkovani nastavradky nastavrastr nastavrejstrik \
+nastavrovnice nastavsadusymbolu nastavsekci nastavseznam nastavseznamodkazu \
+nastavsirkucary nastavsloupce nastavspodek nastavspojeni nastavsynchronizaci \
+nastavsynchronizacnilistu nastavsynonyma nastavsystem nastavtab nastavtabelaci \
+nastavtabulky nastavtenkelinky nastavtext nastavtexthlavicky nastavtextovelinky \
+nastavtextpopisku nastavtexttexty nastavtextyupati nastavtextyzahlavi nastavtlacitka \
+nastavtoleranci nastavtrideni nastavtype nastavumisteniprotejsku nastavumistovani \
+nastavupati nastavupravu nastavurl nastavusporadani nastavvelikostpapiru \
+nastavverze nastavvsechnapole nastavvycty nastavvyplnovelinky nastavvyplnoveradky \
+nastavvystup nastavvzhled nastavzahlavi nastavzakladnifont nastavzarovnani \
+nastavznaceni nastavzuzeni nastrane navigating nejakyradek \
+nekde nextsection neznamo nivy nizky \
+nocap nokap nop numberofsubpages obrazovka \
+odkaz odkaznadatum odkaznastranu odkaznatext odkazujici \
+odsazenishora odsazenizleva odsazovani okr opakovat \
+opis opissoubor oramovani oref orez \
+otocit outeredgedistance outeredgewidth outermargindistance outermarginwidth \
+overbar overbars overstrike overstrikes oznaceni \
+oznacverzi pagedepth pageoffset paragraph parovastrana \
+part pis placefloat placeheadnumber placeheadtext \
+placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
+placereferencelist placerule placetextvariable plnezneni pol \
+pole polozka polozky popisky poppisek \
+porovnejpaletu porovnejskupinubarev positiontext pozadi pozice \
+poznamka poznamkapodcarou pref prelozit premistinamrizku \
+prepninazakladnifont preskoc prizpusobivepole prizpusobvzhled produkt \
+program projekt propojeneznaceni propojenydokument propojenyrejstrik \
+prostredi publikace ran ref register \
+reservefloat reset resetnumber resettextcontent resetznaceni \
+rimskecislice rozdelplvouciobjekt rozmer rozpojeneznaceni roztazene \
+schovejbloky section sedabarva seeregister setnumber \
+settextcontent settextvariable setupanswerarea setupcolumnset setupcolumnsetlines \
+setupcolumnsetstart setupfonthandling setupfontsynonym setupforms setupindentedtext \
+setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupnumber \
+setuppaper setupplacement setuprule setupstartstop setupstrut \
+setuptextposition setuptextvariable sirkalevehookraje sirkalevemarginalie sirkamarginalie \
+sirkaokraje sirkapapiru sirkapravehookraje sirkapravemarginalie sirkasazby \
+sirkaseznamu sirkatextu sirkatiskpapiru sloupec slovovpravo \
+sort spodek stanovcharakteristickuseznamu stanovcislonadpisu startalignment \
+startbarva startbuffer startcislovaniradku startcitace startcolumnmakeup \
+startcolumns startcolumnset startcombination startcomment startdescription \
+startdocument startdokument startenumeration startfakt startfigure \
+startfloattext startformula startframedtext startglobalni starthiding \
+startinteraktivnimenu startitemgroup startkodovani startkomponenta startkorekceradku \
startlegend startline startlinecorrection startlinenumbering startlines \
-startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
-startmarginrule startnamemakeup startnarrower startopposite startoverlay \
-startoverview startpacked startparagraph startpositioning startpostponing \
-startproduct startprofile startproject startquotation startraster \
-startregister startsymbolset startsynchronization starttable starttables \
-starttabulate starttext starttextrule starttyping startunpacked \
-startversion stopalignment stopbackground stopbuffer stopcoding \
-stopcolor stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
-stopcomment stopcomponent stopdescription stopdocument stopenumeration \
-stopenvironment stopfact stopfigure stopfloattext stopformula \
-stopframedtext stopglobal stophiding stopinteractionmenu stopitemgroup \
-stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
-stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
-stopmarginrule stopnamemakeup stopnarrower stopopposite stopoverlay \
-stopoverview stoppacked stopparagraph stoppositioning stoppostponing \
-stopproduct stopprofile stopproject stopquotation stopraster \
-stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
-stoptext stoptextrule stoptyping stopunpacked stopversion \
-stretched sub subformulanumber subject subpagenumber \
-subsection subsubject subsubsection subsubsubject switchtobodyfont \
-switchtorawfont sym symbol synchronizationbar synchronize \
-synonym tab testcolumn testpage tex \
-textheight textreference textrule textvariable textwidth \
-thinrule thinrules title tooltip topdistance \
-topheight topspace totalnumberofpages translate txt \
-typ type typebuffer typefile underbar \
-underbars unitmeaning unknown useJSscripts useURL \
-useXMLfilter useblocks usecommands usedirectory useencoding \
-useexternaldocument useexternalfigure useexternalfile useexternalfiles useexternalsoundtrack \
-usemodule usemodules usereferences usespecials usesymbols \
-usetypescript usetypescriptfile useurl version vl \
-weekday whitespace wordright writebetweenlist writetolist \
-writetoreferencelist writetoregister
+startlocal startlocalenvironment startlocalfootnotes startlokalni startlokalnipoznamkypodcarou \
+startmakeup startmarginalniblok startmarginalnilinka startmarginblock startnamemakeup \
+startnarrower startnezhustene startobraz startopposite startoverlay \
+startoverview startparagraph startpositioning startpostponing startpozadi \
+startprehled startprekryv startprodukt startprofil startprofile \
+startprojekt startprostredi startprotejsek startradek startradky \
+startrastr startregister startsadasymbolu startsloupce startspojeni \
+startsymbolset startsynchronizace startsynchronization starttable starttables \
+starttabulate starttabulka starttabulky starttext starttextovalinka \
+starttyping startumistovani startunpacked startuprava startverze \
+startzarovnavani startzhustene startzuzeni stopalignment stopbarva \
+stopbuffer stopcislovaniradku stopcitace stopcolumnmakeup stopcolumns \
+stopcolumnset stopcombination stopcomment stopdescription stopdocument \
+stopdokument stopenumeration stopfakt stopfigure stopfloattext \
+stopformula stopframedtext stopglobalni stophiding stopinteraktivnimenu \
+stopitemgroup stopkodovani stopkomponenta stopkorekceradku stoplegend \
+stopline stoplinecorrection stoplinenumbering stoplines stoplocal \
+stoplocalenvironment stoplocalfootnotes stoplokalni stoplokalnipoznamkypodcarou stopmakeup \
+stopmarginalniblok stopmarginalnilinka stopmarginblock stopnamemakeup stopnarrower \
+stopnezhustene stopopposite stopoverlay stopoverview stopparagraph \
+stoppositioning stoppostponing stoppozadi stopprehled stopprekryv \
+stopprodukt stopprofil stopprofile stopprojekt stopprostredi \
+stopprotejsek stopradek stopradky stoprastr stopsloupce \
+stopspojeni stopsymbolset stopsynchronizace stopsynchronization stoptable \
+stoptables stoptabulate stoptabulka stoptabulky stoptext \
+stoptextovalinka stoptyping stopumistovani stopunpacked stopuprava \
+stopverze stopzarovnavani stopzhustene stopzuzeni strana \
+sub subject subpagenumber subsection subsubject \
+subsubsection subsubsubject switchtorawfont sym symbol \
+synchronizacnilista synchronizovat synonym tab tecky \
+tenkalinka tenkelinky testcolumn testpage tex \
+texthlavicky textovalinka textpopisku textvariable title \
+tlacitko tlacitkomenu tloustkacary tref tvrdamezera \
+tvrdemezery txt typebuffer ukazbarvu ukazexterniobrazy \
+ukazmrizku ukaznastaveni ukazpaletu ukazpodpery ukazpole \
+ukazpostredizakladnihofontu ukazramecek ukazsadusymbolu ukazskupinubarev ukazupravu \
+ukazvytisk ukazvzhled ukazzakladnifont umistikombinovanyseznam umistilegendu \
+umistiloga umistilokalnipoznamkypodcarou umistinadsebe umistinamrizku umistipodrovnici \
+umistipoznamkypodcarou umistirejstrik umistirovnici umistiseznam umistivedlesebe \
+umistizalozky underbar underbars urcicharakteristikurejstriku useXMLfilter \
+usedirectory usetypescript usetypescriptfile uzijJSscripts uzijURL \
+uzijadresar uzijbloky uzijexternidokument uzijexterniobraz uzijexternisoubor \
+uzijexternisoubory uzijexternizvuk uzijkodovani uzijmodul uzijmoduly \
+uzijodkazy uzijprikazy uzijspeciality uzijsymbol uzijurl \
+verze vl vlasovalinka vlevo vpravo \
+vradku vsedniden vyberbloky vyberpapir vyberverzi \
+vyplnenytext vyplnovelinky vyplnovepole vyplnovyradek vyskahorejsku \
+vyskapapiru vyskasazby vyskaseznamu vyskaspodku vyskatextu \
+vyskatiskpapiru vyskaupati vyskazahlavi vysoky vyznam \
+vzdalenosthorejsku vzdalenostlevehookraje vzdalenostlevemarginalie vzdalenostmarginalie vzdalenostokraje \
+vzdalenostpravehookraje vzdalenostpravemarginalie vzdalenostspodku vzdalenostupati vzdalenostzahlavi \
+zablokujinterakcnimenu zachovejbloky zadnamezera zadnebilemisto zadnedalsibloky \
+zadnedalsisoubory zadnehorniadolniradky zadneodsazovani zadnezahlaviaupati zadneznaceni \
+zadnyrozmer zadnyseznam zadnytest zalozka zapisdorejstriku \
+zapisdoseznamu zapisdoseznamuodkazu zapismeziseznam zaramovani zarovnanonastred \
+zarovnanovlevo zarovnanovpravo zasobnikpoli zaznamovepole zhustene \
+ziskejbuffer ziskejznaceni zlomek znaceni znak \
+znaky zpracujbloky zpracujstranu zrcadlit zref \
+zvysujicicislo
keywordclass.context.fr=\
CAP Cap Caps Caractere \
@@ -311,169 +321,6 @@ utilisepsiteaudioexterne utilisereferences utilisespecialites utilisesymboles ut
va vaalaboite vaalapage vaenbas valeurcouleur \
valeurgris variabletexte version vide vl
-keywordclass.context.pe=\
-CAP Cap Caps Character \
-Characters MONTH Numbers Romannumerals WEEKDAY \
-WORD WORDS Word Words appendix \
-cap chapter chem comment completecombinedlist \
-completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf \
-definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling \
-defineindentedtext definetypeface description enumeration framedtext \
-indentation inmframed its labeling loadsorts \
-loadsynonyms mapfontsize mediaeval mframed name \
-nextsection nocap overbar overbars overstrike \
-overstrikes paragraph part placelistoffloats placelistofsorts \
-placelistofsynonyms ran register reservefloat resettextcontent \
-section seeregister setupanswerarea setupcapitals setupfonthandling \
-setupfontsynonym setupindentedtext setupinterlinespace2 setuplistalternative setupurl \
-sort startalignment startbuffer startcolumns startcombination \
-startcomment startdescription startdocument startenumeration startfigure \
-startfloattext startformula startframedtext starthiding startitemgroup \
-startlegend startline startlinecorrection startlinenumbering startlines \
-startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
-startnamemakeup startnarrower startopposite startoverlay startoverview \
-startparagraph startpositioning startpostponing startprofile startraster \
-startregister startsymbolset startsynchronization starttable starttables \
-starttabulate starttyping startunpacked startتولید startحقیقت \
-startخط‌حاشیه startخط‌متن startرنگ startفشرده startمحیط \
-startمنوی‌پانل startمولفه startنسخه startنقل‌قول startپروژه \
-startپس‌زمینه stopalignment stopbuffer stopcolumns stopcombination \
-stopcomment stopdescription stopdocument stopenumeration stopfigure \
-stopfloattext stopformula stopframedtext stophiding stopitemgroup \
-stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
-stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
-stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview \
-stopparagraph stoppositioning stoppostponing stopprofile stopraster \
-stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
-stoptyping stopunpacked stopتولید stopحقیقت stopخط‌حاشیه \
-stopخط‌متن stopرنگ stopفشرده stopمحیط stopمنوی‌پانل \
-stopمولفه stopنسخه stopنقل‌قول stopپروژه stopپس‌زمینه \
-sub subject subsection subsubject subsubsection \
-subsubsubject synonym title tooltip txt \
-typ underbar underbars useJSscripts useURL \
-useXMLfilter usedirectory useurl آفست‌صفحه آیتم \
-آیتمها آینه اجباربلوکها ارتفاع‌آرایش ارتفاع‌بالا \
-ارتفاع‌برگ ارتفاع‌ته‌برگ ارتفاع‌خط ارتفاع‌سربرگ ارتفاع‌متن \
-ارتفاع‌پایین از ازکارانداختن‌منوی‌پانل استفاده‌بلوکها استفاده‌دستخط‌تایپ \
-استفاده‌رمزینه استفاده‌شکل‌خارجی استفاده‌فرمانها استفاده‌قطعه‌موزیک‌خارجی استفاده‌مدول \
-استفاده‌مدولها استفاده‌مرجعها استفاده‌مسیر استفاده‌نمادها استفاده‌نوشتارخارجی \
-استفاده‌ویژگیها استفاده‌پرونده‌خارجی استفاده‌پرونده‌دستخط‌تایپ استفاده‌پرونده‌های‌خارجی اعدادلاتین \
-افزودن اما امتحان‌نکن انتخاب‌برگ انتخاب‌بلوکها \
-انتخاب‌نسخه انتقال‌به‌توری انتقال‌فرمول انتقال‌کنار‌شناور انجام‌دوباره \
-بارگذاریها بارگذاری‌آرایش بارگذاری‌آیتمها بارگذاری‌ارجاع بارگذاری‌اندازه‌برگ \
-بارگذاری‌باریکتر بارگذاری‌بافر بارگذاری‌بالا بارگذاری‌بخش بارگذاری‌بردباری \
-بارگذاری‌برنامه‌ها بارگذاری‌برگ بارگذاری‌بست بارگذاری‌بلوک بارگذاری‌بلوکهای‌حاشیه \
-بارگذاری‌بلوک‌بخش بارگذاری‌تایپ بارگذاری‌تایپ‌کردن بارگذاری‌تب بارگذاری‌ترتیب \
-بارگذاری‌ترکیب‌ها بارگذاری‌تطابق بارگذاری‌تعریف‌پانوشت بارگذاری‌تنظیم بارگذاری‌تنظیم‌ریاضی \
-بارگذاری‌ته‌برگ بارگذاری‌تورفتگی بارگذاری‌توضیح بارگذاری‌توضیح‌صفحه بارگذاری‌ثبت \
-بارگذاری‌جانشانی بارگذاری‌جدولها بارگذاری‌جدول‌بندی بارگذاری‌خالی بارگذاری‌خروجی \
-بارگذاری‌خط بارگذاری‌خطها بارگذاری‌خطهای‌حاشیه بارگذاری‌خطهای‌سیاه بارگذاری‌خطهای‌متن \
-بارگذاری‌خطهای‌مجموعه‌ستون بارگذاری‌خطها‌ی‌نازک بارگذاری‌درج‌درخطها بارگذاری‌درج‌مخالف بارگذاری‌درون‌حاشیه \
-بارگذاری‌دوران بارگذاری‌دکمه‌ها بارگذاری‌راهنما بارگذاری‌رنگ بارگذاری‌رنگها \
-بارگذاری‌زبان بارگذاری‌ستونها بارگذاری‌سر بارگذاری‌سربرگ بارگذاری‌سرها \
-بارگذاری‌سیستم بارگذاری‌شرح بارگذاری‌شرحها بارگذاری‌شروع‌مجموعه‌ستون بارگذاری‌شروع‌پایان \
-بارگذاری‌شماره بارگذاری‌شماره‌زیرصفحه بارگذاری‌شماره‌سر بارگذاری‌شماره‌صفحه بارگذاری‌شماره‌گذاری \
-بارگذاری‌شماره‌گذاریها بارگذاری‌شماره‌گذاری‌صفحه بارگذاری‌شماره‌گذاری‌پاراگراف بارگذاری‌شماره‌‌گذاری‌خط بارگذاری‌شناور \
-بارگذاری‌شناورها بارگذاری‌شکافتن‌شناورها بارگذاری‌شکلهای‌خارجی بارگذاری‌طرح بارگذاری‌طرح‌بندی \
-بارگذاری‌عرض‌خط بارگذاری‌فاصله‌بین‌خط بارگذاری‌فرمولها بارگذاری‌فضای‌سفید بارگذاری‌فضا‌گذاری \
-بارگذاری‌قالبی بارگذاری‌قلم‌متن بارگذاری‌لوح بارگذاری‌لیست بارگذاری‌لیست‌ترکیبی \
-بارگذاری‌لیست‌مرجع بارگذاری‌مترادفها بارگذاری‌متغیر‌متن بارگذاری‌متن بارگذاری‌متنهای‌بالا \
-بارگذاری‌متن‌سر بارگذاری‌متن‌سربرگ بارگذاری‌متن‌قالبی بارگذاری‌متن‌متنها بارگذاری‌متن‌پانوشت \
-بارگذاری‌متن‌پایین بارگذاری‌مجموعه‌ستون بارگذاری‌مجموعه‌نماد بارگذاری‌محیط‌قلم‌متن بارگذاری‌منوی‌پانل \
-بارگذاری‌مکان‌متن بارگذاری‌مکان‌گذاری بارگذاری‌میدان بارگذاری‌میدانها بارگذاری‌میله‌تطابق \
-بارگذاری‌میله‌زیر بارگذاری‌میله‌پانل بارگذاری‌نسخه‌ها بارگذاری‌نشانه‌شکستن بارگذاری‌نشانه‌گذاری \
-بارگذاری‌نشرها بارگذاری‌نقل بارگذاری‌پاراگرافها بارگذاری‌پانل بارگذاری‌پانوشتها \
-بارگذاری‌پایین بارگذاری‌پرده‌ها بارگذاری‌پرده‌پانل بارگذاری‌پروفایلها بارگذاری‌پرکردن‌خطها \
-بارگذاری‌پس‌زمینه بارگذاری‌پس‌زمینه‌ها بارگذاری‌چیدن بارگذاری‌گذارصفحه بارگذاری‌گروههای‌آیتم \
-بارگذاری‌گروه‌آیتم بازنشانی بازنشانی‌شماره بازنشانی‌متن بازنشانی‌نشانه‌گذاری \
-باگذاری‌متن‌برچسب بدون‌بعد بدون‌بلوکهای‌بیشتر بدون‌تورفتگی بدون‌خط‌بالاوپایین \
-بدون‌خط‌سروته‌برگ بدون‌فایلهای‌بیشتر بدون‌فضا بدون‌فضای‌سفید بدون‌لیست \
-بدون‌نشانه‌گذاری برنامه بروبه بروبه‌جعبه بروبه‌صفحه \
-بروپایین برچسب برچسبها بعد بلند \
-بلوکهای‌پردازش بلوکها‌پنهان بنویس‌بین‌لیست بنویس‌درثبت بنویس‌درلیست‌مرجع \
-بنویس‌در‌لیست تاریخ تاریخ‌جاری تاریخ‌رجوع تایپ \
-تایپ‌بافر تایپ‌پرونده تب ترجمه تطابق \
-تعریف تعریف‌آرایش تعریف‌آرم تعریف‌الگوی‌جدول تعریف‌اندازه‌برگ \
-تعریف‌بافر تعریف‌بخش تعریف‌برنامه تعریف‌برچسب تعریف‌بلوک \
-تعریف‌بلوک‌بخش تعریف‌تایپ تعریف‌تایپ‌کردن تعریف‌تبدیل تعریف‌ترتیب \
-تعریف‌ترکیب تعریف‌تنظیم‌ریاضی تعریف‌توده‌میدان تعریف‌ثبت تعریف‌جانشانی \
-تعریف‌جدول‌بندی تعریف‌جعبه‌‌افقی تعریف‌حرف تعریف‌خالی تعریف‌خروجی \
-تعریف‌خط‌حائل تعریف‌درون‌حاشیه تعریف‌رنگ تعریف‌زیرمیدان تعریف‌سبک \
-تعریف‌سبک‌قلم تعریف‌سر تعریف‌شرح تعریف‌شروع‌پایان تعریف‌شماره‌بندی \
-تعریف‌شمایل‌مرجع تعریف‌شناور تعریف‌شکستن‌ستون تعریف‌شکست‌صفحه تعریف‌طرح‌بندی \
-تعریف‌فرمان تعریف‌قالبی تعریف‌قلم تعریف‌قلم‌خام تعریف‌قلم‌متن \
-تعریف‌لایه تعریف‌لهجه تعریف‌لوح تعریف‌لیست تعریف‌لیست‌ترکیبی \
-تعریف‌لیست‌مرجع تعریف‌مترادفها تعریف‌مترادف‌قلم تعریف‌متغیرمتن تعریف‌متن \
-تعریف‌متن‌قالبی تعریف‌مجموعه‌ستون تعریف‌محیط‌قلم‌بدنه تعریف‌مرجع تعریف‌منوی‌پانل \
-تعریف‌مکان‌متن تعریف‌میدان تعریف‌میدان‌اصلی تعریف‌نسخه تعریف‌نشانه‌گذاری \
-تعریف‌نماد تعریف‌نمادشکل تعریف‌پاراگرافها تعریف‌پروفایل تعریف‌پوشش \
-تعریف‌گروه‌آیتم تعریف‌گروه‌رنگ تعیین‌شماره تعیین‌شماره‌سر تعیین‌متغیر‌متن \
-تعیین‌محتوای‌متن تعیین‌مشخصات‌ثبت تعیین‌مشخصات‌لیست تغییربه‌قلم‌بدنه تغییربه‌قلم‌خام \
-تنظیم‌راست تنظیم‌طرح‌بندی تنظیم‌وسط توجه تورفتگی \
-توری تولید تک ثبت‌زوج ثبت‌کامل \
-جداسازی‌نشانه‌گذاری حاش حرف حرفها حفظ‌بلوکها \
-حقیقت خالی خطهای‌سیاه خطهای‌نازک خطها‌خالی \
-خط‌حاشیه خط‌سیاه خط‌متن خط‌مو خط‌نازک \
-خ‌ا خ‌ع در درج‌آرمها درج‌ثبت \
-درج‌خط درج‌درخط درج‌درخطها درج‌درمتن درج‌درمیدان \
-درج‌در‌بالای‌یکدیگر درج‌در‌توری درج‌راهنما درج‌زیرفرمول درج‌شماره‌سر \
-درج‌شماره‌صفحه درج‌شناور درج‌فرمول درج‌لیست درج‌لیست‌خام \
-درج‌لیست‌مختلط درج‌لیست‌مرجع درج‌متغیرمتن درج‌متن‌سر درج‌پانوشتها \
-درج‌پانوشتهای‌موضعی درج‌چوب‌خط درج‌کنار‌به‌کنار درحاشیه درحاشیه‌دیگر \
-درحاشیه‌راست درحاشیه‌چپ درخارجی درخط درداخلی \
-درراست درصفحه درقالبی درلبه‌راست درلبه‌چپ \
-درمورد درون درپر درچپ دریافت‌بافر \
-دریافت‌شماره دریافت‌نشانه دوران دکمه دکمه‌منو \
-دکمه‌پانل رج رجوع رنگ رنگ‌خاکستری \
-روزهفته ریاضی زبان زبان‌اصلی ستون \
-ستون‌امتحان سر سرپوش‌کوچک‌نه شروع‌آرایش شروع‌آرایش‌ستون \
-شروع‌باریکتر شروع‌بازبینی شروع‌بلوک‌حاشیه شروع‌ترکیب شروع‌تصحیح‌خط \
-شروع‌تطابق شروع‌تنظیم شروع‌تولید شروع‌جدول شروع‌جدولها \
-شروع‌خط شروع‌خطها شروع‌خط‌حاشیه شروع‌خط‌متن شروع‌رنگ \
-شروع‌ستونها شروع‌سراسری شروع‌شماره‌گذاری‌خط شروع‌شکل شروع‌غیر‌فشرده \
-شروع‌فشرده شروع‌متن شروع‌مجموعه‌ستون شروع‌مجموعه‌نماد شروع‌محیط \
-شروع‌مخالف شروع‌موضعی شروع‌مولفه شروع‌مکان‌گذاری شروع‌نسخه \
-شروع‌نقل‌قول شروع‌نوشتار شروع‌پانوشتهای‌موضعی شروع‌پروفایل شروع‌پروژه \
-شروع‌پس‌زمینه شروع‌پوشش شروع‌کد شماره‌افزایش شماره‌زیرصفحه \
-شماره‌زیرفرمول شماره‌سر شماره‌سرجاری شماره‌صفحه شماره‌صفحه‌کامل \
-شماره‌فرمول شماره‌مبدل شماره‌ها شماره‌کاهش شماره‌کل‌صفحه‌ها \
-شکافتن‌شناور شکل‌خارجی صفحه صفحه‌تست صفحه‌زوج \
-صفحه‌پردازش طول‌لیست عبوربلوکها عرض‌آرایش عرض‌برگ \
-عرض‌حاشیه عرض‌حاشیه‌خارجی عرض‌حاشیه‌داخلی عرض‌حاشیه‌راست عرض‌حاشیه‌چپ \
-عرض‌خط عرض‌لبه عرض‌لبه‌خارجی عرض‌لبه‌داخلی عرض‌لبه‌راست \
-عرض‌لبه‌چپ عرض‌لیست عرض‌متن عمق‌صفحه عنوان‌حاشیه \
-فاصله‌بالا فاصله‌ته‌برگ فاصله‌حاشیه فاصله‌حاشیه‌خارجی فاصله‌حاشیه‌داخلی \
-فاصله‌حاشیه‌راست فاصله‌حاشیه‌چپ فاصله‌سربرگ فاصله‌لبه فاصله‌لبه‌خارجی \
-فاصله‌لبه‌داخلی فاصله‌لبه‌راست فاصله‌لبه‌چپ فاصله‌پایین فاصله‌پشت \
-فشرده فضا فضاهای‌ثابت فضای‌بالا فضای‌برش \
-فضای‌ثابت فضای‌سفید فضای‌سفیدصحیح فضای‌پایین فوری‌به‌لیست \
-فوری‌بین‌لیست قالبی لوح‌مقایسه ماه متغیر متن \
-متن‌برچسب متن‌حاشیه متن‌سر متن‌پانوشت محیط \
-مراجعه مرجع مرجع‌صفحه مرجع‌متن مرحله‌سر \
-مسکن معنی‌واحد مقایسه‌گروه‌رنگ مقدارخاکستری مقداررنگ \
-مقیاس منفی منوی‌پانل مولفه مکان \
-مکان‌متن میدان میدانهای‌گزارش میدان‌شبیه‌سازی میدان‌پشته \
-میدان‌کپی میله‌تطابق میله‌رنگ میله‌پانل ناشناس \
-نام‌ماکرو نسخه نسخه‌نشانه نشانه‌گذاری نشانه‌گذاری‌زوج \
-نشر نصب‌زبان نقطه‌ها نقل نقل‌قول \
-نم نماد نمادسر نمادلیست نمایش‌آرایش \
-نمایش‌بارگذاریها نمایش‌بستها نمایش‌توری نمایش‌رنگ نمایش‌شکلهای‌خارجی \
-نمایش‌طرح‌بندی نمایش‌قالب نمایش‌قلم‌بدنه نمایش‌لوح نمایش‌مجموعه‌علامت \
-نمایش‌محیط‌قلم‌بدنه نمایش‌میدانها نمایش‌چاپ نمایش‌گروه‌رنگ نوشتارزوج \
-هدایت پا پابا پانوشت پایان‌آرایش \
-پایان‌آرایش‌ستون پایان‌بازبینی پایان‌بلوک‌حاشیه پایان‌ترکیب پایان‌تصحیح‌خط \
-پایان‌تطابق پایان‌تنظیم پایان‌تولید پایان‌جدول پایان‌جدولها \
-پایان‌خط پایان‌خطها پایان‌خط‌حاشیه پایان‌خط‌متن پایان‌رنگ \
-پایان‌ستونها پایان‌سراسری پایان‌شماره‌گذاری‌خط پایان‌غیرفشرده پایان‌فشرده \
-پایان‌متن پایان‌مجموعه‌ستون پایان‌محیط پایان‌مخالف پایان‌موضعی \
-پایان‌مولفه پایان‌مکان‌گذاری پایان‌نازکتر پایان‌نسخه پایان‌نقل‌قول \
-پایان‌نوشتار پایان‌پانوشتهای‌موضعی پایان‌پروفایل پایان‌پروژه پایان‌پس‌زمینه \
-پایان‌پوشش پایان‌کد پایین پرده پروژه \
-پرکردن‌میدان پس‌زمینه پیروی‌نسخه پیروی‌نسخه‌پروفایل پیروی‌پروفایل \
-چاپ‌ارتفاع‌برگ چاپ‌عرض‌برگ چوبخط چپ‌چین کاغذزوج \
-کسر کشیده کلمه‌حاشیه کلمه‌راست گیره \
-یادداشت یک‌جا یک‌خط
-
keywordclass.context.de=\
Buchstabe Buchstaben CAP Cap \
Caps KAP Kap Kaps MONAT \
@@ -633,6 +480,316 @@ zeigegitter zeigelayout zeigepalette zeigerahmen zeigestruts \
zeigeumbruch zentriert ziffern zitat zitieren \
zu zurbox zurseite zwischenraum
+keywordclass.context.en=\
+CAP Cap Caps Character \
+Characters MONTH Numbers Romannumerals WEEKDAY \
+WORD WORDS Word Words about \
+adaptlayout adding appendix arg at \
+atleftmargin atpage atrightmargin background backspace \
+blackrule blackrules blank bookmark bottomdistance \
+bottomheight bottomspace but button bypassblocks \
+cap chapter character characters chem \
+clip clonefield color colorbar colorvalue \
+column comment comparecolorgroup comparepalet completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms completepagenumber completeregister \
+component convertnumber copyfield correctwhitespace coupledocument \
+coupledregister couplemarking couplepage couplepaper coupleregister \
+crlf currentdate currentheadnumber cutspace date \
+decouplemarking decrementnumber define defineaccent defineblank \
+defineblock definebodyfont definebodyfontDEF definebodyfontREF definebodyfontenvironment \
+definebuffer definecharacter definecolor definecolorgroup definecolumnbreak \
+definecolumnset definecombination definecombinedlist definecommand defineconversion \
+definedescription definedfont defineenumeration definefield definefieldstack \
+definefiguresymbol definefloat definefont definefontfeature definefonthandling \
+definefontstyle definefontsynonym defineframed defineframedtext definehbox \
+definehead defineindentedtext defineinmargin defineinteractionmenu defineitemgroup \
+definelabel definelayer definelayout definelist definelogo \
+definemainfield definemakeup definemarking definemathalignment defineoutput \
+defineoverlay definepagebreak definepalet definepapersize defineparagraphs \
+defineplacement defineprofile defineprogram definerawfont definereference \
+definereferenceformat definereferencelist defineregister definerule definesection \
+definesectionblock definesorting definestartstop definestyle definesubfield \
+definesymbol definesynonyms definetabletemplate definetabulate definetext \
+definetextposition definetextvariable definetype definetypeface definetyping \
+defineversion description determineheadnumber determinelistcharacteristics determineregistercharacteristics \
+dimension disableinteractionmenu domicile donttest edgedistance \
+edgewidth emptylines enumeration environment externalfigure \
+fact field fieldstack fillinfield fillinline \
+fillinrules fillintext fitfield fixedspace fixedspaces \
+followprofile followprofileversion followversion footerdistance footerheight \
+footnote footnotetext forceblocks formulanumber fraction \
+framed framedtext from getbuffer getmarking \
+getnumber godown goto gotobox gotopage \
+graycolor greyvalue grid hairline head \
+headerdistance headerheight headlevel headnumber headsym \
+headtext hideblocks high hl immediatebetweenlist \
+immediatetolist in incrementnumber indentation indenting \
+inframed infull ininner inleft inleftedge \
+inleftmargin inline inmaframed inmargin inneredgedistance \
+inneredgewidth innermargindistance innermarginwidth inothermargin inouter \
+inright inrightedge inrightmargin installlanguage interactionbar \
+interactionbuttons interactionmenu item items its \
+keepblocks label labeling labels labeltext \
+language leftaligned leftedgedistance leftedgewidth leftmargindistance \
+leftmarginwidth leg linethickness listheight listlength \
+listsymbol listwidth loadsorts loadsynonyms logfields \
+lohi low maframed mainlanguage makeupheight \
+makeupwidth mapfontsize mar margindistance marginrule \
+margintext margintitle marginwidth marginword marking \
+markversion mathematics mediaeval menubutton midaligned \
+mirror month moveformula moveongrid movesidefloat \
+name navigating nextsection nocap nodimension \
+noheaderandfooterlines noindenting nolist nomarking nomoreblocks \
+nomorefiles nop nospace note notopandbottomlines \
+nowhitespace numberofsubpages numbers outeredgedistance outeredgewidth \
+outermargindistance outermarginwidth overbar overbars overstrike \
+overstrikes packed page pagedepth pagenumber \
+pageoffset pagereference paperheight paperwidth paragraph \
+part periods placebookmarks placecombinedlist placefloat \
+placefootnotes placeformula placeheadnumber placeheadtext placelegend \
+placelist placelistoffloats placelistofsorts placelistofsynonyms placelocalfootnotes \
+placelogos placeongrid placeontopofeachother placepagenumber placerawlist \
+placereferencelist placeregister placerule placesidebyside placesubformula \
+placetextvariable position positiontext printpaperheight printpaperwidth \
+processblocks processpage product program project \
+publication quotation quote ran redo \
+ref reference referral referraldate referring \
+register remark reservefloat reset resetmarking \
+resetnumber resettextcontent rightaligned rightedgedistance rightedgewidth \
+rightmargindistance rightmarginwidth romannumerals rotate scale \
+screen section seeregister selectblocks selectpaper \
+selectversion setnumber settextcontent settextvariable setupalign \
+setupanswerarea setuparranging setupbackground setupbackgrounds setupblackrules \
+setupblank setupblock setupbodyfont setupbodyfontenvironment setupbottom \
+setupbottomtexts setupbuffer setupbuttons setupcapitals setupcaption \
+setupcaptions setupclipping setupcolor setupcolors setupcolumns \
+setupcolumnset setupcolumnsetlines setupcolumnsetstart setupcombinations setupcombinedlist \
+setupcomment setupdescriptions setupenumerations setupexternalfigures setupfield \
+setupfields setupfillinlines setupfillinrules setupfloat setupfloats \
+setupfloatsplitting setupfonthandling setupfontsynonym setupfooter setupfootertexts \
+setupfootnotedefinition setupfootnotes setupforms setupformulae setupframed \
+setupframedtexts setuphead setupheader setupheadertexts setupheadnumber \
+setupheads setupheadtext setuphyphenmark setupindentedtext setupindenting \
+setupinmargin setupinteraction setupinteractionbar setupinteractionmenu setupinteractionscreen \
+setupinterlinespace setupinterlinespace2 setupitemgroup setupitemizations setupitems \
+setuplabeltext setuplanguage setuplayout setuplegend setuplinenumbering \
+setuplines setuplinewidth setuplist setuplistalternative setupmakeup \
+setupmarginblocks setupmarginrules setupmarking setupmathalignment setupnarrower \
+setupnumber setupnumbering setupoppositeplacing setupoutput setuppagecomment \
+setuppagenumber setuppagenumbering setuppagetransitions setuppalet setuppaper \
+setuppapersize setupparagraphnumbering setupparagraphs setupplacement setuppositioning \
+setupprofiles setupprograms setuppublications setupquote setupreferencelist \
+setupreferencing setupregister setuprotate setuprule setups \
+setupscreens setupsection setupsectionblock setupsorting setupspacing \
+setupstartstop setupstrut setupsubpagenumber setupsymbolset setupsynchronization \
+setupsynchronizationbar setupsynonyms setupsystem setuptab setuptables \
+setuptabulate setuptext setuptextposition setuptextrules setuptexttexts \
+setuptextvariable setupthinrules setuptolerance setuptop setuptoptexts \
+setuptype setuptyping setupunderbar setupurl setupversions \
+setupwhitespace showbodyfont showbodyfontenvironment showcolor showcolorgroup \
+showexternalfigures showfields showframe showgrid showlayout \
+showmakeup showpalet showprint showsetups showstruts \
+showsymbolset someline somewhere sort space \
+splitfloat startalignment startbackground startbuffer startcoding \
+startcolor startcolumnmakeup startcolumns startcolumnset startcombination \
+startcomment startcomponent startdescription startdocument startenumeration \
+startenvironment startfact startfigure startfloattext startformula \
+startframedtext startglobal starthiding startinteractionmenu startitemgroup \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startmarginrule startnamemakeup startnarrower startopposite startoverlay \
+startoverview startpacked startparagraph startpositioning startpostponing \
+startproduct startprofile startproject startquotation startraster \
+startregister startsymbolset startsynchronization starttable starttables \
+starttabulate starttext starttextrule starttyping startunpacked \
+startversion stopalignment stopbackground stopbuffer stopcoding \
+stopcolor stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
+stopcomment stopcomponent stopdescription stopdocument stopenumeration \
+stopenvironment stopfact stopfigure stopfloattext stopformula \
+stopframedtext stopglobal stophiding stopinteractionmenu stopitemgroup \
+stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
+stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
+stopmarginrule stopnamemakeup stopnarrower stopopposite stopoverlay \
+stopoverview stoppacked stopparagraph stoppositioning stoppostponing \
+stopproduct stopprofile stopproject stopquotation stopraster \
+stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
+stoptext stoptextrule stoptyping stopunpacked stopversion \
+stretched sub subformulanumber subject subpagenumber \
+subsection subsubject subsubsection subsubsubject switchtobodyfont \
+switchtorawfont sym symbol symoffset synchronizationbar \
+synchronize synonym tab testcolumn testpage \
+tex textheight textreference textrule textvariable \
+textwidth thinrule thinrules title tooltip \
+topdistance topheight topspace totalnumberofpages translate \
+txt typ type typebuffer typefile \
+underbar underbars unitmeaning unknown useJSscripts \
+useURL useXMLfilter useblocks usecommands usedirectory \
+useencoding useexternaldocument useexternalfigure useexternalfile useexternalfiles \
+useexternalsoundtrack usemodule usemodules usereferences usespecials \
+usesymbols usetypescript usetypescriptfile useurl version \
+vl weekday whitespace wordright writebetweenlist \
+writetolist writetoreferencelist writetoregister
+
+keywordclass.context.nl=\
+CAP Cap Caps Cijfers \
+KAP Kap Kaps Letter Letters \
+MAAND Romeins WEEKDAG WOORD WOORDEN \
+Woord Woorden aantalsubpaginas about achtergrond \
+appendix arg bepaalkopnummer bepaallijstkenmerken bepaalregisterkenmerken \
+betekenis binnenmargeafstand binnenmargebreedte binnenrandafstand binnenrandbreedte \
+blanko blokje blokjes blokkeerinteractiemenu bodemwit \
+bookmark bovenafstand bovenhoogte breuk buitenmargeafstand \
+buitenmargebreedte buitenrandafstand buitenrandbreedte but button \
+cap chapter chem cijfers citaat \
+citeer clip comment completecombinedlist completelistoffloats \
+completelistofsorts completelistofsynonyms converteernummer copieerveld corrigeerwitruimte \
+coupledregister crlf datum definebodyfontDEF definebodyfontREF \
+definedfont definefontfeature definefonthandling definerawfont definetypeface \
+definieer definieeraccent definieeralineas definieerbeeldmerk definieerblanko \
+definieerblok definieerbuffer definieercombinatie definieercommando definieerconversie \
+definieerfiguursymbool definieerfont definieerfontstijl definieerfontsynoniem definieerhbox \
+definieerhoofdveld definieeringesprongentext definieerinmarge definieerinteractiemenu definieeritemgroep \
+definieerkadertekst definieerkarakter definieerkleur definieerkleurgroep definieerkolomgroep \
+definieerkolomovergang definieerkop definieerkorps definieerkorpsomgeving definieerlayer \
+definieerlayout definieerletter definieerlijn definieerlijst definieermarkering \
+definieeromlijnd definieeropmaak definieeroverlay definieerpaginaovergang definieerpalet \
+definieerpapierformaat definieerplaats definieerplaatsblok definieerprofiel definieerprogramma \
+definieerreferentie definieerreferentieformaat definieerreferentielijst definieerregister definieersamengesteldelijst \
+definieersectie definieersectieblok definieersorteren definieerstartstop definieersubveld \
+definieersymbool definieersynoniemen definieertabelvorm definieertabulatie definieertekst \
+definieertekstpositie definieertekstvariabele definieertype definieertypen definieeruitvoer \
+definieerveld definieerveldstapel definieerversie definieerwiskundeuitlijnen description \
+dimensie directnaarlijst directtussenlijst doordefinieren doorlabelen \
+doornummeren dunnelijn dunnelijnen eenregel enumeration \
+ergens externfiguur forceerblokken formulenummer framedtext \
+gebruikJSscripts gebruikURL gebruikXMLfilter gebruikblokken gebruikcommandos \
+gebruikexterndocument gebruikexternefile gebruikexternefiles gebruikexternfiguur gebruikexterngeluidsfragment \
+gebruikgebied gebruikmodule gebruikmodules gebruikreferenties gebruikspecials \
+gebruiksymbolen gebruiktypescript gebruiktypescriptfile gebruikurl geenblokkenmeer \
+geenbovenenonderregels geendimensie geenfilesmeer geenhoofdenvoetregels geenlijst \
+geenmarkering geenspatie geentest geenwitruimte geg \
+grijskleur grijswaarde haalbuffer haalmarkering haalnummer \
+haarlijn handhaafblokken herhaal hl hoofdafstand \
+hoofdhoogte hoofdtaal hoog huidigedatum huidigekopnummer \
+in inanderemarge inbinnen inbuiten indentation \
+inlijnd inlinker inlinkermarge inlinkerrand inmarge \
+inrechter inrechtermarge inrechterrand inregel inspringen \
+installeertaal instellingen interactiebalk interactiebuttons interactiemenu \
+invullijnen invulregel invultekst invulveld inwilijnd \
+items its kantlijn kap kenmerk \
+kenmerkdatum kentekstvariabeletoe kleur kleurenbalk kleurwaarde \
+kloonveld kolom kop kopniveau kopnummer \
+koppeldocument koppelmarkering koppelpagina koppelpapier koppelregister \
+kopsym koptekst kopwit laag label \
+labeling labels labeltekst laho leg \
+legeregels letter letters lijndikte lijstbreedte \
+lijsthoogte lijstlengte lijstsymbool linkermargeafstand linkermargebreedte \
+linkerrandafstand linkerrandbreedte loadsorts loadsynonyms maand \
+mapfontsize mar margeafstand margebreedte margetekst \
+margetitel margewoord markeer markeerversie mediaeval \
+menubutton naam naar naarbox naarpagina \
+name navigerend nextsection nietinspringen nocap \
+nokap noot nop omgeving omlaag \
+omlijnd onbekend onderafstand onderdeel onderhoogte \
+ontkoppelmarkering op opelkaar oplinkermarge oppagina \
+oprechtermarge overbar overbars overstrike overstrikes \
+pagina paginadiepte paginanummer paginaoffset paginareferentie \
+papierbreedte papierhoogte paragraph part paslayoutaan \
+passeerblokken passendveld plaatsbeeldmerken plaatsbookmarks plaatsformule \
+plaatskopnummer plaatskoptekst plaatslegenda plaatslijn plaatslijst \
+plaatslokalevoetnoten plaatsnaastelkaar plaatsonderelkaar plaatsopgrid plaatspaginanummer \
+plaatsplaatsblok plaatsreferentielijst plaatsregister plaatsruwelijst plaatssamengesteldelijst \
+plaatssubformule plaatstekstvariabele plaatsvoetnoten placelistoffloats placelistofsorts \
+placelistofsynonyms positioneer positioneertekst printpapierbreedte printpapierhoogte \
+produkt programma projekt publicatie punten \
+ran randafstand randbreedte rechtermargeafstand rechtermargebreedte \
+rechterrandafstand rechterrandbreedte ref refereer referentie \
+regellinks regelmidden regelrechts register registreervelden \
+reservefloat reset resetmarkering resetnummer resettekstinhoud \
+resettextcontent romeins rooster roteer rugwit \
+schaal scherm schrijfnaarlijst schrijfnaarreferentielijst schrijfnaarregister \
+schrijftussenlijst section seeregister selecteerblokken selecteerpapier \
+selecteerversie setnummer setupfonthandling setupfontsynonym setupinterlinespace2 \
+setuplistalternative snijwit som sort spatie \
+spiegel splitsplaatsblok startachtergrond startalignment startbuffer \
+startcitaat startcodering startcolumns startcombinatie startcombination \
+startcomment startdescription startdocument startenumeration startfigure \
+startfiguur startfloattext startformula startframedtext startgeg \
+startglobaal starthiding startinteractiemenu startitemgroup startkantlijn \
+startkleur startkolomgroep startkolommen startkolomopmaak startlegend \
+startline startlinecorrection startlinenumbering startlines startlocal \
+startlocalenvironment startlocalfootnotes startlokaal startlokalevoetnoten startmakeup \
+startmargeblok startmarginblock startnaast startnamemakeup startnarrower \
+startomgeving startonderdeel startopelkaar startopmaak startopposite \
+startoverlay startoverview startoverzicht startparagraph startpositioneren \
+startpositioning startpostponing startprodukt startprofiel startprofile \
+startprojekt startraster startregel startregelcorrectie startregelnummeren \
+startregels startregister startsmaller startsymbolset startsymboolset \
+startsynchronisatie startsynchronization starttabel starttabellen starttable \
+starttables starttabulate starttekst starttekstlijn starttyping \
+startuitlijnen startunpacked startvanelkaar startversie stelachtergrondenin \
+stelachtergrondin stelalineasin stelantwoordgebiedin stelarrangerenin stelblankoin \
+stelblokin stelblokjesin stelblokkopjein stelblokkopjesin stelbovenin \
+stelboventekstenin stelbufferin stelbuttonsin stelciterenin stelclipin \
+stelcombinatiesin stelcommentaarin steldoordefinierenin steldoornummerenin steldunnelijnenin \
+stelexternefigurenin stelformulesin stelformulierenin stelhoofdin stelhoofdtekstenin \
+stelingesprongentextin stelinmargein stelinspringenin stelinteractiebalkin stelinteractiein \
+stelinteractiemenuin stelinteractieschermin stelinterliniein stelinvullijnenin stelinvulregelsin \
+stelitemgroepin stelitemsin stelkadertekstenin stelkantlijnin stelkapitalenin \
+stelkleurenin stelkleurin stelkolomgroepin stelkolomgroepregelsin stelkolomgroepstartin \
+stelkolommenin stelkopin stelkopnummerin stelkoppeltekenin stelkoppenin \
+stelkoptekstin stelkorpsin stelkorpsomgevingin stellabeltekstin stellayoutin \
+stellegendain stellijndiktein stellijnin stellijstin stelmargeblokkenin \
+stelmarkeringin stelnaastplaatsenin stelnummerenin stelnummerin stelomlijndin \
+stelonderin stelonderstrepenin stelondertekstenin stelopmaakin stelopsommingenin \
+stelpaginacommentaarin stelpaginanummerin stelpaginanummeringin stelpaginaovergangenin stelpaletin \
+stelpapierformaatin stelpapierin stelparagraafnummerenin stelplaatsblokin stelplaatsblokkenin \
+stelplaatsbloksplitsenin stelplaatsin stelpositionerenin stelprofielenin stelprogrammasin \
+stelpublicatiesin stelrastersin stelreferentielijstin stelrefererenin stelregelnummerenin \
+stelregelsin stelregisterin stelroterenin stelsamengesteldelijstin stelsectieblokin \
+stelsectiein stelsmallerin stelsorterenin stelspatieringin stelstartstopin \
+stelstrutin stelsubpaginanummerin stelsymboolsetin stelsynchronisatiebalkin stelsynchronisatiein \
+stelsynoniemenin stelsysteemin steltaalin steltabellenin steltabin \
+steltabulatiein steltekstin steltekstinhoudin steltekstlijnenin steltekstpositiein \
+stelteksttekstenin steltekstvariabelein steltolerantiein steltypein steltypenin \
+steluitlijnenin steluitvoerin stelurlin stelveldenin stelveldin \
+stelversiesin stelvoetin stelvoetnootdefinitiein stelvoetnotenin stelvoettekstenin \
+stelwiskundeuitlijnenin stelwitruimtein stopachtergrond stopalignment stopbuffer \
+stopcitaat stopcodering stopcolumns stopcombinatie stopcombination \
+stopcomment stopdescription stopdocument stopenumeration stopfigure \
+stopfloattext stopformula stopframedtext stopgeg stopglobaal \
+stophiding stopinteractiemenu stopitemgroup stopkantlijn stopkleur \
+stopkolomgroep stopkolommen stopkolomopmaak stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
+stoplocalfootnotes stoplokaal stoplokalevoetnoten stopmakeup stopmargeblok \
+stopmarginblock stopnaast stopnamemakeup stopnarrower stopomgeving \
+stoponderdeel stopopelkaar stopopmaak stopopposite stopoverlay \
+stopoverview stopoverzicht stopparagraph stoppositioneren stoppositioning \
+stoppostponing stopprodukt stopprofiel stopprofile stopprojekt \
+stopraster stopregel stopregelcorrectie stopregelnummeren stopregels \
+stopsmaller stopsymbolset stopsynchronisatie stopsynchronization stoptabel \
+stoptabellen stoptable stoptables stoptabulate stoptekst \
+stoptekstlijn stoptyping stopuitlijnen stopunpacked stopvanelkaar \
+stopversie sub subformulenummer subject subpaginanummer \
+subsection subsubject subsubsection subsubsubject suggestie \
+switchnaarkorps switchtorawfont sym symbool symoffset \
+synchronisatiebalk synchroniseer synonym taal tab \
+tekstbreedte teksthoogte tekstlijn tekstreferentie tekstvariabele \
+testkolom testpagina tex title toelichting \
+toonexternefiguren toongrid tooninstellingen toonkader toonkleur \
+toonkleurgroep toonkorps toonkorpsomgeving toonlayout toonopmaak \
+toonpalet toonprint toonstruts toonsymboolset toonvelden \
+totaalaantalpaginas txt typ type typebuffer \
+typefile uit uitgerekt underbar underbars \
+usecodering usedirectory vastespatie vastespaties veld \
+veldstapel verbergblokken vergelijkkleurgroep vergelijkpalet verhoognummer \
+verlaagnummer verplaatsformule verplaatsopgrid verplaatszijblok versie \
+vertaal verwerkblokken verwerkpagina vl voetafstand \
+voethoogte voetnoot voetnoottekst volgprofiel volgprofielversie \
+volgversie volledigepaginanummer volledigregister voluit weekdag \
+wilijnd wiskunde witruimte woonplaats woordrechts \
+zetbreedte zethoogte
+
keywordclass.context.ro=\
CAP CUVANT CUVINTE Cap \
Caps Cuvant Cuvinte KAP Kap \
@@ -791,325 +948,168 @@ urmeazaversiune urmeazaversiuneprofil useXMLfilter usedirectory usetypescript \
usetypescriptfile valoareculoare valoaregri variabilatext versiune \
vl zidinsaptamana
-keywordclass.context.cs=\
-CAP Cap Caps Cisla \
-KAP Kap Kaps MESIC Rimskecislice \
-SLOVA SLOVO Slova Slovo VSEDNIDEN \
-Znak Znaky aktualnicislonadpisu aktualnidatum appendix \
-arg atleftmargin atrightmargin barevnalista barva \
-bilemisto bottomspace bublinkovanapoveda bydliste bypassblocks \
-cap celkovypocetstran cernalinka cernelinky chapter \
-chem cisla cislonadpisu cislopodrovnice cislorovnice \
-cislostrany citace citovat comment completecombinedlist \
-completelistoffloats completelistofsorts completelistofsynonyms completepagenumber completeregister \
-coupledregister crlf cutspace datum decrementnumber \
-definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset definecombination \
-definedfont definefontfeature definefonthandling defineindentedtext defineinmargin \
-defineitemgroup definelayer definelayout definemathalignment definepagebreak \
-defineplacement definerawfont definerule definetextposition definetextvariable \
-definetype definetypeface definuj definujakcent definujbarvu \
-definujblok definujbloksekce definujbuffer definujfont definujformatodkazu \
-definujhbox definujhlavnipole definujinterakcnimenu definujkombinovanyseznam definujkonverzi \
-definujlogo definujnadpis definujobrazeksymbol definujodkaz definujodstavce \
-definujopis definujoramovani definujoramovanytext definujpaletu definujplvouciobjekt \
-definujpodpole definujpole definujpopis definujpopisek definujprekryv \
-definujpreskok definujprikaz definujprofil definujprogram definujprostredizakladnihofontu \
-definujrejstrik definujsablonutabulky definujsekci definujseznam definujseznamodkazu \
-definujskupinubarev definujstartstop definujstyl definujstylfontu definujsymbol \
-definujsynonumumfontu definujsynonyma definujtabelaci definujtext definujtrideni \
-definujupravu definujvelikostpapiru definujverzi definujvycet definujvystup \
-definujzakladnifont definujzasobnikpoli definujznaceni definujznak delkaseznamu \
-description dodrzujprofil dodrzujverzi dodrzujverziprofilu dvoustrannypapir \
-emptylines enumeration externiobraz fakt footnotetext \
-forceblocks framedtext getnumber headsym hl \
-hlavnijazyk hlavniuroven hodnotabarvy hodnotasedi immediatebetweenlist \
-immediatetolist indentation ininner inneredgedistance inneredgewidth \
-innermargindistance innermarginwidth inouter instalacejazyka interakcnilista \
-interakcnitlacitka interaktivnimenu jazyk jdidolu jdina \
-jdinabox jdinastranu jmeno kap klonujpole \
-komponenta konvertujcislo kopirujpole korekcebilehomista labeling \
-leg listsymbol loadsorts loadsynonyms maoramovani \
-mapfontsize marginalnilinka marginalninadpis marginalnislovo marginalnitext \
-matematika mazaramovani mediaeval meritko mesic \
-mezera moveformula movesidefloat mrizka nadpis \
-nadruhyokraj nalevo nalevyokraj name naokraj \
-napravo napravyokraj nastavbarvu nastavbarvy nastavbilamista \
-nastavblok nastavbloksekce nastavbuffer nastavcernelinky nastavcislonadpisu \
-nastavcislostrany nastavcislovani nastavcislovaniodstavcu nastavcislovaniradku nastavcislovanistran \
-nastavcitaci nastavdefinicipoznamekpodcarou nastavdeleniplvoucichobjektu nastavdelitko nastavdolnitexty \
-nastaveni nastavexterniobrazy nastavhorejsek nastavhornitexty nastavinterakci \
-nastavinterakcnilistu nastavinterakcnimenu nastavinterakcniobrazovku nastavjazyk nastavkapitalky \
-nastavkombinovanyseznam nastavkomentar nastavkomentarstrany nastavlegendu nastavmarginalie \
-nastavmarginalniblok nastavmarginalnilinky nastavmeziradkovoumezeru nastavnadpis nastavnadpisy \
-nastavodkazovani nastavodsazovani nastavodstavce nastavopis nastavoramovanetexty \
-nastavoramovani nastavorez nastavotoceni nastavpaletu nastavplvouciobjekt \
-nastavplvouciobjekty nastavpodcislostrany nastavpodtrzeni nastavpole nastavpolozky \
-nastavpopisek nastavpopisky nastavpopisy nastavpozadi nastavpoznamkypodcarou \
-nastavprechodstrany nastavpreskok nastavprofily nastavprogramy nastavprostredizakladnihofontu \
-nastavpublikace nastavradkovani nastavradky nastavrastr nastavrejstrik \
-nastavrovnice nastavsadusymbolu nastavsekci nastavseznam nastavseznamodkazu \
-nastavsirkucary nastavsloupce nastavspodek nastavspojeni nastavsynchronizaci \
-nastavsynchronizacnilistu nastavsynonyma nastavsystem nastavtab nastavtabelaci \
-nastavtabulky nastavtenkelinky nastavtext nastavtexthlavicky nastavtextovelinky \
-nastavtextpopisku nastavtexttexty nastavtextyupati nastavtextyzahlavi nastavtlacitka \
-nastavtoleranci nastavtrideni nastavtype nastavumisteniprotejsku nastavumistovani \
-nastavupati nastavupravu nastavurl nastavusporadani nastavvelikostpapiru \
-nastavverze nastavvsechnapole nastavvycty nastavvyplnovelinky nastavvyplnoveradky \
-nastavvystup nastavvzhled nastavzahlavi nastavzakladnifont nastavzarovnani \
-nastavznaceni nastavzuzeni nastrane navigating nejakyradek \
-nekde nextsection neznamo nivy nizky \
-nocap nokap nop numberofsubpages obrazovka \
-odkaz odkaznadatum odkaznastranu odkaznatext odkazujici \
-odsazenishora odsazenizleva odsazovani okr opakovat \
-opis opissoubor oramovani oref orez \
-otocit outeredgedistance outeredgewidth outermargindistance outermarginwidth \
-overbar overbars overstrike overstrikes oznaceni \
-oznacverzi pagedepth pageoffset paragraph parovastrana \
-part pis placefloat placeheadnumber placeheadtext \
-placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
-placereferencelist placerule placetextvariable plnezneni pol \
-pole polozka polozky popisky poppisek \
-porovnejpaletu porovnejskupinubarev positiontext pozadi pozice \
-poznamka poznamkapodcarou pref prelozit premistinamrizku \
-prepninazakladnifont preskoc prizpusobivepole prizpusobvzhled produkt \
-program projekt propojeneznaceni propojenydokument propojenyrejstrik \
-prostredi publikace ran ref register \
-reservefloat reset resetnumber resettextcontent resetznaceni \
-rimskecislice rozdelplvouciobjekt rozmer rozpojeneznaceni roztazene \
-schovejbloky section sedabarva seeregister setnumber \
-settextcontent settextvariable setupanswerarea setupcolumnset setupcolumnsetlines \
-setupcolumnsetstart setupfonthandling setupfontsynonym setupforms setupindentedtext \
-setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupnumber \
-setuppaper setupplacement setuprule setupstartstop setupstrut \
-setuptextposition setuptextvariable sirkalevehookraje sirkalevemarginalie sirkamarginalie \
-sirkaokraje sirkapapiru sirkapravehookraje sirkapravemarginalie sirkasazby \
-sirkaseznamu sirkatextu sirkatiskpapiru sloupec slovovpravo \
-sort spodek stanovcharakteristickuseznamu stanovcislonadpisu startalignment \
-startbarva startbuffer startcislovaniradku startcitace startcolumnmakeup \
-startcolumns startcolumnset startcombination startcomment startdescription \
-startdocument startdokument startenumeration startfakt startfigure \
-startfloattext startformula startframedtext startglobalni starthiding \
-startinteraktivnimenu startitemgroup startkodovani startkomponenta startkorekceradku \
-startlegend startline startlinecorrection startlinenumbering startlines \
-startlocal startlocalenvironment startlocalfootnotes startlokalni startlokalnipoznamkypodcarou \
-startmakeup startmarginalniblok startmarginalnilinka startmarginblock startnamemakeup \
-startnarrower startnezhustene startobraz startopposite startoverlay \
-startoverview startparagraph startpositioning startpostponing startpozadi \
-startprehled startprekryv startprodukt startprofil startprofile \
-startprojekt startprostredi startprotejsek startradek startradky \
-startrastr startregister startsadasymbolu startsloupce startspojeni \
-startsymbolset startsynchronizace startsynchronization starttable starttables \
-starttabulate starttabulka starttabulky starttext starttextovalinka \
-starttyping startumistovani startunpacked startuprava startverze \
-startzarovnavani startzhustene startzuzeni stopalignment stopbarva \
-stopbuffer stopcislovaniradku stopcitace stopcolumnmakeup stopcolumns \
-stopcolumnset stopcombination stopcomment stopdescription stopdocument \
-stopdokument stopenumeration stopfakt stopfigure stopfloattext \
-stopformula stopframedtext stopglobalni stophiding stopinteraktivnimenu \
-stopitemgroup stopkodovani stopkomponenta stopkorekceradku stoplegend \
-stopline stoplinecorrection stoplinenumbering stoplines stoplocal \
-stoplocalenvironment stoplocalfootnotes stoplokalni stoplokalnipoznamkypodcarou stopmakeup \
-stopmarginalniblok stopmarginalnilinka stopmarginblock stopnamemakeup stopnarrower \
-stopnezhustene stopopposite stopoverlay stopoverview stopparagraph \
-stoppositioning stoppostponing stoppozadi stopprehled stopprekryv \
-stopprodukt stopprofil stopprofile stopprojekt stopprostredi \
-stopprotejsek stopradek stopradky stoprastr stopsloupce \
-stopspojeni stopsymbolset stopsynchronizace stopsynchronization stoptable \
-stoptables stoptabulate stoptabulka stoptabulky stoptext \
-stoptextovalinka stoptyping stopumistovani stopunpacked stopuprava \
-stopverze stopzarovnavani stopzhustene stopzuzeni strana \
-sub subject subpagenumber subsection subsubject \
-subsubsection subsubsubject switchtorawfont sym symbol \
-synchronizacnilista synchronizovat synonym tab tecky \
-tenkalinka tenkelinky testcolumn testpage tex \
-texthlavicky textovalinka textpopisku textvariable title \
-tlacitko tlacitkomenu tloustkacary tref tvrdamezera \
-tvrdemezery txt typebuffer ukazbarvu ukazexterniobrazy \
-ukazmrizku ukaznastaveni ukazpaletu ukazpodpery ukazpole \
-ukazpostredizakladnihofontu ukazramecek ukazsadusymbolu ukazskupinubarev ukazupravu \
-ukazvytisk ukazvzhled ukazzakladnifont umistikombinovanyseznam umistilegendu \
-umistiloga umistilokalnipoznamkypodcarou umistinadsebe umistinamrizku umistipodrovnici \
-umistipoznamkypodcarou umistirejstrik umistirovnici umistiseznam umistivedlesebe \
-umistizalozky underbar underbars urcicharakteristikurejstriku useXMLfilter \
-usedirectory usetypescript usetypescriptfile uzijJSscripts uzijURL \
-uzijadresar uzijbloky uzijexternidokument uzijexterniobraz uzijexternisoubor \
-uzijexternisoubory uzijexternizvuk uzijkodovani uzijmodul uzijmoduly \
-uzijodkazy uzijprikazy uzijspeciality uzijsymbol uzijurl \
-verze vl vlasovalinka vlevo vpravo \
-vradku vsedniden vyberbloky vyberpapir vyberverzi \
-vyplnenytext vyplnovelinky vyplnovepole vyplnovyradek vyskahorejsku \
-vyskapapiru vyskasazby vyskaseznamu vyskaspodku vyskatextu \
-vyskatiskpapiru vyskaupati vyskazahlavi vysoky vyznam \
-vzdalenosthorejsku vzdalenostlevehookraje vzdalenostlevemarginalie vzdalenostmarginalie vzdalenostokraje \
-vzdalenostpravehookraje vzdalenostpravemarginalie vzdalenostspodku vzdalenostupati vzdalenostzahlavi \
-zablokujinterakcnimenu zachovejbloky zadnamezera zadnebilemisto zadnedalsibloky \
-zadnedalsisoubory zadnehorniadolniradky zadneodsazovani zadnezahlaviaupati zadneznaceni \
-zadnyrozmer zadnyseznam zadnytest zalozka zapisdorejstriku \
-zapisdoseznamu zapisdoseznamuodkazu zapismeziseznam zaramovani zarovnanonastred \
-zarovnanovlevo zarovnanovpravo zasobnikpoli zaznamovepole zhustene \
-ziskejbuffer ziskejznaceni zlomek znaceni znak \
-znaky zpracujbloky zpracujstranu zrcadlit zref \
-zvysujicicislo
-
-keywordclass.context.nl=\
-CAP Cap Caps Cijfers \
-KAP Kap Kaps Letter Letters \
-MAAND Romeins WEEKDAG WOORD WOORDEN \
-Woord Woorden aantalsubpaginas about achtergrond \
-appendix arg bepaalkopnummer bepaallijstkenmerken bepaalregisterkenmerken \
-betekenis binnenmargeafstand binnenmargebreedte binnenrandafstand binnenrandbreedte \
-blanko blokje blokjes blokkeerinteractiemenu bodemwit \
-bookmark bovenafstand bovenhoogte breuk buitenmargeafstand \
-buitenmargebreedte buitenrandafstand buitenrandbreedte but button \
-cap chapter chem cijfers citaat \
-citeer clip comment completecombinedlist completelistoffloats \
-completelistofsorts completelistofsynonyms converteernummer copieerveld corrigeerwitruimte \
-coupledregister crlf datum definebodyfontDEF definebodyfontREF \
-definedfont definefontfeature definefonthandling definerawfont definetypeface \
-definieer definieeraccent definieeralineas definieerbeeldmerk definieerblanko \
-definieerblok definieerbuffer definieercombinatie definieercommando definieerconversie \
-definieerfiguursymbool definieerfont definieerfontstijl definieerfontsynoniem definieerhbox \
-definieerhoofdveld definieeringesprongentext definieerinmarge definieerinteractiemenu definieeritemgroep \
-definieerkadertekst definieerkarakter definieerkleur definieerkleurgroep definieerkolomgroep \
-definieerkolomovergang definieerkop definieerkorps definieerkorpsomgeving definieerlayer \
-definieerlayout definieerletter definieerlijn definieerlijst definieermarkering \
-definieeromlijnd definieeropmaak definieeroverlay definieerpaginaovergang definieerpalet \
-definieerpapierformaat definieerplaats definieerplaatsblok definieerprofiel definieerprogramma \
-definieerreferentie definieerreferentieformaat definieerreferentielijst definieerregister definieersamengesteldelijst \
-definieersectie definieersectieblok definieersorteren definieerstartstop definieersubveld \
-definieersymbool definieersynoniemen definieertabelvorm definieertabulatie definieertekst \
-definieertekstpositie definieertekstvariabele definieertype definieertypen definieeruitvoer \
-definieerveld definieerveldstapel definieerversie definieerwiskundeuitlijnen description \
-dimensie directnaarlijst directtussenlijst doordefinieren doorlabelen \
-doornummeren dunnelijn dunnelijnen eenregel enumeration \
-ergens externfiguur forceerblokken formulenummer framedtext \
-gebruikJSscripts gebruikURL gebruikXMLfilter gebruikblokken gebruikcommandos \
-gebruikexterndocument gebruikexternefile gebruikexternefiles gebruikexternfiguur gebruikexterngeluidsfragment \
-gebruikgebied gebruikmodule gebruikmodules gebruikreferenties gebruikspecials \
-gebruiksymbolen gebruiktypescript gebruiktypescriptfile gebruikurl geenblokkenmeer \
-geenbovenenonderregels geendimensie geenfilesmeer geenhoofdenvoetregels geenlijst \
-geenmarkering geenspatie geentest geenwitruimte geg \
-grijskleur grijswaarde haalbuffer haalmarkering haalnummer \
-haarlijn handhaafblokken herhaal hl hoofdafstand \
-hoofdhoogte hoofdtaal hoog huidigedatum huidigekopnummer \
-in inanderemarge inbinnen inbuiten indentation \
-inlijnd inlinker inlinkermarge inlinkerrand inmarge \
-inrechter inrechtermarge inrechterrand inregel inspringen \
-installeertaal instellingen interactiebalk interactiebuttons interactiemenu \
-invullijnen invulregel invultekst invulveld inwilijnd \
-items its kantlijn kap kenmerk \
-kenmerkdatum kentekstvariabeletoe kleur kleurenbalk kleurwaarde \
-kloonveld kolom kop kopniveau kopnummer \
-koppeldocument koppelmarkering koppelpagina koppelpapier koppelregister \
-kopsym koptekst kopwit laag label \
-labeling labels labeltekst laho leg \
-legeregels letter letters lijndikte lijstbreedte \
-lijsthoogte lijstlengte lijstsymbool linkermargeafstand linkermargebreedte \
-linkerrandafstand linkerrandbreedte loadsorts loadsynonyms maand \
-mapfontsize mar margeafstand margebreedte margetekst \
-margetitel margewoord markeer markeerversie mediaeval \
-menubutton naam naar naarbox naarpagina \
-name navigerend nextsection nietinspringen nocap \
-nokap noot nop omgeving omlaag \
-omlijnd onbekend onderafstand onderdeel onderhoogte \
-ontkoppelmarkering op opelkaar oplinkermarge oppagina \
-oprechtermarge overbar overbars overstrike overstrikes \
-pagina paginadiepte paginanummer paginaoffset paginareferentie \
-papierbreedte papierhoogte paragraph part paslayoutaan \
-passeerblokken passendveld plaatsbeeldmerken plaatsbookmarks plaatsformule \
-plaatskopnummer plaatskoptekst plaatslegenda plaatslijn plaatslijst \
-plaatslokalevoetnoten plaatsnaastelkaar plaatsonderelkaar plaatsopgrid plaatspaginanummer \
-plaatsplaatsblok plaatsreferentielijst plaatsregister plaatsruwelijst plaatssamengesteldelijst \
-plaatssubformule plaatstekstvariabele plaatsvoetnoten placelistoffloats placelistofsorts \
-placelistofsynonyms positioneer positioneertekst printpapierbreedte printpapierhoogte \
-produkt programma projekt publicatie punten \
-ran randafstand randbreedte rechtermargeafstand rechtermargebreedte \
-rechterrandafstand rechterrandbreedte ref refereer referentie \
-regellinks regelmidden regelrechts register registreervelden \
-reservefloat reset resetmarkering resetnummer resettekstinhoud \
-resettextcontent romeins rooster roteer rugwit \
-schaal scherm schrijfnaarlijst schrijfnaarreferentielijst schrijfnaarregister \
-schrijftussenlijst section seeregister selecteerblokken selecteerpapier \
-selecteerversie setnummer setupfonthandling setupfontsynonym setupinterlinespace2 \
-setuplistalternative snijwit som sort spatie \
-spiegel splitsplaatsblok startachtergrond startalignment startbuffer \
-startcitaat startcodering startcolumns startcombinatie startcombination \
+keywordclass.context.pe=\
+CAP Cap Caps Character \
+Characters MONTH Numbers Romannumerals WEEKDAY \
+WORD WORDS Word Words appendix \
+cap chapter chem comment completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf \
+definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling \
+defineindentedtext definetypeface description enumeration framedtext \
+indentation inmframed its labeling loadsorts \
+loadsynonyms mapfontsize mediaeval mframed name \
+nextsection nocap overbar overbars overstrike \
+overstrikes paragraph part placelistoffloats placelistofsorts \
+placelistofsynonyms ran register reservefloat resettextcontent \
+section seeregister setupanswerarea setupcapitals setupfonthandling \
+setupfontsynonym setupindentedtext setupinterlinespace2 setuplistalternative setupurl \
+sort startalignment startbuffer startcolumns startcombination \
startcomment startdescription startdocument startenumeration startfigure \
-startfiguur startfloattext startformula startframedtext startgeg \
-startglobaal starthiding startinteractiemenu startitemgroup startkantlijn \
-startkleur startkolomgroep startkolommen startkolomopmaak startlegend \
-startline startlinecorrection startlinenumbering startlines startlocal \
-startlocalenvironment startlocalfootnotes startlokaal startlokalevoetnoten startmakeup \
-startmargeblok startmarginblock startnaast startnamemakeup startnarrower \
-startomgeving startonderdeel startopelkaar startopmaak startopposite \
-startoverlay startoverview startoverzicht startparagraph startpositioneren \
-startpositioning startpostponing startprodukt startprofiel startprofile \
-startprojekt startraster startregel startregelcorrectie startregelnummeren \
-startregels startregister startsmaller startsymbolset startsymboolset \
-startsynchronisatie startsynchronization starttabel starttabellen starttable \
-starttables starttabulate starttekst starttekstlijn starttyping \
-startuitlijnen startunpacked startvanelkaar startversie stelachtergrondenin \
-stelachtergrondin stelalineasin stelantwoordgebiedin stelarrangerenin stelblankoin \
-stelblokin stelblokjesin stelblokkopjein stelblokkopjesin stelbovenin \
-stelboventekstenin stelbufferin stelbuttonsin stelciterenin stelclipin \
-stelcombinatiesin stelcommentaarin steldoordefinierenin steldoornummerenin steldunnelijnenin \
-stelexternefigurenin stelformulesin stelformulierenin stelhoofdin stelhoofdtekstenin \
-stelingesprongentextin stelinmargein stelinspringenin stelinteractiebalkin stelinteractiein \
-stelinteractiemenuin stelinteractieschermin stelinterliniein stelinvullijnenin stelinvulregelsin \
-stelitemgroepin stelitemsin stelkadertekstenin stelkantlijnin stelkapitalenin \
-stelkleurenin stelkleurin stelkolomgroepin stelkolomgroepregelsin stelkolomgroepstartin \
-stelkolommenin stelkopin stelkopnummerin stelkoppeltekenin stelkoppenin \
-stelkoptekstin stelkorpsin stelkorpsomgevingin stellabeltekstin stellayoutin \
-stellegendain stellijndiktein stellijnin stellijstin stelmargeblokkenin \
-stelmarkeringin stelnaastplaatsenin stelnummerenin stelnummerin stelomlijndin \
-stelonderin stelonderstrepenin stelondertekstenin stelopmaakin stelopsommingenin \
-stelpaginacommentaarin stelpaginanummerin stelpaginanummeringin stelpaginaovergangenin stelpaletin \
-stelpapierformaatin stelpapierin stelparagraafnummerenin stelplaatsblokin stelplaatsblokkenin \
-stelplaatsbloksplitsenin stelplaatsin stelpositionerenin stelprofielenin stelprogrammasin \
-stelpublicatiesin stelrastersin stelreferentielijstin stelrefererenin stelregelnummerenin \
-stelregelsin stelregisterin stelroterenin stelsamengesteldelijstin stelsectieblokin \
-stelsectiein stelsmallerin stelsorterenin stelspatieringin stelstartstopin \
-stelstrutin stelsubpaginanummerin stelsymboolsetin stelsynchronisatiebalkin stelsynchronisatiein \
-stelsynoniemenin stelsysteemin steltaalin steltabellenin steltabin \
-steltabulatiein steltekstin steltekstinhoudin steltekstlijnenin steltekstpositiein \
-stelteksttekstenin steltekstvariabelein steltolerantiein steltypein steltypenin \
-steluitlijnenin steluitvoerin stelurlin stelveldenin stelveldin \
-stelversiesin stelvoetin stelvoetnootdefinitiein stelvoetnotenin stelvoettekstenin \
-stelwiskundeuitlijnenin stelwitruimtein stopachtergrond stopalignment stopbuffer \
-stopcitaat stopcodering stopcolumns stopcombinatie stopcombination \
+startfloattext startformula startframedtext starthiding startitemgroup \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startnamemakeup startnarrower startopposite startoverlay startoverview \
+startparagraph startpositioning startpostponing startprofile startraster \
+startregister startsymbolset startsynchronization starttable starttables \
+starttabulate starttyping startunpacked startتولید startحقیقت \
+startخط‌حاشیه startخط‌متن startرنگ startفشرده startمحیط \
+startمنوی‌پانل startمولفه startنسخه startنقل‌قول startپروژه \
+startپس‌زمینه stopalignment stopbuffer stopcolumns stopcombination \
stopcomment stopdescription stopdocument stopenumeration stopfigure \
-stopfloattext stopformula stopframedtext stopgeg stopglobaal \
-stophiding stopinteractiemenu stopitemgroup stopkantlijn stopkleur \
-stopkolomgroep stopkolommen stopkolomopmaak stoplegend stopline \
-stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
-stoplocalfootnotes stoplokaal stoplokalevoetnoten stopmakeup stopmargeblok \
-stopmarginblock stopnaast stopnamemakeup stopnarrower stopomgeving \
-stoponderdeel stopopelkaar stopopmaak stopopposite stopoverlay \
-stopoverview stopoverzicht stopparagraph stoppositioneren stoppositioning \
-stoppostponing stopprodukt stopprofiel stopprofile stopprojekt \
-stopraster stopregel stopregelcorrectie stopregelnummeren stopregels \
-stopsmaller stopsymbolset stopsynchronisatie stopsynchronization stoptabel \
-stoptabellen stoptable stoptables stoptabulate stoptekst \
-stoptekstlijn stoptyping stopuitlijnen stopunpacked stopvanelkaar \
-stopversie sub subformulenummer subject subpaginanummer \
-subsection subsubject subsubsection subsubsubject suggestie \
-switchnaarkorps switchtorawfont sym symbool synchronisatiebalk \
-synchroniseer synonym taal tab tekstbreedte \
-teksthoogte tekstlijn tekstreferentie tekstvariabele testkolom \
-testpagina tex title toelichting toonexternefiguren \
-toongrid tooninstellingen toonkader toonkleur toonkleurgroep \
-toonkorps toonkorpsomgeving toonlayout toonopmaak toonpalet \
-toonprint toonstruts toonsymboolset toonvelden totaalaantalpaginas \
-txt typ type typebuffer typefile \
-uit uitgerekt underbar underbars usecodering \
-usedirectory vastespatie vastespaties veld veldstapel \
-verbergblokken vergelijkkleurgroep vergelijkpalet verhoognummer verlaagnummer \
-verplaatsformule verplaatsopgrid verplaatszijblok versie vertaal \
-verwerkblokken verwerkpagina vl voetafstand voethoogte \
-voetnoot voetnoottekst volgprofiel volgprofielversie volgversie \
-volledigepaginanummer volledigregister voluit weekdag wilijnd \
-wiskunde witruimte woonplaats woordrechts zetbreedte \
-zethoogte
+stopfloattext stopformula stopframedtext stophiding stopitemgroup \
+stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
+stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
+stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview \
+stopparagraph stoppositioning stoppostponing stopprofile stopraster \
+stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
+stoptyping stopunpacked stopتولید stopحقیقت stopخط‌حاشیه \
+stopخط‌متن stopرنگ stopفشرده stopمحیط stopمنوی‌پانل \
+stopمولفه stopنسخه stopنقل‌قول stopپروژه stopپس‌زمینه \
+sub subject subsection subsubject subsubsection \
+subsubsubject synonym title tooltip txt \
+typ underbar underbars useJSscripts useURL \
+useXMLfilter usedirectory useurl آفست‌صفحه آیتم \
+آیتمها آینه اجباربلوکها ارتفاع‌آرایش ارتفاع‌بالا \
+ارتفاع‌برگ ارتفاع‌ته‌برگ ارتفاع‌خط ارتفاع‌سربرگ ارتفاع‌متن \
+ارتفاع‌پایین از ازکارانداختن‌منوی‌پانل استفاده‌بلوکها استفاده‌دستخط‌تایپ \
+استفاده‌رمزینه استفاده‌شکل‌خارجی استفاده‌فرمانها استفاده‌قطعه‌موزیک‌خارجی استفاده‌مدول \
+استفاده‌مدولها استفاده‌مرجعها استفاده‌مسیر استفاده‌نمادها استفاده‌نوشتارخارجی \
+استفاده‌ویژگیها استفاده‌پرونده‌خارجی استفاده‌پرونده‌دستخط‌تایپ استفاده‌پرونده‌های‌خارجی اعدادلاتین \
+افزودن اما امتحان‌نکن انتخاب‌برگ انتخاب‌بلوکها \
+انتخاب‌نسخه انتقال‌به‌توری انتقال‌فرمول انتقال‌کنار‌شناور انجام‌دوباره \
+بارگذاریها بارگذاری‌آرایش بارگذاری‌آیتمها بارگذاری‌ارجاع بارگذاری‌اندازه‌برگ \
+بارگذاری‌باریکتر بارگذاری‌بافر بارگذاری‌بالا بارگذاری‌بخش بارگذاری‌بردباری \
+بارگذاری‌برنامه‌ها بارگذاری‌برگ بارگذاری‌بست بارگذاری‌بلوک بارگذاری‌بلوکهای‌حاشیه \
+بارگذاری‌بلوک‌بخش بارگذاری‌تایپ بارگذاری‌تایپ‌کردن بارگذاری‌تب بارگذاری‌ترتیب \
+بارگذاری‌ترکیب‌ها بارگذاری‌تطابق بارگذاری‌تعریف‌پانوشت بارگذاری‌تنظیم بارگذاری‌تنظیم‌ریاضی \
+بارگذاری‌ته‌برگ بارگذاری‌تورفتگی بارگذاری‌توضیح بارگذاری‌توضیح‌صفحه بارگذاری‌ثبت \
+بارگذاری‌جانشانی بارگذاری‌جدولها بارگذاری‌جدول‌بندی بارگذاری‌خالی بارگذاری‌خروجی \
+بارگذاری‌خط بارگذاری‌خطها بارگذاری‌خطهای‌حاشیه بارگذاری‌خطهای‌سیاه بارگذاری‌خطهای‌متن \
+بارگذاری‌خطهای‌مجموعه‌ستون بارگذاری‌خطها‌ی‌نازک بارگذاری‌درج‌درخطها بارگذاری‌درج‌مخالف بارگذاری‌درون‌حاشیه \
+بارگذاری‌دوران بارگذاری‌دکمه‌ها بارگذاری‌راهنما بارگذاری‌رنگ بارگذاری‌رنگها \
+بارگذاری‌زبان بارگذاری‌ستونها بارگذاری‌سر بارگذاری‌سربرگ بارگذاری‌سرها \
+بارگذاری‌سیستم بارگذاری‌شرح بارگذاری‌شرحها بارگذاری‌شروع‌مجموعه‌ستون بارگذاری‌شروع‌پایان \
+بارگذاری‌شماره بارگذاری‌شماره‌زیرصفحه بارگذاری‌شماره‌سر بارگذاری‌شماره‌صفحه بارگذاری‌شماره‌گذاری \
+بارگذاری‌شماره‌گذاریها بارگذاری‌شماره‌گذاری‌صفحه بارگذاری‌شماره‌گذاری‌پاراگراف بارگذاری‌شماره‌‌گذاری‌خط بارگذاری‌شناور \
+بارگذاری‌شناورها بارگذاری‌شکافتن‌شناورها بارگذاری‌شکلهای‌خارجی بارگذاری‌طرح بارگذاری‌طرح‌بندی \
+بارگذاری‌عرض‌خط بارگذاری‌فاصله‌بین‌خط بارگذاری‌فرمولها بارگذاری‌فضای‌سفید بارگذاری‌فضا‌گذاری \
+بارگذاری‌قالبی بارگذاری‌قلم‌متن بارگذاری‌لوح بارگذاری‌لیست بارگذاری‌لیست‌ترکیبی \
+بارگذاری‌لیست‌مرجع بارگذاری‌مترادفها بارگذاری‌متغیر‌متن بارگذاری‌متن بارگذاری‌متنهای‌بالا \
+بارگذاری‌متن‌سر بارگذاری‌متن‌سربرگ بارگذاری‌متن‌قالبی بارگذاری‌متن‌متنها بارگذاری‌متن‌پانوشت \
+بارگذاری‌متن‌پایین بارگذاری‌مجموعه‌ستون بارگذاری‌مجموعه‌نماد بارگذاری‌محیط‌قلم‌متن بارگذاری‌منوی‌پانل \
+بارگذاری‌مکان‌متن بارگذاری‌مکان‌گذاری بارگذاری‌میدان بارگذاری‌میدانها بارگذاری‌میله‌تطابق \
+بارگذاری‌میله‌زیر بارگذاری‌میله‌پانل بارگذاری‌نسخه‌ها بارگذاری‌نشانه‌شکستن بارگذاری‌نشانه‌گذاری \
+بارگذاری‌نشرها بارگذاری‌نقل بارگذاری‌پاراگرافها بارگذاری‌پانل بارگذاری‌پانوشتها \
+بارگذاری‌پایین بارگذاری‌پرده‌ها بارگذاری‌پرده‌پانل بارگذاری‌پروفایلها بارگذاری‌پرکردن‌خطها \
+بارگذاری‌پس‌زمینه بارگذاری‌پس‌زمینه‌ها بارگذاری‌چیدن بارگذاری‌گذارصفحه بارگذاری‌گروههای‌آیتم \
+بارگذاری‌گروه‌آیتم بازنشانی بازنشانی‌شماره بازنشانی‌متن بازنشانی‌نشانه‌گذاری \
+باگذاری‌متن‌برچسب بدون‌بعد بدون‌بلوکهای‌بیشتر بدون‌تورفتگی بدون‌خط‌بالاوپایین \
+بدون‌خط‌سروته‌برگ بدون‌فایلهای‌بیشتر بدون‌فضا بدون‌فضای‌سفید بدون‌لیست \
+بدون‌نشانه‌گذاری برنامه بروبه بروبه‌جعبه بروبه‌صفحه \
+بروپایین برچسب برچسبها بعد بلند \
+بلوکهای‌پردازش بلوکها‌پنهان بنویس‌بین‌لیست بنویس‌درثبت بنویس‌درلیست‌مرجع \
+بنویس‌در‌لیست تاریخ تاریخ‌جاری تاریخ‌رجوع تایپ \
+تایپ‌بافر تایپ‌پرونده تب ترجمه تطابق \
+تعریف تعریف‌آرایش تعریف‌آرم تعریف‌الگوی‌جدول تعریف‌اندازه‌برگ \
+تعریف‌بافر تعریف‌بخش تعریف‌برنامه تعریف‌برچسب تعریف‌بلوک \
+تعریف‌بلوک‌بخش تعریف‌تایپ تعریف‌تایپ‌کردن تعریف‌تبدیل تعریف‌ترتیب \
+تعریف‌ترکیب تعریف‌تنظیم‌ریاضی تعریف‌توده‌میدان تعریف‌ثبت تعریف‌جانشانی \
+تعریف‌جدول‌بندی تعریف‌جعبه‌‌افقی تعریف‌حرف تعریف‌خالی تعریف‌خروجی \
+تعریف‌خط‌حائل تعریف‌درون‌حاشیه تعریف‌رنگ تعریف‌زیرمیدان تعریف‌سبک \
+تعریف‌سبک‌قلم تعریف‌سر تعریف‌شرح تعریف‌شروع‌پایان تعریف‌شماره‌بندی \
+تعریف‌شمایل‌مرجع تعریف‌شناور تعریف‌شکستن‌ستون تعریف‌شکست‌صفحه تعریف‌طرح‌بندی \
+تعریف‌فرمان تعریف‌قالبی تعریف‌قلم تعریف‌قلم‌خام تعریف‌قلم‌متن \
+تعریف‌لایه تعریف‌لهجه تعریف‌لوح تعریف‌لیست تعریف‌لیست‌ترکیبی \
+تعریف‌لیست‌مرجع تعریف‌مترادفها تعریف‌مترادف‌قلم تعریف‌متغیرمتن تعریف‌متن \
+تعریف‌متن‌قالبی تعریف‌مجموعه‌ستون تعریف‌محیط‌قلم‌بدنه تعریف‌مرجع تعریف‌منوی‌پانل \
+تعریف‌مکان‌متن تعریف‌میدان تعریف‌میدان‌اصلی تعریف‌نسخه تعریف‌نشانه‌گذاری \
+تعریف‌نماد تعریف‌نمادشکل تعریف‌پاراگرافها تعریف‌پروفایل تعریف‌پوشش \
+تعریف‌گروه‌آیتم تعریف‌گروه‌رنگ تعیین‌شماره تعیین‌شماره‌سر تعیین‌متغیر‌متن \
+تعیین‌محتوای‌متن تعیین‌مشخصات‌ثبت تعیین‌مشخصات‌لیست تغییربه‌قلم‌بدنه تغییربه‌قلم‌خام \
+تنظیم‌راست تنظیم‌طرح‌بندی تنظیم‌وسط توجه تورفتگی \
+توری تولید تک ثبت‌زوج ثبت‌کامل \
+جداسازی‌نشانه‌گذاری حاش حرف حرفها حفظ‌بلوکها \
+حقیقت خالی خطهای‌سیاه خطهای‌نازک خطها‌خالی \
+خط‌حاشیه خط‌سیاه خط‌متن خط‌مو خط‌نازک \
+خ‌ا خ‌ع در درج‌آرمها درج‌ثبت \
+درج‌خط درج‌درخط درج‌درخطها درج‌درمتن درج‌درمیدان \
+درج‌در‌بالای‌یکدیگر درج‌در‌توری درج‌راهنما درج‌زیرفرمول درج‌شماره‌سر \
+درج‌شماره‌صفحه درج‌شناور درج‌فرمول درج‌لیست درج‌لیست‌خام \
+درج‌لیست‌مختلط درج‌لیست‌مرجع درج‌متغیرمتن درج‌متن‌سر درج‌پانوشتها \
+درج‌پانوشتهای‌موضعی درج‌چوب‌خط درج‌کنار‌به‌کنار درحاشیه درحاشیه‌دیگر \
+درحاشیه‌راست درحاشیه‌چپ درخارجی درخط درداخلی \
+درراست درصفحه درقالبی درلبه‌راست درلبه‌چپ \
+درمورد درون درپر درچپ دریافت‌بافر \
+دریافت‌شماره دریافت‌نشانه دوران دکمه دکمه‌منو \
+دکمه‌پانل رج رجوع رنگ رنگ‌خاکستری \
+روزهفته ریاضی زبان زبان‌اصلی ستون \
+ستون‌امتحان سر سرپوش‌کوچک‌نه شروع‌آرایش شروع‌آرایش‌ستون \
+شروع‌باریکتر شروع‌بازبینی شروع‌بلوک‌حاشیه شروع‌ترکیب شروع‌تصحیح‌خط \
+شروع‌تطابق شروع‌تنظیم شروع‌تولید شروع‌جدول شروع‌جدولها \
+شروع‌خط شروع‌خطها شروع‌خط‌حاشیه شروع‌خط‌متن شروع‌رنگ \
+شروع‌ستونها شروع‌سراسری شروع‌شماره‌گذاری‌خط شروع‌شکل شروع‌غیر‌فشرده \
+شروع‌فشرده شروع‌متن شروع‌مجموعه‌ستون شروع‌مجموعه‌نماد شروع‌محیط \
+شروع‌مخالف شروع‌موضعی شروع‌مولفه شروع‌مکان‌گذاری شروع‌نسخه \
+شروع‌نقل‌قول شروع‌نوشتار شروع‌پانوشتهای‌موضعی شروع‌پروفایل شروع‌پروژه \
+شروع‌پس‌زمینه شروع‌پوشش شروع‌کد شماره‌افزایش شماره‌زیرصفحه \
+شماره‌زیرفرمول شماره‌سر شماره‌سرجاری شماره‌صفحه شماره‌صفحه‌کامل \
+شماره‌فرمول شماره‌مبدل شماره‌ها شماره‌کاهش شماره‌کل‌صفحه‌ها \
+شکافتن‌شناور شکل‌خارجی صفحه صفحه‌تست صفحه‌زوج \
+صفحه‌پردازش طول‌لیست عبوربلوکها عرض‌آرایش عرض‌برگ \
+عرض‌حاشیه عرض‌حاشیه‌خارجی عرض‌حاشیه‌داخلی عرض‌حاشیه‌راست عرض‌حاشیه‌چپ \
+عرض‌خط عرض‌لبه عرض‌لبه‌خارجی عرض‌لبه‌داخلی عرض‌لبه‌راست \
+عرض‌لبه‌چپ عرض‌لیست عرض‌متن عمق‌صفحه عنوان‌حاشیه \
+فاصله‌بالا فاصله‌ته‌برگ فاصله‌حاشیه فاصله‌حاشیه‌خارجی فاصله‌حاشیه‌داخلی \
+فاصله‌حاشیه‌راست فاصله‌حاشیه‌چپ فاصله‌سربرگ فاصله‌لبه فاصله‌لبه‌خارجی \
+فاصله‌لبه‌داخلی فاصله‌لبه‌راست فاصله‌لبه‌چپ فاصله‌پایین فاصله‌پشت \
+فشرده فضا فضاهای‌ثابت فضای‌بالا فضای‌برش \
+فضای‌ثابت فضای‌سفید فضای‌سفیدصحیح فضای‌پایین فوری‌به‌لیست \
+فوری‌بین‌لیست قالبی لوح‌مقایسه ماه متغیر متن \
+متن‌برچسب متن‌حاشیه متن‌سر متن‌پانوشت محیط \
+مراجعه مرجع مرجع‌صفحه مرجع‌متن مرحله‌سر \
+مسکن معنی‌واحد مقایسه‌گروه‌رنگ مقدارخاکستری مقداررنگ \
+مقیاس منفی منوی‌پانل مولفه مکان \
+مکان‌متن میدان میدانهای‌گزارش میدان‌شبیه‌سازی میدان‌پشته \
+میدان‌کپی میله‌تطابق میله‌رنگ میله‌پانل ناشناس \
+نام‌ماکرو نسخه نسخه‌نشانه نشانه‌گذاری نشانه‌گذاری‌زوج \
+نشر نصب‌زبان نقطه‌ها نقل نقل‌قول \
+نم نماد نمادسر نمادلیست نمایش‌آرایش \
+نمایش‌بارگذاریها نمایش‌بستها نمایش‌توری نمایش‌رنگ نمایش‌شکلهای‌خارجی \
+نمایش‌طرح‌بندی نمایش‌قالب نمایش‌قلم‌بدنه نمایش‌لوح نمایش‌مجموعه‌علامت \
+نمایش‌محیط‌قلم‌بدنه نمایش‌میدانها نمایش‌چاپ نمایش‌گروه‌رنگ نوشتارزوج \
+هدایت پا پابا پانوشت پایان‌آرایش \
+پایان‌آرایش‌ستون پایان‌بازبینی پایان‌بلوک‌حاشیه پایان‌ترکیب پایان‌تصحیح‌خط \
+پایان‌تطابق پایان‌تنظیم پایان‌تولید پایان‌جدول پایان‌جدولها \
+پایان‌خط پایان‌خطها پایان‌خط‌حاشیه پایان‌خط‌متن پایان‌رنگ \
+پایان‌ستونها پایان‌سراسری پایان‌شماره‌گذاری‌خط پایان‌غیرفشرده پایان‌فشرده \
+پایان‌متن پایان‌مجموعه‌ستون پایان‌محیط پایان‌مخالف پایان‌موضعی \
+پایان‌مولفه پایان‌مکان‌گذاری پایان‌نازکتر پایان‌نسخه پایان‌نقل‌قول \
+پایان‌نوشتار پایان‌پانوشتهای‌موضعی پایان‌پروفایل پایان‌پروژه پایان‌پس‌زمینه \
+پایان‌پوشش پایان‌کد پایین پرده پروژه \
+پرکردن‌میدان پس‌زمینه پیروی‌نسخه پیروی‌نسخه‌پروفایل پیروی‌پروفایل \
+چاپ‌ارتفاع‌برگ چاپ‌عرض‌برگ چوبخط چپ‌چین کاغذزوج \
+کسر کشیده کلمه‌حاشیه کلمه‌راست گیره \
+یادداشت یک‌جا یک‌خط
keywordclass.context.it=\
CAP Cap Caps GIORNOSETTIMANA \
diff --git a/context/data/scite/scite-context-data-metapost.properties b/context/data/scite/scite-context-data-metapost.properties
index 565df0927..7715856b0 100644
--- a/context/data/scite/scite-context-data-metapost.properties
+++ b/context/data/scite/scite-context-data-metapost.properties
@@ -1,9 +1,6 @@
-keywordclass.metapost.internals=\
-mitered rounded beveled butt \
-squared eps epsilon infinity bboxmargin \
-ahlength ahangle labeloffset dotlabeldiam defaultpen \
-defaultscale join_radius pen_lft pen_rt pen_top \
-pen_bot
+keywordclass.metapost.shortcuts=\
+.. ... -- --- \
+&
keywordclass.metapost.primitives=\
charcode day linecap linejoin \
@@ -58,10 +55,6 @@ graycolor colormodel graypart dashpart penpart \
stroked filled textual clipped bounded \
expandafter
-keywordclass.metapost.shortcuts=\
-.. ... -- --- \
-&
-
keywordclass.metapost.commands=\
beginfig endfig rotatedaround reflectedabout \
arrowhead currentpen currentpicture cuttings defaultfont \
@@ -96,3 +89,10 @@ cm pc cc in
keywordclass.metapost.tex=\
btex etex verbatimtex
+keywordclass.metapost.internals=\
+mitered rounded beveled butt \
+squared eps epsilon infinity bboxmargin \
+ahlength ahangle labeloffset dotlabeldiam defaultpen \
+defaultscale join_radius pen_lft pen_rt pen_top \
+pen_bot
+
diff --git a/context/data/scite/scite-context-data-tex.properties b/context/data/scite/scite-context-data-tex.properties
index df065e374..a4eaac843 100644
--- a/context/data/scite/scite-context-data-tex.properties
+++ b/context/data/scite/scite-context-data-tex.properties
@@ -1,3 +1,11 @@
+keywordclass.tex.aleph=\
+AlephVersion Alephminorversion Alephrevision Alephversion \
+Omegaminorversion Omegarevision Omegaversion boxdir pagebottomoffset \
+pagerightoffset
+
+keywordclass.tex.xetex=\
+XeTeXversion
+
keywordclass.tex.pdftex=\
efcode expanded ifincsname ifpdfabsdim \
ifpdfabsnum ifpdfprimitive leftmarginkern letterspacefont lpcode \
@@ -23,65 +31,13 @@ pdftrailer pdfuniformdeviate pdfuniqueresname pdfvorigin pdfxform \
pdfxformattr pdfxformname pdfxformresources pdfximage pdfximagebbox \
quitvmode rightmarginkern rpcode tagcode
-keywordclass.tex.luatex=\
-Udelcode Udelcodenum Udelimiter Udelimiterover \
-Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
-Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
-Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
-Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
-Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
-Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
-Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
-Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
-Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
-Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
-Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
-Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
-Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
-Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
-Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
-Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
-Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
-Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
-Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
-Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
-Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
-Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
-Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
-Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
-Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
-Ustopmath Usubscript Usuperscript Uunderdelimiter alignmark \
-aligntab attribute attributedef catcodetable clearmarks \
-crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle fontid \
-formatname gleaders ifabsdim ifabsnum ifprimitive \
-initcatcodetable latelua luaescapestring luastartup luatexdatestamp \
-luatexrevision luatexversion mathstyle nokerns noligs \
-outputbox pageleftoffset pagetopoffset postexhyphenchar posthyphenchar \
-preexhyphenchar prehyphenchar primitive savecatcodetable scantextokens \
-suppressfontnotfounderror suppressifcsnameerror suppresslongerror suppressoutererror synctex
-
-keywordclass.tex.etex=\
-botmarks clubpenalties currentgrouplevel currentgrouptype \
-currentifbranch currentiflevel currentiftype detokenize dimexpr \
-displaywidowpenalties eTeXVersion eTeXminorversion eTeXrevision eTeXversion \
-everyeof firstmarks fontchardp fontcharht fontcharic \
-fontcharwd glueexpr glueshrink glueshrinkorder gluestretch \
-gluestretchorder gluetomu ifcsname ifdefined iffontchar \
-interactionmode interlinepenalties lastlinefit lastnodetype marks \
-muexpr mutoglue numexpr pagediscards parshapedimen \
-parshapeindent parshapelength predisplaydirection protected readline \
-savinghyphcodes savingvdiscards scantokens showgroups showifs \
-showtokens splitbotmarks splitdiscards splitfirstmarks topmarks \
-tracingassigns tracinggroups tracingifs tracingnesting tracingscantokens \
-unexpanded unless widowpenalties
-
-keywordclass.tex.xetex=\
-XeTeXversion
-
-keywordclass.tex.aleph=\
-AlephVersion Alephminorversion Alephrevision Alephversion \
-Omegaminorversion Omegarevision Omegaversion boxdir pagebottomoffset \
-pagerightoffset
+keywordclass.tex.omega=\
+OmegaVersion bodydir chardp charht \
+charit charwd leftghost localbrokenpenalty localinterlinepenalty \
+localleftbox localrightbox mathdir odelcode odelimiter \
+omathaccent omathchar omathchardef omathcode oradical \
+pagedir pageheight pagewidth pardir rightghost \
+textdir
keywordclass.tex.tex=\
- / AlephVersion Alephminorversion \
@@ -228,11 +184,55 @@ vrule vsize vskip vsplit vss \
vtop wd widowpenalties widowpenalty write \
xdef xleaders xspaceskip year
-keywordclass.tex.omega=\
-OmegaVersion bodydir chardp charht \
-charit charwd leftghost localbrokenpenalty localinterlinepenalty \
-localleftbox localrightbox mathdir odelcode odelimiter \
-omathaccent omathchar omathchardef omathcode oradical \
-pagedir pageheight pagewidth pardir rightghost \
-textdir
+keywordclass.tex.etex=\
+botmarks clubpenalties currentgrouplevel currentgrouptype \
+currentifbranch currentiflevel currentiftype detokenize dimexpr \
+displaywidowpenalties eTeXVersion eTeXminorversion eTeXrevision eTeXversion \
+everyeof firstmarks fontchardp fontcharht fontcharic \
+fontcharwd glueexpr glueshrink glueshrinkorder gluestretch \
+gluestretchorder gluetomu ifcsname ifdefined iffontchar \
+interactionmode interlinepenalties lastlinefit lastnodetype marks \
+muexpr mutoglue numexpr pagediscards parshapedimen \
+parshapeindent parshapelength predisplaydirection protected readline \
+savinghyphcodes savingvdiscards scantokens showgroups showifs \
+showtokens splitbotmarks splitdiscards splitfirstmarks topmarks \
+tracingassigns tracinggroups tracingifs tracingnesting tracingscantokens \
+unexpanded unless widowpenalties
+
+keywordclass.tex.luatex=\
+Udelcode Udelcodenum Udelimiter Udelimiterover \
+Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
+Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
+Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
+Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
+Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
+Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
+Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
+Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
+Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
+Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
+Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
+Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
+Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
+Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
+Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
+Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
+Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
+Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
+Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
+Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
+Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
+Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
+Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
+Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
+Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
+Ustopmath Usubscript Usuperscript Uunderdelimiter alignmark \
+aligntab attribute attributedef catcodetable clearmarks \
+crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle fontid \
+formatname gleaders ifabsdim ifabsnum ifprimitive \
+initcatcodetable latelua luaescapestring luastartup luatexdatestamp \
+luatexrevision luatexversion mathstyle nokerns noligs \
+outputbox pageleftoffset pagetopoffset postexhyphenchar posthyphenchar \
+preexhyphenchar prehyphenchar primitive savecatcodetable scantextokens \
+suppressfontnotfounderror suppressifcsnameerror suppresslongerror suppressoutererror synctex
diff --git a/metapost/context/base/mp-chem.mpiv b/metapost/context/base/mp-chem.mpiv
index 7d3ce6d26..954174f0d 100644
--- a/metapost/context/base/mp-chem.mpiv
+++ b/metapost/context/base/mp-chem.mpiv
@@ -28,7 +28,7 @@ numeric
chem_center_offset, chem_dbl_offset,
chem_bb_angle, chem_axis_rulethickness,
chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b,
- chem_emwidth, chem_b_length,
+ chem_setting_rotation, chem_emwidth, chem_b_length,
chem_front_b[] ;
boolean
@@ -39,9 +39,6 @@ boolean
string
chem_previous ;
-color
- chem_axis_color ;
-
path
chem_setting_bbox,
chem_path[], % scratch
@@ -51,46 +48,52 @@ path
pair
chem_origin, chem_mirror,
chem_pair[], % scratch
- chem_sb_pair, chem_sb_pair.m, chem_sb_pair.p ;
+ chem_sb_pair, chem_sb_pair.m, chem_sb_pair.p, chem_sb_pair.b ;
picture
chem_pic, % scratch
- chem_sb_dash, chem_sb_dash.m, chem_sb_dash.p ;
+ % The use of dashpattern is found to dot the starting point with chem_sb_dash.m...
+ %chem_sb_dash, chem_sb_dash.m, chem_sb_dash.p, chem_sb_dash.b,
+ chem_axis_color ;
transform
chem_t ; % scratch
+color lightblue ; lightblue := (173/255,216/255,230/255) ;
+
+chem_axis_color := image(draw origin withcolor lightblue) ;
chem_setting_axis := false ;
-chem_axis_color := (173/255,216/255,230/255) ; % lightblue
chem_axis_rulethickness := 1pt ;
chem_emwidth := 10pt ; % EmWidth or \the\emwidth does not work...
chem_b_length := 3 chem_emwidth ;
-chem_text_offset := .25chem_emwidth ; % ?
-chem_center_offset := .5 chem_emwidth ;
-chem_picture_offset := chem_emwidth ;
+chem_text_offset := -.71chem_emwidth ; % 1/sqrt(2)
+chem_center_offset := .5 chem_emwidth ;
+chem_picture_offset := chem_emwidth ;
chem_dbl_offset := .05 ;
chem_bb_angle := angle(1,2chem_dbl_offset) ;
chem_text_min := 0.75 ;
chem_text_max := 1.25 ;
chem_dot_factor := 4 ; % *linewidth
-chem_sb_pair := (0.25,0.75) ; chem_sb_dash := dashpattern(off 0.25 on 0.5 off 0.25) ;
-chem_sb_pair.m := (0.25,1.00) ; chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ;
-chem_sb_pair.p := (0.00,0.75) ; chem_sb_dash.p := dashpattern(on 0.75 off 0.25) ;
+chem_sb_pair := (0.25,0.75) ; %chem_sb_dash := dashpattern(off 0.25 on 0.5 off 0.25) ;
+chem_sb_pair.m := (0.25,1 ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ;
+chem_sb_pair.p := (0 ,0.75) ; %chem_sb_dash.p := dashpattern(on 0.75 off 0.25) ;
+chem_sb_pair.b := (0, 1 ) ; %chem_sb_dash.b := dashpattern(on 1) ;
chem_text_trace := false ; % debugging
chem_bd_wedge := false ; % true is incorrect, but quite common...
def chem_reset =
- chem_rotation := 0 ;
- chem_mirror := origin ;
- chem_adjacent := 0 ;
- chem_substituent := 0 ;
- chem_substituent.lft := 0 ;
- chem_substituent.rt := 0 ;
- chem_stack_n := 0 ;
- chem_doing_pb := false ;
- chem_origin := origin ;
- chem_previous := "one" ;
+ chem_rotation := 0 ;
+ chem_mirror := origin ;
+ chem_adjacent := 0 ;
+ chem_substituent := 0 ;
+ chem_substituent.lft := 0 ;
+ chem_substituent.rt := 0 ;
+ chem_stack_n := 0 ;
+ chem_doing_pb := false ;
+ chem_origin := origin ;
+ chem_previous := "one" ;
+ pair chem_mark_pair[] ;
enddef ;
chem_reset ;
@@ -100,21 +103,13 @@ newinternal numeric
three, four, five, six, seven, eight, nine,
fivefront, sixfront, chair, boat ;
-% We define all paths as closed, so that they may be indexed mod length.
-
vardef chem_init_some (suffix $) (expr e) =
- if not known chem_star[$]:
- chem_star[$] := false ;
- fi
- if not known chem_front[$]:
- chem_front[$] := false ;
- fi
- if not known chem_stacked[$]:
- chem_stacked[$] := false ;
- fi
- if not known chem_tetra[$]:
- chem_tetra[$] := false ;
- fi
+ if not known chem_star[$] : chem_star[$] := false ; fi
+ if not known chem_front[$] : chem_front[$] := false ; fi
+ if not known chem_stacked[$] : chem_stacked[$] := false ; fi
+ if not known chem_tetra[$] : chem_tetra[$] := false ; fi
+
+ % We define all paths as closed, so that they may be indexed mod length.
if path(e) :
chem_b_path[$] := e if not cycle(e) : -- cycle fi ;
chem_num0 := length(chem_b_path[$]) ;
@@ -249,10 +244,12 @@ begingroup
newmaneclipsed := incr indx ; % 14
chem_star[one] := true ;
- chem_star[carbon] := true ; chem_tetra[carbon] := true ;
- chem_star[alkyl] := true ; chem_tetra[alkyl] := true ;
- chem_star[newmanstagger] := true ; chem_stacked[newmanstagger] := true ;
- chem_star[newmaneclipsed] := true ; chem_stacked[newmaneclipsed] := true ;
+ chem_star[carbon] := true ; chem_tetra[carbon] := true ;
+ chem_star[alkyl] := true ; chem_tetra[alkyl] := true ;
+ chem_star[newmanstagger] := true ; chem_tetra[newmanstagger] := true ;
+ chem_star[newmaneclipsed] := true ; chem_tetra[newmaneclipsed] := true ;
+ chem_stacked[newmanstagger] := true ;
+ chem_stacked[newmaneclipsed] := true ;
chem_init_some(one, 8) ;
chem_init_some(carbon, dir(0)--dir(360-a)--dir(180-.5a+b)--dir(180-.5a)) ;
chem_init_some(alkyl, dir(0)--dir(360-a)--dir(360-a-90)--dir(90)) ;
@@ -305,7 +302,7 @@ chem_init_all ; % WHY does this not work unless defined and then called?
% unless of course the error be too harmful...
% \startchemical
-vardef chem_start_structure(expr i, l, r, t, b, scale, fitwidth, fitheight,
+def chem_start_structure(expr i, l, r, t, b, scale, rotation, fitwidth, fitheight,
emwidth, offset, axis, rulethickness, axiscolor) =
chem_emwidth := emwidth ; % EmWidth or \the\emwidth does not work...
@@ -316,10 +313,12 @@ vardef chem_start_structure(expr i, l, r, t, b, scale, fitwidth, fitheight,
chem_setting_r := r * chem_b_length ;
chem_setting_t := t * chem_b_length ;
chem_setting_b := b * chem_b_length ;
+ chem_setting_rotation := rotation ;
chem_setting_offset := offset ;
chem_setting_axis := if boolean axis : axis else : (axis<>0) fi ;
chem_axis_rulethickness := .75*(rulethickness) ; % axis 50% thinner than frame and bonds.
- chem_axis_color := if color axiscolor : axiscolor else : axiscolor*[white,black] fi ;
+ % We store the following as a picture in order to allow ALL color models...
+ chem_axis_color := image(draw origin withcolor axiscolor) ; % \MPcolor{axiscolor}) ;
chem_reset ;
enddef ;
@@ -327,7 +326,13 @@ enddef ;
% \stopchemical
vardef chem_stop_structure =
- currentpicture := currentpicture shifted - chem_origin ;
+ % Make sure that all of the saved stack has been restored... (this was a gotcha!)
+ forever :
+ exitif chem_stack_n=0 ;
+ chem_restore ;
+ endfor
+
+ currentpicture := (currentpicture shifted -chem_origin) rotated chem_setting_rotation ;
% axis here
if chem_setting_fitwidth :
chem_setting_l := - xpart llcorner currentpicture ;
@@ -345,18 +350,26 @@ vardef chem_stop_structure =
chem_num0 := .5chem_b_length ;
chem_num1 := .2chem_num0 ;
draw (-chem_setting_l,0) -- (chem_setting_r,0)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
draw (0,-chem_setting_b) -- (0,chem_setting_t)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
- for i = 0 step chem_num0 until chem_setting_r : draw (i,-chem_num1) -- (i,chem_num1)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor
- for i = 0 step -chem_num0 until -chem_setting_l : draw (i,-chem_num1) -- (i,chem_num1)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor
- for i = 0 step chem_num0 until chem_setting_t : draw (-chem_num1,i) -- (chem_num1,i)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor
- for i = 0 step -chem_num0 until -chem_setting_b : draw (-chem_num1,i) -- (chem_num1,i)
- withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor
- % frame=on : draw chem_setting_bbox withcolor chem_axis_color ;
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ for i = 0 step chem_num0 until chem_setting_r :
+ draw (i,-chem_num1) -- (i,chem_num1)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step -chem_num0 until -chem_setting_l :
+ draw (i,-chem_num1) -- (i,chem_num1)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step chem_num0 until chem_setting_t :
+ draw (-chem_num1,i) -- (chem_num1,i)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step -chem_num0 until -chem_setting_b :
+ draw (-chem_num1,i) -- (chem_num1,i)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ % frame=on : draw chem_setting_bbox withcolor colorpart(chem_axis_color) ;
addto currentpicture also chem_pic ;
fi ;
setbounds currentpicture to chem_setting_bbox ;
@@ -371,8 +384,9 @@ vardef chem_stop_component = enddef ;
vardef chem_pb = % PB :
if chem_trace_nesting :
- draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor chem_axis_color ;
- draw origin withpen pencircle scaled 2mm withcolor chem_axis_color ;
+ draw boundingbox currentpicture
+ withpen pencircle scaled 1mm withcolor colorpart(chem_axis_color) ;
+ draw origin withpen pencircle scaled 2mm withcolor colorpart(chem_axis_color) ;
fi ;
chem_doing_pb := true ;
enddef ;
@@ -382,7 +396,7 @@ vardef chem_pe = % PE
draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
draw origin withpen pencircle scaled 1mm withcolor red ;
fi ;
- currentpicture := currentpicture shifted - chem_origin ;
+ currentpicture := currentpicture shifted -chem_origin ;
if chem_trace_nesting :
draw origin withpen pencircle scaled .5mm withcolor green ;
fi ;
@@ -395,8 +409,8 @@ vardef chem_do (expr pos) =
pos
else :
chem_doing_pb := false ;
- currentpicture := currentpicture shifted - pos ;
- chem_origin := chem_origin - pos ;
+ currentpicture := currentpicture shifted -pos ;
+ chem_origin := chem_origin shifted -pos ;
origin % nullpicture
fi
enddef ;
@@ -418,11 +432,11 @@ enddef ;
vardef chem_restore = % RESTORE
if chem_stack_n>0 :
- currentpicture := currentpicture shifted - chem_origin ;
+ currentpicture := currentpicture shifted -chem_origin ;
addto chem_stack_p [chem_stack_n] also currentpicture ;
currentpicture := chem_stack_p [chem_stack_n] ;
chem_stack_p[chem_stack_n] := nullpicture ;
- chem_origin := chem_stack_origin [chem_stack_n] ;
+ chem_origin := chem_stack_origin [chem_stack_n] ;
chem_rotation := chem_stack_rotation[chem_stack_n] ;
chem_mirror := chem_stack_mirror [chem_stack_n] ;
chem_previous := chem_stack_previous[chem_stack_n] ;
@@ -471,21 +485,21 @@ enddef ;
vardef chem_draw (expr what, r, c) (text extra) =
draw what
withpen pencircle scaled r
- withcolor c
+ withcolor c %\MPcolor{c}
extra ;
enddef ;
vardef chem_fill (expr what, r, c) (text extra) =
fill what
withpen pencircle scaled r
- withcolor c
+ withcolor c %\MPcolor{c}
extra ;
enddef ;
vardef chem_drawarrow (expr what, r, c) (text extra) =
drawarrow what
withpen pencircle scaled r
- withcolor c
+ withcolor c %\MPcolor{c}
extra ;
enddef ;
@@ -517,8 +531,10 @@ vardef chem_set (suffix $) =
% find the closest opposite bond of the second structure
chem_pair1 := chem_pair0 rotated if chem_star[P] : 90 else : 180 fi ;
chem_num0 := abs(chem_pair1) ;
+ chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
% only consider even indices (cardinal points) for ONE
- for i=0 step if chem_star[$] : 2 else : 1 fi until (length chem_b_path[$]) :
+ chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
+ for i=0 step chem_num2 until chem_num1 :
chem_pair2 := (
(
unitvector
@@ -534,10 +550,10 @@ vardef chem_set (suffix $) =
) chem_transformed($) ;
if i=0 :
chem_pair3 := chem_pair2 ;
- chem_num1 := 0 ;
+ chem_num3 := 0 ;
elseif (abs(chem_pair1 shifted -chem_pair2)) < (abs(chem_pair1 shifted -chem_pair3)) :
chem_pair3 := chem_pair2 ;
- chem_num1 := i ;
+ chem_num3 := i ;
fi
endfor
if chem_star[$] :
@@ -549,9 +565,9 @@ vardef chem_set (suffix $) =
if not chem_star[$] :
chem_pair4 :=
if chem_star[P] :
- (point chem_num1
+ (point chem_num3
else :
- center(subpath (chem_num1,chem_num1+1)
+ center(subpath (chem_num3,chem_num3+1)
fi
of chem_b_path[$])
chem_transformed($) ;
@@ -560,8 +576,8 @@ vardef chem_set (suffix $) =
chem_pair4 := chem_pair4 shifted -chem_pair0 ;
fi
currentpicture := currentpicture shifted chem_pair4 ;
- chem_origin := chem_origin + chem_pair4 ;
- chem_adjacent := 0 ;
+ chem_origin := chem_origin shifted chem_pair4 ;
+ chem_adjacent := 0 ;
fi ;
% Insure that only one, if any, will be nonzero
@@ -588,36 +604,55 @@ vardef chem_set (suffix $) =
chem_pair1 := chem_pair0 if not chem_star[P] :
shifted -(point chem_substituent-1 of chem_b_path[P]) fi ;
chem_t := identity chem_transformed(P) ;
- chem_pair0 := chem_pair0 transformed chem_t ;
- chem_pair1 := chem_pair1 transformed chem_t ;
+ chem_pair0 := chem_pair0 transformed chem_t ; % radical
+ chem_pair1 := chem_pair1 transformed chem_t ; % recentered (see below)
currentpicture := currentpicture shifted -chem_pair0 ;
- chem_origin := chem_origin - chem_pair0 ;
- if not (chem_star[P] and chem_star[$]) :
- % find the closest node
- chem_pair1 := chem_pair1 rotated 180 ;
- chem_num0 := abs(chem_pair1) ;
- chem_num1 := length chem_b_path[$] ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ if (not (chem_star[P] and chem_star[$])) or chem_tetra[P] or chem_tetra[$] :
+ if chem_tetra[P] and chem_tetra[$] and ((chem_substituent=1) or (chem_substituent=2)):
+ chem_rotation := (chem_rotation + 180) mod 360 ; % trans-alkane
+ chem_pair2 := (point .5 of chem_b_path[$]) ; % bisector, not chem_transformed
+ if chem_mirror=origin :
+ chem_mirror := chem_pair2 ;
+ else :
+ chem_num0 := angle(chem_mirror)-angle(chem_pair2) ;
+ if (chem_num0>0) and (chem_num0> 180) :
+ chem_num0 := 360 - chem_num0 ;
+ elseif (chem_num0<0) and (chem_num0<-180) :
+ chem_num0 := -360 - chem_num0 ;
+ fi
+ chem_rotation := (chem_rotation + 2chem_num0) mod 360 ;
+ chem_mirror := origin ;
+ fi
+ fi
chem_t := identity chem_transformed($) ;
+ chem_pair1 := chem_pair1 rotated 180 ; % opposite direction of radical bond
+ % find the closest node
+ chem_num0 := abs(chem_pair1) ; % distance
+ % search to find the nearest node of $; only consider 1 and 2 for CARBON,ALKYL
+ chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
% only consider even indices (cardinal points) for ONE
- for i=0 step if chem_star[$] : 2 else : 1 fi until chem_num1 :
+ chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
+ for i=0 step chem_num2 until chem_num1 :
chem_pair2 := (unitvector(point i of chem_b_path[$]) scaled chem_num0)
transformed chem_t ;
if i=0 :
chem_pair3 := chem_pair2 ;
- chem_num2 := 0 ;
+ chem_num3 := 0 ;
elseif (abs(chem_pair1 shifted -chem_pair2)) <
(abs(chem_pair1 shifted -chem_pair3)) :
chem_pair3 := chem_pair2 ;
- chem_num2 := i ;
+ chem_num3 := i ;
fi
endfor
- if not chem_front[$] :
+ if not chem_front[$] : % adjust rotation
chem_rotation := (chem_rotation + angle(chem_pair1)-angle(chem_pair3)) mod 360 ;
fi ;
- chem_pair4 := (point chem_num2 of chem_b_path[$]) transformed chem_t ;
+ chem_t := identity chem_transformed($) ;
+ chem_pair4 := (point chem_num3 of chem_b_path[$]) transformed chem_t ;
if not chem_star[$] :
currentpicture := currentpicture shifted chem_pair4 ;
- chem_origin := chem_origin + chem_pair4 ;
+ chem_origin := chem_origin shifted chem_pair4 ;
fi
fi
chem_substituent := 0 ;
@@ -628,9 +663,11 @@ enddef ;
% line (f_rom, t_o, r_ule, c_olor)
-vardef chem_b (suffix $) (expr f, t, r, c) = % B
+vardef chem_b@# (suffix $) (expr f, t, r, c) = % B
if chem_star[$] :
- chem_r($,f,t,r,c) ;
+ chem_r@#($,f,t,r,c) ;
+ elseif length(str @#)>0 :
+ chem_sb@#($,f,t,r,c) ;
else :
chem_draw(
(subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
@@ -642,22 +679,32 @@ vardef chem_sb@# (suffix $) (expr f, t, r, c) = % SB
if chem_star[$] :
chem_sr@#($,f,t,r,c) ;
else :
- chem_draw(
- (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
- r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
- %chem_t := identity chem_transformed($) ;
- %for i=f upto t :
- % chem_draw(
- % (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
- % transformed chem_t,
- % r,c,) ;
- %endfor
+ %chem_draw(
+ % (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ transformed chem_t,
+ r,c,) ;
+ endfor
fi
enddef ;
-% Would it be better (faster?) to pre-calculate these and many other path fragments
-% and store them in arrays (with startup overhead), as Hans did before,
-% or continue to calculate them on the fly?
+vardef chem_sd@# (suffix $) (expr f, t, r, c) = % SD
+ if chem_star[$] :
+ chem_rd@#($,f,t,r,c) ;
+ else :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
+enddef ;
vardef chem_r_fragment@# (suffix $) (expr i) =
(
@@ -670,22 +717,27 @@ vardef chem_r_fragment@# (suffix $) (expr i) =
) % no ;
enddef ;
-vardef chem_r (suffix $) (expr f, t, r, c) = % R
- chem_num0 := length chem_b_path[$] ;
- chem_num1 := if chem_stacked[$] : floor(.5chem_num0) else : chem_num0 fi ;
- chem_t := identity chem_transformed($) ;
- for i=f upto t :
- chem_draw(
- (if i>chem_num1 : subpath (.5,1) of fi chem_r_fragment($,i)) transformed chem_t,
- r,c,) ;
- endfor
+vardef chem_r@# (suffix $) (expr f, t, r, c) = % R
+ if length(str @#)>0 :
+ chem_sr@#($,f,t,r,c) ;
+ else :
+ chem_sr.b($,f,t,r,c) ;
+ fi
+enddef ;
+
+vardef chem_er@# (suffix $) (expr f, t, r, c) = % ER
+ if length(str @#)>0:
+ chem_dr@#($,f,t,r,c) ;
+ else :
+ chem_dr.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_er (suffix $) (expr f, t, r, c) = % ER
+vardef chem_dr@# (suffix $) (expr f, t, r, c) = % DR
if not chem_front[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
- chem_path0 := chem_r_fragment($,i) ;
+ chem_path0 := (subpath chem_sb_pair@# of chem_r_fragment($,i)) ;
chem_draw(
(chem_path0 paralleled chem_dbl_offset) transformed chem_t,
r,c,) ;
@@ -696,69 +748,64 @@ vardef chem_er (suffix $) (expr f, t, r, c) = % ER
fi
enddef ;
-vardef chem_lr (suffix $) (expr f, t, r, c) = % LR
- if not chem_star[$] :
- chem_t := identity chem_transformed($) ;
- for i=f upto t :
- chem_draw(
- chem_r_fragment.lft($,i) transformed chem_t,
- r,c,) ;
- endfor
+vardef chem_lr@# (suffix $) (expr f, t, r, c) = % LR
+ if length(str @#)>0 :
+ chem_lsr@#($,f,t,r,c) ;
+ else :
+ chem_lsr.b($,f,t,r,c) ;
fi
enddef ;
-vardef chem_rr (suffix $) (expr f, t, r, c) = % RR
+vardef chem_rr@# (suffix $) (expr f, t, r, c) = % RR
+ if length(str @#)>0 :
+ chem_rsr@#($,f,t,r,c) ;
+ else :
+ chem_rsr.b($,f,t,r,c) ;
+ fi
+enddef ;
+
+vardef chem_eb@# (suffix $) (expr f, t, r, c) = % EB
if not chem_star[$] :
- chem_t := identity chem_transformed($) ;
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled -2chem_dbl_offset)
+ % chem_transformed($),
+ % r,c,dashed chem_sb_dash scaled chem_b_length) ;
for i=f upto t :
+ chem_t := identity chem_transformed($) ;
chem_draw(
- chem_r_fragment.rt($,i) transformed chem_t,
+ ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ paralleled -2chem_dbl_offset) transformed chem_t,
r,c,) ;
endfor
fi
enddef ;
-vardef chem_eb (suffix $) (expr f, t, r, c) = % EB
- if not chem_star[$] :
- chem_draw(
- ((subpath (f-1,t) of chem_b_path[$]) paralleled -2chem_dbl_offset) chem_transformed($),
- r,c,dashed chem_sb_dash scaled chem_b_length) ;
- %for i=f upto t :
- % chem_t := identity chem_transformed($) ;
- % chem_draw(
- % ((subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$])
- % paralleled -2chem_dbl_offset) transformed chem_t,
- % r,c,) ;
- %endfor
- fi
-enddef ;
-
-vardef chem_ad (suffix $) (expr f, t, r, c) = % AD
+vardef chem_ad@# (suffix $) (expr f, t, r, c) = % AD
if not chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
chem_drawarrow(
- ((subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$])
+ ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
paralleled 2chem_dbl_offset) transformed chem_t,
r,c,) ;
endfor
fi
enddef ;
-vardef chem_au (suffix $) (expr f, t, r, c) = % AU
+vardef chem_au@# (suffix $) (expr f, t, r, c) = % AU
if not chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
chem_drawarrow(
reverse(
- (subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$])
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
paralleled 2chem_dbl_offset) transformed chem_t,
r,c,) ;
endfor
fi
enddef ;
-vardef chem_es (suffix $) (expr f, t, r, c) = % ES
+vardef chem_es@# (suffix $) (expr f, t, r, c) = % ES
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
@@ -769,7 +816,7 @@ vardef chem_es (suffix $) (expr f, t, r, c) = % ES
fi
enddef ;
-vardef chem_ed (suffix $) (expr f, t, r, c) = % ED
+vardef chem_ed@# (suffix $) (expr f, t, r, c) = % ED
chem_t := identity chem_transformed($) ;
for i=f upto t :
if chem_star[$] :
@@ -789,7 +836,7 @@ vardef chem_ed (suffix $) (expr f, t, r, c) = % ED
endfor
enddef ;
-vardef chem_ep (suffix $) (expr f, t, r, c) = % EP
+vardef chem_ep@# (suffix $) (expr f, t, r, c) = % EP
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
@@ -802,7 +849,7 @@ vardef chem_ep (suffix $) (expr f, t, r, c) = % EP
fi
enddef ;
-vardef chem_et (suffix $) (expr f, t, r, c) = % ET
+vardef chem_et@# (suffix $) (expr f, t, r, c) = % ET
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
@@ -825,22 +872,24 @@ vardef chem_db@# (suffix $) (expr f, t, r, c) = % DB
chem_dr@#($,f,t,r,c) ;
elseif not chem_front[$] :
chem_t := identity chem_transformed($) ;
- chem_draw(
- ((subpath (f-1,t) of chem_b_path[$]) paralleled -chem_dbl_offset) transformed chem_t,
- r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
- chem_draw(
- ((subpath (f-1,t) of chem_b_path[$]) paralleled chem_dbl_offset) transformed chem_t,
- r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
- %for i=f upto t :
- % chem_path0 := subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ;
- % chem_draw(
- % (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
- % r,c,) ;
- % chem_draw(
- % (chem_path0 paralleled chem_dbl_offset) transformed chem_t,
- % r,c,) ;
- % % todo : this should be cut-off where it overlaps a neighboring standard bond.
- %endfor
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled -chem_dbl_offset)
+ % transformed chem_t,
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled chem_dbl_offset)
+ % transformed chem_t,
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ for i=f upto t :
+ chem_path0 := subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ;
+ chem_draw(
+ (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ % todo : this should be cut-off where it overlaps a neighboring standard bond.
+ endfor
fi
enddef ;
@@ -872,77 +921,66 @@ vardef chem_sr@# (suffix $) (expr f, t, r, c) = % SR
transformed chem_t,
r,c,) ;
endfor
- else:
- for i=f upto t :
- if chem_front[$] : % length=3...
- chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,0) of chem_r_fragment($,i)))
- transformed chem_t,
- r,c,) ;
- chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,2) of chem_r_fragment($,i)))
- transformed chem_t,
- r,c,) ;
- else :
- chem_draw(
- (subpath chem_sb_pair@# of chem_r_fragment($,i))
- transformed chem_t,
- r,c,) ;
- fi
- endfor
- fi
-enddef ;
-
-vardef chem_sd@# (suffix $) (expr f, t, r, c) = % SD
- if chem_star[$] :
- chem_t := identity chem_transformed($) ;
+ else :
for i=f upto t :
chem_draw(
- (subpath chem_sb_pair@# of chem_r_fragment($,i)) transformed chem_t,
- r,c,dashed evenly) ;
+ (subpath chem_sb_pair@# of chem_r_fragment($,i))
+ transformed chem_t,
+ r,c,) ;
endfor
fi
enddef ;
vardef chem_rd@# (suffix $) (expr f, t, r, c) = % RD
chem_t := identity chem_transformed($) ;
- for i=f upto t :
- if chem_front[$] :
- chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,0) of chem_r_fragment($,i)))
- transformed chem_t,
- r,c,dashed evenly) ;
+ if chem_stacked[$] :
+ chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ;
+ for i=f upto t :
chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,2) of chem_r_fragment($,i)))
+ (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i))
transformed chem_t,
r,c,dashed evenly) ;
- else :
+ endfor
+ else :
+ for i=f upto t :
chem_draw(
(subpath chem_sb_pair@# of chem_r_fragment($,i))
transformed chem_t,
r,c,dashed evenly) ;
- fi :
- endfor
+ endfor
+ fi
enddef ;
vardef chem_rh@# (suffix $) (expr f, t, r, c) = % RH
chem_t := identity chem_transformed($) ;
for i=f upto t :
- if chem_front[$] :
- chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,0) of chem_r_fragment($,i)))
- transformed chem_t,
- r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
- chem_draw(
- (subpath chem_sb_pair@# of (subpath (1,2) of chem_r_fragment($,i)))
- transformed chem_t,
- r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
- else :
- chem_draw(
- (subpath chem_sb_pair@# of chem_r_fragment($,i))
- transformed chem_t,
- chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
- fi
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
+ endfor
+enddef ;
+
+vardef chem_lrh@# (suffix $) (expr f, t, r, c) = % LRH
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.lft($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
+ endfor
+enddef ;
+
+vardef chem_rrh@# (suffix $) (expr f, t, r, c) = % RRH
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.rt($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
endfor
enddef ;
@@ -952,24 +990,9 @@ vardef chem_hb@# (suffix $) (expr f, t, r, c) = % HB
fi
enddef ;
-vardef chem_dr@# (suffix $) (expr f, t, r, c) = % DR
- if not chem_front[$] :
- chem_t := identity chem_transformed($) ;
- for i=f upto t :
- chem_path0 := (subpath chem_sb_pair@# of chem_r_fragment($,i)) ;
- chem_draw(
- (chem_path0 paralleled chem_dbl_offset) transformed chem_t,
- r,c,) ;
- chem_draw(
- (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
- r,c,) ;
- endfor
- fi
-enddef ;
-
-vardef chem_bb (suffix $) (expr f, t, r, c) = % BB
+vardef chem_bb@# (suffix $) (expr f, t, r, c) = % BB
if chem_star[$] :
- chem_rb($,f,t,r,c) ;
+ chem_rb@#($,f,t,r,c) ;
elseif chem_front[$] :
chem_t := identity chem_transformed($) ;
chem_draw(
@@ -989,8 +1012,8 @@ vardef chem_bb (suffix $) (expr f, t, r, c) = % BB
if chem_num2=1 : % Skip the first bold bond.
chem_fill(
(point chem_num2-1 of chem_b_path[$] --
- point chem_num2 of chem_b_path[$] shifted (0,-.5chem_dbl_offset) --
- point chem_num2 of chem_b_path[$] shifted (0, .5chem_dbl_offset) --
+ point chem_num2 of chem_b_path[$] shifted (0,-chem_dbl_offset) --
+ point chem_num2 of chem_b_path[$] shifted (0, chem_dbl_offset) --
cycle) transformed chem_t,
r,c,) ;
fi
@@ -999,16 +1022,16 @@ vardef chem_bb (suffix $) (expr f, t, r, c) = % BB
if chem_num3<chem_num1 : chem_num3 else : chem_num1-1 fi)
of chem_b_path[$] ;
chem_fill(
- (chem_path0 paralleled -.5chem_dbl_offset --
- reverse(chem_path0) paralleled -.5chem_dbl_offset --
+ (chem_path0 paralleled -chem_dbl_offset --
+ reverse(chem_path0) paralleled -chem_dbl_offset --
cycle) transformed chem_t,
r,c,) ;
fi
if chem_num3>=chem_num1 :
chem_fill(
(point chem_num1 of chem_b_path[$] --
- point chem_num1-1 of chem_b_path[$] shifted (0,-.5chem_dbl_offset) --
- point chem_num1-1 of chem_b_path[$] shifted (0, .5chem_dbl_offset) --
+ point chem_num1-1 of chem_b_path[$] shifted (0,-chem_dbl_offset) --
+ point chem_num1-1 of chem_b_path[$] shifted (0, chem_dbl_offset) --
cycle) transformed chem_t,
r,c,) ;
fi
@@ -1016,23 +1039,49 @@ vardef chem_bb (suffix $) (expr f, t, r, c) = % BB
fi
enddef ;
-vardef chem_lrb (suffix $) (expr f, t, r, c) = % LRB
- chem_rb.lft($,f,t,r,c) ;
+vardef chem_rb@# (suffix $) (expr f, t, r, c) = % RB
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_fill(
+ (point 0 of chem_path0 --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ endfor
enddef ;
-vardef chem_rrb (suffix $) (expr f, t, r, c) = % RRB
- chem_rb.rt ($,f,t,r,c) ;
+vardef chem_lrb@# (suffix $) (expr f, t, r, c) = % LRB
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
+ chem_fill(
+ (point 0 of chem_path0 --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_rb@# (suffix $) (expr f, t, r, c) = % RB
- if not chem_front[$] :
+vardef chem_rrb@# (suffix $) (expr f, t, r, c) = % RRB
+ if not chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
- chem_path0 := subpath chem_sb_pair of chem_r_fragment@#($,i) ;
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
chem_fill(
(point 0 of chem_path0 --
- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
cycle) transformed chem_t,
r,c,) ;
endfor
@@ -1083,11 +1132,11 @@ vardef chem_rrd@# (suffix $) (expr f, t, r, c) = % RRD
fi
enddef ;
-vardef chem_s (suffix $) (expr f, t, r, c) = % S
- if not (chem_star[$] or chem_front[$]) :
- chem_draw(
- (point f-2 of chem_b_path[$] -- point t of chem_b_path[$]) chem_transformed($),
- r,c,) ;
+vardef chem_s@# (suffix $) (expr f, t, r, c) = % S
+ if length(str @#)>0 :
+ chem_ss@#($,f,t,r,c) ;
+ else :
+ chem_ss.b($,f,t,r,c) ;
fi
enddef ;
@@ -1100,14 +1149,11 @@ vardef chem_ss@# (suffix $) (expr f, t, r, c) = % SS
fi
enddef ;
-vardef chem_mid (suffix $) (expr f, t, r, c) = % MID
- if not (chem_star[$] or chem_front[$]) :
- chem_t := identity chem_transformed($) ;
- for i=f upto t :
- chem_draw(
- (origin -- point i-1 of chem_b_path[$]) transformed chem_t,
- r,c,) ;
- endfor
+vardef chem_mid@# (suffix $) (expr f, t, r, c) = % MID
+ if length(str @#)>0 :
+ chem_mids@#($,f,t,r,c) ;
+ else :
+ chem_mids.b($,f,t,r,c) ;
fi
enddef ;
@@ -1161,7 +1207,7 @@ vardef chem_cc (suffix $) (expr f, t, r, c) = % CC
r,c,) ;
enddef ;
-vardef chem_ld@# (suffix $) (expr f, t, r, c) = % LD
+vardef chem_ldb@# (suffix $) (expr f, t, r, c) = % LD
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
@@ -1176,7 +1222,7 @@ vardef chem_ld@# (suffix $) (expr f, t, r, c) = % LD
fi
enddef ;
-vardef chem_rd@# (suffix $) (expr f, t, r, c) = % RD
+vardef chem_rdb@# (suffix $) (expr f, t, r, c) = % LD
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
@@ -1221,11 +1267,11 @@ vardef chem_rdd@# (suffix $) (expr f, t, r, c) = % RDD
fi
enddef ;
-vardef chem_oe (suffix $) (expr f, t, r, c) = % OE
+vardef chem_oe@# (suffix $) (expr f, t, r, c) = % OE
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
- chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
chem_draw(
@@ -1243,11 +1289,11 @@ vardef chem_oe (suffix $) (expr f, t, r, c) = % OE
fi
enddef ;
-vardef chem_bw (suffix $) (expr f, t, r, c) = % BW
+vardef chem_bw@# (suffix $) (expr f, t, r, c) = % BW
if chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
- chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
chem_draw(
@@ -1267,11 +1313,34 @@ vardef chem_bw (suffix $) (expr f, t, r, c) = % BW
fi
enddef ;
-vardef chem_bd (suffix $) (expr f, t, r, c) = % BD
- if chem_star[$] :
+vardef chem_bd@# (suffix $) (expr f, t, r, c) = % BD
+ if chem_star[$] : chem_rbd#@($,f,t,r,c) ; fi
+enddef ;
+
+vardef chem_rbd@# (suffix $) (expr f, t, r, c) = % RBD
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ if chem_bd_wedge :
+ chem_path1 := chem_path0 rotated -chem_bb_angle ;
+ chem_path2 := chem_path0 rotated chem_bb_angle ;
+ else :
+ chem_path1 := chem_path0 paralleled -chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled chem_dbl_offset ;
+ fi
+ for j=0 upto 3 :
+ chem_draw(
+ (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
+ 2r,c,) ;
+ endfor
+ endfor
+enddef ;
+
+vardef chem_lrbd@# (suffix $) (expr f, t, r, c) = % LRBD
+ if not chem_star[$] :
chem_t := identity chem_transformed($) ;
for i=f upto t :
- chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
if chem_bd_wedge :
chem_path1 := chem_path0 rotated -chem_bb_angle ;
chem_path2 := chem_path0 rotated chem_bb_angle ;
@@ -1288,79 +1357,76 @@ vardef chem_bd (suffix $) (expr f, t, r, c) = % BD
fi
enddef ;
-% text, number
-
-vardef chem_z@#(suffix $) (expr p) (text t) = % Z
- draw chem_text@#(t,
- chem_do (
- if p=0 :
- origin
+vardef chem_rrbd@# (suffix $) (expr f, t, r, c) = % RRBD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
+ if chem_bd_wedge :
+ chem_path1 := chem_path0 rotated -chem_bb_angle ;
+ chem_path2 := chem_path0 rotated chem_bb_angle ;
else :
- (point p-1 of chem_b_path[$]) chem_transformed($)
+ chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
fi
- )
- ) ;
+ for j=0 upto 3 :
+ chem_draw(
+ (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
+ 2r,c,) ;
+ endfor
+ endfor
+ fi
enddef ;
-vardef chem_cz@#(suffix $) (expr p) (text t) = % CZ ? (same as above)
- draw chem_text@#(t,
- chem_do (
+% text, number (no alignment on number);
+
+vardef chem_z@#(suffix $) (expr p) (text t) = % Z
+ draw chem_text@#
+ (t,chem_do(
if p=0 :
origin
else :
(point p-1 of chem_b_path[$]) chem_transformed($)
fi
- )
- ) ;
+ )) ;
enddef ;
+vardef chem_cz@#(suffix $) (expr p) (text t) = chem_z@#($,p,t) ; enddef ; % CZ ?
+
vardef chem_midz@#(suffix $) (expr p) (text t) = % MIDZ
if not (chem_star[$] or chem_front[$]) :
- draw chem_text@#(t,
- chem_do (
+ draw chem_text@#
+ (t,chem_do(
(xpart chem_sb_pair, 0) scaled (xpart point 0 of chem_b_path[$])
chem_transformed($)
- )
- ) ;
+ )) ;
fi
enddef ;
vardef chem_rz@#(suffix $) (expr p) (text t) = % RZ
- draw
- if (length(str @#)>0) and (str @# = "auto") :
- chem_text.autoalign(angle((point p-1 of chem_r_path[$]) chem_transformed($)))
- else :
- chem_text@#
- fi
- (t, chem_do((point p-1 of chem_r_path[$]) chem_transformed($))) ;
+% draw chem_text@#
+% (t, chem_do((point p-1 of chem_r_path[$]) chem_transformed($))) ;
+% freedotlabel(t,chem_do((point p-1 of chem_r_path[$]) chem_transformed($)),center chem_r_path[$] chem_transformed($))
+ freelabel(t,chem_do((point p-1 of chem_r_path[$]) chem_transformed($)),center chem_r_path[$] chem_transformed($))
enddef ;
vardef chem_lrz@#(suffix $) (expr p) (text t) = % LRZ
if not chem_star[$] :
- draw
- if (length(str @#)>0) and (str @# = "auto") :
- chem_text.autoalign(angle((point p-1 of chem_r_path.lft[$]) chem_transformed($)))
- else :
- chem_text@#
- fi
- (t, chem_do((point p-1 of chem_r_path.lft[$]) chem_transformed($))) ;
+ draw chem_text@#
+ (t,
+ chem_do((point p-1 of chem_r_path.lft[$]) chem_transformed($))) ;
fi
enddef ;
vardef chem_rrz@#(suffix $) (expr p) (text t) = % RRZ
if not chem_star[$] :
- draw
- if (length(str @#)>0) and (str @# = "auto") :
- chem_text.autoalign(angle((point p-1 of chem_r_path.rt[$]) chem_transformed($)))
- else :
- chem_text@#
- fi
+ draw chem_text@#
(t, chem_do((point p-1 of chem_r_path.rt[$]) chem_transformed($))) ;
fi
enddef ;
vardef chem_zn@#(suffix $) (expr p) (text t) = % ZN
- chem_zt@#($,p,t) ;
+ chem_zt($,p,t) ;
enddef ;
vardef chem_zt@#(suffix $) (expr p) (text t) = % ZT
@@ -1369,7 +1435,7 @@ vardef chem_zt@#(suffix $) (expr p) (text t) = % ZT
enddef ;
vardef chem_zln@#(suffix $) (expr p) (text t) = % ZLN
- chem_zlt@#($,p,t) ;
+ chem_zlt($,p,t) ;
enddef ;
vardef chem_zlt@#(suffix $) (expr p) (text t) = % ZLT
@@ -1378,7 +1444,7 @@ vardef chem_zlt@#(suffix $) (expr p) (text t) = % ZLT
enddef ;
vardef chem_zrn@#(suffix $) (expr p) (text t) = % ZRN
- chem_zrt@#($,p,t) ;
+ chem_zrt($,p,t) ;
enddef ;
vardef chem_zrt@#(suffix $) (expr p) (text t) = % ZRT
@@ -1388,25 +1454,28 @@ enddef ;
vardef chem_crz@#(suffix $) (expr p) (text t) = % CRZ ????
if chem_star[$] :
- draw chem_text(t, chem_do((point p-1 of chem_b_path[$] enlonged chem_center_offset)
+ draw chem_text@#(t, chem_do((point p-1 of chem_b_path[$] enlonged chem_center_offset)
chem_transformed($))) ;
fi
enddef ;
vardef chem_rn@#(suffix $) (expr i, t) = % RN
- chem_rt@#($,i,t) ;
+ chem_rt($,i,t) ;
enddef ;
vardef chem_rt@#(suffix $) (expr p) (text t) = % RT
draw chem_text@#(t, chem_do((center chem_r_fragment($,p)) chem_transformed($))) ;
enddef ;
-vardef chem_lrn@#(suffix $) (expr i, t) = chem_lrt@#($,i,t) ; enddef ; % LRN
+vardef chem_lrn@#(suffix $) (expr i, t) = % LRN
+ chem_lrt($,i,t) ;
+enddef ;
+
vardef chem_lrt@#(suffix $) (expr p) (text t) = % LRT
draw chem_text@#(t, chem_do((center chem_r_fragment.lft($,p)) chem_transformed($))) ;
enddef ;
-vardef chem_rrn (suffix $) (expr i, t) = % RRN
+vardef chem_rrn@# (suffix $) (expr i, t) = % RRN
chem_rrt($,i,t) ;
enddef ;
@@ -1416,13 +1485,28 @@ enddef ;
vardef chem_symbol(expr t) = draw textext(t) ; enddef ;
-vardef chem_text@#(expr txt, z) = % adapted copy of thelabel@
- chem_pic := textext(txt) ;
- chem_pic := chem_pic
+vardef chem_align@#(expr pic,off) =
+ pic
if (mfun_labtype@# >= 10) :
- shifted (0,ypart center chem_pic)
+ shifted (0,ypart center pic)
fi
- shifted (z + chem_text_offset*mfun_laboff@# - (mfun_labxf@#*lrcorner chem_pic + mfun_labyf@#*ulcorner chem_pic + (1-mfun_labxf@#-mfun_labyf@#)*llcorner chem_pic)) ;
+ shifted (chem_text_offset*mfun_laboff@# - (mfun_labxf@#*lrcorner pic + mfun_labyf@#*ulcorner pic + (1-mfun_labxf@#-mfun_labyf@#)*llcorner pic))
+enddef ;
+
+vardef chem_text@#(expr txt, z) = % adapted copy of thelabel@
+ save off ; numeric off ; off := chem_text_offset ;
+
+ chem_pic := textext(txt) rotated -chem_setting_rotation ;
+ chem_pic :=
+ if (length(str @#) > 0) and ((str @#) = "auto") :
+ if (abs z)>.71chem_emwidth : chem_align.autoalign(angle(z))
+ else : chem_align fi
+ else :
+ chem_align@#
+ fi
+ (chem_pic,off) ;
+ chem_pic := chem_pic shifted z ;
+
if chem_text_trace :
draw z withpen pencircle scaled 2pt withcolor red ;
draw boundingbox chem_pic withpen pencircle scaled 1pt withcolor red ;
@@ -1481,84 +1565,102 @@ enddef ;
vardef chem_dir (suffix $) (expr d, s) = % DIR (same as MOV(d-1)MOV(d+1))
if not chem_front[$] :
if d=0 :
- currentpicture := currentpicture shifted - chem_origin ;
- chem_origin := origin ;
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
else :
chem_pair0 :=
(((point d-2 of chem_b_path[$]) shifted (point d of chem_b_path[$])) scaled s)
chem_transformed($) ;
currentpicture := currentpicture shifted -chem_pair0 ;
- chem_origin := chem_origin - chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
fi
fi
enddef ;
vardef chem_mov (suffix $) (expr d, s) = % MOV
if d=0 :
- currentpicture := currentpicture shifted - chem_origin ;
- chem_origin := origin ;
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
else :
chem_pair0 := ((point d-1 of chem_b_path[$]) scaled s) chem_transformed($) ;
currentpicture := currentpicture shifted -chem_pair0 ;
- chem_origin := chem_origin - chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
fi ;
enddef ;
-pair chem_mark_pair[] ;
-
vardef chem_mark (suffix $) (expr d, s) = % MARK
% scale s is ignored
- if d>0 :
- chem_mark_pair[d] := chem_origin scaled -1 ;
+ if d<>0 :
+ chem_mark_pair[d] := -chem_origin ;
fi
enddef ;
vardef chem_marked (expr d) =
- if known chem_mark_pair[d] :
+ if d=0 :
+ chem_origin
+ elseif known chem_mark_pair[d] :
chem_mark_pair[d] shifted chem_origin
else :
origin
fi
enddef ;
+vardef chem_number@#(suffix $) (expr p) (text t) = chem_label@#($,p,t) enddef ; % NUMBER
+vardef chem_label@# (suffix $) (expr p) (text t) = % LABEL
+ draw chem_text@#(t,chem_do(chem_marked(p))) ;
+enddef ;
+
+vardef chem_move (suffix $) (expr d, s) = % MOVE
+ chem_pair0 := chem_marked(d) scaled s ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+enddef ;
+
+vardef chem_diff (suffix $) (expr d, s) = % DIFF
+ chem_pair0 := (chem_marked(d) shifted -chem_origin) scaled s ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+enddef ;
+
vardef chem_line (suffix $) (expr f, t, r, c) = % LINE
- draw chem_marked(f) -- chem_marked(t)
+ draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
% no chem_transformed
withpen pencircle scaled r
- withcolor c ;
+ withcolor c %\MPcolor{c}
enddef ;
vardef chem_dash (suffix $) (expr f, t, r, c) = % DASH
- draw chem_marked(f) -- chem_marked(t)
+ draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
% no chem_transformed
withpen pencircle scaled r
- withcolor c
+ withcolor c %\MPcolor{c}
dashed evenly ;
enddef ;
vardef chem_arrow (suffix $) (expr f, t, r, c) = % ARROW
- drawarrow chem_marked(f) -- chem_marked(t)
+ drawarrow if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
% no chem_transformed
withpen pencircle scaled r
- withcolor c ;
+ withcolor c %\MPcolor{c}
enddef ;
+
vardef chem_rm (suffix $) (expr d, s) = % RM
if (not chem_front[$]) and (d<>0) :
chem_pair0 := ((point d-1 of chem_r_path[$]) scaled s) chem_transformed($) ;
currentpicture := currentpicture shifted -chem_pair0 ;
- chem_origin := chem_origin - chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
fi ;
enddef ;
vardef chem_off (suffix $) (expr d, s) = % OFF
if d=0 :
- currentpicture := currentpicture shifted - chem_origin ;
- chem_origin := origin ;
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
else :
chem_pair0 := (unitvector(point d-1 of chem_b_path[one])) scaled chem_setting_offset*s ;
% not chem_transformed
currentpicture := currentpicture shifted -chem_pair0 ;
- chem_origin := chem_origin - chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
fi ;
enddef ;
diff --git a/metapost/context/base/mp-mlib.mpiv b/metapost/context/base/mp-mlib.mpiv
index 029bd3d6e..6fc694cf4 100644
--- a/metapost/context/base/mp-mlib.mpiv
+++ b/metapost/context/base/mp-mlib.mpiv
@@ -655,5 +655,3 @@ enddef ;
% draw textext.autoalign(160)("\strut oeps 2") ;
% draw textext.autoalign(260)("\strut oeps 3") ;
% draw textext.autoalign(360)("\strut oeps 4") ;
-
-
diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv
index 0566c5b44..a947143c4 100644
--- a/metapost/context/base/mp-tool.mpiv
+++ b/metapost/context/base/mp-tool.mpiv
@@ -2293,3 +2293,17 @@ vardef redecorated (text imagedata) text decoration =
endfor ;
currentpicture
enddef ;
+
+% path mfun_bleed_box ;
+
+% primarydef p bleeded d =
+% image (
+% mfun_bleed_box := boundingbox p ;
+% if pair d :
+% draw p xysized (bbwidth(p)+2*xpart d,bbheight(p)+2*ypart d) shifted -d ;
+% else :
+% draw p xysized (bbwidth(p)+2d,bbheight(p)+2d) shifted (-d,-d) ;
+% fi ;
+% setbounds currentpicture to mfun_bleed_box ;
+% )
+% enddef ;
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index 698a6f142..e4b5fb302 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -145,6 +145,30 @@ local report = application.report
scripts = scripts or { }
scripts.context = scripts.context or { }
+-- for the moment here
+
+local engine_new = getargument("engine") or directives.value("system.engine")
+local engine_old = environment.ownbin
+
+local function restart(engine_old,engine_new)
+ local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline())
+ report(format("redirect %s -> %s: %s",engine_old,engine_new,command))
+ local result = os.execute(command)
+ os.exit(result)
+end
+
+if getargument("redirected") then
+ setargument("engine",engine_old) -- later on we need this
+elseif engine_new == engine_old then
+ setargument("engine",engine_new) -- later on we need this
+elseif environment.validengines[engine_new] and engine_new ~= environment.basicengines[engine_old] then
+ restart(engine_old,engine_new)
+else
+ setargument("engine",engine_new) -- later on we need this
+end
+
+-- so far
+
-- constants
local usedfiles = {
@@ -334,7 +358,12 @@ local function preamble_analyze(filename) -- only files on current path
multipass_nofruns = t.nofruns
end
if not t.engine then
- t.engine = 'luatex'
+ t.engine = environment.basicengines[engine_old] --'luatex'
+ end
+ if t.engine ~= engine_old then -- hack
+ if environment.validengines[t.engine] and t.engine ~= environment.basicengines[engine_old] then
+ restart(engine_old,t.engine)
+ end
end
end
return t
@@ -430,8 +459,9 @@ local function flags_to_string(flags,prefix) -- context flags get prepended by c
return concat(t," ")
end
-local function luatex_command(l_flags,c_flags,filename)
- return format('luatex %s %s "%s"',
+local function luatex_command(l_flags,c_flags,filename,engine)
+ return format('%s %s %s "%s"',
+ engine or "luatex",
flags_to_string(l_flags),
flags_to_string(c_flags,true),
filename
@@ -470,6 +500,7 @@ end
function scripts.context.run(ctxdata,filename)
--
local a_nofile = getargument("nofile")
+ local a_engine = getargument("engine")
--
local files = environment.files or { }
--
@@ -496,11 +527,11 @@ function scripts.context.run(ctxdata,filename)
--
local interface = validstring(getargument("interface")) or "en"
local formatname = formatofinterface[interface] or "cont-en"
- local formatfile, scriptfile = resolvers.locateformat(formatname)
+ local formatfile, scriptfile = resolvers.locateformat(formatname) -- regular engine !
if not formatfile or not scriptfile then
report("warning: no format found, forcing remake (commandline driven)")
scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname) -- variant
end
if formatfile and scriptfile then
-- okay
@@ -526,6 +557,7 @@ function scripts.context.run(ctxdata,filename)
local a_backend = getargument("backend")
local a_arrange = getargument("arrange")
local a_noarrange = getargument("noarrange")
+ local a_jit = getargument("jit")
--
for i=1,#filelist do
--
@@ -550,11 +582,10 @@ function scripts.context.run(ctxdata,filename)
end
if not formatfile or not scriptfile then
report("warning: no format found, forcing remake (source driven)")
- scripts.context.make(formatname)
+ scripts.context.make(formatname,a_engine)
formatfile, scriptfile = resolvers.locateformat(formatname)
end
if formatfile and scriptfile then
- --
local suffix = validstring(getargument("suffix"))
local resultname = validstring(getargument("result"))
if suffix then
@@ -583,13 +614,17 @@ function scripts.context.run(ctxdata,filename)
pdf_close(resultname,pdfview)
end
end
- --
- local okay = statistics.checkfmtstatus(formatfile)
+ local okay = statistics.checkfmtstatus(formatfile,a_engine)
if okay ~= true then
report("warning: %s, forcing remake",tostring(okay))
scripts.context.make(formatname)
end
--
+-- if a_engine and a_engine ~= "" and a_engine ~= "luatex" then
+-- formatfile = gsub(formatfile,"/luatex%-cache/",format("/%s-cache/",a_engine))
+-- scriptfile = gsub(scriptfile,"/luatex%-cache/",format("/%s-cache/",a_engine))
+-- end
+ --
local oldhash = multipass_hashfiles(jobname)
local newhash = { }
local maxnofruns = once and 1 or multipass_nofruns
@@ -621,6 +656,7 @@ function scripts.context.run(ctxdata,filename)
["fmt"] = formatfile,
["lua"] = scriptfile,
["jobname"] = jobname,
+ ["jiton"] = a_jit and true or nil,
}
--
if a_synctex then
@@ -652,7 +688,7 @@ function scripts.context.run(ctxdata,filename)
c_flags.currentrun = currentrun
c_flags.noarrange = a_noarrange or a_arrange or nil
--
- local command = luatex_command(l_flags,c_flags,mainfile)
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
--
report("run %s: %s",i,command)
print("") -- cleaner, else continuation on same line
@@ -690,7 +726,7 @@ function scripts.context.run(ctxdata,filename)
c_flags.currentrun = c_flags.currentrun + 1
c_flags.noarrange = nil
--
- local command = luatex_command(l_flags,c_flags,mainfile)
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
--
report("arrange run: %s",command)
local returncode, errorstring = os.spawn(command)
@@ -808,7 +844,9 @@ function scripts.context.pipe() -- still used?
end
end
-local make_mkiv_format = environment.make_format
+local function make_mkiv_format(name,engine)
+ environment.make_format(name)
+end
local function make_mkii_format(name,engine)
local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
@@ -833,8 +871,8 @@ function scripts.context.make(name)
name = formatofinterface[name] or name or ""
if name == "" then
-- nothing
- elseif engine == "luatex" then
- make_mkiv_format(name)
+ elseif engine == "luatex" or engine == "luajittex" then
+ make_mkiv_format(name,engine)
elseif engine == "pdftex" or engine == "xetex" then
make_mkii_format(name,engine)
end
@@ -1438,7 +1476,3 @@ elseif getargument("purgeall") then
else
application.help("basic")
end
-
-if getargument("profile") then
- os.setenv("MTX_PROFILE_RUN","NO")
-end
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 01c601eb5..3a02ad582 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,7 +54,7 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-functions'] = {
+if not modules then modules = { } end modules ['l-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -51,16 +62,112 @@ if not modules then modules = { } end modules ['l-functions'] = {
license = "see context related readme files"
}
-functions = functions or { }
+-- compatibility hacks ... try to avoid usage
-function functions.dummy() end
+local major, minor = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+
+_MAJORVERSION = tonumber(major) or 5
+_MINORVERSION = tonumber(minor) or 1
+
+-- basics:
+
+if loadstring then
+
+ local loadnormal = load
+
+ function load(first,...)
+ if type(first) == "string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+
+else
+
+ loadstring = load
+
+end
+
+-- table:
+
+-- Starting with version 5.2 Lua no longer provide ipairs, which makes
+-- sense. As we already used the for loop and # in most places the
+-- impact on ConTeXt was not that large; the remaining ipairs already
+-- have been replaced. In a similar fashion we also hardly used pairs.
+--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- The unpack function has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+
+ table.unpack = _G.unpack
+
+elseif not unpack then
+
+ _G.unpack = table.unpack
+
+end
+
+-- package:
+
+-- if not package.seachers then
+--
+-- package.searchers = package.loaders -- 5.2
+--
+-- elseif not package.loaders then
+--
+-- package.loaders = package.searchers
+--
+-- end
+
+if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type
+
+ package.loaders = package.searchers
+
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
+if not modules then modules = { } end modules ['l-lpeg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -68,34 +175,843 @@ if not modules then modules = { } end modules ['l-string'] = {
license = "see context related readme files"
}
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
--- some functions may disappear as they are not used anywhere
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
-if not string.split then
+local lpeg = require("lpeg")
- -- this will be overloaded by a faster lpeg variant
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
+-- some code will move to unicode and string
+
+local report = texio and texio.write_nl or print
+
+-- local lpmatch = lpeg.match
+-- local lpprint = lpeg.print
+-- local lpp = lpeg.P
+-- local lpr = lpeg.R
+-- local lps = lpeg.S
+-- local lpc = lpeg.C
+-- local lpb = lpeg.B
+-- local lpv = lpeg.V
+-- local lpcf = lpeg.Cf
+-- local lpcb = lpeg.Cb
+-- local lpcg = lpeg.Cg
+-- local lpct = lpeg.Ct
+-- local lpcs = lpeg.Cs
+-- local lpcc = lpeg.Cc
+-- local lpcmt = lpeg.Cmt
+-- local lpcarg = lpeg.Carg
+
+-- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+-- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+-- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+-- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+-- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+-- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+-- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+-- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+-- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+-- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+-- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+-- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+-- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+-- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+-- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+patterns.utfoffset = utfoffset
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * P(-1) / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
+
+patterns.stripper = stripper
+patterns.collapser = collapser
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.unsigned = digit^0 * P('.') * digit^1
+patterns.float = sign^0 * patterns.unsigned
+patterns.cunsigned = digit^0 * P(',') * digit^1
+patterns.cfloat = sign^0 * patterns.cunsigned
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
+patterns.propername = R("AZ","az","__") * R("09","AZ","az", "__")^0 * P(-1)
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
+end
+
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.split(str,separator)
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+
+-- lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+-- from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(anything^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * endofstring)^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
+ local pattern
+ local u = isutf and utf8char or 1
+ if type(one) == "table" then
+ local no = #one
+ local p = P(false)
+ if no == 0 then
+ for k, v in next, one do
+ p = p + P(k) / v
+ end
+ pattern = Cs((p + u)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ -- pattern = Cs(((1-one)^1 + one/two)^0)
+ pattern = Cs((one/two + u)^0)
+ else
+ for i=1,no do
+ local o = one[i]
+ p = p + P(o[1]) / o[2]
+ end
+ pattern = Cs((p + u)^0)
+ end
+ else
+ pattern = Cs((P(one)/(two or "") + u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst) == "table" then
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
+ end
+ else
+ pattern = P(lst)
+ end
+ pattern = (1-pattern)^0 * pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+
+-- utf extensies
+
+local utfcharacters = utf and utf.characters or string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+local utfchar = utf and utf.char or (unicode and unicode.utf8 and unicode.utf8.char)
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfcharacters(str) do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfgmatch(str,".") do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p = P(false)
+ local f = function(uc)
+ p = p + P(uc)
+ end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
+ local p = P(false)
+ for i=first,last do
+ p = p + P(utfchar(i))
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ -- tricky, these nested captures
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+-- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
+
+-- lpeg.print(lpeg.R("ab","cd","gh"))
+-- lpeg.print(lpeg.P("a","b","c"))
+-- lpeg.print(lpeg.S("a","b","c"))
+
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- table.sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = t[k]
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
end
end
- return t
end
+ return p
+end
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
end
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
+
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-functions'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+functions = functions or { }
+
+function functions.dummy() end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-string'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string = string
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
+
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
+
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
+
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
+
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
+
function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+ return lpegmatch(unquoted,str) or str
end
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function string.quoted(str)
return format("%q",str) -- always "
@@ -118,65 +1034,112 @@ function string.limit(str,n,sentinel) -- not utf proof
end
end
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+local stripper = patterns.stripper
+local collapser = patterns.collapser
function string.strip(str)
return lpegmatch(stripper,str) or ""
end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1)
+
function string.is_empty(str)
- return not find(str,"%S")
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
if str == "" then
return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
- end
- if strict then
- return "^" .. str .. "$"
- else
- return str
- end
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
end
end
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
function string.valid(str,default)
return (type(str) == "string" and str ~= "" and str) or default or nil
end
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
-
-- handy fallback
string.itself = function(s) return s end
@@ -189,6 +1152,19 @@ function string.totable(str)
return lpegmatch(pattern,str)
end
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
+
end -- of closure
@@ -202,68 +1178,23 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
local table, string = table, string
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local getinfo = debug.getinfo
-
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Hm, actually ipairs was retained, but we no longer use it anyway.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
-
-if not ipairs then
-
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
-
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
-
- function ipairs(a)
- return iterate, a, 0
- end
-
-end
-
-if not pairs then
-
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
-
- function pairs(t)
- return next, t -- , nil
- end
-
-end
-
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
-
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local floor = math.floor
-- extra functions, some might go (when not used)
+local stripper = patterns.stripper
+
function table.strip(tab)
local lst, l = { }, 0
for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
-- skip this one
else
@@ -372,7 +1303,7 @@ local function sortedhash(t)
end
table.sortedhash = sortedhash
-table.sortedpairs = sortedhash
+table.sortedpairs = sortedhash -- obsolete
function table.append(t,list)
local n = #t
@@ -396,31 +1327,63 @@ function table.prepend(t, list)
return t
end
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
t[k] = v
end
end
return t
end
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
function table.merged(...)
- local tmp, lst = { }, { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
- tmp[k] = v
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
end
end
- return tmp
+ return t
end
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
function table.imerge(t, ...)
- local lst, nt = { ... }, #t
- for i=1,#lst do
- local nst = lst[i]
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
nt = nt + 1
t[nt] = nst[j]
@@ -429,10 +1392,22 @@ function table.imerge(t, ...)
return t
end
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
function table.imerged(...)
- local tmp, ntmp, lst = { }, 0, {...}
- for i=1,#lst do
- local nst = lst[i]
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
ntmp = ntmp + 1
tmp[ntmp] = nst[j]
@@ -444,7 +1419,7 @@ end
local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
- for k,v in next, old do
+ for k, v in next, old do
if type(v) == "table" then
new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
@@ -498,7 +1473,7 @@ end
table.fastcopy = fastcopy
table.copy = copy
-function table.derive(parent)
+function table.derive(parent) -- for the moment not public
local child = { }
if parent then
setmetatable(child,{ __index = parent })
@@ -579,6 +1554,13 @@ end
-- problem: there no good number_to_string converter with the best resolution
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
local function dummy() end
local function do_serialize(root,name,depth,level,indexed)
@@ -588,14 +1570,14 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s{",depth))
else
local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
+ if tn == "number" then
if hexify then
handle(format("%s[0x%04X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
handle(format("%s%s={",depth,name))
else
handle(format("%s[%q]={",depth,name))
@@ -621,7 +1603,6 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
--- if not root[k] then
if root[k] == nil then
last = k - 1
break
@@ -667,7 +1648,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
+ handle(format('%s load(%q),',depth,dump(v)))
else
handle(format('%s "function",',depth))
end
@@ -679,7 +1660,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s __p__=nil,",depth))
end
elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
else
@@ -691,7 +1672,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%04X,",depth,k,v))
else
@@ -706,7 +1687,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "string" then
if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,v))
else
@@ -714,13 +1695,13 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,v))
else
@@ -728,7 +1709,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
handle(format("%s [%q]=%q,",depth,k,v))
@@ -736,7 +1717,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "table" then
if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={},",depth,k))
else
@@ -744,7 +1725,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
handle(format("%s [%q]={},",depth,k))
@@ -752,15 +1733,15 @@ local function do_serialize(root,name,depth,level,indexed)
elseif inline then
local st = simple_table(v)
if st then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
@@ -772,15 +1753,15 @@ local function do_serialize(root,name,depth,level,indexed)
do_serialize(v,k,depth,level+1)
end
elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%s,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%s,",depth,k,tostring(v)))
@@ -789,30 +1770,30 @@ local function do_serialize(root,name,depth,level,indexed)
if functions then
local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
@@ -892,6 +1873,14 @@ local function serialize(_handle,root,name,specification) -- handle wins
handle("}")
end
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
function table.serialize(root,name,specification)
local t, n = { }, 0
@@ -980,7 +1969,7 @@ table.flattened = flattened
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
- f = { }
+ f = { } -- this one can become obsolete
end
for i=1,#t do
local v = t[i]
@@ -1009,7 +1998,7 @@ local function are_equal(a,b,n,m) -- indexed
local ai, bi = a[i], b[i]
if ai==bi then
-- same
- elseif type(ai)=="table" and type(bi)=="table" then
+ elseif type(ai) == "table" and type(bi) == "table" then
if not are_equal(ai,bi) then
return false
end
@@ -1044,10 +2033,10 @@ table.are_equal = are_equal
-- maybe also make a combined one
-function table.compact(t)
+function table.compact(t) -- remove empty tables, assumes subtables
if t then
- for k,v in next, t do
- if not next(v) then
+ for k, v in next, t do
+ if not next(v) then -- no type checking
t[k] = nil
end
end
@@ -1086,7 +2075,7 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirror(t) -- hash
+function table.mirrored(t) -- hash
local n = { }
for k, v in next, t do
n[v] = k
@@ -1109,6 +2098,17 @@ function table.reversed(t)
end
end
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
function table.sequenced(t,sep) -- hash only
if t then
local s, n = { }, 0
@@ -1196,848 +2196,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
--- some code will move to unicode and string
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type, next = type, next
-local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
-local lpegtype, lpegmatch = lpeg.type, lpeg.match
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-local eol = S("\n\r")
-local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-local whitespace = eol + spacer
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.unsigned = digit^0 * P('.') * digit^1
-patterns.float = sign^0 * patterns.unsigned
-patterns.cunsigned = digit^0 * P(',') * digit^1
-patterns.cfloat = sign^0 * patterns.cunsigned
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = eol
-patterns.spacer = spacer
-patterns.whitespace = whitespace
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - spacer
-patterns.nonwhitespace = 1 - whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.singlequoted = squote * patterns.nosquote * squote
-patterns.doublequoted = dquote * patterns.nodquote * dquote
-patterns.quoted = patterns.doublequoted + patterns.singlequoted
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-local function anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) }
-end
-
-lpeg.anywhere = anywhere
-
-function lpeg.instringchecker(p)
- p = anywhere(p)
- return function(str)
- return lpegmatch(p,str) and true or false
- end
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return lpegmatch(splitters_m[separator] or splitat(separator),str)
-end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.split(str,separator)
- if separator then
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
- else
- return { str }
- end
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = tsplitat(newline)
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return lpegmatch(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return lpegmatch(utflinesplitter,str or "")
-end
-
-local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
-local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
-
-function string.utfsplit(str,ignorewhitespace) -- new
- if ignorewhitespace then
- return lpegmatch(utfcharsplitter_iws,str or "")
- else
- return lpegmatch(utfcharsplitter_ows,str or "")
- end
-end
-
--- inspect(string.utfsplit("a b c d"))
--- inspect(string.utfsplit("a b c d",true))
-
--- -- alternative 1: 0.77
---
--- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
---
--- function string.utflength(str)
--- return #lpegmatch(utfcharcounter,str or "")
--- end
---
--- -- alternative 2: 1.70
---
--- local n = 0
---
--- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
---
--- function string.utflength(str)
--- n = 0
--- lpegmatch(utfcharcounter,str or "")
--- return n
--- end
---
--- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
-
-local n = 0
-
-local utfcharcounter = utfbom^-1 * Cs ( (
- Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
- + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
- + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
- + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
-)^0 )
-
-function string.utflength(str)
- n = 0
- lpegmatch(utfcharcounter,str or "")
- return n
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(anything^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * endofstring)^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two,makefunction)
- local pattern
- if type(one) == "table" then
- local no = #one
- local p = P(false)
- if no == 0 then
- for k, v in next, one do
- p = p + P(k) / v
- end
- pattern = Cs((p + 1)^0)
- elseif no == 1 then
- local o = one[1]
- one, two = P(o[1]), o[2]
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two + 1)^0)
- else
- for i=1,no do
- local o = one[i]
- p = p + P(o[1]) / o[2]
- end
- pattern = Cs((p + 1)^0)
- end
- else
- one = P(one)
- two = two or ""
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two +1)^0)
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
-function lpeg.finder(lst,makefunction)
- local pattern
- if type(lst) == "table" then
- local p = P(false)
- for i=1,#lst do
- p = p + P(lst[i])
- end
- pattern = (p + 1)^0
- else
- pattern = (P(lst) + 1)^0
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
--- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
--- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
--- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #lpegmatch(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #lpegmatch(p,str)
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfcharacters(str) do
- p = p + P(uc)
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfgmatch(str,".") do
- p = p + P(uc)
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p = P(false)
- local f = function(uc)
- p = p + P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
- local p = P(false)
- for i=first,last do
- p = p + P(utfchar(i))
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- -- tricky, these nested captures
- return utf8byte / f -- nil when invalid range
- end
-end
-
--- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
-
-
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- table.sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
-
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
-
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
-
--- experiment:
-
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
-end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
- end
- return make(tree)
-end
-
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
--- handy from within tex:
-
-local lpegmatch = lpeg.match
-
-local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
-
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-
--- strips leading and trailing spaces and collapsed all other spaces
-
-local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
-
-function string.collapsespaces(str)
- return lpegmatch(pattern,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-io'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -2368,7 +2526,7 @@ function io.readstring(f,n,m)
f:seek("set",n)
n = m
end
- local str = gsub(f:read(n),"%z","")
+ local str = gsub(f:read(n),"\000","")
return str
end
@@ -2418,10 +2576,129 @@ local lpegmatch = lpeg.match
number = number or { }
local number = number
--- a,b,c,d,e,f = number.toset(100101)
+if bit32 then
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p)
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
+
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ }
+
+ function number.tobitstring(b,m)
+ -- if really needed we can speed this one up
+ -- because small numbers need less extraction
+ local n = 32
+ for i=0,31 do
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
end
function number.toevenhex(n)
@@ -2433,86 +2710,59 @@ function number.toevenhex(n)
end
end
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
--
-- for i=1,1000000 do
-- local a,b,c,d,e,f,g,h = number.toset(12345678)
-- local a,b,c,d = number.toset(1234)
-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
-- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-local one = lpeg.C(1-lpeg.S(''))^1
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
function number.toset(n)
return lpegmatch(one,tostring(n))
end
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
local m = n % 2
+ local n = floor(n/2)
if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
- end
- return t
-end
-
-
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
-
-function number.setbit(x, p)
- return (x % (p + p) >= p) and x or x + p
-end
-
-function number.clearbit(x, p)
- return (x % (p + p) >= p) and x - p or x
-end
-
-
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+ return bits(n, i+1, i, ...)
else
- return "00000000"
+ return bits(n, i+1, ...)
end
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ return ...
end
end
-
-function number.valid(str,default)
- return tonumber(str) or default or nil
+function number.bits(n)
+ return { bits(n,1) }
end
@@ -3104,25 +3354,25 @@ local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = C((noslashes^0 * slashes^1)^1)
local function pathpart(name,default)
- return lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
end
local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
local function basename(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
local function nameonly(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
local function suffixonly(name)
- return lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
end
file.pathpart = pathpart
@@ -3153,7 +3403,9 @@ local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra capture
local pattern_d = path * rest
function file.splitname(str,splitdrive)
- if splitdrive then
+ if not str then
+ -- error
+ elseif splitdrive then
return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
else
return lpegmatch(pattern_b,str) -- returns path, base, suffix
@@ -3161,34 +3413,36 @@ function file.splitname(str,splitdrive)
end
function file.splitbase(str)
- return lpegmatch(pattern_d,str) -- returns path, base+suffix
+ return str and lpegmatch(pattern_d,str) -- returns path, base+suffix
end
function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
- else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
end
local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1)
function file.removesuffix(name)
- return lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
end
-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
@@ -3205,8 +3459,8 @@ end
local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
return filename
elseif criterium == true then
return filename .. "." .. suffix
@@ -3252,7 +3506,7 @@ local suffix = period * (1-period-slashes)^1 * -1
local pattern = Cs((1-suffix)^0)
function file.replacesuffix(name,suffix)
- if suffix and suffix ~= "" then
+ if name and suffix and suffix ~= "" then
return lpegmatch(pattern,name) .. "." .. suffix
else
return name
@@ -3261,10 +3515,10 @@ end
--
-local reslasher = lpeg.replacer(S("\\"),"/")
+local reslasher = lpeg.replacer(P("\\"),"/")
function file.reslash(str)
- return lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
end
-- We should be able to use:
@@ -3280,7 +3534,9 @@ end
-- variant:
function file.is_writable(name)
- if lfs.isdir(name) then
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
local f = io.open(name,"wb")
if f then
@@ -3308,24 +3564,32 @@ end
local readable = P("r") * Cc(true)
function file.is_readable(name)
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
function file.size(name)
- local a = attributes(name)
- return a and a.size or 0
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
end
function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
- return checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
end
function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
local stripper = Cs(P(fwslash)^0/"" * reslasher)
@@ -3333,14 +3597,23 @@ local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
-function file.join(...) -- rather dirty
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
return one .. "/" .. two
elseif lpegmatch(isroot,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
return two
else
@@ -3349,7 +3622,7 @@ function file.join(...) -- rather dirty
elseif one == "" then
return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(reslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat(lst,"/"))
end
end
@@ -3378,6 +3651,9 @@ local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * C
local absolute = fwslash
function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
if anchor and not lpegmatch(anchors,str) then
str = getcurrentdir() .. "/" .. str
end
@@ -3387,7 +3663,6 @@ function file.collapsepath(str,anchor)
return lpegmatch(reslasher,str)
end
local starter, oldelements = lpegmatch(splitstarter,str)
--- inspect(oldelements)
local newelements = { }
local i = #oldelements
while i > 0 do
@@ -3441,11 +3716,13 @@ local whatever = P("-")^0 / ""
local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
function file.robustname(str,strict)
- str = lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
- else
- return str
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
end
end
@@ -3453,7 +3730,9 @@ file.readdata = io.loaddata
file.savedata = io.savedata
function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+ if oldname and newname then
+ file.savedata(newname,io.loaddata(oldname))
+ end
end
-- also rewrite previous
@@ -3474,11 +3753,11 @@ lpeg.patterns.rootbased = rootbased
-- ./name ../name /name c: :// name/name
function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+ return filename and lpegmatch(qualified,filename) ~= nil
end
function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
+ return filename and lpegmatch(rootbased,filename) ~= nil
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -3500,8 +3779,10 @@ end
-- for myself:
function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
end
-- local debuglist = {
@@ -3943,7 +4224,7 @@ if not modules then modules = { } end modules ['l-dir'] = {
-- dir.expandname will be merged with cleanpath and collapsepath
-local type = type
+local type, select = type, select
local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
@@ -4165,15 +4446,15 @@ local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
if onwindows then
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
end
end
local first, middle, last
@@ -4222,9 +4503,9 @@ if onwindows then
else
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
if s and s ~= "" then -- we catch nil and false
if str ~= "" then
str = str .. "/" .. s
@@ -4424,29 +4705,45 @@ if not modules then modules = { } end modules ['l-unicode'] = {
-- todo: utf.sub replacement (used in syst-aux)
-local concat = table.concat
+-- we put these in the utf namespace:
+
+utf = utf or (unicode and unicode.utf8) or { }
+
+utf.characters = utf.characters or string.utfcharacters
+utf.values = utf.values or string.utfvalues
+
+-- string.utfvalues
+-- string.utfcharacters
+-- string.characters
+-- string.characterpairs
+-- string.bytes
+-- string.bytepairs
+
local type = type
-local P, C, R, Cs, Ct, Cmt = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt
+local char, byte, format, sub = string.char, string.byte, string.format, string.sub
+local concat = table.concat
+local P, C, R, Cs, Ct, Cmt, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local utftype = patterns.utftype
-local char, byte, find, bytepairs, utfvalues, format, sub = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format, string.sub
-local utfsplitlines = string.utfsplitlines
-if not unicode then
+local bytepairs = string.bytepairs
- unicode = { }
+local finder = lpeg.finder
+local replacer = lpeg.replacer
-end
+local utfvalues = utf.values
+local utfgmatch = utf.gmatch -- not always present
-local unicode = unicode
+local p_utftype = patterns.utftype
+local p_utfoffset = patterns.utfoffset
+local p_utf8char = patterns.utf8char
+local p_utf8byte = patterns.utf8byte
+local p_utfbom = patterns.utfbom
+local p_newline = patterns.newline
+local p_whitespace = patterns.whitespace
-utf = utf or unicode.utf8
-
-if not utf then
+if not unicode then
- utf8 = { }
- unicode.utf8 = utf8
- utf = utf8
+ unicode = { utf = utf } -- for a while
end
@@ -4503,64 +4800,13 @@ if not utf.byte then
end
-if not utf.sub then
-
- local utf8char = patterns.utf8char
-
- -- inefficient as lpeg just copies ^n
-
- -- local function sub(str,start,stop)
- -- local pattern = utf8char^-(start-1) * C(utf8char^-(stop-start+1))
- -- inspect(pattern)
- -- return lpegmatch(pattern,str) or ""
- -- end
-
- local b, e, n, first, last = 0, 0, 0, 0, 0
-
- local function slide(s,p)
- n = n + 1
- if n == first then
- b = p
- if not last then
- return nil
- end
- end
- if n == last then
- e = p
- return nil
- else
- return p
- end
- end
-
- local pattern = Cmt(utf8char,slide)^0
-
- function utf.sub(str,start,stop) -- todo: from the end
- if not start then
- return str
- end
- b, e, n, first, last = 0, 0, 0, start, stop
- lpegmatch(pattern,str)
- if not stop then
- return sub(str,b)
- else
- return sub(str,b,e)
- end
- end
-
- -- print(utf.sub("Hans Hagen is my name"))
- -- print(utf.sub("Hans Hagen is my name",5))
- -- print(utf.sub("Hans Hagen is my name",5,10))
-
-end
-
local utfchar, utfbyte = utf.char, utf.byte
-- As we want to get rid of the (unmaintained) utf library we implement our own
-- variants (in due time an independent module):
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
end
local toentities = Cs (
@@ -4647,7 +4893,7 @@ local pattern = P("\254\255") * Cs( (
+ one
)^1 )
-function string.toutf(s)
+function string.toutf(s) -- in string namespace
return lpegmatch(pattern,s) or s -- todo: utf32
end
@@ -4663,26 +4909,269 @@ local validatedutf = Cs (
patterns.validatedutf = validatedutf
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.is_valid(str)
+ return type(str) == "string" and lpegmatch(validatedutf,str) or false
end
+if not utf.len then
-utf.length = string.utflength
-utf.split = string.utfsplit
-utf.splitines = string.utfsplitlines
-utf.valid = string.validutf
+ -- -- alternative 1: 0.77
+ --
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ --
+ -- function utf.len(str)
+ -- return #lpegmatch(utfcharcounter,str or "")
+ -- end
+ --
+ -- -- alternative 2: 1.70
+ --
+ -- local n = 0
+ --
+ -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ --
+ -- function utf.length(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+ --
+ -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+ -- local n = 0
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * (
+ -- -- patterns.utf8one ^1 * Cc(1)
+ -- -- + patterns.utf8two ^1 * Cc(2)
+ -- -- + patterns.utf8three^1 * Cc(3)
+ -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end
+ -- -- )^0 ) -- just as many captures as below
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( (
+ -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end))
+ -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end))
+ -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end))
+ -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end))
+ -- -- )^0 ) -- not interesting as it creates strings but sometimes faster
+ --
+ -- -- The best so far:
+ --
+ -- local utfcharcounter = utfbom^-1 * P ( (
+ -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+ -- )^0 )
+
+ -- function utf.len(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+
+ local n, f = 0, 1
+
+ local utfcharcounter = patterns.utfbom^-1 * Cmt (
+ Cc(1) * patterns.utf8one ^1
+ + Cc(2) * patterns.utf8two ^1
+ + Cc(3) * patterns.utf8three^1
+ + Cc(4) * patterns.utf8four ^1,
+ function(_,t,d) -- due to Cc no string captures, so faster
+ n = n + (t - f)/d
+ f = t
+ return true
+ end
+ )^0
+
+ function utf.len(str)
+ n, f = 0, 1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
-if not utf.len then
- utf.len = utf.length
end
--- a replacement for simple gsubs:
+utf.length = utf.len
+
+if not utf.sub then
+
+ -- inefficient as lpeg just copies ^n
+
+ -- local function sub(str,start,stop)
+ -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1))
+ -- inspect(pattern)
+ -- return lpegmatch(pattern,str) or ""
+ -- end
+
+ -- local b, e, n, first, last = 0, 0, 0, 0, 0
+ --
+ -- local function slide(s,p)
+ -- n = n + 1
+ -- if n == first then
+ -- b = p
+ -- if not last then
+ -- return nil
+ -- end
+ -- end
+ -- if n == last then
+ -- e = p
+ -- return nil
+ -- else
+ -- return p
+ -- end
+ -- end
+ --
+ -- local pattern = Cmt(p_utf8char,slide)^0
+ --
+ -- function utf.sub(str,start,stop) -- todo: from the end
+ -- if not start then
+ -- return str
+ -- end
+ -- b, e, n, first, last = 0, 0, 0, start, stop
+ -- lpegmatch(pattern,str)
+ -- if not stop then
+ -- return sub(str,b)
+ -- else
+ -- return sub(str,b,e-1)
+ -- end
+ -- end
+
+ -- print(utf.sub("Hans Hagen is my name"))
+ -- print(utf.sub("Hans Hagen is my name",5))
+ -- print(utf.sub("Hans Hagen is my name",5,10))
+
+ local utflength = utf.length
+
+ -- also negative indices, upto 10 times slower than a c variant
+
+ local b, e, n, first, last = 0, 0, 0, 0, 0
+
+ local function slide_zero(s,p)
+ n = n + 1
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_one(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ end
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_two(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ else
+ return true
+ end
+ end
+
+ local pattern_zero = Cmt(p_utf8char,slide_zero)^0
+ local pattern_one = Cmt(p_utf8char,slide_one )^0
+ local pattern_two = Cmt(p_utf8char,slide_two )^0
+
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start == 0 then
+ start = 1
+ end
+ if not stop then
+ if start < 0 then
+ local l = utflength(str) -- we can inline this function if needed
+ start = l + start
+ else
+ start = start - 1
+ end
+ b, n, first = 0, 0, start
+ lpegmatch(pattern_two,str)
+ if n >= first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start < 0 or stop < 0 then
+ local l = utf.length(str)
+ if start < 0 then
+ start = l + start
+ if start <= 0 then
+ start = 1
+ else
+ start = start + 1
+ end
+ end
+ if stop < 0 then
+ stop = l + stop
+ if stop == 0 then
+ stop = 1
+ else
+ stop = stop + 1
+ end
+ end
+ end
+ if start > stop then
+ return ""
+ elseif start > 1 then
+ b, e, n, first, last = 0, 0, 0, start - 1, stop
+ lpegmatch(pattern_one,str)
+ if n >= first and e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ else
+ b, e, n, last = 1, 0, 0, stop
+ lpegmatch(pattern_zero,str)
+ if e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ end
+ end
-local utf8char = patterns.utf8char
+ -- local n = 100000
+ -- local str = string.rep("123456àáâãäå",100)
+ --
+ -- for i=-15,15,1 do
+ -- for j=-15,15,1 do
+ -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then
+ -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j))
+ -- end
+ -- end
+ -- if utf.xsub(str,i) ~= utf.sub(str,i) then
+ -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i))
+ -- end
+ -- end
+
+ -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7))
+ -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7))
+ -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9))
+ -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 ))
+ -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 ))
+ -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0))
+ -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4))
+ -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0))
+ -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0))
+ -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3))
+ -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3))
+ -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 ))
+
+end
+
+-- a replacement for simple gsubs:
function utf.remapper(mapping)
- local pattern = Cs((utf8char/mapping)^0)
+ local pattern = Cs((p_utf8char/mapping)^0)
return function(str)
if not str or str == "" then
return ""
@@ -4695,55 +5184,113 @@ end
-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
-- print(remap("abcd 1234 abcd"))
+--
+
+function utf.replacer(t) -- no precheck, always string builder
+ local r = replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+
+function utf.subtituter(t) -- with precheck and no building if no match
+ local f = finder (t)
+ local r = replacer(t,false,false,true)
+ return function(str)
+ local i = lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i > #str then
+ return str
+ else
+ -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower
+ return lpegmatch(r,str)
+ end
+ end
+end
+
+-- inspect(utf.split("a b c d"))
+-- inspect(utf.split("a b c d",true))
+
+local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0)
+local utfcharsplitter_raw = Ct(C(p_utf8char)^0)
+
+patterns.utflinesplitter = utflinesplitter
+
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+function utf.split(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+function utf.totable(str) -- keeps bom
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
-- 2 FE FF UTF-16-big-endian
-- 3 FF FE 00 00 UTF-32-little-endian
-- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
-}
-
+--
-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
- else
- f:seek('set')
- return 0
+-- utf.name = {
+-- [0] = 'utf-8',
+-- [1] = 'utf-16-le',
+-- [2] = 'utf-16-be',
+-- [3] = 'utf-32-le',
+-- [4] = 'utf-32-be'
+-- }
+--
+-- function utf.magic(f)
+-- local str = f:read(4)
+-- if not str then
+-- f:seek('set')
+-- return 0
+-- -- elseif find(str,"^%z%z\254\255") then -- depricated
+-- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+-- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+-- return 4
+-- -- elseif find(str,"^\255\254%z%z") then -- depricated
+-- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+-- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+-- return 3
+-- elseif find(str,"^\254\255") then
+-- f:seek('set',2)
+-- return 2
+-- elseif find(str,"^\255\254") then
+-- f:seek('set',2)
+-- return 1
+-- elseif find(str,"^\239\187\191") then
+-- f:seek('set',3)
+-- return 0
+-- else
+-- f:seek('set')
+-- return 0
+-- end
+-- end
+
+function utf.magic(f) -- not used
+ local str = f:read(4) or ""
+ local off = lpegmatch(p_utfoffset,str)
+ if off < 4 then
+ f:seek('set',off)
end
+ return lpegmatch(p_utftype,str)
end
-
-
local function utf16_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4771,7 +5318,7 @@ end
local function utf16_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4799,7 +5346,7 @@ end
local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4824,7 +5371,7 @@ end
local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4847,20 +5394,20 @@ local function utf32_to_utf8_le(t)
return t
end
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
+utf.utf32_to_utf8_be = utf32_to_utf8_be
+utf.utf32_to_utf8_le = utf32_to_utf8_le
+utf.utf16_to_utf8_be = utf16_to_utf8_be
+utf.utf16_to_utf8_le = utf16_to_utf8_le
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+function utf.utf8_to_utf8(t)
+ return type(t) == "string" and lpegmatch(utflinesplitter,t) or t
end
-function unicode.utf16_to_utf8(t,endian)
+function utf.utf16_to_utf8(t,endian)
return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
end
-function unicode.utf32_to_utf8(t,endian)
+function utf.utf32_to_utf8(t,endian)
return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
end
@@ -4886,7 +5433,7 @@ local function big(c)
end
end
--- function unicode.utf8_to_utf16(str,littleendian)
+-- function utf.utf8_to_utf16(str,littleendian)
-- if littleendian then
-- return char(255,254) .. utfgsub(str,".",little)
-- else
@@ -4897,7 +5444,7 @@ end
local _, l_remap = utf.remapper(little)
local _, b_remap = utf.remapper(big)
-function unicode.utf8_to_utf16(str,littleendian)
+function utf.utf8_to_utf16(str,littleendian)
if littleendian then
return char(255,254) .. lpegmatch(l_remap,str)
else
@@ -4905,31 +5452,71 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+-- function utf.tocodes(str,separator) -- can be sped up with an lpeg
+-- local t, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- t[n] = format("0x%04X",u)
+-- end
+-- return concat(t,separator or " ")
+-- end
+
+local pattern = Cs (
+ (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) *
+ (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
end
-function unicode.ustring(s)
+function utf.ustring(s)
return format("U+%05X",type(s) == "number" and s or utfbyte(s))
end
-function unicode.xstring(s)
+function utf.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
--
-local pattern = Ct(C(patterns.utf8char)^0)
+local p_nany = p_utf8char / ""
+
+if utfgmatch then
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + p_nany)^0)
+ cache[p] = p
+ end
+ return #lpegmatch(p,str)
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
-function utf.totable(str)
- return lpegmatch(pattern,str)
end
+-- maybe also register as string.utf*
+
end -- of closure
@@ -4990,24 +5577,10 @@ local tables = utilities.tables
local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local type, next, rawset, tonumber, load, select = type, next, rawset, tonumber, load, select
local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
local serialize = table.serialize
--- function tables.definetable(target) -- defines undefined tables
--- local composed, t, n = nil, { }, 0
--- for name in gmatch(target,"([^%.]+)") do
--- n = n + 1
--- if composed then
--- composed = composed .. "." .. name
--- else
--- composed = name
--- end
--- t[n] = format("%s = %s or { }",composed,composed)
--- end
--- return concat(t,"\n")
--- end
-
local splitter = lpeg.tsplitat(".")
function tables.definetable(target,nofirst,nolast) -- defines undefined tables
@@ -5036,13 +5609,13 @@ end
-- local t = tables.definedtable("a","b","c","d")
function tables.definedtable(...)
- local l = { ... }
local t = _G
- for i=1,#l do
- local tl = t[l[i]]
+ for i=1,select("#",...) do
+ local li = select(i,...)
+ local tl = t[li]
if not tl then
tl = { }
- t[l[i]] = tl
+ t[li] = tl
end
t = tl
end
@@ -5235,7 +5808,7 @@ function table.deserialize(str)
if not str or str == "" then
return
end
- local code = loadstring(str)
+ local code = load(str)
if not code then
return
end
@@ -5252,7 +5825,7 @@ function table.load(filename)
if filename then
local t = io.loaddata(filename)
if t and t ~= "" then
- t = loadstring(t)
+ t = load(t)
if type(t) == "function" then
t = t()
if type(t) == "table" then
@@ -5331,9 +5904,11 @@ utilities = utilities or { }
utilities.storage = utilities.storage or { }
local storage = utilities.storage
+local report = texio and texio.write_nl or print
+
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage cannot be marked")
+ report("fatal error: storage cannot be marked")
return -- os.exit()
end
local m = getmetatable(t)
@@ -5363,12 +5938,36 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage has not been allocated")
+ report("fatal error: storage has not been allocated")
return -- os.exit()
end
return t
end
+-- function utilities.storage.delay(parent,name,filename)
+-- local m = getmetatable(parent)
+-- m.__list[name] = filename
+-- end
+--
+-- function utilities.storage.predefine(parent)
+-- local list = { }
+-- local m = getmetatable(parent) or {
+-- __list = list,
+-- __index = function(t,k)
+-- local l = require(list[k])
+-- t[k] = l
+-- return l
+-- end
+-- }
+-- setmetatable(parent,m)
+-- end
+--
+-- bla = { }
+-- utilities.storage.predefine(bla)
+-- utilities.storage.delay(bla,"test","oepsoeps")
+-- local t = bla.test
+-- table.print(t)
+-- print(t.a)
function storage.setinitializer(data,initialize)
local m = getmetatable(data) or { }
@@ -5393,12 +5992,14 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_table (t,k) local v = { } t[k] = v return v end
+local function f_ignore() end -- t,k,v
local t_empty = { __index = f_empty }
local t_self = { __index = f_self }
+local t_table = { __index = f_table }
local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
@@ -5408,6 +6009,8 @@ function table.setmetatableindex(t,f)
m.__index = f_empty
elseif f == "key" then
m.__index = f_self
+ elseif f == "table" then
+ m.__index = f_table
else
m.__index = f
end
@@ -5416,6 +6019,8 @@ function table.setmetatableindex(t,f)
setmetatable(t, t_empty)
elseif f == "key" then
setmetatable(t, t_self)
+ elseif f == "table" then
+ setmetatable(t, t_table)
else
setmetatable(t,{ __index = f })
end
@@ -5626,7 +6231,7 @@ if not modules then modules = { } end modules ['util-lua'] = {
}
local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
-local loadstring, loadfile, type = loadstring, loadfile, type
+local load, loadfile, type = load, loadfile, type
utilities = utilities or {}
utilities.lua = utilities.lua or { }
@@ -5643,11 +6248,23 @@ luautilities.nofstrippedbytes = 0
local strippedchunks = { } -- allocate()
luautilities.strippedchunks = strippedchunks
+luautilities.suffixes = {
+ tma = "tma",
+ tmc = jit and "tmb" or "tmc",
+ lua = "lua",
+ luc = jit and "lub" or "luc",
+ lui = "lui",
+ luv = "luv",
+ luj = "luj",
+ tua = "tua",
+ tuc = "tuc",
+}
+
local function fatalerror(name)
utilities.report(format("fatal error in %q",name or "unknown"))
end
-if jit then
+if jit or status.luatex_version >= 74 then
local function register(name)
if tracestripping then
@@ -5660,7 +6277,7 @@ if jit then
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if code then
code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
if code and code ~= "" then
@@ -5692,13 +6309,13 @@ if jit then
end
if forcestrip or luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
elseif luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
@@ -5706,14 +6323,14 @@ if jit then
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
register(name)
code = dump(code,true)
end
- return loadstring(code), 0
+ return load(code), 0
end
function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
@@ -5754,67 +6371,79 @@ else
return delta
end
- local function strip_code_pc(dump,name)
- local before = #dump
- local version, format, endian, int, size, ins, num = byte(dump,5,11)
- local subint
- if endian == 1 then
- subint = function(dump, i, l)
- local val = 0
- for n = l, 1, -1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_code_pc
+
+ if _MAJORVERSION == 5 and _MINORVERSION == 1 then
+
+ strip_code_pc = function(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
- return val, i + l
end
- else
- subint = function(dump, i, l)
- local val = 0
- for n = 1, l, 1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
end
- return val, i + l
- end
- end
- local strip_function
- strip_function = function(dump)
- local count, offset = subint(dump, 1, size)
- local stripped, dirty = rep("\0", size), offset + count
- offset = offset + count + int * 2 + 4
- offset = offset + int + subint(dump, offset, int) * ins
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- local t
- t, offset = subint(dump, offset, 1)
- if t == 1 then
- offset = offset + 1
- elseif t == 4 then
- offset = offset + size + subint(dump, offset, size)
- elseif t == 3 then
- offset = offset + num
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
end
- count, offset = subint(dump, offset, int)
- stripped = stripped .. sub(dump,dirty, offset - 1)
- for n = 1, count do
- local proto, off = strip_function(sub(dump,offset, -1))
- stripped, offset = stripped .. proto, offset + off - 1
- end
- offset = offset + subint(dump, offset, int) * int + int
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size + int * 2
- end
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size
- end
- stripped = stripped .. rep("\0", int * 3)
- return stripped, offset
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = register(name,before,after)
+ return dump, delta
+ end
+
+ else
+
+ strip_code_pc = function(dump,name)
+ return dump, 0
end
- dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
- local after = #dump
- local delta = register(name,before,after)
- return dump, delta
+
end
-- ... end of borrowed code.
@@ -5834,14 +6463,14 @@ else
end
if forcestrip then
local code, n = strip_code_pc(dump(code),name)
- return loadstring(code), n
+ return load(code), n
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
@@ -5850,20 +6479,20 @@ else
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
local n = 0
if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
code, n = strip_code_pc(dump(code),name)
end
- return loadstring(code), n
+ return load(code), n
end
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
local n = 0
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror()
end
@@ -5903,6 +6532,7 @@ else
utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
end
cleanup = false -- better see how bad it is
+ done = true -- hm
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -5949,7 +6579,6 @@ if not modules then modules = { } end modules ['util-prs'] = {
}
local lpeg, table, string = lpeg, table, string
-
local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
@@ -6367,6 +6996,45 @@ function parsers.rfc4180splitter(specification)
end
end
+-- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- utilities.parsers.stepper("1-3,7,8,9")
+-- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- utilities.parsers.stepper(" 1 : 3, ,7 ")
+-- utilities.parsers.stepper("1:4,9:13,24:*",30)
+
+local function ranger(first,last,n,action)
+ if not first then
+ -- forget about it
+ elseif last == true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+
+local cardinal = patterns.cardinal / tonumber
+local spacers = patterns.spacer^0
+local endofstring = patterns.endofstring
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring)
+
+function utilities.parsers.stepper(str,n,action)
+ if type(n) == "function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
end -- of closure
@@ -6817,7 +7485,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
+local format, find, lower, gsub, topattern = string.format, string.find, string.lower, string.gsub, string.topattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -6905,7 +7573,7 @@ local function set(t,what,newvalue)
else
value = is_boolean(value,value)
end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
+ w = topattern(w,true,true)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
@@ -6959,7 +7627,8 @@ function setters.register(t,what,...)
end
end
local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
+ for i=1,select("#",...) do
+ local fnc = select(i,...)
local typ = type(fnc)
if typ == "string" then
if trace_initialize then
@@ -7028,7 +7697,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
end
end
t.report()
@@ -7052,17 +7721,29 @@ local function report(setter,...)
end
end
-function setters.new(name)
+local function default(setter,name)
+ local d = setter.data[name]
+ return d and d.default
+end
+
+local function value(setter,name)
+ local d = setter.data[name]
+ return d and (d.value or d.default)
+end
+
+function setters.new(name) -- we could use foo:bar syntax (but not used that often)
local setter -- we need to access it in setter itself
setter = {
data = allocate(), -- indexed, but also default and value fields
name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
+ report = function(...) report (setter,...) end,
+ enable = function(...) enable (setter,...) end,
+ disable = function(...) disable (setter,...) end,
+ register = function(...) register(setter,...) end,
+ list = function(...) list (setter,...) end,
+ show = function(...) show (setter,...) end,
+ default = function(...) return default (setter,...) end,
+ value = function(...) return value (setter,...) end,
}
data[name] = setter
return setter
@@ -7189,9 +7870,9 @@ if not modules then modules = { } end modules ['trac-log'] = {
local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
local format, gmatch, find = string.format, string.gmatch, string.find
local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
+local topattern = string.topattern
local texcount = tex and tex.count
-local next, type = next, type
+local next, type, select = next, type, select
local setmetatableindex = table.setmetatableindex
@@ -7502,7 +8183,7 @@ local function setblocked(category,value)
if data[c] then
v.state = value
else
- c = escapedpattern(c,true)
+ c = topattern(c,true,true)
for k, v in next, data do
if find(k,c) then
v.state = value
@@ -7720,10 +8401,10 @@ local function reporthelp(t,...)
if type(helpinfo) == "string" then
reportlines(t,helpinfo)
elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
+ local n = select("#",...)
+ for i=1,n do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i < n then
t.report()
end
end
@@ -8013,6 +8694,10 @@ local format, sub, match, gsub, find = string.format, string.sub, string.match,
local unquoted, quoted = string.unquoted, string.quoted
local concat, insert, remove = table.concat, table.insert, table.remove
local loadedluacode = utilities.lua.loadedluacode
+local luasuffixes = utilities.lua.suffixes
+
+environment = environment or { }
+local environment = environment
-- precautions
@@ -8022,9 +8707,29 @@ function os.setlocale()
-- no way you can mess with it
end
--- dirty tricks
+-- dirty tricks (we will replace the texlua call by luatex --luaonly)
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+local validengines = allocate {
+ ["luatex"] = true,
+ ["luajittex"] = true,
+ -- ["luatex.exe"] = true,
+ -- ["luajittex.exe"] = true,
+}
+
+local basicengines = allocate {
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex",
+ ["texluac"] = "luatex",
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex",
+ -- ["texlua.exe"] = "luatex",
+ -- ["texluajit.exe"] = "luajittex",
+}
+
+environment.validengines = validengines
+environment.basicengines = basicengines
+
+if arg and validengines[file.removesuffix(arg[0])] and arg[1] == "--luaonly" then
arg[-1] = arg[0]
arg[ 0] = arg[2]
for k=3,#arg do
@@ -8056,9 +8761,6 @@ end
-- environment
-environment = environment or { }
-local environment = environment
-
environment.arguments = allocate()
environment.files = allocate()
environment.sortedflags = nil
@@ -8114,7 +8816,7 @@ function environment.initializearguments(arg)
end
end
end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
+ environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
function environment.setargument(name,value)
@@ -8195,6 +8897,22 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+-- -- to be tested:
+--
+-- function environment.reconstructcommandline(arg,noquote)
+-- arg = arg or environment.originalarguments
+-- if noquote and #arg == 1 then
+-- return unquoted(resolvers.resolve(arg[1]))
+-- elseif #arg > 0 then
+-- local result = { }
+-- for i=1,#arg do
+-- result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
+-- end
+-- return concat(result," ")
+-- else
+-- return ""
+-- end
+-- end
if arg then
@@ -8289,9 +9007,11 @@ function environment.loadluafile(filename, version)
local lucname, luaname, chunk
local basename = file.removesuffix(filename)
if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
+ luaname = fiule.addsuffix(basename,luasuffixes.lua)
+ lucname = fiule.addsuffix(basename,luasuffixes.luc)
else
- lucname, luaname = nil, basename -- forced suffix
+ luaname = basename -- forced suffix
+ lucname = nil
end
-- when not overloaded by explicit suffix we look for a luc file first
local fullname = (lucname and environment.luafile(lucname)) or ""
@@ -8372,7 +9092,6 @@ xml = xml or { }
local xml = xml
-local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
@@ -9583,7 +10302,7 @@ if not modules then modules = { } end modules ['lxml-lpt'] = {
-- todo: B/C/[get first match]
local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local type, next, tonumber, tostring, setmetatable, load, select = type, next, tonumber, tostring, setmetatable, load, select
local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
@@ -10195,7 +10914,7 @@ end
local function register_expression(expression)
local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
+ local runner = load(format(template_e,converted))
runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
end
@@ -10203,9 +10922,9 @@ end
local function register_finalizer(protocol,name,arguments)
local runner
if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ runner = load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
+ runner = load(format(template_f_n,protocol or xml.defaultprotocol,name))
end
runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
@@ -10597,6 +11316,7 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
+
expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
return pattern and (collected and #collected) or 0
@@ -10604,13 +11324,30 @@ end
-- external
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+-- expressions.oneof = function(s,...)
+-- local t = {...}
+-- for i=1,#t do
+-- if s == t[i] then
+-- return true
+-- end
+-- end
+-- return false
+-- end
+
+expressions.oneof = function(s,...)
+ for i=1,select("#",...) do
+ if s == select(i,...) then
+ return true
+ end
+ end
+ return false
end
+
expressions.error = function(str)
xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
+
expressions.undefined = function(s)
return s == nil
end
@@ -12220,7 +12957,6 @@ if not modules then modules = { } end modules ['data-ini'] = {
}
local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
local next, type = next, type
local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
@@ -12311,6 +13047,10 @@ do
local args = environment.originalarguments or arg -- this needs a cleanup
+ if not environment.ownmain then
+ environment.ownmain = status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
@@ -12427,19 +13167,6 @@ end
environment.texroot = file.collapsepath(texroot)
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
if profiler then
directives.register("system.profile",function()
profiler.start("luatex-profile.log")
@@ -12946,6 +13673,8 @@ resolvers.suffixes = suffixes
resolvers.dangerous = dangerous
resolvers.suffixmap = suffixmap
+local luasuffixes = utilities.lua.suffixes
+
local relations = allocate { -- todo: handlers also here
core = {
ofm = { -- will become obsolete
@@ -13031,7 +13760,7 @@ local relations = allocate { -- todo: handlers also here
lua = {
names = { "lua" },
variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
+ suffixes = { luasuffixes.lua, luasuffixes.luc, luasuffixes.tma, luasuffixes.tmc },
},
lib = {
names = { "lib" },
@@ -13227,6 +13956,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
+local addsuffix, is_writable, is_readable = file.addsuffix, file.is_writable, file.is_readable
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
@@ -13251,8 +13981,10 @@ end
-- end of intermezzo
-caches = caches or { }
-local caches = caches
+caches = caches or { }
+local caches = caches
+
+local luasuffixes = utilities.lua.suffixes
caches.base = caches.base or "luatex-cache"
caches.more = caches.more or "context"
@@ -13280,18 +14012,18 @@ local function identify()
cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
- if file.is_readable(cachepath) then
+ if is_readable(cachepath) then
readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
+ if not writable and is_writable(cachepath) then
writable = cachepath
end
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
+ if is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
+ if isdir(cachepath) and is_writable(cachepath) then
report_caches("created: %s",cachepath)
writable = cachepath
readables[#readables+1] = cachepath
@@ -13313,8 +14045,8 @@ local function identify()
cachepath = resolvers.resolve(cachepath)
cachepath = resolvers.cleanpath(cachepath)
local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
readables[#readables+1] = cachepath
writable = cachepath
break
@@ -13403,7 +14135,7 @@ end
local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
+local function getreadablepaths(...)
local tags = { ... }
local hash = concat(tags,"/")
local done = r_cache[hash]
@@ -13446,7 +14178,7 @@ function caches.getfirstreadablefile(filename,...)
for i=1,#rd do
local path = rd[i]
local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
+ if is_readable(fullname) then
usedreadables[i] = true
return fullname, path
end
@@ -13467,7 +14199,7 @@ function caches.define(category,subcategory) -- for old times sake
end
function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
+ return format("%s/%s.%s",path,name,luasuffixes.tma), format("%s/%s.%s",path,name,luasuffixes.tmc)
end
function caches.loaddata(readables,name)
@@ -13477,7 +14209,13 @@ function caches.loaddata(readables,name)
for i=1,#readables do
local path = readables[i]
local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
+ local loader = loadfile(tmcname)
+ if not loader then
+ -- in case we have a different engine
+ utilities.lua.compile(tmaname,tmcname)
+ --
+ loader = loadfile(tmaname)
+ end
if loader then
loader = loader()
collectgarbage("step")
@@ -13489,11 +14227,15 @@ end
function caches.is_writable(filepath,filename)
local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
+ return is_writable(tmaname)
end
local saveoptions = { compact = true }
+-- add some point we will only use the internal bytecode compiler and
+-- then we can flag success in the tma so that it can trigger a compile
+-- if the other engine
+
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -13519,9 +14261,9 @@ end
function caches.loadcontent(cachename,dataname)
local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
+ local full, path = caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
+ local blob = loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data = blob()
if data and data.content then
@@ -13556,9 +14298,10 @@ end
function caches.savecontent(cachename,dataname,content)
local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
+ local full, path = caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
+ local luaname = addsuffix(filename,luasuffixes.lua)
+ local lucname = addsuffix(filename,luasuffixes.luc)
if trace_locating then
report_resolvers("preparing '%s' for '%s'",dataname,cachename)
end
@@ -13763,6 +14506,7 @@ local joinpath = file.joinpath
local allocate = utilities.storage.allocate
local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
+local luasuffixes = utilities.lua.suffixes
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -15325,15 +16069,19 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
+ local engine = environment.ownmain or "luatex"
+ local barename = file.removesuffix(name)
+ local fullname = file.addsuffix(barename,"fmt")
+ local fmtname = caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
+ fmtname = resolvers.findfile(fullname)
fmtname = resolvers.cleanpath(fmtname)
end
if fmtname ~= "" then
local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
+ local luaname = file.addsuffix(barename,luasuffixes.lua)
+ local lucname = file.addsuffix(barename,luasuffixes.luc)
+ local luiname = file.addsuffix(barename,luasuffixes.lui)
if lfs.isfile(luiname) then
return barename, luiname
elseif lfs.isfile(lucname) then
@@ -15430,10 +16178,9 @@ local resolvers = resolvers
local prefixes = utilities.storage.allocate()
resolvers.prefixes = prefixes
-local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
local joinpath, basename, dirname = file.join, file.basename, file.dirname
local getmetatable, rawset, type = getmetatable, rawset, type
@@ -15555,6 +16302,28 @@ end
-- todo: use an lpeg (see data-lua for !! / stripper)
+-- local function resolve(str) -- use schemes, this one is then for the commandline only
+-- if type(str) == "table" then
+-- local t = { }
+-- for i=1,#str do
+-- t[i] = resolve(str[i])
+-- end
+-- return t
+-- else
+-- local res = resolved[str]
+-- if not res then
+-- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+-- resolved[str] = res
+-- abstract[res] = str
+-- end
+-- return res
+-- end
+-- end
+
+-- home:xx;selfautoparent:xx;
+
+local pattern = Cs((C(R("az")^2) * P(":") * C((1-S(" \"\';,"))^1) / _resolve_ + P(1))^0)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -15565,7 +16334,7 @@ local function resolve(str) -- use schemes, this one is then for the commandline
else
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+ res = lpegmatch(pattern,str)
resolved[str] = res
abstract[res] = str
end
@@ -15998,7 +16767,7 @@ statistics.register("used cache path", function() return caches.usedpaths() end
function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
local enginebanner = status.list().banner
if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
local luvdata = {
enginebanner = enginebanner,
formatbanner = formatbanner,
@@ -16009,10 +16778,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname ==
end
end
+-- todo: check this at startup and return (say) 999 as signal that the run
+-- was aborted due to a wrong format in which case mtx-context can trigger
+-- a remake
+
function statistics.checkfmtstatus(texname)
local enginebanner = status.list().banner
if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
if lfs.isfile(luvname) then
local luv = dofile(luvname)
if luv and luv.sourcefile then
@@ -16389,7 +17162,7 @@ if not modules then modules = { } end modules ['data-sch'] = {
license = "see context related readme files"
}
-local loadstring = loadstring
+local load = load
local gsub, concat, format = string.gsub, table.concat, string.format
local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
@@ -16575,7 +17348,7 @@ schemes.fetchstring = fetchstring
function schemes.fetchtable(url,data)
local reply = fetchstring(url,data)
if reply then
- local s = loadstring("return " .. reply)
+ local s = load("return " .. reply)
if s then
return s()
end
@@ -16603,6 +17376,8 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- -- local mylib = require("libtest")
-- -- local mysql = require("luasql.mysql")
+local searchers = package.searchers or package.loaders
+
local concat = table.concat
local trace_libraries = false
@@ -16704,13 +17479,9 @@ function package.extraclibpath(...)
end
end
-if not package.loaders then
- package.loaders = package.searchers -- 5.2
-end
-
-if not package.loaders[-2] then
+if not searchers[-2] then
-- use package-path and package-cpath
- package.loaders[-2] = package.loaders[2]
+ searchers[-2] = searchers[2]
end
local function loadedaslib(resolved,rawname)
@@ -16721,7 +17492,7 @@ local function loadedbylua(name)
if trace_libraries then
report_libraries("! locating %q using normal loader",name)
end
- local resolved = package.loaders[-2](name)
+ local resolved = searchers[-2](name)
end
local function loadedbyformat(name,rawname,suffixes,islib)
@@ -16776,7 +17547,7 @@ local function notloaded(name)
end
end
-package.loaders[2] = function(name)
+searchers[2] = function(name)
local thename = gsub(name,"%.","/")
local luaname = file.addsuffix(thename,"lua")
local libname = file.addsuffix(thename,os.libsuffix)
@@ -16790,8 +17561,8 @@ package.loaders[2] = function(name)
or notloaded (name)
end
--- package.loaders[3] = nil
--- package.loaders[4] = nil
+-- searchers[3] = nil
+-- searchers[4] = nil
resolvers.loadlualib = require
@@ -17161,13 +17932,11 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
local format = string.format
+local quoted = string.quoted
+local luasuffixes = utilities.lua.suffixes
local report_format = logs.reporter("resolvers","formats")
--- helper for mtxrun
-
-local quoted = string.quoted
-
local function primaryflags() -- not yet ok
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
@@ -17182,13 +17951,14 @@ local function primaryflags() -- not yet ok
end
function environment.make_format(name)
+ local engine = environment.ownmain or "luatex"
-- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
+ local olddir = dir.current()
+ local path = caches.getwritablepath("formats",engine) or "" -- maybe platform
if path ~= "" then
lfs.chdir(path)
end
- report_format("format path: %s",lfs.currentdir())
+ report_format("format path: %s",dir.current())
-- check source file
local texsourcename = file.addsuffix(name,"mkiv")
local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
@@ -17225,13 +17995,12 @@ function environment.make_format(name)
elseif type(usedlualibs) == "table" then
report_format("using stub specification: %s",fullspecificationname)
local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
+ local luastubname = file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname = file.addsuffix(texbasename,luasuffixes.luc)
-- pack libraries in stub
report_format("creating initialization file: %s",luastubname)
utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
-- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
report_format("using compiled initialization file: %s",lucstubname)
usedluastub = lucstubname
@@ -17245,7 +18014,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -17264,8 +18033,9 @@ end
function environment.run_format(name,data,more)
if name and name ~= "" then
+ local engine = environment.ownmain or "luatex"
local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
+ local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
if fmtname == "" then
fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
end
@@ -17282,7 +18052,7 @@ function environment.run_format(name,data,more)
report_format("using format name: %s",fmtname)
report_format("no luc/lua with name: %s",barename)
else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
+ local command = format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
report_format("running command: %s",command)
os.spawn(command)
end
@@ -17423,10 +18193,11 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -17656,6 +18427,10 @@ local helpinfo = [[
--variables show configuration variables
--configurations show configuration order
+--directives show (known) directives
+--trackers show (known) trackers
+--experiments show (known) experiments
+
--expand-braces expand complex variable
--expand-path expand variable (resolve paths)
--expand-var expand variable (resolve references)
@@ -18346,8 +19121,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
-if e_argument("selfmerge") then
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18377,17 +19162,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -18615,6 +19389,18 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index 01c601eb5..3a02ad582 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,7 +54,7 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-functions'] = {
+if not modules then modules = { } end modules ['l-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -51,16 +62,112 @@ if not modules then modules = { } end modules ['l-functions'] = {
license = "see context related readme files"
}
-functions = functions or { }
+-- compatibility hacks ... try to avoid usage
-function functions.dummy() end
+local major, minor = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+
+_MAJORVERSION = tonumber(major) or 5
+_MINORVERSION = tonumber(minor) or 1
+
+-- basics:
+
+if loadstring then
+
+ local loadnormal = load
+
+ function load(first,...)
+ if type(first) == "string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+
+else
+
+ loadstring = load
+
+end
+
+-- table:
+
+-- Starting with version 5.2 Lua no longer provide ipairs, which makes
+-- sense. As we already used the for loop and # in most places the
+-- impact on ConTeXt was not that large; the remaining ipairs already
+-- have been replaced. In a similar fashion we also hardly used pairs.
+--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- The unpack function has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+
+ table.unpack = _G.unpack
+
+elseif not unpack then
+
+ _G.unpack = table.unpack
+
+end
+
+-- package:
+
+-- if not package.seachers then
+--
+-- package.searchers = package.loaders -- 5.2
+--
+-- elseif not package.loaders then
+--
+-- package.loaders = package.searchers
+--
+-- end
+
+if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type
+
+ package.loaders = package.searchers
+
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
+if not modules then modules = { } end modules ['l-lpeg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -68,34 +175,843 @@ if not modules then modules = { } end modules ['l-string'] = {
license = "see context related readme files"
}
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
--- some functions may disappear as they are not used anywhere
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
-if not string.split then
+local lpeg = require("lpeg")
- -- this will be overloaded by a faster lpeg variant
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
+-- some code will move to unicode and string
+
+local report = texio and texio.write_nl or print
+
+-- local lpmatch = lpeg.match
+-- local lpprint = lpeg.print
+-- local lpp = lpeg.P
+-- local lpr = lpeg.R
+-- local lps = lpeg.S
+-- local lpc = lpeg.C
+-- local lpb = lpeg.B
+-- local lpv = lpeg.V
+-- local lpcf = lpeg.Cf
+-- local lpcb = lpeg.Cb
+-- local lpcg = lpeg.Cg
+-- local lpct = lpeg.Ct
+-- local lpcs = lpeg.Cs
+-- local lpcc = lpeg.Cc
+-- local lpcmt = lpeg.Cmt
+-- local lpcarg = lpeg.Carg
+
+-- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+-- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+-- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+-- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+-- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+-- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+-- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+-- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+-- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+-- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+-- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+-- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+-- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+-- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+-- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+patterns.utfoffset = utfoffset
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * P(-1) / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
+
+patterns.stripper = stripper
+patterns.collapser = collapser
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.unsigned = digit^0 * P('.') * digit^1
+patterns.float = sign^0 * patterns.unsigned
+patterns.cunsigned = digit^0 * P(',') * digit^1
+patterns.cfloat = sign^0 * patterns.cunsigned
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
+patterns.propername = R("AZ","az","__") * R("09","AZ","az", "__")^0 * P(-1)
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
+end
+
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.split(str,separator)
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+
+-- lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+-- from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(anything^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * endofstring)^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
+ local pattern
+ local u = isutf and utf8char or 1
+ if type(one) == "table" then
+ local no = #one
+ local p = P(false)
+ if no == 0 then
+ for k, v in next, one do
+ p = p + P(k) / v
+ end
+ pattern = Cs((p + u)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ -- pattern = Cs(((1-one)^1 + one/two)^0)
+ pattern = Cs((one/two + u)^0)
+ else
+ for i=1,no do
+ local o = one[i]
+ p = p + P(o[1]) / o[2]
+ end
+ pattern = Cs((p + u)^0)
+ end
+ else
+ pattern = Cs((P(one)/(two or "") + u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst) == "table" then
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
+ end
+ else
+ pattern = P(lst)
+ end
+ pattern = (1-pattern)^0 * pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+
+-- utf extensies
+
+local utfcharacters = utf and utf.characters or string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+local utfchar = utf and utf.char or (unicode and unicode.utf8 and unicode.utf8.char)
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfcharacters(str) do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfgmatch(str,".") do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p = P(false)
+ local f = function(uc)
+ p = p + P(uc)
+ end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
+ local p = P(false)
+ for i=first,last do
+ p = p + P(utfchar(i))
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ -- tricky, these nested captures
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+-- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
+
+-- lpeg.print(lpeg.R("ab","cd","gh"))
+-- lpeg.print(lpeg.P("a","b","c"))
+-- lpeg.print(lpeg.S("a","b","c"))
+
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- table.sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = t[k]
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
end
end
- return t
end
+ return p
+end
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
end
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
+
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-functions'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+functions = functions or { }
+
+function functions.dummy() end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-string'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string = string
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
+
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
+
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
+
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
+
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
+
function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+ return lpegmatch(unquoted,str) or str
end
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function string.quoted(str)
return format("%q",str) -- always "
@@ -118,65 +1034,112 @@ function string.limit(str,n,sentinel) -- not utf proof
end
end
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+local stripper = patterns.stripper
+local collapser = patterns.collapser
function string.strip(str)
return lpegmatch(stripper,str) or ""
end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1)
+
function string.is_empty(str)
- return not find(str,"%S")
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
if str == "" then
return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
- end
- if strict then
- return "^" .. str .. "$"
- else
- return str
- end
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
end
end
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
function string.valid(str,default)
return (type(str) == "string" and str ~= "" and str) or default or nil
end
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
-
-- handy fallback
string.itself = function(s) return s end
@@ -189,6 +1152,19 @@ function string.totable(str)
return lpegmatch(pattern,str)
end
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
+
end -- of closure
@@ -202,68 +1178,23 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
local table, string = table, string
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local getinfo = debug.getinfo
-
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Hm, actually ipairs was retained, but we no longer use it anyway.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
-
-if not ipairs then
-
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
-
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
-
- function ipairs(a)
- return iterate, a, 0
- end
-
-end
-
-if not pairs then
-
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
-
- function pairs(t)
- return next, t -- , nil
- end
-
-end
-
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
-
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local floor = math.floor
-- extra functions, some might go (when not used)
+local stripper = patterns.stripper
+
function table.strip(tab)
local lst, l = { }, 0
for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
-- skip this one
else
@@ -372,7 +1303,7 @@ local function sortedhash(t)
end
table.sortedhash = sortedhash
-table.sortedpairs = sortedhash
+table.sortedpairs = sortedhash -- obsolete
function table.append(t,list)
local n = #t
@@ -396,31 +1327,63 @@ function table.prepend(t, list)
return t
end
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
t[k] = v
end
end
return t
end
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
function table.merged(...)
- local tmp, lst = { }, { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
- tmp[k] = v
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
end
end
- return tmp
+ return t
end
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
function table.imerge(t, ...)
- local lst, nt = { ... }, #t
- for i=1,#lst do
- local nst = lst[i]
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
nt = nt + 1
t[nt] = nst[j]
@@ -429,10 +1392,22 @@ function table.imerge(t, ...)
return t
end
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
function table.imerged(...)
- local tmp, ntmp, lst = { }, 0, {...}
- for i=1,#lst do
- local nst = lst[i]
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
ntmp = ntmp + 1
tmp[ntmp] = nst[j]
@@ -444,7 +1419,7 @@ end
local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
- for k,v in next, old do
+ for k, v in next, old do
if type(v) == "table" then
new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
@@ -498,7 +1473,7 @@ end
table.fastcopy = fastcopy
table.copy = copy
-function table.derive(parent)
+function table.derive(parent) -- for the moment not public
local child = { }
if parent then
setmetatable(child,{ __index = parent })
@@ -579,6 +1554,13 @@ end
-- problem: there no good number_to_string converter with the best resolution
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
local function dummy() end
local function do_serialize(root,name,depth,level,indexed)
@@ -588,14 +1570,14 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s{",depth))
else
local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
+ if tn == "number" then
if hexify then
handle(format("%s[0x%04X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
handle(format("%s%s={",depth,name))
else
handle(format("%s[%q]={",depth,name))
@@ -621,7 +1603,6 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
--- if not root[k] then
if root[k] == nil then
last = k - 1
break
@@ -667,7 +1648,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
+ handle(format('%s load(%q),',depth,dump(v)))
else
handle(format('%s "function",',depth))
end
@@ -679,7 +1660,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s __p__=nil,",depth))
end
elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
else
@@ -691,7 +1672,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%04X,",depth,k,v))
else
@@ -706,7 +1687,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "string" then
if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,v))
else
@@ -714,13 +1695,13 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,v))
else
@@ -728,7 +1709,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
handle(format("%s [%q]=%q,",depth,k,v))
@@ -736,7 +1717,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "table" then
if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={},",depth,k))
else
@@ -744,7 +1725,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
handle(format("%s [%q]={},",depth,k))
@@ -752,15 +1733,15 @@ local function do_serialize(root,name,depth,level,indexed)
elseif inline then
local st = simple_table(v)
if st then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
@@ -772,15 +1753,15 @@ local function do_serialize(root,name,depth,level,indexed)
do_serialize(v,k,depth,level+1)
end
elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%s,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%s,",depth,k,tostring(v)))
@@ -789,30 +1770,30 @@ local function do_serialize(root,name,depth,level,indexed)
if functions then
local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
@@ -892,6 +1873,14 @@ local function serialize(_handle,root,name,specification) -- handle wins
handle("}")
end
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
function table.serialize(root,name,specification)
local t, n = { }, 0
@@ -980,7 +1969,7 @@ table.flattened = flattened
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
- f = { }
+ f = { } -- this one can become obsolete
end
for i=1,#t do
local v = t[i]
@@ -1009,7 +1998,7 @@ local function are_equal(a,b,n,m) -- indexed
local ai, bi = a[i], b[i]
if ai==bi then
-- same
- elseif type(ai)=="table" and type(bi)=="table" then
+ elseif type(ai) == "table" and type(bi) == "table" then
if not are_equal(ai,bi) then
return false
end
@@ -1044,10 +2033,10 @@ table.are_equal = are_equal
-- maybe also make a combined one
-function table.compact(t)
+function table.compact(t) -- remove empty tables, assumes subtables
if t then
- for k,v in next, t do
- if not next(v) then
+ for k, v in next, t do
+ if not next(v) then -- no type checking
t[k] = nil
end
end
@@ -1086,7 +2075,7 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirror(t) -- hash
+function table.mirrored(t) -- hash
local n = { }
for k, v in next, t do
n[v] = k
@@ -1109,6 +2098,17 @@ function table.reversed(t)
end
end
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
function table.sequenced(t,sep) -- hash only
if t then
local s, n = { }, 0
@@ -1196,848 +2196,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
--- some code will move to unicode and string
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type, next = type, next
-local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
-local lpegtype, lpegmatch = lpeg.type, lpeg.match
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-local eol = S("\n\r")
-local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-local whitespace = eol + spacer
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.unsigned = digit^0 * P('.') * digit^1
-patterns.float = sign^0 * patterns.unsigned
-patterns.cunsigned = digit^0 * P(',') * digit^1
-patterns.cfloat = sign^0 * patterns.cunsigned
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = eol
-patterns.spacer = spacer
-patterns.whitespace = whitespace
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - spacer
-patterns.nonwhitespace = 1 - whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.singlequoted = squote * patterns.nosquote * squote
-patterns.doublequoted = dquote * patterns.nodquote * dquote
-patterns.quoted = patterns.doublequoted + patterns.singlequoted
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-local function anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) }
-end
-
-lpeg.anywhere = anywhere
-
-function lpeg.instringchecker(p)
- p = anywhere(p)
- return function(str)
- return lpegmatch(p,str) and true or false
- end
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return lpegmatch(splitters_m[separator] or splitat(separator),str)
-end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.split(str,separator)
- if separator then
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
- else
- return { str }
- end
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = tsplitat(newline)
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return lpegmatch(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return lpegmatch(utflinesplitter,str or "")
-end
-
-local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
-local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
-
-function string.utfsplit(str,ignorewhitespace) -- new
- if ignorewhitespace then
- return lpegmatch(utfcharsplitter_iws,str or "")
- else
- return lpegmatch(utfcharsplitter_ows,str or "")
- end
-end
-
--- inspect(string.utfsplit("a b c d"))
--- inspect(string.utfsplit("a b c d",true))
-
--- -- alternative 1: 0.77
---
--- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
---
--- function string.utflength(str)
--- return #lpegmatch(utfcharcounter,str or "")
--- end
---
--- -- alternative 2: 1.70
---
--- local n = 0
---
--- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
---
--- function string.utflength(str)
--- n = 0
--- lpegmatch(utfcharcounter,str or "")
--- return n
--- end
---
--- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
-
-local n = 0
-
-local utfcharcounter = utfbom^-1 * Cs ( (
- Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
- + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
- + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
- + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
-)^0 )
-
-function string.utflength(str)
- n = 0
- lpegmatch(utfcharcounter,str or "")
- return n
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(anything^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * endofstring)^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two,makefunction)
- local pattern
- if type(one) == "table" then
- local no = #one
- local p = P(false)
- if no == 0 then
- for k, v in next, one do
- p = p + P(k) / v
- end
- pattern = Cs((p + 1)^0)
- elseif no == 1 then
- local o = one[1]
- one, two = P(o[1]), o[2]
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two + 1)^0)
- else
- for i=1,no do
- local o = one[i]
- p = p + P(o[1]) / o[2]
- end
- pattern = Cs((p + 1)^0)
- end
- else
- one = P(one)
- two = two or ""
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two +1)^0)
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
-function lpeg.finder(lst,makefunction)
- local pattern
- if type(lst) == "table" then
- local p = P(false)
- for i=1,#lst do
- p = p + P(lst[i])
- end
- pattern = (p + 1)^0
- else
- pattern = (P(lst) + 1)^0
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
--- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
--- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
--- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #lpegmatch(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #lpegmatch(p,str)
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfcharacters(str) do
- p = p + P(uc)
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfgmatch(str,".") do
- p = p + P(uc)
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p = P(false)
- local f = function(uc)
- p = p + P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
- local p = P(false)
- for i=first,last do
- p = p + P(utfchar(i))
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- -- tricky, these nested captures
- return utf8byte / f -- nil when invalid range
- end
-end
-
--- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
-
-
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- table.sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
-
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
-
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
-
--- experiment:
-
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
-end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
- end
- return make(tree)
-end
-
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
--- handy from within tex:
-
-local lpegmatch = lpeg.match
-
-local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
-
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-
--- strips leading and trailing spaces and collapsed all other spaces
-
-local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
-
-function string.collapsespaces(str)
- return lpegmatch(pattern,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-io'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -2368,7 +2526,7 @@ function io.readstring(f,n,m)
f:seek("set",n)
n = m
end
- local str = gsub(f:read(n),"%z","")
+ local str = gsub(f:read(n),"\000","")
return str
end
@@ -2418,10 +2576,129 @@ local lpegmatch = lpeg.match
number = number or { }
local number = number
--- a,b,c,d,e,f = number.toset(100101)
+if bit32 then
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p)
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
+
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ }
+
+ function number.tobitstring(b,m)
+ -- if really needed we can speed this one up
+ -- because small numbers need less extraction
+ local n = 32
+ for i=0,31 do
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
end
function number.toevenhex(n)
@@ -2433,86 +2710,59 @@ function number.toevenhex(n)
end
end
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
--
-- for i=1,1000000 do
-- local a,b,c,d,e,f,g,h = number.toset(12345678)
-- local a,b,c,d = number.toset(1234)
-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
-- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-local one = lpeg.C(1-lpeg.S(''))^1
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
function number.toset(n)
return lpegmatch(one,tostring(n))
end
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
local m = n % 2
+ local n = floor(n/2)
if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
- end
- return t
-end
-
-
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
-
-function number.setbit(x, p)
- return (x % (p + p) >= p) and x or x + p
-end
-
-function number.clearbit(x, p)
- return (x % (p + p) >= p) and x - p or x
-end
-
-
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+ return bits(n, i+1, i, ...)
else
- return "00000000"
+ return bits(n, i+1, ...)
end
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ return ...
end
end
-
-function number.valid(str,default)
- return tonumber(str) or default or nil
+function number.bits(n)
+ return { bits(n,1) }
end
@@ -3104,25 +3354,25 @@ local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = C((noslashes^0 * slashes^1)^1)
local function pathpart(name,default)
- return lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
end
local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
local function basename(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
local function nameonly(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
local function suffixonly(name)
- return lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
end
file.pathpart = pathpart
@@ -3153,7 +3403,9 @@ local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra capture
local pattern_d = path * rest
function file.splitname(str,splitdrive)
- if splitdrive then
+ if not str then
+ -- error
+ elseif splitdrive then
return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
else
return lpegmatch(pattern_b,str) -- returns path, base, suffix
@@ -3161,34 +3413,36 @@ function file.splitname(str,splitdrive)
end
function file.splitbase(str)
- return lpegmatch(pattern_d,str) -- returns path, base+suffix
+ return str and lpegmatch(pattern_d,str) -- returns path, base+suffix
end
function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
- else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
end
local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1)
function file.removesuffix(name)
- return lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
end
-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
@@ -3205,8 +3459,8 @@ end
local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
return filename
elseif criterium == true then
return filename .. "." .. suffix
@@ -3252,7 +3506,7 @@ local suffix = period * (1-period-slashes)^1 * -1
local pattern = Cs((1-suffix)^0)
function file.replacesuffix(name,suffix)
- if suffix and suffix ~= "" then
+ if name and suffix and suffix ~= "" then
return lpegmatch(pattern,name) .. "." .. suffix
else
return name
@@ -3261,10 +3515,10 @@ end
--
-local reslasher = lpeg.replacer(S("\\"),"/")
+local reslasher = lpeg.replacer(P("\\"),"/")
function file.reslash(str)
- return lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
end
-- We should be able to use:
@@ -3280,7 +3534,9 @@ end
-- variant:
function file.is_writable(name)
- if lfs.isdir(name) then
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
local f = io.open(name,"wb")
if f then
@@ -3308,24 +3564,32 @@ end
local readable = P("r") * Cc(true)
function file.is_readable(name)
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
function file.size(name)
- local a = attributes(name)
- return a and a.size or 0
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
end
function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
- return checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
end
function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
local stripper = Cs(P(fwslash)^0/"" * reslasher)
@@ -3333,14 +3597,23 @@ local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
-function file.join(...) -- rather dirty
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
return one .. "/" .. two
elseif lpegmatch(isroot,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
return two
else
@@ -3349,7 +3622,7 @@ function file.join(...) -- rather dirty
elseif one == "" then
return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(reslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat(lst,"/"))
end
end
@@ -3378,6 +3651,9 @@ local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * C
local absolute = fwslash
function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
if anchor and not lpegmatch(anchors,str) then
str = getcurrentdir() .. "/" .. str
end
@@ -3387,7 +3663,6 @@ function file.collapsepath(str,anchor)
return lpegmatch(reslasher,str)
end
local starter, oldelements = lpegmatch(splitstarter,str)
--- inspect(oldelements)
local newelements = { }
local i = #oldelements
while i > 0 do
@@ -3441,11 +3716,13 @@ local whatever = P("-")^0 / ""
local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
function file.robustname(str,strict)
- str = lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
- else
- return str
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
end
end
@@ -3453,7 +3730,9 @@ file.readdata = io.loaddata
file.savedata = io.savedata
function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+ if oldname and newname then
+ file.savedata(newname,io.loaddata(oldname))
+ end
end
-- also rewrite previous
@@ -3474,11 +3753,11 @@ lpeg.patterns.rootbased = rootbased
-- ./name ../name /name c: :// name/name
function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+ return filename and lpegmatch(qualified,filename) ~= nil
end
function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
+ return filename and lpegmatch(rootbased,filename) ~= nil
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -3500,8 +3779,10 @@ end
-- for myself:
function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
end
-- local debuglist = {
@@ -3943,7 +4224,7 @@ if not modules then modules = { } end modules ['l-dir'] = {
-- dir.expandname will be merged with cleanpath and collapsepath
-local type = type
+local type, select = type, select
local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
@@ -4165,15 +4446,15 @@ local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
if onwindows then
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
end
end
local first, middle, last
@@ -4222,9 +4503,9 @@ if onwindows then
else
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
if s and s ~= "" then -- we catch nil and false
if str ~= "" then
str = str .. "/" .. s
@@ -4424,29 +4705,45 @@ if not modules then modules = { } end modules ['l-unicode'] = {
-- todo: utf.sub replacement (used in syst-aux)
-local concat = table.concat
+-- we put these in the utf namespace:
+
+utf = utf or (unicode and unicode.utf8) or { }
+
+utf.characters = utf.characters or string.utfcharacters
+utf.values = utf.values or string.utfvalues
+
+-- string.utfvalues
+-- string.utfcharacters
+-- string.characters
+-- string.characterpairs
+-- string.bytes
+-- string.bytepairs
+
local type = type
-local P, C, R, Cs, Ct, Cmt = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt
+local char, byte, format, sub = string.char, string.byte, string.format, string.sub
+local concat = table.concat
+local P, C, R, Cs, Ct, Cmt, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local utftype = patterns.utftype
-local char, byte, find, bytepairs, utfvalues, format, sub = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format, string.sub
-local utfsplitlines = string.utfsplitlines
-if not unicode then
+local bytepairs = string.bytepairs
- unicode = { }
+local finder = lpeg.finder
+local replacer = lpeg.replacer
-end
+local utfvalues = utf.values
+local utfgmatch = utf.gmatch -- not always present
-local unicode = unicode
+local p_utftype = patterns.utftype
+local p_utfoffset = patterns.utfoffset
+local p_utf8char = patterns.utf8char
+local p_utf8byte = patterns.utf8byte
+local p_utfbom = patterns.utfbom
+local p_newline = patterns.newline
+local p_whitespace = patterns.whitespace
-utf = utf or unicode.utf8
-
-if not utf then
+if not unicode then
- utf8 = { }
- unicode.utf8 = utf8
- utf = utf8
+ unicode = { utf = utf } -- for a while
end
@@ -4503,64 +4800,13 @@ if not utf.byte then
end
-if not utf.sub then
-
- local utf8char = patterns.utf8char
-
- -- inefficient as lpeg just copies ^n
-
- -- local function sub(str,start,stop)
- -- local pattern = utf8char^-(start-1) * C(utf8char^-(stop-start+1))
- -- inspect(pattern)
- -- return lpegmatch(pattern,str) or ""
- -- end
-
- local b, e, n, first, last = 0, 0, 0, 0, 0
-
- local function slide(s,p)
- n = n + 1
- if n == first then
- b = p
- if not last then
- return nil
- end
- end
- if n == last then
- e = p
- return nil
- else
- return p
- end
- end
-
- local pattern = Cmt(utf8char,slide)^0
-
- function utf.sub(str,start,stop) -- todo: from the end
- if not start then
- return str
- end
- b, e, n, first, last = 0, 0, 0, start, stop
- lpegmatch(pattern,str)
- if not stop then
- return sub(str,b)
- else
- return sub(str,b,e)
- end
- end
-
- -- print(utf.sub("Hans Hagen is my name"))
- -- print(utf.sub("Hans Hagen is my name",5))
- -- print(utf.sub("Hans Hagen is my name",5,10))
-
-end
-
local utfchar, utfbyte = utf.char, utf.byte
-- As we want to get rid of the (unmaintained) utf library we implement our own
-- variants (in due time an independent module):
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
end
local toentities = Cs (
@@ -4647,7 +4893,7 @@ local pattern = P("\254\255") * Cs( (
+ one
)^1 )
-function string.toutf(s)
+function string.toutf(s) -- in string namespace
return lpegmatch(pattern,s) or s -- todo: utf32
end
@@ -4663,26 +4909,269 @@ local validatedutf = Cs (
patterns.validatedutf = validatedutf
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.is_valid(str)
+ return type(str) == "string" and lpegmatch(validatedutf,str) or false
end
+if not utf.len then
-utf.length = string.utflength
-utf.split = string.utfsplit
-utf.splitines = string.utfsplitlines
-utf.valid = string.validutf
+ -- -- alternative 1: 0.77
+ --
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ --
+ -- function utf.len(str)
+ -- return #lpegmatch(utfcharcounter,str or "")
+ -- end
+ --
+ -- -- alternative 2: 1.70
+ --
+ -- local n = 0
+ --
+ -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ --
+ -- function utf.length(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+ --
+ -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+ -- local n = 0
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * (
+ -- -- patterns.utf8one ^1 * Cc(1)
+ -- -- + patterns.utf8two ^1 * Cc(2)
+ -- -- + patterns.utf8three^1 * Cc(3)
+ -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end
+ -- -- )^0 ) -- just as many captures as below
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( (
+ -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end))
+ -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end))
+ -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end))
+ -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end))
+ -- -- )^0 ) -- not interesting as it creates strings but sometimes faster
+ --
+ -- -- The best so far:
+ --
+ -- local utfcharcounter = utfbom^-1 * P ( (
+ -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+ -- )^0 )
+
+ -- function utf.len(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+
+ local n, f = 0, 1
+
+ local utfcharcounter = patterns.utfbom^-1 * Cmt (
+ Cc(1) * patterns.utf8one ^1
+ + Cc(2) * patterns.utf8two ^1
+ + Cc(3) * patterns.utf8three^1
+ + Cc(4) * patterns.utf8four ^1,
+ function(_,t,d) -- due to Cc no string captures, so faster
+ n = n + (t - f)/d
+ f = t
+ return true
+ end
+ )^0
+
+ function utf.len(str)
+ n, f = 0, 1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
-if not utf.len then
- utf.len = utf.length
end
--- a replacement for simple gsubs:
+utf.length = utf.len
+
+if not utf.sub then
+
+ -- inefficient as lpeg just copies ^n
+
+ -- local function sub(str,start,stop)
+ -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1))
+ -- inspect(pattern)
+ -- return lpegmatch(pattern,str) or ""
+ -- end
+
+ -- local b, e, n, first, last = 0, 0, 0, 0, 0
+ --
+ -- local function slide(s,p)
+ -- n = n + 1
+ -- if n == first then
+ -- b = p
+ -- if not last then
+ -- return nil
+ -- end
+ -- end
+ -- if n == last then
+ -- e = p
+ -- return nil
+ -- else
+ -- return p
+ -- end
+ -- end
+ --
+ -- local pattern = Cmt(p_utf8char,slide)^0
+ --
+ -- function utf.sub(str,start,stop) -- todo: from the end
+ -- if not start then
+ -- return str
+ -- end
+ -- b, e, n, first, last = 0, 0, 0, start, stop
+ -- lpegmatch(pattern,str)
+ -- if not stop then
+ -- return sub(str,b)
+ -- else
+ -- return sub(str,b,e-1)
+ -- end
+ -- end
+
+ -- print(utf.sub("Hans Hagen is my name"))
+ -- print(utf.sub("Hans Hagen is my name",5))
+ -- print(utf.sub("Hans Hagen is my name",5,10))
+
+ local utflength = utf.length
+
+ -- also negative indices, upto 10 times slower than a c variant
+
+ local b, e, n, first, last = 0, 0, 0, 0, 0
+
+ local function slide_zero(s,p)
+ n = n + 1
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_one(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ end
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_two(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ else
+ return true
+ end
+ end
+
+ local pattern_zero = Cmt(p_utf8char,slide_zero)^0
+ local pattern_one = Cmt(p_utf8char,slide_one )^0
+ local pattern_two = Cmt(p_utf8char,slide_two )^0
+
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start == 0 then
+ start = 1
+ end
+ if not stop then
+ if start < 0 then
+ local l = utflength(str) -- we can inline this function if needed
+ start = l + start
+ else
+ start = start - 1
+ end
+ b, n, first = 0, 0, start
+ lpegmatch(pattern_two,str)
+ if n >= first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start < 0 or stop < 0 then
+ local l = utf.length(str)
+ if start < 0 then
+ start = l + start
+ if start <= 0 then
+ start = 1
+ else
+ start = start + 1
+ end
+ end
+ if stop < 0 then
+ stop = l + stop
+ if stop == 0 then
+ stop = 1
+ else
+ stop = stop + 1
+ end
+ end
+ end
+ if start > stop then
+ return ""
+ elseif start > 1 then
+ b, e, n, first, last = 0, 0, 0, start - 1, stop
+ lpegmatch(pattern_one,str)
+ if n >= first and e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ else
+ b, e, n, last = 1, 0, 0, stop
+ lpegmatch(pattern_zero,str)
+ if e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ end
+ end
-local utf8char = patterns.utf8char
+ -- local n = 100000
+ -- local str = string.rep("123456àáâãäå",100)
+ --
+ -- for i=-15,15,1 do
+ -- for j=-15,15,1 do
+ -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then
+ -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j))
+ -- end
+ -- end
+ -- if utf.xsub(str,i) ~= utf.sub(str,i) then
+ -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i))
+ -- end
+ -- end
+
+ -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7))
+ -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7))
+ -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9))
+ -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 ))
+ -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 ))
+ -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0))
+ -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4))
+ -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0))
+ -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0))
+ -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3))
+ -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3))
+ -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 ))
+
+end
+
+-- a replacement for simple gsubs:
function utf.remapper(mapping)
- local pattern = Cs((utf8char/mapping)^0)
+ local pattern = Cs((p_utf8char/mapping)^0)
return function(str)
if not str or str == "" then
return ""
@@ -4695,55 +5184,113 @@ end
-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
-- print(remap("abcd 1234 abcd"))
+--
+
+function utf.replacer(t) -- no precheck, always string builder
+ local r = replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+
+function utf.subtituter(t) -- with precheck and no building if no match
+ local f = finder (t)
+ local r = replacer(t,false,false,true)
+ return function(str)
+ local i = lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i > #str then
+ return str
+ else
+ -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower
+ return lpegmatch(r,str)
+ end
+ end
+end
+
+-- inspect(utf.split("a b c d"))
+-- inspect(utf.split("a b c d",true))
+
+local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0)
+local utfcharsplitter_raw = Ct(C(p_utf8char)^0)
+
+patterns.utflinesplitter = utflinesplitter
+
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+function utf.split(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+function utf.totable(str) -- keeps bom
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
-- 2 FE FF UTF-16-big-endian
-- 3 FF FE 00 00 UTF-32-little-endian
-- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
-}
-
+--
-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
- else
- f:seek('set')
- return 0
+-- utf.name = {
+-- [0] = 'utf-8',
+-- [1] = 'utf-16-le',
+-- [2] = 'utf-16-be',
+-- [3] = 'utf-32-le',
+-- [4] = 'utf-32-be'
+-- }
+--
+-- function utf.magic(f)
+-- local str = f:read(4)
+-- if not str then
+-- f:seek('set')
+-- return 0
+-- -- elseif find(str,"^%z%z\254\255") then -- depricated
+-- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+-- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+-- return 4
+-- -- elseif find(str,"^\255\254%z%z") then -- depricated
+-- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+-- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+-- return 3
+-- elseif find(str,"^\254\255") then
+-- f:seek('set',2)
+-- return 2
+-- elseif find(str,"^\255\254") then
+-- f:seek('set',2)
+-- return 1
+-- elseif find(str,"^\239\187\191") then
+-- f:seek('set',3)
+-- return 0
+-- else
+-- f:seek('set')
+-- return 0
+-- end
+-- end
+
+function utf.magic(f) -- not used
+ local str = f:read(4) or ""
+ local off = lpegmatch(p_utfoffset,str)
+ if off < 4 then
+ f:seek('set',off)
end
+ return lpegmatch(p_utftype,str)
end
-
-
local function utf16_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4771,7 +5318,7 @@ end
local function utf16_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4799,7 +5346,7 @@ end
local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4824,7 +5371,7 @@ end
local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4847,20 +5394,20 @@ local function utf32_to_utf8_le(t)
return t
end
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
+utf.utf32_to_utf8_be = utf32_to_utf8_be
+utf.utf32_to_utf8_le = utf32_to_utf8_le
+utf.utf16_to_utf8_be = utf16_to_utf8_be
+utf.utf16_to_utf8_le = utf16_to_utf8_le
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+function utf.utf8_to_utf8(t)
+ return type(t) == "string" and lpegmatch(utflinesplitter,t) or t
end
-function unicode.utf16_to_utf8(t,endian)
+function utf.utf16_to_utf8(t,endian)
return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
end
-function unicode.utf32_to_utf8(t,endian)
+function utf.utf32_to_utf8(t,endian)
return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
end
@@ -4886,7 +5433,7 @@ local function big(c)
end
end
--- function unicode.utf8_to_utf16(str,littleendian)
+-- function utf.utf8_to_utf16(str,littleendian)
-- if littleendian then
-- return char(255,254) .. utfgsub(str,".",little)
-- else
@@ -4897,7 +5444,7 @@ end
local _, l_remap = utf.remapper(little)
local _, b_remap = utf.remapper(big)
-function unicode.utf8_to_utf16(str,littleendian)
+function utf.utf8_to_utf16(str,littleendian)
if littleendian then
return char(255,254) .. lpegmatch(l_remap,str)
else
@@ -4905,31 +5452,71 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+-- function utf.tocodes(str,separator) -- can be sped up with an lpeg
+-- local t, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- t[n] = format("0x%04X",u)
+-- end
+-- return concat(t,separator or " ")
+-- end
+
+local pattern = Cs (
+ (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) *
+ (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
end
-function unicode.ustring(s)
+function utf.ustring(s)
return format("U+%05X",type(s) == "number" and s or utfbyte(s))
end
-function unicode.xstring(s)
+function utf.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
--
-local pattern = Ct(C(patterns.utf8char)^0)
+local p_nany = p_utf8char / ""
+
+if utfgmatch then
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + p_nany)^0)
+ cache[p] = p
+ end
+ return #lpegmatch(p,str)
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
-function utf.totable(str)
- return lpegmatch(pattern,str)
end
+-- maybe also register as string.utf*
+
end -- of closure
@@ -4990,24 +5577,10 @@ local tables = utilities.tables
local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local type, next, rawset, tonumber, load, select = type, next, rawset, tonumber, load, select
local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
local serialize = table.serialize
--- function tables.definetable(target) -- defines undefined tables
--- local composed, t, n = nil, { }, 0
--- for name in gmatch(target,"([^%.]+)") do
--- n = n + 1
--- if composed then
--- composed = composed .. "." .. name
--- else
--- composed = name
--- end
--- t[n] = format("%s = %s or { }",composed,composed)
--- end
--- return concat(t,"\n")
--- end
-
local splitter = lpeg.tsplitat(".")
function tables.definetable(target,nofirst,nolast) -- defines undefined tables
@@ -5036,13 +5609,13 @@ end
-- local t = tables.definedtable("a","b","c","d")
function tables.definedtable(...)
- local l = { ... }
local t = _G
- for i=1,#l do
- local tl = t[l[i]]
+ for i=1,select("#",...) do
+ local li = select(i,...)
+ local tl = t[li]
if not tl then
tl = { }
- t[l[i]] = tl
+ t[li] = tl
end
t = tl
end
@@ -5235,7 +5808,7 @@ function table.deserialize(str)
if not str or str == "" then
return
end
- local code = loadstring(str)
+ local code = load(str)
if not code then
return
end
@@ -5252,7 +5825,7 @@ function table.load(filename)
if filename then
local t = io.loaddata(filename)
if t and t ~= "" then
- t = loadstring(t)
+ t = load(t)
if type(t) == "function" then
t = t()
if type(t) == "table" then
@@ -5331,9 +5904,11 @@ utilities = utilities or { }
utilities.storage = utilities.storage or { }
local storage = utilities.storage
+local report = texio and texio.write_nl or print
+
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage cannot be marked")
+ report("fatal error: storage cannot be marked")
return -- os.exit()
end
local m = getmetatable(t)
@@ -5363,12 +5938,36 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage has not been allocated")
+ report("fatal error: storage has not been allocated")
return -- os.exit()
end
return t
end
+-- function utilities.storage.delay(parent,name,filename)
+-- local m = getmetatable(parent)
+-- m.__list[name] = filename
+-- end
+--
+-- function utilities.storage.predefine(parent)
+-- local list = { }
+-- local m = getmetatable(parent) or {
+-- __list = list,
+-- __index = function(t,k)
+-- local l = require(list[k])
+-- t[k] = l
+-- return l
+-- end
+-- }
+-- setmetatable(parent,m)
+-- end
+--
+-- bla = { }
+-- utilities.storage.predefine(bla)
+-- utilities.storage.delay(bla,"test","oepsoeps")
+-- local t = bla.test
+-- table.print(t)
+-- print(t.a)
function storage.setinitializer(data,initialize)
local m = getmetatable(data) or { }
@@ -5393,12 +5992,14 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_table (t,k) local v = { } t[k] = v return v end
+local function f_ignore() end -- t,k,v
local t_empty = { __index = f_empty }
local t_self = { __index = f_self }
+local t_table = { __index = f_table }
local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
@@ -5408,6 +6009,8 @@ function table.setmetatableindex(t,f)
m.__index = f_empty
elseif f == "key" then
m.__index = f_self
+ elseif f == "table" then
+ m.__index = f_table
else
m.__index = f
end
@@ -5416,6 +6019,8 @@ function table.setmetatableindex(t,f)
setmetatable(t, t_empty)
elseif f == "key" then
setmetatable(t, t_self)
+ elseif f == "table" then
+ setmetatable(t, t_table)
else
setmetatable(t,{ __index = f })
end
@@ -5626,7 +6231,7 @@ if not modules then modules = { } end modules ['util-lua'] = {
}
local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
-local loadstring, loadfile, type = loadstring, loadfile, type
+local load, loadfile, type = load, loadfile, type
utilities = utilities or {}
utilities.lua = utilities.lua or { }
@@ -5643,11 +6248,23 @@ luautilities.nofstrippedbytes = 0
local strippedchunks = { } -- allocate()
luautilities.strippedchunks = strippedchunks
+luautilities.suffixes = {
+ tma = "tma",
+ tmc = jit and "tmb" or "tmc",
+ lua = "lua",
+ luc = jit and "lub" or "luc",
+ lui = "lui",
+ luv = "luv",
+ luj = "luj",
+ tua = "tua",
+ tuc = "tuc",
+}
+
local function fatalerror(name)
utilities.report(format("fatal error in %q",name or "unknown"))
end
-if jit then
+if jit or status.luatex_version >= 74 then
local function register(name)
if tracestripping then
@@ -5660,7 +6277,7 @@ if jit then
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if code then
code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
if code and code ~= "" then
@@ -5692,13 +6309,13 @@ if jit then
end
if forcestrip or luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
elseif luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
@@ -5706,14 +6323,14 @@ if jit then
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
register(name)
code = dump(code,true)
end
- return loadstring(code), 0
+ return load(code), 0
end
function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
@@ -5754,67 +6371,79 @@ else
return delta
end
- local function strip_code_pc(dump,name)
- local before = #dump
- local version, format, endian, int, size, ins, num = byte(dump,5,11)
- local subint
- if endian == 1 then
- subint = function(dump, i, l)
- local val = 0
- for n = l, 1, -1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_code_pc
+
+ if _MAJORVERSION == 5 and _MINORVERSION == 1 then
+
+ strip_code_pc = function(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
- return val, i + l
end
- else
- subint = function(dump, i, l)
- local val = 0
- for n = 1, l, 1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
end
- return val, i + l
- end
- end
- local strip_function
- strip_function = function(dump)
- local count, offset = subint(dump, 1, size)
- local stripped, dirty = rep("\0", size), offset + count
- offset = offset + count + int * 2 + 4
- offset = offset + int + subint(dump, offset, int) * ins
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- local t
- t, offset = subint(dump, offset, 1)
- if t == 1 then
- offset = offset + 1
- elseif t == 4 then
- offset = offset + size + subint(dump, offset, size)
- elseif t == 3 then
- offset = offset + num
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
end
- count, offset = subint(dump, offset, int)
- stripped = stripped .. sub(dump,dirty, offset - 1)
- for n = 1, count do
- local proto, off = strip_function(sub(dump,offset, -1))
- stripped, offset = stripped .. proto, offset + off - 1
- end
- offset = offset + subint(dump, offset, int) * int + int
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size + int * 2
- end
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size
- end
- stripped = stripped .. rep("\0", int * 3)
- return stripped, offset
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = register(name,before,after)
+ return dump, delta
+ end
+
+ else
+
+ strip_code_pc = function(dump,name)
+ return dump, 0
end
- dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
- local after = #dump
- local delta = register(name,before,after)
- return dump, delta
+
end
-- ... end of borrowed code.
@@ -5834,14 +6463,14 @@ else
end
if forcestrip then
local code, n = strip_code_pc(dump(code),name)
- return loadstring(code), n
+ return load(code), n
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
@@ -5850,20 +6479,20 @@ else
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
local n = 0
if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
code, n = strip_code_pc(dump(code),name)
end
- return loadstring(code), n
+ return load(code), n
end
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
local n = 0
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror()
end
@@ -5903,6 +6532,7 @@ else
utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
end
cleanup = false -- better see how bad it is
+ done = true -- hm
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -5949,7 +6579,6 @@ if not modules then modules = { } end modules ['util-prs'] = {
}
local lpeg, table, string = lpeg, table, string
-
local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
@@ -6367,6 +6996,45 @@ function parsers.rfc4180splitter(specification)
end
end
+-- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- utilities.parsers.stepper("1-3,7,8,9")
+-- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- utilities.parsers.stepper(" 1 : 3, ,7 ")
+-- utilities.parsers.stepper("1:4,9:13,24:*",30)
+
+local function ranger(first,last,n,action)
+ if not first then
+ -- forget about it
+ elseif last == true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+
+local cardinal = patterns.cardinal / tonumber
+local spacers = patterns.spacer^0
+local endofstring = patterns.endofstring
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring)
+
+function utilities.parsers.stepper(str,n,action)
+ if type(n) == "function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
end -- of closure
@@ -6817,7 +7485,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
+local format, find, lower, gsub, topattern = string.format, string.find, string.lower, string.gsub, string.topattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -6905,7 +7573,7 @@ local function set(t,what,newvalue)
else
value = is_boolean(value,value)
end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
+ w = topattern(w,true,true)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
@@ -6959,7 +7627,8 @@ function setters.register(t,what,...)
end
end
local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
+ for i=1,select("#",...) do
+ local fnc = select(i,...)
local typ = type(fnc)
if typ == "string" then
if trace_initialize then
@@ -7028,7 +7697,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
end
end
t.report()
@@ -7052,17 +7721,29 @@ local function report(setter,...)
end
end
-function setters.new(name)
+local function default(setter,name)
+ local d = setter.data[name]
+ return d and d.default
+end
+
+local function value(setter,name)
+ local d = setter.data[name]
+ return d and (d.value or d.default)
+end
+
+function setters.new(name) -- we could use foo:bar syntax (but not used that often)
local setter -- we need to access it in setter itself
setter = {
data = allocate(), -- indexed, but also default and value fields
name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
+ report = function(...) report (setter,...) end,
+ enable = function(...) enable (setter,...) end,
+ disable = function(...) disable (setter,...) end,
+ register = function(...) register(setter,...) end,
+ list = function(...) list (setter,...) end,
+ show = function(...) show (setter,...) end,
+ default = function(...) return default (setter,...) end,
+ value = function(...) return value (setter,...) end,
}
data[name] = setter
return setter
@@ -7189,9 +7870,9 @@ if not modules then modules = { } end modules ['trac-log'] = {
local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
local format, gmatch, find = string.format, string.gmatch, string.find
local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
+local topattern = string.topattern
local texcount = tex and tex.count
-local next, type = next, type
+local next, type, select = next, type, select
local setmetatableindex = table.setmetatableindex
@@ -7502,7 +8183,7 @@ local function setblocked(category,value)
if data[c] then
v.state = value
else
- c = escapedpattern(c,true)
+ c = topattern(c,true,true)
for k, v in next, data do
if find(k,c) then
v.state = value
@@ -7720,10 +8401,10 @@ local function reporthelp(t,...)
if type(helpinfo) == "string" then
reportlines(t,helpinfo)
elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
+ local n = select("#",...)
+ for i=1,n do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i < n then
t.report()
end
end
@@ -8013,6 +8694,10 @@ local format, sub, match, gsub, find = string.format, string.sub, string.match,
local unquoted, quoted = string.unquoted, string.quoted
local concat, insert, remove = table.concat, table.insert, table.remove
local loadedluacode = utilities.lua.loadedluacode
+local luasuffixes = utilities.lua.suffixes
+
+environment = environment or { }
+local environment = environment
-- precautions
@@ -8022,9 +8707,29 @@ function os.setlocale()
-- no way you can mess with it
end
--- dirty tricks
+-- dirty tricks (we will replace the texlua call by luatex --luaonly)
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+local validengines = allocate {
+ ["luatex"] = true,
+ ["luajittex"] = true,
+ -- ["luatex.exe"] = true,
+ -- ["luajittex.exe"] = true,
+}
+
+local basicengines = allocate {
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex",
+ ["texluac"] = "luatex",
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex",
+ -- ["texlua.exe"] = "luatex",
+ -- ["texluajit.exe"] = "luajittex",
+}
+
+environment.validengines = validengines
+environment.basicengines = basicengines
+
+if arg and validengines[file.removesuffix(arg[0])] and arg[1] == "--luaonly" then
arg[-1] = arg[0]
arg[ 0] = arg[2]
for k=3,#arg do
@@ -8056,9 +8761,6 @@ end
-- environment
-environment = environment or { }
-local environment = environment
-
environment.arguments = allocate()
environment.files = allocate()
environment.sortedflags = nil
@@ -8114,7 +8816,7 @@ function environment.initializearguments(arg)
end
end
end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
+ environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
function environment.setargument(name,value)
@@ -8195,6 +8897,22 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+-- -- to be tested:
+--
+-- function environment.reconstructcommandline(arg,noquote)
+-- arg = arg or environment.originalarguments
+-- if noquote and #arg == 1 then
+-- return unquoted(resolvers.resolve(arg[1]))
+-- elseif #arg > 0 then
+-- local result = { }
+-- for i=1,#arg do
+-- result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
+-- end
+-- return concat(result," ")
+-- else
+-- return ""
+-- end
+-- end
if arg then
@@ -8289,9 +9007,11 @@ function environment.loadluafile(filename, version)
local lucname, luaname, chunk
local basename = file.removesuffix(filename)
if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
+ luaname = fiule.addsuffix(basename,luasuffixes.lua)
+ lucname = fiule.addsuffix(basename,luasuffixes.luc)
else
- lucname, luaname = nil, basename -- forced suffix
+ luaname = basename -- forced suffix
+ lucname = nil
end
-- when not overloaded by explicit suffix we look for a luc file first
local fullname = (lucname and environment.luafile(lucname)) or ""
@@ -8372,7 +9092,6 @@ xml = xml or { }
local xml = xml
-local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
@@ -9583,7 +10302,7 @@ if not modules then modules = { } end modules ['lxml-lpt'] = {
-- todo: B/C/[get first match]
local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local type, next, tonumber, tostring, setmetatable, load, select = type, next, tonumber, tostring, setmetatable, load, select
local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
@@ -10195,7 +10914,7 @@ end
local function register_expression(expression)
local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
+ local runner = load(format(template_e,converted))
runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
end
@@ -10203,9 +10922,9 @@ end
local function register_finalizer(protocol,name,arguments)
local runner
if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ runner = load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
+ runner = load(format(template_f_n,protocol or xml.defaultprotocol,name))
end
runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
@@ -10597,6 +11316,7 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
+
expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
return pattern and (collected and #collected) or 0
@@ -10604,13 +11324,30 @@ end
-- external
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+-- expressions.oneof = function(s,...)
+-- local t = {...}
+-- for i=1,#t do
+-- if s == t[i] then
+-- return true
+-- end
+-- end
+-- return false
+-- end
+
+expressions.oneof = function(s,...)
+ for i=1,select("#",...) do
+ if s == select(i,...) then
+ return true
+ end
+ end
+ return false
end
+
expressions.error = function(str)
xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
+
expressions.undefined = function(s)
return s == nil
end
@@ -12220,7 +12957,6 @@ if not modules then modules = { } end modules ['data-ini'] = {
}
local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
local next, type = next, type
local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
@@ -12311,6 +13047,10 @@ do
local args = environment.originalarguments or arg -- this needs a cleanup
+ if not environment.ownmain then
+ environment.ownmain = status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
@@ -12427,19 +13167,6 @@ end
environment.texroot = file.collapsepath(texroot)
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
if profiler then
directives.register("system.profile",function()
profiler.start("luatex-profile.log")
@@ -12946,6 +13673,8 @@ resolvers.suffixes = suffixes
resolvers.dangerous = dangerous
resolvers.suffixmap = suffixmap
+local luasuffixes = utilities.lua.suffixes
+
local relations = allocate { -- todo: handlers also here
core = {
ofm = { -- will become obsolete
@@ -13031,7 +13760,7 @@ local relations = allocate { -- todo: handlers also here
lua = {
names = { "lua" },
variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
+ suffixes = { luasuffixes.lua, luasuffixes.luc, luasuffixes.tma, luasuffixes.tmc },
},
lib = {
names = { "lib" },
@@ -13227,6 +13956,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
+local addsuffix, is_writable, is_readable = file.addsuffix, file.is_writable, file.is_readable
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
@@ -13251,8 +13981,10 @@ end
-- end of intermezzo
-caches = caches or { }
-local caches = caches
+caches = caches or { }
+local caches = caches
+
+local luasuffixes = utilities.lua.suffixes
caches.base = caches.base or "luatex-cache"
caches.more = caches.more or "context"
@@ -13280,18 +14012,18 @@ local function identify()
cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
- if file.is_readable(cachepath) then
+ if is_readable(cachepath) then
readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
+ if not writable and is_writable(cachepath) then
writable = cachepath
end
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
+ if is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
+ if isdir(cachepath) and is_writable(cachepath) then
report_caches("created: %s",cachepath)
writable = cachepath
readables[#readables+1] = cachepath
@@ -13313,8 +14045,8 @@ local function identify()
cachepath = resolvers.resolve(cachepath)
cachepath = resolvers.cleanpath(cachepath)
local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
readables[#readables+1] = cachepath
writable = cachepath
break
@@ -13403,7 +14135,7 @@ end
local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
+local function getreadablepaths(...)
local tags = { ... }
local hash = concat(tags,"/")
local done = r_cache[hash]
@@ -13446,7 +14178,7 @@ function caches.getfirstreadablefile(filename,...)
for i=1,#rd do
local path = rd[i]
local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
+ if is_readable(fullname) then
usedreadables[i] = true
return fullname, path
end
@@ -13467,7 +14199,7 @@ function caches.define(category,subcategory) -- for old times sake
end
function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
+ return format("%s/%s.%s",path,name,luasuffixes.tma), format("%s/%s.%s",path,name,luasuffixes.tmc)
end
function caches.loaddata(readables,name)
@@ -13477,7 +14209,13 @@ function caches.loaddata(readables,name)
for i=1,#readables do
local path = readables[i]
local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
+ local loader = loadfile(tmcname)
+ if not loader then
+ -- in case we have a different engine
+ utilities.lua.compile(tmaname,tmcname)
+ --
+ loader = loadfile(tmaname)
+ end
if loader then
loader = loader()
collectgarbage("step")
@@ -13489,11 +14227,15 @@ end
function caches.is_writable(filepath,filename)
local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
+ return is_writable(tmaname)
end
local saveoptions = { compact = true }
+-- add some point we will only use the internal bytecode compiler and
+-- then we can flag success in the tma so that it can trigger a compile
+-- if the other engine
+
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -13519,9 +14261,9 @@ end
function caches.loadcontent(cachename,dataname)
local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
+ local full, path = caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
+ local blob = loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data = blob()
if data and data.content then
@@ -13556,9 +14298,10 @@ end
function caches.savecontent(cachename,dataname,content)
local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
+ local full, path = caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
+ local luaname = addsuffix(filename,luasuffixes.lua)
+ local lucname = addsuffix(filename,luasuffixes.luc)
if trace_locating then
report_resolvers("preparing '%s' for '%s'",dataname,cachename)
end
@@ -13763,6 +14506,7 @@ local joinpath = file.joinpath
local allocate = utilities.storage.allocate
local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
+local luasuffixes = utilities.lua.suffixes
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -15325,15 +16069,19 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
+ local engine = environment.ownmain or "luatex"
+ local barename = file.removesuffix(name)
+ local fullname = file.addsuffix(barename,"fmt")
+ local fmtname = caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
+ fmtname = resolvers.findfile(fullname)
fmtname = resolvers.cleanpath(fmtname)
end
if fmtname ~= "" then
local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
+ local luaname = file.addsuffix(barename,luasuffixes.lua)
+ local lucname = file.addsuffix(barename,luasuffixes.luc)
+ local luiname = file.addsuffix(barename,luasuffixes.lui)
if lfs.isfile(luiname) then
return barename, luiname
elseif lfs.isfile(lucname) then
@@ -15430,10 +16178,9 @@ local resolvers = resolvers
local prefixes = utilities.storage.allocate()
resolvers.prefixes = prefixes
-local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
local joinpath, basename, dirname = file.join, file.basename, file.dirname
local getmetatable, rawset, type = getmetatable, rawset, type
@@ -15555,6 +16302,28 @@ end
-- todo: use an lpeg (see data-lua for !! / stripper)
+-- local function resolve(str) -- use schemes, this one is then for the commandline only
+-- if type(str) == "table" then
+-- local t = { }
+-- for i=1,#str do
+-- t[i] = resolve(str[i])
+-- end
+-- return t
+-- else
+-- local res = resolved[str]
+-- if not res then
+-- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+-- resolved[str] = res
+-- abstract[res] = str
+-- end
+-- return res
+-- end
+-- end
+
+-- home:xx;selfautoparent:xx;
+
+local pattern = Cs((C(R("az")^2) * P(":") * C((1-S(" \"\';,"))^1) / _resolve_ + P(1))^0)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -15565,7 +16334,7 @@ local function resolve(str) -- use schemes, this one is then for the commandline
else
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+ res = lpegmatch(pattern,str)
resolved[str] = res
abstract[res] = str
end
@@ -15998,7 +16767,7 @@ statistics.register("used cache path", function() return caches.usedpaths() end
function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
local enginebanner = status.list().banner
if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
local luvdata = {
enginebanner = enginebanner,
formatbanner = formatbanner,
@@ -16009,10 +16778,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname ==
end
end
+-- todo: check this at startup and return (say) 999 as signal that the run
+-- was aborted due to a wrong format in which case mtx-context can trigger
+-- a remake
+
function statistics.checkfmtstatus(texname)
local enginebanner = status.list().banner
if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
if lfs.isfile(luvname) then
local luv = dofile(luvname)
if luv and luv.sourcefile then
@@ -16389,7 +17162,7 @@ if not modules then modules = { } end modules ['data-sch'] = {
license = "see context related readme files"
}
-local loadstring = loadstring
+local load = load
local gsub, concat, format = string.gsub, table.concat, string.format
local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
@@ -16575,7 +17348,7 @@ schemes.fetchstring = fetchstring
function schemes.fetchtable(url,data)
local reply = fetchstring(url,data)
if reply then
- local s = loadstring("return " .. reply)
+ local s = load("return " .. reply)
if s then
return s()
end
@@ -16603,6 +17376,8 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- -- local mylib = require("libtest")
-- -- local mysql = require("luasql.mysql")
+local searchers = package.searchers or package.loaders
+
local concat = table.concat
local trace_libraries = false
@@ -16704,13 +17479,9 @@ function package.extraclibpath(...)
end
end
-if not package.loaders then
- package.loaders = package.searchers -- 5.2
-end
-
-if not package.loaders[-2] then
+if not searchers[-2] then
-- use package-path and package-cpath
- package.loaders[-2] = package.loaders[2]
+ searchers[-2] = searchers[2]
end
local function loadedaslib(resolved,rawname)
@@ -16721,7 +17492,7 @@ local function loadedbylua(name)
if trace_libraries then
report_libraries("! locating %q using normal loader",name)
end
- local resolved = package.loaders[-2](name)
+ local resolved = searchers[-2](name)
end
local function loadedbyformat(name,rawname,suffixes,islib)
@@ -16776,7 +17547,7 @@ local function notloaded(name)
end
end
-package.loaders[2] = function(name)
+searchers[2] = function(name)
local thename = gsub(name,"%.","/")
local luaname = file.addsuffix(thename,"lua")
local libname = file.addsuffix(thename,os.libsuffix)
@@ -16790,8 +17561,8 @@ package.loaders[2] = function(name)
or notloaded (name)
end
--- package.loaders[3] = nil
--- package.loaders[4] = nil
+-- searchers[3] = nil
+-- searchers[4] = nil
resolvers.loadlualib = require
@@ -17161,13 +17932,11 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
local format = string.format
+local quoted = string.quoted
+local luasuffixes = utilities.lua.suffixes
local report_format = logs.reporter("resolvers","formats")
--- helper for mtxrun
-
-local quoted = string.quoted
-
local function primaryflags() -- not yet ok
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
@@ -17182,13 +17951,14 @@ local function primaryflags() -- not yet ok
end
function environment.make_format(name)
+ local engine = environment.ownmain or "luatex"
-- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
+ local olddir = dir.current()
+ local path = caches.getwritablepath("formats",engine) or "" -- maybe platform
if path ~= "" then
lfs.chdir(path)
end
- report_format("format path: %s",lfs.currentdir())
+ report_format("format path: %s",dir.current())
-- check source file
local texsourcename = file.addsuffix(name,"mkiv")
local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
@@ -17225,13 +17995,12 @@ function environment.make_format(name)
elseif type(usedlualibs) == "table" then
report_format("using stub specification: %s",fullspecificationname)
local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
+ local luastubname = file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname = file.addsuffix(texbasename,luasuffixes.luc)
-- pack libraries in stub
report_format("creating initialization file: %s",luastubname)
utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
-- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
report_format("using compiled initialization file: %s",lucstubname)
usedluastub = lucstubname
@@ -17245,7 +18014,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -17264,8 +18033,9 @@ end
function environment.run_format(name,data,more)
if name and name ~= "" then
+ local engine = environment.ownmain or "luatex"
local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
+ local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
if fmtname == "" then
fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
end
@@ -17282,7 +18052,7 @@ function environment.run_format(name,data,more)
report_format("using format name: %s",fmtname)
report_format("no luc/lua with name: %s",barename)
else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
+ local command = format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
report_format("running command: %s",command)
os.spawn(command)
end
@@ -17423,10 +18193,11 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -17656,6 +18427,10 @@ local helpinfo = [[
--variables show configuration variables
--configurations show configuration order
+--directives show (known) directives
+--trackers show (known) trackers
+--experiments show (known) experiments
+
--expand-braces expand complex variable
--expand-path expand variable (resolve paths)
--expand-var expand variable (resolve references)
@@ -18346,8 +19121,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
-if e_argument("selfmerge") then
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18377,17 +19162,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -18615,6 +19389,18 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index 01c601eb5..3a02ad582 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,7 +54,7 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-functions'] = {
+if not modules then modules = { } end modules ['l-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -51,16 +62,112 @@ if not modules then modules = { } end modules ['l-functions'] = {
license = "see context related readme files"
}
-functions = functions or { }
+-- compatibility hacks ... try to avoid usage
-function functions.dummy() end
+local major, minor = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+
+_MAJORVERSION = tonumber(major) or 5
+_MINORVERSION = tonumber(minor) or 1
+
+-- basics:
+
+if loadstring then
+
+ local loadnormal = load
+
+ function load(first,...)
+ if type(first) == "string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+
+else
+
+ loadstring = load
+
+end
+
+-- table:
+
+-- Starting with version 5.2 Lua no longer provide ipairs, which makes
+-- sense. As we already used the for loop and # in most places the
+-- impact on ConTeXt was not that large; the remaining ipairs already
+-- have been replaced. In a similar fashion we also hardly used pairs.
+--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- The unpack function has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+
+ table.unpack = _G.unpack
+
+elseif not unpack then
+
+ _G.unpack = table.unpack
+
+end
+
+-- package:
+
+-- if not package.seachers then
+--
+-- package.searchers = package.loaders -- 5.2
+--
+-- elseif not package.loaders then
+--
+-- package.loaders = package.searchers
+--
+-- end
+
+if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type
+
+ package.loaders = package.searchers
+
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
+if not modules then modules = { } end modules ['l-lpeg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -68,34 +175,843 @@ if not modules then modules = { } end modules ['l-string'] = {
license = "see context related readme files"
}
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
--- some functions may disappear as they are not used anywhere
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
-if not string.split then
+local lpeg = require("lpeg")
- -- this will be overloaded by a faster lpeg variant
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
+-- some code will move to unicode and string
+
+local report = texio and texio.write_nl or print
+
+-- local lpmatch = lpeg.match
+-- local lpprint = lpeg.print
+-- local lpp = lpeg.P
+-- local lpr = lpeg.R
+-- local lps = lpeg.S
+-- local lpc = lpeg.C
+-- local lpb = lpeg.B
+-- local lpv = lpeg.V
+-- local lpcf = lpeg.Cf
+-- local lpcb = lpeg.Cb
+-- local lpcg = lpeg.Cg
+-- local lpct = lpeg.Ct
+-- local lpcs = lpeg.Cs
+-- local lpcc = lpeg.Cc
+-- local lpcmt = lpeg.Cmt
+-- local lpcarg = lpeg.Carg
+
+-- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+-- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+-- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+-- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+-- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+-- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+-- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+-- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+-- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+-- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+-- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+-- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+-- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+-- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+-- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+patterns.utfoffset = utfoffset
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * P(-1) / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
+
+patterns.stripper = stripper
+patterns.collapser = collapser
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.unsigned = digit^0 * P('.') * digit^1
+patterns.float = sign^0 * patterns.unsigned
+patterns.cunsigned = digit^0 * P(',') * digit^1
+patterns.cfloat = sign^0 * patterns.cunsigned
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
+patterns.propername = R("AZ","az","__") * R("09","AZ","az", "__")^0 * P(-1)
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
+end
+
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.split(str,separator)
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+
+-- lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+-- from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(anything^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * endofstring)^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
+ local pattern
+ local u = isutf and utf8char or 1
+ if type(one) == "table" then
+ local no = #one
+ local p = P(false)
+ if no == 0 then
+ for k, v in next, one do
+ p = p + P(k) / v
+ end
+ pattern = Cs((p + u)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ -- pattern = Cs(((1-one)^1 + one/two)^0)
+ pattern = Cs((one/two + u)^0)
+ else
+ for i=1,no do
+ local o = one[i]
+ p = p + P(o[1]) / o[2]
+ end
+ pattern = Cs((p + u)^0)
+ end
+ else
+ pattern = Cs((P(one)/(two or "") + u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst) == "table" then
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
+ end
+ else
+ pattern = P(lst)
+ end
+ pattern = (1-pattern)^0 * pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+
+-- utf extensies
+
+local utfcharacters = utf and utf.characters or string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+local utfchar = utf and utf.char or (unicode and unicode.utf8 and unicode.utf8.char)
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfcharacters(str) do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfgmatch(str,".") do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p = P(false)
+ local f = function(uc)
+ p = p + P(uc)
+ end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
+ local p = P(false)
+ for i=first,last do
+ p = p + P(utfchar(i))
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ -- tricky, these nested captures
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+-- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
+
+-- lpeg.print(lpeg.R("ab","cd","gh"))
+-- lpeg.print(lpeg.P("a","b","c"))
+-- lpeg.print(lpeg.S("a","b","c"))
+
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- table.sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = t[k]
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
end
end
- return t
end
+ return p
+end
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
end
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
+
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-functions'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+functions = functions or { }
+
+function functions.dummy() end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-string'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string = string
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
+
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
+
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
+
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
+
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
+
function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+ return lpegmatch(unquoted,str) or str
end
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function string.quoted(str)
return format("%q",str) -- always "
@@ -118,65 +1034,112 @@ function string.limit(str,n,sentinel) -- not utf proof
end
end
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+local stripper = patterns.stripper
+local collapser = patterns.collapser
function string.strip(str)
return lpegmatch(stripper,str) or ""
end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1)
+
function string.is_empty(str)
- return not find(str,"%S")
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
if str == "" then
return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
- end
- if strict then
- return "^" .. str .. "$"
- else
- return str
- end
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
end
end
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
function string.valid(str,default)
return (type(str) == "string" and str ~= "" and str) or default or nil
end
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
-
-- handy fallback
string.itself = function(s) return s end
@@ -189,6 +1152,19 @@ function string.totable(str)
return lpegmatch(pattern,str)
end
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
+
end -- of closure
@@ -202,68 +1178,23 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
local table, string = table, string
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local getinfo = debug.getinfo
-
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Hm, actually ipairs was retained, but we no longer use it anyway.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
-
-if not ipairs then
-
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
-
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
-
- function ipairs(a)
- return iterate, a, 0
- end
-
-end
-
-if not pairs then
-
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
-
- function pairs(t)
- return next, t -- , nil
- end
-
-end
-
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
-
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local floor = math.floor
-- extra functions, some might go (when not used)
+local stripper = patterns.stripper
+
function table.strip(tab)
local lst, l = { }, 0
for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
-- skip this one
else
@@ -372,7 +1303,7 @@ local function sortedhash(t)
end
table.sortedhash = sortedhash
-table.sortedpairs = sortedhash
+table.sortedpairs = sortedhash -- obsolete
function table.append(t,list)
local n = #t
@@ -396,31 +1327,63 @@ function table.prepend(t, list)
return t
end
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
t[k] = v
end
end
return t
end
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
function table.merged(...)
- local tmp, lst = { }, { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
- tmp[k] = v
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
end
end
- return tmp
+ return t
end
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
function table.imerge(t, ...)
- local lst, nt = { ... }, #t
- for i=1,#lst do
- local nst = lst[i]
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
nt = nt + 1
t[nt] = nst[j]
@@ -429,10 +1392,22 @@ function table.imerge(t, ...)
return t
end
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
function table.imerged(...)
- local tmp, ntmp, lst = { }, 0, {...}
- for i=1,#lst do
- local nst = lst[i]
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
ntmp = ntmp + 1
tmp[ntmp] = nst[j]
@@ -444,7 +1419,7 @@ end
local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
- for k,v in next, old do
+ for k, v in next, old do
if type(v) == "table" then
new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
@@ -498,7 +1473,7 @@ end
table.fastcopy = fastcopy
table.copy = copy
-function table.derive(parent)
+function table.derive(parent) -- for the moment not public
local child = { }
if parent then
setmetatable(child,{ __index = parent })
@@ -579,6 +1554,13 @@ end
-- problem: there no good number_to_string converter with the best resolution
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
local function dummy() end
local function do_serialize(root,name,depth,level,indexed)
@@ -588,14 +1570,14 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s{",depth))
else
local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
+ if tn == "number" then
if hexify then
handle(format("%s[0x%04X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
handle(format("%s%s={",depth,name))
else
handle(format("%s[%q]={",depth,name))
@@ -621,7 +1603,6 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
--- if not root[k] then
if root[k] == nil then
last = k - 1
break
@@ -667,7 +1648,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
+ handle(format('%s load(%q),',depth,dump(v)))
else
handle(format('%s "function",',depth))
end
@@ -679,7 +1660,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s __p__=nil,",depth))
end
elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
else
@@ -691,7 +1672,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%04X,",depth,k,v))
else
@@ -706,7 +1687,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "string" then
if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,v))
else
@@ -714,13 +1695,13 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,v))
else
@@ -728,7 +1709,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
handle(format("%s [%q]=%q,",depth,k,v))
@@ -736,7 +1717,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "table" then
if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={},",depth,k))
else
@@ -744,7 +1725,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
handle(format("%s [%q]={},",depth,k))
@@ -752,15 +1733,15 @@ local function do_serialize(root,name,depth,level,indexed)
elseif inline then
local st = simple_table(v)
if st then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
@@ -772,15 +1753,15 @@ local function do_serialize(root,name,depth,level,indexed)
do_serialize(v,k,depth,level+1)
end
elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%s,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%s,",depth,k,tostring(v)))
@@ -789,30 +1770,30 @@ local function do_serialize(root,name,depth,level,indexed)
if functions then
local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
@@ -892,6 +1873,14 @@ local function serialize(_handle,root,name,specification) -- handle wins
handle("}")
end
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
function table.serialize(root,name,specification)
local t, n = { }, 0
@@ -980,7 +1969,7 @@ table.flattened = flattened
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
- f = { }
+ f = { } -- this one can become obsolete
end
for i=1,#t do
local v = t[i]
@@ -1009,7 +1998,7 @@ local function are_equal(a,b,n,m) -- indexed
local ai, bi = a[i], b[i]
if ai==bi then
-- same
- elseif type(ai)=="table" and type(bi)=="table" then
+ elseif type(ai) == "table" and type(bi) == "table" then
if not are_equal(ai,bi) then
return false
end
@@ -1044,10 +2033,10 @@ table.are_equal = are_equal
-- maybe also make a combined one
-function table.compact(t)
+function table.compact(t) -- remove empty tables, assumes subtables
if t then
- for k,v in next, t do
- if not next(v) then
+ for k, v in next, t do
+ if not next(v) then -- no type checking
t[k] = nil
end
end
@@ -1086,7 +2075,7 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirror(t) -- hash
+function table.mirrored(t) -- hash
local n = { }
for k, v in next, t do
n[v] = k
@@ -1109,6 +2098,17 @@ function table.reversed(t)
end
end
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
function table.sequenced(t,sep) -- hash only
if t then
local s, n = { }, 0
@@ -1196,848 +2196,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
--- some code will move to unicode and string
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type, next = type, next
-local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
-local lpegtype, lpegmatch = lpeg.type, lpeg.match
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-local eol = S("\n\r")
-local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-local whitespace = eol + spacer
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.unsigned = digit^0 * P('.') * digit^1
-patterns.float = sign^0 * patterns.unsigned
-patterns.cunsigned = digit^0 * P(',') * digit^1
-patterns.cfloat = sign^0 * patterns.cunsigned
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = eol
-patterns.spacer = spacer
-patterns.whitespace = whitespace
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - spacer
-patterns.nonwhitespace = 1 - whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.singlequoted = squote * patterns.nosquote * squote
-patterns.doublequoted = dquote * patterns.nodquote * dquote
-patterns.quoted = patterns.doublequoted + patterns.singlequoted
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-local function anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) }
-end
-
-lpeg.anywhere = anywhere
-
-function lpeg.instringchecker(p)
- p = anywhere(p)
- return function(str)
- return lpegmatch(p,str) and true or false
- end
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return lpegmatch(splitters_m[separator] or splitat(separator),str)
-end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.split(str,separator)
- if separator then
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
- else
- return { str }
- end
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = tsplitat(newline)
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return lpegmatch(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return lpegmatch(utflinesplitter,str or "")
-end
-
-local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
-local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
-
-function string.utfsplit(str,ignorewhitespace) -- new
- if ignorewhitespace then
- return lpegmatch(utfcharsplitter_iws,str or "")
- else
- return lpegmatch(utfcharsplitter_ows,str or "")
- end
-end
-
--- inspect(string.utfsplit("a b c d"))
--- inspect(string.utfsplit("a b c d",true))
-
--- -- alternative 1: 0.77
---
--- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
---
--- function string.utflength(str)
--- return #lpegmatch(utfcharcounter,str or "")
--- end
---
--- -- alternative 2: 1.70
---
--- local n = 0
---
--- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
---
--- function string.utflength(str)
--- n = 0
--- lpegmatch(utfcharcounter,str or "")
--- return n
--- end
---
--- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
-
-local n = 0
-
-local utfcharcounter = utfbom^-1 * Cs ( (
- Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
- + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
- + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
- + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
-)^0 )
-
-function string.utflength(str)
- n = 0
- lpegmatch(utfcharcounter,str or "")
- return n
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(anything^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * endofstring)^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two,makefunction)
- local pattern
- if type(one) == "table" then
- local no = #one
- local p = P(false)
- if no == 0 then
- for k, v in next, one do
- p = p + P(k) / v
- end
- pattern = Cs((p + 1)^0)
- elseif no == 1 then
- local o = one[1]
- one, two = P(o[1]), o[2]
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two + 1)^0)
- else
- for i=1,no do
- local o = one[i]
- p = p + P(o[1]) / o[2]
- end
- pattern = Cs((p + 1)^0)
- end
- else
- one = P(one)
- two = two or ""
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two +1)^0)
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
-function lpeg.finder(lst,makefunction)
- local pattern
- if type(lst) == "table" then
- local p = P(false)
- for i=1,#lst do
- p = p + P(lst[i])
- end
- pattern = (p + 1)^0
- else
- pattern = (P(lst) + 1)^0
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
--- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
--- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
--- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #lpegmatch(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #lpegmatch(p,str)
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfcharacters(str) do
- p = p + P(uc)
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfgmatch(str,".") do
- p = p + P(uc)
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p = P(false)
- local f = function(uc)
- p = p + P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
- local p = P(false)
- for i=first,last do
- p = p + P(utfchar(i))
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- -- tricky, these nested captures
- return utf8byte / f -- nil when invalid range
- end
-end
-
--- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
-
-
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- table.sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
-
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
-
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
-
--- experiment:
-
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
-end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
- end
- return make(tree)
-end
-
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
--- handy from within tex:
-
-local lpegmatch = lpeg.match
-
-local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
-
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-
--- strips leading and trailing spaces and collapsed all other spaces
-
-local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
-
-function string.collapsespaces(str)
- return lpegmatch(pattern,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-io'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -2368,7 +2526,7 @@ function io.readstring(f,n,m)
f:seek("set",n)
n = m
end
- local str = gsub(f:read(n),"%z","")
+ local str = gsub(f:read(n),"\000","")
return str
end
@@ -2418,10 +2576,129 @@ local lpegmatch = lpeg.match
number = number or { }
local number = number
--- a,b,c,d,e,f = number.toset(100101)
+if bit32 then
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p)
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
+
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ }
+
+ function number.tobitstring(b,m)
+ -- if really needed we can speed this one up
+ -- because small numbers need less extraction
+ local n = 32
+ for i=0,31 do
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
end
function number.toevenhex(n)
@@ -2433,86 +2710,59 @@ function number.toevenhex(n)
end
end
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
--
-- for i=1,1000000 do
-- local a,b,c,d,e,f,g,h = number.toset(12345678)
-- local a,b,c,d = number.toset(1234)
-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
-- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-local one = lpeg.C(1-lpeg.S(''))^1
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
function number.toset(n)
return lpegmatch(one,tostring(n))
end
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
local m = n % 2
+ local n = floor(n/2)
if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
- end
- return t
-end
-
-
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
-
-function number.setbit(x, p)
- return (x % (p + p) >= p) and x or x + p
-end
-
-function number.clearbit(x, p)
- return (x % (p + p) >= p) and x - p or x
-end
-
-
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+ return bits(n, i+1, i, ...)
else
- return "00000000"
+ return bits(n, i+1, ...)
end
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ return ...
end
end
-
-function number.valid(str,default)
- return tonumber(str) or default or nil
+function number.bits(n)
+ return { bits(n,1) }
end
@@ -3104,25 +3354,25 @@ local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = C((noslashes^0 * slashes^1)^1)
local function pathpart(name,default)
- return lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
end
local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
local function basename(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
local function nameonly(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
local function suffixonly(name)
- return lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
end
file.pathpart = pathpart
@@ -3153,7 +3403,9 @@ local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra capture
local pattern_d = path * rest
function file.splitname(str,splitdrive)
- if splitdrive then
+ if not str then
+ -- error
+ elseif splitdrive then
return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
else
return lpegmatch(pattern_b,str) -- returns path, base, suffix
@@ -3161,34 +3413,36 @@ function file.splitname(str,splitdrive)
end
function file.splitbase(str)
- return lpegmatch(pattern_d,str) -- returns path, base+suffix
+ return str and lpegmatch(pattern_d,str) -- returns path, base+suffix
end
function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
- else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
end
local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1)
function file.removesuffix(name)
- return lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
end
-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
@@ -3205,8 +3459,8 @@ end
local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
return filename
elseif criterium == true then
return filename .. "." .. suffix
@@ -3252,7 +3506,7 @@ local suffix = period * (1-period-slashes)^1 * -1
local pattern = Cs((1-suffix)^0)
function file.replacesuffix(name,suffix)
- if suffix and suffix ~= "" then
+ if name and suffix and suffix ~= "" then
return lpegmatch(pattern,name) .. "." .. suffix
else
return name
@@ -3261,10 +3515,10 @@ end
--
-local reslasher = lpeg.replacer(S("\\"),"/")
+local reslasher = lpeg.replacer(P("\\"),"/")
function file.reslash(str)
- return lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
end
-- We should be able to use:
@@ -3280,7 +3534,9 @@ end
-- variant:
function file.is_writable(name)
- if lfs.isdir(name) then
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
local f = io.open(name,"wb")
if f then
@@ -3308,24 +3564,32 @@ end
local readable = P("r") * Cc(true)
function file.is_readable(name)
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
function file.size(name)
- local a = attributes(name)
- return a and a.size or 0
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
end
function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
- return checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
end
function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
local stripper = Cs(P(fwslash)^0/"" * reslasher)
@@ -3333,14 +3597,23 @@ local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
-function file.join(...) -- rather dirty
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
return one .. "/" .. two
elseif lpegmatch(isroot,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
return two
else
@@ -3349,7 +3622,7 @@ function file.join(...) -- rather dirty
elseif one == "" then
return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(reslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat(lst,"/"))
end
end
@@ -3378,6 +3651,9 @@ local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * C
local absolute = fwslash
function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
if anchor and not lpegmatch(anchors,str) then
str = getcurrentdir() .. "/" .. str
end
@@ -3387,7 +3663,6 @@ function file.collapsepath(str,anchor)
return lpegmatch(reslasher,str)
end
local starter, oldelements = lpegmatch(splitstarter,str)
--- inspect(oldelements)
local newelements = { }
local i = #oldelements
while i > 0 do
@@ -3441,11 +3716,13 @@ local whatever = P("-")^0 / ""
local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
function file.robustname(str,strict)
- str = lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
- else
- return str
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
end
end
@@ -3453,7 +3730,9 @@ file.readdata = io.loaddata
file.savedata = io.savedata
function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+ if oldname and newname then
+ file.savedata(newname,io.loaddata(oldname))
+ end
end
-- also rewrite previous
@@ -3474,11 +3753,11 @@ lpeg.patterns.rootbased = rootbased
-- ./name ../name /name c: :// name/name
function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+ return filename and lpegmatch(qualified,filename) ~= nil
end
function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
+ return filename and lpegmatch(rootbased,filename) ~= nil
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -3500,8 +3779,10 @@ end
-- for myself:
function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
end
-- local debuglist = {
@@ -3943,7 +4224,7 @@ if not modules then modules = { } end modules ['l-dir'] = {
-- dir.expandname will be merged with cleanpath and collapsepath
-local type = type
+local type, select = type, select
local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
@@ -4165,15 +4446,15 @@ local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
if onwindows then
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
end
end
local first, middle, last
@@ -4222,9 +4503,9 @@ if onwindows then
else
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
if s and s ~= "" then -- we catch nil and false
if str ~= "" then
str = str .. "/" .. s
@@ -4424,29 +4705,45 @@ if not modules then modules = { } end modules ['l-unicode'] = {
-- todo: utf.sub replacement (used in syst-aux)
-local concat = table.concat
+-- we put these in the utf namespace:
+
+utf = utf or (unicode and unicode.utf8) or { }
+
+utf.characters = utf.characters or string.utfcharacters
+utf.values = utf.values or string.utfvalues
+
+-- string.utfvalues
+-- string.utfcharacters
+-- string.characters
+-- string.characterpairs
+-- string.bytes
+-- string.bytepairs
+
local type = type
-local P, C, R, Cs, Ct, Cmt = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt
+local char, byte, format, sub = string.char, string.byte, string.format, string.sub
+local concat = table.concat
+local P, C, R, Cs, Ct, Cmt, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local utftype = patterns.utftype
-local char, byte, find, bytepairs, utfvalues, format, sub = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format, string.sub
-local utfsplitlines = string.utfsplitlines
-if not unicode then
+local bytepairs = string.bytepairs
- unicode = { }
+local finder = lpeg.finder
+local replacer = lpeg.replacer
-end
+local utfvalues = utf.values
+local utfgmatch = utf.gmatch -- not always present
-local unicode = unicode
+local p_utftype = patterns.utftype
+local p_utfoffset = patterns.utfoffset
+local p_utf8char = patterns.utf8char
+local p_utf8byte = patterns.utf8byte
+local p_utfbom = patterns.utfbom
+local p_newline = patterns.newline
+local p_whitespace = patterns.whitespace
-utf = utf or unicode.utf8
-
-if not utf then
+if not unicode then
- utf8 = { }
- unicode.utf8 = utf8
- utf = utf8
+ unicode = { utf = utf } -- for a while
end
@@ -4503,64 +4800,13 @@ if not utf.byte then
end
-if not utf.sub then
-
- local utf8char = patterns.utf8char
-
- -- inefficient as lpeg just copies ^n
-
- -- local function sub(str,start,stop)
- -- local pattern = utf8char^-(start-1) * C(utf8char^-(stop-start+1))
- -- inspect(pattern)
- -- return lpegmatch(pattern,str) or ""
- -- end
-
- local b, e, n, first, last = 0, 0, 0, 0, 0
-
- local function slide(s,p)
- n = n + 1
- if n == first then
- b = p
- if not last then
- return nil
- end
- end
- if n == last then
- e = p
- return nil
- else
- return p
- end
- end
-
- local pattern = Cmt(utf8char,slide)^0
-
- function utf.sub(str,start,stop) -- todo: from the end
- if not start then
- return str
- end
- b, e, n, first, last = 0, 0, 0, start, stop
- lpegmatch(pattern,str)
- if not stop then
- return sub(str,b)
- else
- return sub(str,b,e)
- end
- end
-
- -- print(utf.sub("Hans Hagen is my name"))
- -- print(utf.sub("Hans Hagen is my name",5))
- -- print(utf.sub("Hans Hagen is my name",5,10))
-
-end
-
local utfchar, utfbyte = utf.char, utf.byte
-- As we want to get rid of the (unmaintained) utf library we implement our own
-- variants (in due time an independent module):
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
end
local toentities = Cs (
@@ -4647,7 +4893,7 @@ local pattern = P("\254\255") * Cs( (
+ one
)^1 )
-function string.toutf(s)
+function string.toutf(s) -- in string namespace
return lpegmatch(pattern,s) or s -- todo: utf32
end
@@ -4663,26 +4909,269 @@ local validatedutf = Cs (
patterns.validatedutf = validatedutf
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.is_valid(str)
+ return type(str) == "string" and lpegmatch(validatedutf,str) or false
end
+if not utf.len then
-utf.length = string.utflength
-utf.split = string.utfsplit
-utf.splitines = string.utfsplitlines
-utf.valid = string.validutf
+ -- -- alternative 1: 0.77
+ --
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ --
+ -- function utf.len(str)
+ -- return #lpegmatch(utfcharcounter,str or "")
+ -- end
+ --
+ -- -- alternative 2: 1.70
+ --
+ -- local n = 0
+ --
+ -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ --
+ -- function utf.length(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+ --
+ -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+ -- local n = 0
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * (
+ -- -- patterns.utf8one ^1 * Cc(1)
+ -- -- + patterns.utf8two ^1 * Cc(2)
+ -- -- + patterns.utf8three^1 * Cc(3)
+ -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end
+ -- -- )^0 ) -- just as many captures as below
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( (
+ -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end))
+ -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end))
+ -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end))
+ -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end))
+ -- -- )^0 ) -- not interesting as it creates strings but sometimes faster
+ --
+ -- -- The best so far:
+ --
+ -- local utfcharcounter = utfbom^-1 * P ( (
+ -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+ -- )^0 )
+
+ -- function utf.len(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+
+ local n, f = 0, 1
+
+ local utfcharcounter = patterns.utfbom^-1 * Cmt (
+ Cc(1) * patterns.utf8one ^1
+ + Cc(2) * patterns.utf8two ^1
+ + Cc(3) * patterns.utf8three^1
+ + Cc(4) * patterns.utf8four ^1,
+ function(_,t,d) -- due to Cc no string captures, so faster
+ n = n + (t - f)/d
+ f = t
+ return true
+ end
+ )^0
+
+ function utf.len(str)
+ n, f = 0, 1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
-if not utf.len then
- utf.len = utf.length
end
--- a replacement for simple gsubs:
+utf.length = utf.len
+
+if not utf.sub then
+
+ -- inefficient as lpeg just copies ^n
+
+ -- local function sub(str,start,stop)
+ -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1))
+ -- inspect(pattern)
+ -- return lpegmatch(pattern,str) or ""
+ -- end
+
+ -- local b, e, n, first, last = 0, 0, 0, 0, 0
+ --
+ -- local function slide(s,p)
+ -- n = n + 1
+ -- if n == first then
+ -- b = p
+ -- if not last then
+ -- return nil
+ -- end
+ -- end
+ -- if n == last then
+ -- e = p
+ -- return nil
+ -- else
+ -- return p
+ -- end
+ -- end
+ --
+ -- local pattern = Cmt(p_utf8char,slide)^0
+ --
+ -- function utf.sub(str,start,stop) -- todo: from the end
+ -- if not start then
+ -- return str
+ -- end
+ -- b, e, n, first, last = 0, 0, 0, start, stop
+ -- lpegmatch(pattern,str)
+ -- if not stop then
+ -- return sub(str,b)
+ -- else
+ -- return sub(str,b,e-1)
+ -- end
+ -- end
+
+ -- print(utf.sub("Hans Hagen is my name"))
+ -- print(utf.sub("Hans Hagen is my name",5))
+ -- print(utf.sub("Hans Hagen is my name",5,10))
+
+ local utflength = utf.length
+
+ -- also negative indices, upto 10 times slower than a c variant
+
+ local b, e, n, first, last = 0, 0, 0, 0, 0
+
+ local function slide_zero(s,p)
+ n = n + 1
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_one(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ end
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_two(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ else
+ return true
+ end
+ end
+
+ local pattern_zero = Cmt(p_utf8char,slide_zero)^0
+ local pattern_one = Cmt(p_utf8char,slide_one )^0
+ local pattern_two = Cmt(p_utf8char,slide_two )^0
+
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start == 0 then
+ start = 1
+ end
+ if not stop then
+ if start < 0 then
+ local l = utflength(str) -- we can inline this function if needed
+ start = l + start
+ else
+ start = start - 1
+ end
+ b, n, first = 0, 0, start
+ lpegmatch(pattern_two,str)
+ if n >= first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start < 0 or stop < 0 then
+ local l = utf.length(str)
+ if start < 0 then
+ start = l + start
+ if start <= 0 then
+ start = 1
+ else
+ start = start + 1
+ end
+ end
+ if stop < 0 then
+ stop = l + stop
+ if stop == 0 then
+ stop = 1
+ else
+ stop = stop + 1
+ end
+ end
+ end
+ if start > stop then
+ return ""
+ elseif start > 1 then
+ b, e, n, first, last = 0, 0, 0, start - 1, stop
+ lpegmatch(pattern_one,str)
+ if n >= first and e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ else
+ b, e, n, last = 1, 0, 0, stop
+ lpegmatch(pattern_zero,str)
+ if e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ end
+ end
-local utf8char = patterns.utf8char
+ -- local n = 100000
+ -- local str = string.rep("123456àáâãäå",100)
+ --
+ -- for i=-15,15,1 do
+ -- for j=-15,15,1 do
+ -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then
+ -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j))
+ -- end
+ -- end
+ -- if utf.xsub(str,i) ~= utf.sub(str,i) then
+ -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i))
+ -- end
+ -- end
+
+ -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7))
+ -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7))
+ -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9))
+ -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 ))
+ -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 ))
+ -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0))
+ -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4))
+ -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0))
+ -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0))
+ -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3))
+ -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3))
+ -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 ))
+
+end
+
+-- a replacement for simple gsubs:
function utf.remapper(mapping)
- local pattern = Cs((utf8char/mapping)^0)
+ local pattern = Cs((p_utf8char/mapping)^0)
return function(str)
if not str or str == "" then
return ""
@@ -4695,55 +5184,113 @@ end
-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
-- print(remap("abcd 1234 abcd"))
+--
+
+function utf.replacer(t) -- no precheck, always string builder
+ local r = replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+
+function utf.subtituter(t) -- with precheck and no building if no match
+ local f = finder (t)
+ local r = replacer(t,false,false,true)
+ return function(str)
+ local i = lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i > #str then
+ return str
+ else
+ -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower
+ return lpegmatch(r,str)
+ end
+ end
+end
+
+-- inspect(utf.split("a b c d"))
+-- inspect(utf.split("a b c d",true))
+
+local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0)
+local utfcharsplitter_raw = Ct(C(p_utf8char)^0)
+
+patterns.utflinesplitter = utflinesplitter
+
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+function utf.split(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+function utf.totable(str) -- keeps bom
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
-- 2 FE FF UTF-16-big-endian
-- 3 FF FE 00 00 UTF-32-little-endian
-- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
-}
-
+--
-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
- else
- f:seek('set')
- return 0
+-- utf.name = {
+-- [0] = 'utf-8',
+-- [1] = 'utf-16-le',
+-- [2] = 'utf-16-be',
+-- [3] = 'utf-32-le',
+-- [4] = 'utf-32-be'
+-- }
+--
+-- function utf.magic(f)
+-- local str = f:read(4)
+-- if not str then
+-- f:seek('set')
+-- return 0
+-- -- elseif find(str,"^%z%z\254\255") then -- depricated
+-- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+-- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+-- return 4
+-- -- elseif find(str,"^\255\254%z%z") then -- depricated
+-- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+-- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+-- return 3
+-- elseif find(str,"^\254\255") then
+-- f:seek('set',2)
+-- return 2
+-- elseif find(str,"^\255\254") then
+-- f:seek('set',2)
+-- return 1
+-- elseif find(str,"^\239\187\191") then
+-- f:seek('set',3)
+-- return 0
+-- else
+-- f:seek('set')
+-- return 0
+-- end
+-- end
+
+function utf.magic(f) -- not used
+ local str = f:read(4) or ""
+ local off = lpegmatch(p_utfoffset,str)
+ if off < 4 then
+ f:seek('set',off)
end
+ return lpegmatch(p_utftype,str)
end
-
-
local function utf16_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4771,7 +5318,7 @@ end
local function utf16_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4799,7 +5346,7 @@ end
local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4824,7 +5371,7 @@ end
local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -4847,20 +5394,20 @@ local function utf32_to_utf8_le(t)
return t
end
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
+utf.utf32_to_utf8_be = utf32_to_utf8_be
+utf.utf32_to_utf8_le = utf32_to_utf8_le
+utf.utf16_to_utf8_be = utf16_to_utf8_be
+utf.utf16_to_utf8_le = utf16_to_utf8_le
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+function utf.utf8_to_utf8(t)
+ return type(t) == "string" and lpegmatch(utflinesplitter,t) or t
end
-function unicode.utf16_to_utf8(t,endian)
+function utf.utf16_to_utf8(t,endian)
return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
end
-function unicode.utf32_to_utf8(t,endian)
+function utf.utf32_to_utf8(t,endian)
return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
end
@@ -4886,7 +5433,7 @@ local function big(c)
end
end
--- function unicode.utf8_to_utf16(str,littleendian)
+-- function utf.utf8_to_utf16(str,littleendian)
-- if littleendian then
-- return char(255,254) .. utfgsub(str,".",little)
-- else
@@ -4897,7 +5444,7 @@ end
local _, l_remap = utf.remapper(little)
local _, b_remap = utf.remapper(big)
-function unicode.utf8_to_utf16(str,littleendian)
+function utf.utf8_to_utf16(str,littleendian)
if littleendian then
return char(255,254) .. lpegmatch(l_remap,str)
else
@@ -4905,31 +5452,71 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+-- function utf.tocodes(str,separator) -- can be sped up with an lpeg
+-- local t, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- t[n] = format("0x%04X",u)
+-- end
+-- return concat(t,separator or " ")
+-- end
+
+local pattern = Cs (
+ (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) *
+ (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
end
-function unicode.ustring(s)
+function utf.ustring(s)
return format("U+%05X",type(s) == "number" and s or utfbyte(s))
end
-function unicode.xstring(s)
+function utf.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
--
-local pattern = Ct(C(patterns.utf8char)^0)
+local p_nany = p_utf8char / ""
+
+if utfgmatch then
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + p_nany)^0)
+ cache[p] = p
+ end
+ return #lpegmatch(p,str)
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
-function utf.totable(str)
- return lpegmatch(pattern,str)
end
+-- maybe also register as string.utf*
+
end -- of closure
@@ -4990,24 +5577,10 @@ local tables = utilities.tables
local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local type, next, rawset, tonumber, load, select = type, next, rawset, tonumber, load, select
local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
local serialize = table.serialize
--- function tables.definetable(target) -- defines undefined tables
--- local composed, t, n = nil, { }, 0
--- for name in gmatch(target,"([^%.]+)") do
--- n = n + 1
--- if composed then
--- composed = composed .. "." .. name
--- else
--- composed = name
--- end
--- t[n] = format("%s = %s or { }",composed,composed)
--- end
--- return concat(t,"\n")
--- end
-
local splitter = lpeg.tsplitat(".")
function tables.definetable(target,nofirst,nolast) -- defines undefined tables
@@ -5036,13 +5609,13 @@ end
-- local t = tables.definedtable("a","b","c","d")
function tables.definedtable(...)
- local l = { ... }
local t = _G
- for i=1,#l do
- local tl = t[l[i]]
+ for i=1,select("#",...) do
+ local li = select(i,...)
+ local tl = t[li]
if not tl then
tl = { }
- t[l[i]] = tl
+ t[li] = tl
end
t = tl
end
@@ -5235,7 +5808,7 @@ function table.deserialize(str)
if not str or str == "" then
return
end
- local code = loadstring(str)
+ local code = load(str)
if not code then
return
end
@@ -5252,7 +5825,7 @@ function table.load(filename)
if filename then
local t = io.loaddata(filename)
if t and t ~= "" then
- t = loadstring(t)
+ t = load(t)
if type(t) == "function" then
t = t()
if type(t) == "table" then
@@ -5331,9 +5904,11 @@ utilities = utilities or { }
utilities.storage = utilities.storage or { }
local storage = utilities.storage
+local report = texio and texio.write_nl or print
+
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage cannot be marked")
+ report("fatal error: storage cannot be marked")
return -- os.exit()
end
local m = getmetatable(t)
@@ -5363,12 +5938,36 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage has not been allocated")
+ report("fatal error: storage has not been allocated")
return -- os.exit()
end
return t
end
+-- function utilities.storage.delay(parent,name,filename)
+-- local m = getmetatable(parent)
+-- m.__list[name] = filename
+-- end
+--
+-- function utilities.storage.predefine(parent)
+-- local list = { }
+-- local m = getmetatable(parent) or {
+-- __list = list,
+-- __index = function(t,k)
+-- local l = require(list[k])
+-- t[k] = l
+-- return l
+-- end
+-- }
+-- setmetatable(parent,m)
+-- end
+--
+-- bla = { }
+-- utilities.storage.predefine(bla)
+-- utilities.storage.delay(bla,"test","oepsoeps")
+-- local t = bla.test
+-- table.print(t)
+-- print(t.a)
function storage.setinitializer(data,initialize)
local m = getmetatable(data) or { }
@@ -5393,12 +5992,14 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_table (t,k) local v = { } t[k] = v return v end
+local function f_ignore() end -- t,k,v
local t_empty = { __index = f_empty }
local t_self = { __index = f_self }
+local t_table = { __index = f_table }
local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
@@ -5408,6 +6009,8 @@ function table.setmetatableindex(t,f)
m.__index = f_empty
elseif f == "key" then
m.__index = f_self
+ elseif f == "table" then
+ m.__index = f_table
else
m.__index = f
end
@@ -5416,6 +6019,8 @@ function table.setmetatableindex(t,f)
setmetatable(t, t_empty)
elseif f == "key" then
setmetatable(t, t_self)
+ elseif f == "table" then
+ setmetatable(t, t_table)
else
setmetatable(t,{ __index = f })
end
@@ -5626,7 +6231,7 @@ if not modules then modules = { } end modules ['util-lua'] = {
}
local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
-local loadstring, loadfile, type = loadstring, loadfile, type
+local load, loadfile, type = load, loadfile, type
utilities = utilities or {}
utilities.lua = utilities.lua or { }
@@ -5643,11 +6248,23 @@ luautilities.nofstrippedbytes = 0
local strippedchunks = { } -- allocate()
luautilities.strippedchunks = strippedchunks
+luautilities.suffixes = {
+ tma = "tma",
+ tmc = jit and "tmb" or "tmc",
+ lua = "lua",
+ luc = jit and "lub" or "luc",
+ lui = "lui",
+ luv = "luv",
+ luj = "luj",
+ tua = "tua",
+ tuc = "tuc",
+}
+
local function fatalerror(name)
utilities.report(format("fatal error in %q",name or "unknown"))
end
-if jit then
+if jit or status.luatex_version >= 74 then
local function register(name)
if tracestripping then
@@ -5660,7 +6277,7 @@ if jit then
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if code then
code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
if code and code ~= "" then
@@ -5692,13 +6309,13 @@ if jit then
end
if forcestrip or luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
elseif luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
@@ -5706,14 +6323,14 @@ if jit then
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
register(name)
code = dump(code,true)
end
- return loadstring(code), 0
+ return load(code), 0
end
function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
@@ -5754,67 +6371,79 @@ else
return delta
end
- local function strip_code_pc(dump,name)
- local before = #dump
- local version, format, endian, int, size, ins, num = byte(dump,5,11)
- local subint
- if endian == 1 then
- subint = function(dump, i, l)
- local val = 0
- for n = l, 1, -1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_code_pc
+
+ if _MAJORVERSION == 5 and _MINORVERSION == 1 then
+
+ strip_code_pc = function(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
- return val, i + l
end
- else
- subint = function(dump, i, l)
- local val = 0
- for n = 1, l, 1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
end
- return val, i + l
- end
- end
- local strip_function
- strip_function = function(dump)
- local count, offset = subint(dump, 1, size)
- local stripped, dirty = rep("\0", size), offset + count
- offset = offset + count + int * 2 + 4
- offset = offset + int + subint(dump, offset, int) * ins
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- local t
- t, offset = subint(dump, offset, 1)
- if t == 1 then
- offset = offset + 1
- elseif t == 4 then
- offset = offset + size + subint(dump, offset, size)
- elseif t == 3 then
- offset = offset + num
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
end
- count, offset = subint(dump, offset, int)
- stripped = stripped .. sub(dump,dirty, offset - 1)
- for n = 1, count do
- local proto, off = strip_function(sub(dump,offset, -1))
- stripped, offset = stripped .. proto, offset + off - 1
- end
- offset = offset + subint(dump, offset, int) * int + int
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size + int * 2
- end
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size
- end
- stripped = stripped .. rep("\0", int * 3)
- return stripped, offset
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = register(name,before,after)
+ return dump, delta
+ end
+
+ else
+
+ strip_code_pc = function(dump,name)
+ return dump, 0
end
- dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
- local after = #dump
- local delta = register(name,before,after)
- return dump, delta
+
end
-- ... end of borrowed code.
@@ -5834,14 +6463,14 @@ else
end
if forcestrip then
local code, n = strip_code_pc(dump(code),name)
- return loadstring(code), n
+ return load(code), n
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
@@ -5850,20 +6479,20 @@ else
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
local n = 0
if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
code, n = strip_code_pc(dump(code),name)
end
- return loadstring(code), n
+ return load(code), n
end
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
local n = 0
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror()
end
@@ -5903,6 +6532,7 @@ else
utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
end
cleanup = false -- better see how bad it is
+ done = true -- hm
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -5949,7 +6579,6 @@ if not modules then modules = { } end modules ['util-prs'] = {
}
local lpeg, table, string = lpeg, table, string
-
local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
@@ -6367,6 +6996,45 @@ function parsers.rfc4180splitter(specification)
end
end
+-- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- utilities.parsers.stepper("1-3,7,8,9")
+-- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- utilities.parsers.stepper(" 1 : 3, ,7 ")
+-- utilities.parsers.stepper("1:4,9:13,24:*",30)
+
+local function ranger(first,last,n,action)
+ if not first then
+ -- forget about it
+ elseif last == true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+
+local cardinal = patterns.cardinal / tonumber
+local spacers = patterns.spacer^0
+local endofstring = patterns.endofstring
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring)
+
+function utilities.parsers.stepper(str,n,action)
+ if type(n) == "function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
end -- of closure
@@ -6817,7 +7485,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
+local format, find, lower, gsub, topattern = string.format, string.find, string.lower, string.gsub, string.topattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -6905,7 +7573,7 @@ local function set(t,what,newvalue)
else
value = is_boolean(value,value)
end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
+ w = topattern(w,true,true)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
@@ -6959,7 +7627,8 @@ function setters.register(t,what,...)
end
end
local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
+ for i=1,select("#",...) do
+ local fnc = select(i,...)
local typ = type(fnc)
if typ == "string" then
if trace_initialize then
@@ -7028,7 +7697,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
end
end
t.report()
@@ -7052,17 +7721,29 @@ local function report(setter,...)
end
end
-function setters.new(name)
+local function default(setter,name)
+ local d = setter.data[name]
+ return d and d.default
+end
+
+local function value(setter,name)
+ local d = setter.data[name]
+ return d and (d.value or d.default)
+end
+
+function setters.new(name) -- we could use foo:bar syntax (but not used that often)
local setter -- we need to access it in setter itself
setter = {
data = allocate(), -- indexed, but also default and value fields
name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
+ report = function(...) report (setter,...) end,
+ enable = function(...) enable (setter,...) end,
+ disable = function(...) disable (setter,...) end,
+ register = function(...) register(setter,...) end,
+ list = function(...) list (setter,...) end,
+ show = function(...) show (setter,...) end,
+ default = function(...) return default (setter,...) end,
+ value = function(...) return value (setter,...) end,
}
data[name] = setter
return setter
@@ -7189,9 +7870,9 @@ if not modules then modules = { } end modules ['trac-log'] = {
local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
local format, gmatch, find = string.format, string.gmatch, string.find
local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
+local topattern = string.topattern
local texcount = tex and tex.count
-local next, type = next, type
+local next, type, select = next, type, select
local setmetatableindex = table.setmetatableindex
@@ -7502,7 +8183,7 @@ local function setblocked(category,value)
if data[c] then
v.state = value
else
- c = escapedpattern(c,true)
+ c = topattern(c,true,true)
for k, v in next, data do
if find(k,c) then
v.state = value
@@ -7720,10 +8401,10 @@ local function reporthelp(t,...)
if type(helpinfo) == "string" then
reportlines(t,helpinfo)
elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
+ local n = select("#",...)
+ for i=1,n do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i < n then
t.report()
end
end
@@ -8013,6 +8694,10 @@ local format, sub, match, gsub, find = string.format, string.sub, string.match,
local unquoted, quoted = string.unquoted, string.quoted
local concat, insert, remove = table.concat, table.insert, table.remove
local loadedluacode = utilities.lua.loadedluacode
+local luasuffixes = utilities.lua.suffixes
+
+environment = environment or { }
+local environment = environment
-- precautions
@@ -8022,9 +8707,29 @@ function os.setlocale()
-- no way you can mess with it
end
--- dirty tricks
+-- dirty tricks (we will replace the texlua call by luatex --luaonly)
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+local validengines = allocate {
+ ["luatex"] = true,
+ ["luajittex"] = true,
+ -- ["luatex.exe"] = true,
+ -- ["luajittex.exe"] = true,
+}
+
+local basicengines = allocate {
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex",
+ ["texluac"] = "luatex",
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex",
+ -- ["texlua.exe"] = "luatex",
+ -- ["texluajit.exe"] = "luajittex",
+}
+
+environment.validengines = validengines
+environment.basicengines = basicengines
+
+if arg and validengines[file.removesuffix(arg[0])] and arg[1] == "--luaonly" then
arg[-1] = arg[0]
arg[ 0] = arg[2]
for k=3,#arg do
@@ -8056,9 +8761,6 @@ end
-- environment
-environment = environment or { }
-local environment = environment
-
environment.arguments = allocate()
environment.files = allocate()
environment.sortedflags = nil
@@ -8114,7 +8816,7 @@ function environment.initializearguments(arg)
end
end
end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
+ environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
function environment.setargument(name,value)
@@ -8195,6 +8897,22 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+-- -- to be tested:
+--
+-- function environment.reconstructcommandline(arg,noquote)
+-- arg = arg or environment.originalarguments
+-- if noquote and #arg == 1 then
+-- return unquoted(resolvers.resolve(arg[1]))
+-- elseif #arg > 0 then
+-- local result = { }
+-- for i=1,#arg do
+-- result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
+-- end
+-- return concat(result," ")
+-- else
+-- return ""
+-- end
+-- end
if arg then
@@ -8289,9 +9007,11 @@ function environment.loadluafile(filename, version)
local lucname, luaname, chunk
local basename = file.removesuffix(filename)
if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
+ luaname = fiule.addsuffix(basename,luasuffixes.lua)
+ lucname = fiule.addsuffix(basename,luasuffixes.luc)
else
- lucname, luaname = nil, basename -- forced suffix
+ luaname = basename -- forced suffix
+ lucname = nil
end
-- when not overloaded by explicit suffix we look for a luc file first
local fullname = (lucname and environment.luafile(lucname)) or ""
@@ -8372,7 +9092,6 @@ xml = xml or { }
local xml = xml
-local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
@@ -9583,7 +10302,7 @@ if not modules then modules = { } end modules ['lxml-lpt'] = {
-- todo: B/C/[get first match]
local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local type, next, tonumber, tostring, setmetatable, load, select = type, next, tonumber, tostring, setmetatable, load, select
local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
@@ -10195,7 +10914,7 @@ end
local function register_expression(expression)
local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
+ local runner = load(format(template_e,converted))
runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
end
@@ -10203,9 +10922,9 @@ end
local function register_finalizer(protocol,name,arguments)
local runner
if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ runner = load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
+ runner = load(format(template_f_n,protocol or xml.defaultprotocol,name))
end
runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
@@ -10597,6 +11316,7 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
+
expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
return pattern and (collected and #collected) or 0
@@ -10604,13 +11324,30 @@ end
-- external
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+-- expressions.oneof = function(s,...)
+-- local t = {...}
+-- for i=1,#t do
+-- if s == t[i] then
+-- return true
+-- end
+-- end
+-- return false
+-- end
+
+expressions.oneof = function(s,...)
+ for i=1,select("#",...) do
+ if s == select(i,...) then
+ return true
+ end
+ end
+ return false
end
+
expressions.error = function(str)
xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
+
expressions.undefined = function(s)
return s == nil
end
@@ -12220,7 +12957,6 @@ if not modules then modules = { } end modules ['data-ini'] = {
}
local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
local next, type = next, type
local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
@@ -12311,6 +13047,10 @@ do
local args = environment.originalarguments or arg -- this needs a cleanup
+ if not environment.ownmain then
+ environment.ownmain = status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
@@ -12427,19 +13167,6 @@ end
environment.texroot = file.collapsepath(texroot)
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
if profiler then
directives.register("system.profile",function()
profiler.start("luatex-profile.log")
@@ -12946,6 +13673,8 @@ resolvers.suffixes = suffixes
resolvers.dangerous = dangerous
resolvers.suffixmap = suffixmap
+local luasuffixes = utilities.lua.suffixes
+
local relations = allocate { -- todo: handlers also here
core = {
ofm = { -- will become obsolete
@@ -13031,7 +13760,7 @@ local relations = allocate { -- todo: handlers also here
lua = {
names = { "lua" },
variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
+ suffixes = { luasuffixes.lua, luasuffixes.luc, luasuffixes.tma, luasuffixes.tmc },
},
lib = {
names = { "lib" },
@@ -13227,6 +13956,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
+local addsuffix, is_writable, is_readable = file.addsuffix, file.is_writable, file.is_readable
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
@@ -13251,8 +13981,10 @@ end
-- end of intermezzo
-caches = caches or { }
-local caches = caches
+caches = caches or { }
+local caches = caches
+
+local luasuffixes = utilities.lua.suffixes
caches.base = caches.base or "luatex-cache"
caches.more = caches.more or "context"
@@ -13280,18 +14012,18 @@ local function identify()
cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
- if file.is_readable(cachepath) then
+ if is_readable(cachepath) then
readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
+ if not writable and is_writable(cachepath) then
writable = cachepath
end
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
+ if is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
+ if isdir(cachepath) and is_writable(cachepath) then
report_caches("created: %s",cachepath)
writable = cachepath
readables[#readables+1] = cachepath
@@ -13313,8 +14045,8 @@ local function identify()
cachepath = resolvers.resolve(cachepath)
cachepath = resolvers.cleanpath(cachepath)
local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
readables[#readables+1] = cachepath
writable = cachepath
break
@@ -13403,7 +14135,7 @@ end
local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
+local function getreadablepaths(...)
local tags = { ... }
local hash = concat(tags,"/")
local done = r_cache[hash]
@@ -13446,7 +14178,7 @@ function caches.getfirstreadablefile(filename,...)
for i=1,#rd do
local path = rd[i]
local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
+ if is_readable(fullname) then
usedreadables[i] = true
return fullname, path
end
@@ -13467,7 +14199,7 @@ function caches.define(category,subcategory) -- for old times sake
end
function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
+ return format("%s/%s.%s",path,name,luasuffixes.tma), format("%s/%s.%s",path,name,luasuffixes.tmc)
end
function caches.loaddata(readables,name)
@@ -13477,7 +14209,13 @@ function caches.loaddata(readables,name)
for i=1,#readables do
local path = readables[i]
local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
+ local loader = loadfile(tmcname)
+ if not loader then
+ -- in case we have a different engine
+ utilities.lua.compile(tmaname,tmcname)
+ --
+ loader = loadfile(tmaname)
+ end
if loader then
loader = loader()
collectgarbage("step")
@@ -13489,11 +14227,15 @@ end
function caches.is_writable(filepath,filename)
local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
+ return is_writable(tmaname)
end
local saveoptions = { compact = true }
+-- add some point we will only use the internal bytecode compiler and
+-- then we can flag success in the tma so that it can trigger a compile
+-- if the other engine
+
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -13519,9 +14261,9 @@ end
function caches.loadcontent(cachename,dataname)
local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
+ local full, path = caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
+ local blob = loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data = blob()
if data and data.content then
@@ -13556,9 +14298,10 @@ end
function caches.savecontent(cachename,dataname,content)
local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
+ local full, path = caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
+ local luaname = addsuffix(filename,luasuffixes.lua)
+ local lucname = addsuffix(filename,luasuffixes.luc)
if trace_locating then
report_resolvers("preparing '%s' for '%s'",dataname,cachename)
end
@@ -13763,6 +14506,7 @@ local joinpath = file.joinpath
local allocate = utilities.storage.allocate
local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
+local luasuffixes = utilities.lua.suffixes
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -15325,15 +16069,19 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
+ local engine = environment.ownmain or "luatex"
+ local barename = file.removesuffix(name)
+ local fullname = file.addsuffix(barename,"fmt")
+ local fmtname = caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
+ fmtname = resolvers.findfile(fullname)
fmtname = resolvers.cleanpath(fmtname)
end
if fmtname ~= "" then
local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
+ local luaname = file.addsuffix(barename,luasuffixes.lua)
+ local lucname = file.addsuffix(barename,luasuffixes.luc)
+ local luiname = file.addsuffix(barename,luasuffixes.lui)
if lfs.isfile(luiname) then
return barename, luiname
elseif lfs.isfile(lucname) then
@@ -15430,10 +16178,9 @@ local resolvers = resolvers
local prefixes = utilities.storage.allocate()
resolvers.prefixes = prefixes
-local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
local joinpath, basename, dirname = file.join, file.basename, file.dirname
local getmetatable, rawset, type = getmetatable, rawset, type
@@ -15555,6 +16302,28 @@ end
-- todo: use an lpeg (see data-lua for !! / stripper)
+-- local function resolve(str) -- use schemes, this one is then for the commandline only
+-- if type(str) == "table" then
+-- local t = { }
+-- for i=1,#str do
+-- t[i] = resolve(str[i])
+-- end
+-- return t
+-- else
+-- local res = resolved[str]
+-- if not res then
+-- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+-- resolved[str] = res
+-- abstract[res] = str
+-- end
+-- return res
+-- end
+-- end
+
+-- home:xx;selfautoparent:xx;
+
+local pattern = Cs((C(R("az")^2) * P(":") * C((1-S(" \"\';,"))^1) / _resolve_ + P(1))^0)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -15565,7 +16334,7 @@ local function resolve(str) -- use schemes, this one is then for the commandline
else
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+ res = lpegmatch(pattern,str)
resolved[str] = res
abstract[res] = str
end
@@ -15998,7 +16767,7 @@ statistics.register("used cache path", function() return caches.usedpaths() end
function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
local enginebanner = status.list().banner
if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
local luvdata = {
enginebanner = enginebanner,
formatbanner = formatbanner,
@@ -16009,10 +16778,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname ==
end
end
+-- todo: check this at startup and return (say) 999 as signal that the run
+-- was aborted due to a wrong format in which case mtx-context can trigger
+-- a remake
+
function statistics.checkfmtstatus(texname)
local enginebanner = status.list().banner
if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
if lfs.isfile(luvname) then
local luv = dofile(luvname)
if luv and luv.sourcefile then
@@ -16389,7 +17162,7 @@ if not modules then modules = { } end modules ['data-sch'] = {
license = "see context related readme files"
}
-local loadstring = loadstring
+local load = load
local gsub, concat, format = string.gsub, table.concat, string.format
local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
@@ -16575,7 +17348,7 @@ schemes.fetchstring = fetchstring
function schemes.fetchtable(url,data)
local reply = fetchstring(url,data)
if reply then
- local s = loadstring("return " .. reply)
+ local s = load("return " .. reply)
if s then
return s()
end
@@ -16603,6 +17376,8 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- -- local mylib = require("libtest")
-- -- local mysql = require("luasql.mysql")
+local searchers = package.searchers or package.loaders
+
local concat = table.concat
local trace_libraries = false
@@ -16704,13 +17479,9 @@ function package.extraclibpath(...)
end
end
-if not package.loaders then
- package.loaders = package.searchers -- 5.2
-end
-
-if not package.loaders[-2] then
+if not searchers[-2] then
-- use package-path and package-cpath
- package.loaders[-2] = package.loaders[2]
+ searchers[-2] = searchers[2]
end
local function loadedaslib(resolved,rawname)
@@ -16721,7 +17492,7 @@ local function loadedbylua(name)
if trace_libraries then
report_libraries("! locating %q using normal loader",name)
end
- local resolved = package.loaders[-2](name)
+ local resolved = searchers[-2](name)
end
local function loadedbyformat(name,rawname,suffixes,islib)
@@ -16776,7 +17547,7 @@ local function notloaded(name)
end
end
-package.loaders[2] = function(name)
+searchers[2] = function(name)
local thename = gsub(name,"%.","/")
local luaname = file.addsuffix(thename,"lua")
local libname = file.addsuffix(thename,os.libsuffix)
@@ -16790,8 +17561,8 @@ package.loaders[2] = function(name)
or notloaded (name)
end
--- package.loaders[3] = nil
--- package.loaders[4] = nil
+-- searchers[3] = nil
+-- searchers[4] = nil
resolvers.loadlualib = require
@@ -17161,13 +17932,11 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
local format = string.format
+local quoted = string.quoted
+local luasuffixes = utilities.lua.suffixes
local report_format = logs.reporter("resolvers","formats")
--- helper for mtxrun
-
-local quoted = string.quoted
-
local function primaryflags() -- not yet ok
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
@@ -17182,13 +17951,14 @@ local function primaryflags() -- not yet ok
end
function environment.make_format(name)
+ local engine = environment.ownmain or "luatex"
-- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
+ local olddir = dir.current()
+ local path = caches.getwritablepath("formats",engine) or "" -- maybe platform
if path ~= "" then
lfs.chdir(path)
end
- report_format("format path: %s",lfs.currentdir())
+ report_format("format path: %s",dir.current())
-- check source file
local texsourcename = file.addsuffix(name,"mkiv")
local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
@@ -17225,13 +17995,12 @@ function environment.make_format(name)
elseif type(usedlualibs) == "table" then
report_format("using stub specification: %s",fullspecificationname)
local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
+ local luastubname = file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname = file.addsuffix(texbasename,luasuffixes.luc)
-- pack libraries in stub
report_format("creating initialization file: %s",luastubname)
utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
-- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
report_format("using compiled initialization file: %s",lucstubname)
usedluastub = lucstubname
@@ -17245,7 +18014,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -17264,8 +18033,9 @@ end
function environment.run_format(name,data,more)
if name and name ~= "" then
+ local engine = environment.ownmain or "luatex"
local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
+ local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
if fmtname == "" then
fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
end
@@ -17282,7 +18052,7 @@ function environment.run_format(name,data,more)
report_format("using format name: %s",fmtname)
report_format("no luc/lua with name: %s",barename)
else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
+ local command = format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
report_format("running command: %s",command)
os.spawn(command)
end
@@ -17423,10 +18193,11 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -17656,6 +18427,10 @@ local helpinfo = [[
--variables show configuration variables
--configurations show configuration order
+--directives show (known) directives
+--trackers show (known) trackers
+--experiments show (known) experiments
+
--expand-braces expand complex variable
--expand-path expand variable (resolve paths)
--expand-var expand variable (resolve references)
@@ -18346,8 +19121,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
-if e_argument("selfmerge") then
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18377,17 +19162,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -18615,6 +19389,18 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua
index 6fa916291..eda0ba37a 100644
--- a/tex/context/base/anch-pos.lua
+++ b/tex/context/base/anch-pos.lua
@@ -20,7 +20,7 @@ more efficient.</p>
local commands, context = commands, context
local tostring, next, rawget, setmetatable = tostring, next, rawget, setmetatable
-local concat, sort = table.concat, table.sort
+local sort = table.sort
local format, gmatch, match = string.format, string.gmatch, string.match
local rawget = rawget
local lpegmatch = lpeg.match
diff --git a/tex/context/base/attr-lay.lua b/tex/context/base/attr-lay.lua
index 5e5e81ff1..059353116 100644
--- a/tex/context/base/attr-lay.lua
+++ b/tex/context/base/attr-lay.lua
@@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['attr-lay'] = {
local type = type
local format = string.format
-local insert, remove, concat = table.insert, table.remove, table.concat
+local insert, remove = table.insert, table.remove
local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
local commands, context, interfaces = commands, context, interfaces
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 56d300ba3..37af87505 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -22,10 +22,9 @@ local next, type = next, type
local format, match, concat, rep, sub, gsub, gmatch, find = string.format, string.match, table.concat, string.rep, string.sub, string.gsub, string.gmatch, string.find
local validstring = string.valid
local lpegmatch = lpeg.match
-local utfchar, utfbyte = utf.char, utf.byte
+local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values
local insert, remove = table.insert, table.remove
local topoints = number.topoints
-local utfvalues = string.utfvalues
local fromunicode16 = fonts.mappings.fromunicode16
local sortedhash = table.sortedhash
diff --git a/tex/context/base/bibl-bib.lua b/tex/context/base/bibl-bib.lua
index 444f7e9bc..a995d7429 100644
--- a/tex/context/base/bibl-bib.lua
+++ b/tex/context/base/bibl-bib.lua
@@ -12,7 +12,6 @@ bibtex files and converts them to xml so that the we access the content
in a convenient way. Actually handling the data takes place elsewhere.</p>
--ldx]]--
-local utf = unicode.utf8
local lower, format, gsub, concat = string.lower, string.format, string.gsub, table.concat
local next = next
local utfchar = utf.char
diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua
index 11d7cc9f6..3aa361297 100644
--- a/tex/context/base/buff-ini.lua
+++ b/tex/context/base/buff-ini.lua
@@ -16,9 +16,10 @@ local report_grabbing = logs.reporter("buffers","grabbing")
local context, commands = context, commands
local concat = table.concat
-local type, next = type, next
-local sub, format, match, find = string.sub, string.format, string.match, string.find
-local count, splitlines, validstring = string.count, string.splitlines, string.valid
+local type, next, load = type, next, load
+local sub, format = string.sub, string.format
+local splitlines, validstring = string.splitlines, string.valid
+local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match
local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
@@ -100,8 +101,6 @@ buffers.collectcontent = collectcontent
commands.erasebuffer = erase
commands.assignbuffer = assign
-local P, patterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
-
local anything = patterns.anything
local alwaysmatched = patterns.alwaysmatched
@@ -128,6 +127,65 @@ local continue = false
-- An \n is unlikely to show up as \r is the endlinechar but \n is more generic
-- for us.
+-- This fits the way we fetch verbatim: the indentatio before the sentinel
+-- determines the stripping.
+
+-- str = [[
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+--
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+-- ]]
+
+-- local function undent(str)
+-- local margin = match(str,"[\n\r]( +)[\n\r]*$") or ""
+-- local indent = #margin
+-- if indent > 0 then
+-- local lines = splitlines(str)
+-- local ok = true
+-- local pattern = "^" .. margin
+-- for i=1,#lines do
+-- local l = lines[i]
+-- if find(l,pattern) then
+-- lines[i] = sub(l,indent+1)
+-- else
+-- ok = false
+-- break
+-- end
+-- end
+-- if ok then
+-- return concat(lines,"\n")
+-- end
+-- end
+-- return str
+-- end
+
+local getmargin = (Cs(P(" ")^1)*P(-1)+1)^1
+local eol = patterns.eol
+local whatever = (P(1)-eol)^0 * eol^1
+
+local strippers = { }
+
+local function undent(str) -- new version, needs testing
+ local margin = lpegmatch(getmargin,str)
+ if type(margin) ~= "string" then
+ return str
+ end
+ local indent = #margin
+ if indent == 0 then
+ return str
+ end
+ local stripper = strippers[indent]
+ if not stripper then
+ stripper = Cs((P(margin)/"" * whatever + eol^1)^1)
+ strippers[indent] = stripper
+ end
+ return lpegmatch(stripper,str) or str
+end
+
function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe move \\ to call
local dn = getcontent(name)
if dn == "" then
@@ -165,25 +223,7 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe
dn = sub(dn,1,-2)
end
if autoundent then
- local margin = match(dn,"[\n\r]( +)[\n\r]*$") or ""
- local indent = #margin
- if indent > 0 then
- local lines = splitlines(dn)
- local ok = true
- local pattern = "^" .. margin
- for i=1,#lines do
- local l = lines[i]
- if find(l,pattern) then
- lines[i] = sub(l,indent+1)
- else
- ok = false
- break
- end
- end
- if ok then
- dn = concat(lines,"\n")
- end
- end
+ dn = undent(dn)
end
end
assign(name,dn,catcodes)
@@ -259,7 +299,7 @@ function commands.gettexbuffer(name)
end
function commands.getbufferctxlua(name)
- local ok = loadstring(getcontent(name))
+ local ok = load(getcontent(name))
if ok then
ok()
else
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index e0480df65..f35d7d2a9 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -12,12 +12,14 @@ if not modules then modules = { } end modules ['char-ini'] = {
local tex = tex
-local utfchar, utfbyte, utfvalues = utf.char, utf.byte, string.utfvalues
-local ustring, utf = unicode.ustring, unicode.utf8
+local utfchar, utfbyte, utfvalues, ustring = utf.char, utf.byte, utf.values, utf.ustring
local concat, unpack, tohash = table.concat, table.unpack, table.tohash
local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch
-local P, R, lpegmatch = lpeg.P, lpeg.R, lpeg.match
+local P, R, Cs, lpegmatch, patterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.match, lpeg.patterns
+
+local utf8byte = patterns.utf8byte
+local utf8char = patterns.utf8char
local allocate = utilities.storage.allocate
local mark = utilities.storage.mark
@@ -62,7 +64,7 @@ end
local pattern = (P("0x") + P("U+")) * ((R("09","AF")^1 * P(-1)) / function(s) return tonumber(s,16) end)
-lpeg.patterns.chartonumber = pattern
+patterns.chartonumber = pattern
local function chartonumber(k)
if type(k) == "string" then
@@ -746,7 +748,7 @@ characters.activeoffset = 0x10000 -- there will be remapped in that byte range
-- table.setmetatableindex(utfbytes,function(t,k) local v= utfchar(k) t[k] = v return v end)
-- table.setmetatableindex(utfchars,function(t,k) local v= utfbyte(k) t[k] = v return v end)
-local function utfstring(s)
+local function toutfstring(s)
if type(s) == "table" then
return utfchar(unpack(s)) -- concat { utfchar( unpack(s) ) }
else
@@ -754,7 +756,7 @@ local function utfstring(s)
end
end
-utf.string = utf.string or utfstring
+utf.tostring = toutfstring
local categories = allocate() characters.categories = categories -- lazy table
@@ -775,10 +777,10 @@ local ucchars = allocate() characters.ucchars = ucchars -- lazy table
local shchars = allocate() characters.shchars = shchars -- lazy table
local fschars = allocate() characters.fschars = fschars -- lazy table
-setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
local decomposed = allocate() characters.decomposed = decomposed -- lazy table
local specials = allocate() characters.specials = specials -- lazy table
@@ -857,32 +859,48 @@ function characters.unicodechar(asked)
end
end
-function characters.lower(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = lcchars[u]
- end
- return concat(new)
-end
+-- function characters.lower(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = lcchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.upper(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = ucchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.shaped(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = shchars[u]
+-- end
+-- return concat(new)
+-- end
-function characters.upper(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = ucchars[u]
- end
- return concat(new)
-end
+----- tolower = Cs((utf8byte/lcchars)^0)
+----- toupper = Cs((utf8byte/ucchars)^0)
+----- toshape = Cs((utf8byte/shchars)^0)
-function characters.shaped(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = shchars[u]
- end
- return concat(new)
-end
+local tolower = Cs((utf8char/lcchars)^0)
+local toupper = Cs((utf8char/ucchars)^0)
+local toshape = Cs((utf8char/shchars)^0)
+
+patterns.tolower = tolower
+patterns.toupper = toupper
+patterns.toshape = toshape
+
+function characters.lower (str) return lpegmatch(tolower,str) end
+function characters.upper (str) return lpegmatch(toupper,str) end
+function characters.shaped(str) return lpegmatch(toshape,str) end
function characters.lettered(str,spacing)
local new, n = { }, 0
diff --git a/tex/context/base/char-tex.lua b/tex/context/base/char-tex.lua
index e6d6c41e0..91aa387b9 100644
--- a/tex/context/base/char-tex.lua
+++ b/tex/context/base/char-tex.lua
@@ -189,14 +189,13 @@ local convert_accents_strip = Cs((no_l * accents * no_r + accents + P(1))^0)
local convert_commands_strip = Cs((no_l * commands * no_r + commands + P(1))^0)
function characters.tex.toutf(str,strip)
- if find(str,"\\") then -- we can start at the found position
- if strip then
- return lpegmatch(convert_accents_strip,lpegmatch(convert_commands_strip,str))
- else
- return lpegmatch(convert_accents, lpegmatch(convert_commands, str))
- end
+ if not find(str,"\\") then -- we can start at the found position
+ return str
+ elseif strip then
+ return lpegmatch(convert_accents_strip,lpegmatch(convert_commands_strip,str))
+ else
+ return lpegmatch(convert_accents, lpegmatch(convert_commands, str))
end
- return str
end
--~ print(characters.tex.toutf([[\"{e}]]),true)
diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua
index 52fdfc0d0..54ace8c9b 100644
--- a/tex/context/base/char-utf.lua
+++ b/tex/context/base/char-utf.lua
@@ -19,10 +19,10 @@ in special kinds of output (for instance <l n='pdf'/>).</p>
over a string.</p>
--ldx]]--
-local utfchar, utfbyte = utf.char, utf.byte
local concat, gmatch, gsub, find = table.concat, string.gmatch, string.gsub, string.find
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local utfchar, utfbyte, utfcharacters, utfvalues = utf.char, utf.byte, utf.characters, utf.values
local allocate = utilities.storage.allocate
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local charfromnumber = characters.fromnumber
@@ -194,6 +194,20 @@ local private = {
utffilters.private = private
+local tohigh = lpeg.replacer(low) -- frozen, only for basic tex
+local tolow = lpeg.replacer(high) -- frozen, only for basic tex
+
+lpegpatterns.utftohigh = tohigh
+lpegpatterns.utftolow = tolow
+
+function utffilters.harden(str)
+ return lpegmatch(tohigh,str)
+end
+
+function utffilters.soften(str)
+ return lpegmatch(tolow,str)
+end
+
local function set(ch)
local cb
if type(ch) == "number" then
@@ -202,9 +216,12 @@ local function set(ch)
cb = utfbyte(ch)
end
if cb < 256 then
+ escapes[ch] = "\\" .. ch
low[ch] = utfchar(0x0F0000 + cb)
+ if ch == "%" then
+ ch = "%%" -- nasty, but we need this as in replacements (also in lpeg) % is interpreted
+ end
high[utfchar(0x0F0000 + cb)] = ch
- escapes[ch] = "\\" .. ch
end
end
diff --git a/tex/context/base/chem-ini.lua b/tex/context/base/chem-ini.lua
index 192953ec9..c862e00e3 100644
--- a/tex/context/base/chem-ini.lua
+++ b/tex/context/base/chem-ini.lua
@@ -7,73 +7,37 @@ if not modules then modules = { } end modules ['chem-ini'] = {
}
local format = string.format
-local lpegmatch = lpeg.match
-
-local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local trace_molecules = false trackers.register("chemistry.molecules", function(v) trace_molecules = v end)
local report_chemistry = logs.reporter("chemistry")
-local context = context
+local context = context
+local cpatterns = patterns.context
chemistry = chemistry or { }
local chemistry = chemistry
--[[
-<p>The next code is an adaptation of code from Wolfgang Schuster
-as posted on the mailing list. This version supports nested
-braces and unbraced integers as scripts. We could consider
-spaces as terminals for them but first let collect a bunch
-of input then.</p>
+<p>The next code started out as adaptation of code from Wolfgang Schuster as
+posted on the mailing list. The current version supports nested braces and
+unbraced integers as scripts.</p>
]]--
--- some lpeg, maybe i'll make an syst-lpg module
-
-local lowercase = R("az")
-local uppercase = R("AZ")
-local backslash = P("\\")
-local csname = backslash * P(1) * (1-backslash)^0
-local plus = P("+") / "\\textplus "
-local minus = P("-") / "\\textminus "
-local digit = R("09")
-local sign = plus + minus
-local cardinal = digit^1
-local integer = sign^0 * cardinal
-
-local leftbrace = P("{")
-local rightbrace = P("}")
-local nobrace = 1 - (leftbrace + rightbrace)
-local nested = P { leftbrace * (csname + sign + nobrace + V(1))^0 * rightbrace }
-local any = P(1)
-
-local subscript = P("_")
-local superscript = P("^")
-local somescript = subscript + superscript
-
-local content = Cs(csname + nested + sign + any)
-
--- could be made more efficient
-
-local lowhigh = Cc("\\lohi{%s}{%s}") * subscript * content * superscript * content / format
-local highlow = Cc("\\hilo{%s}{%s}") * superscript * content * subscript * content / format
-local low = Cc("\\low{%s}") * subscript * content / format
-local high = Cc("\\high{%s}") * superscript * content / format
-local justtext = (1 - somescript)^1
-local parser = Cs((csname + lowhigh + highlow + low + high + sign + any)^0)
-
-chemistry.moleculeparser = parser -- can be used to avoid functioncall
+local moleculeparser = cpatterns.scripted
+chemistry.moleculeparser = moleculeparser
function chemistry.molecule(str)
- return lpegmatch(parser,str)
+ return lpegmatch(moleculeparser,str)
end
function commands.molecule(str)
if trace_molecules then
- local rep = lpegmatch(parser,str)
+ local rep = lpegmatch(moleculeparser,str)
report_chemistry("molecule %s => %s",str,rep)
context(rep)
else
- context(lpegmatch(parser,str))
+ context(lpegmatch(moleculeparser,str))
end
end
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
index dc4bd746f..3ab2e53b6 100644
--- a/tex/context/base/chem-str.lua
+++ b/tex/context/base/chem-str.lua
@@ -21,24 +21,40 @@ if not modules then modules = { } end modules ['chem-str'] = {
-- the current user interface is slightly different from the old one but hopefully users
-- will like the added value.
-local trace_structure = false trackers.register("chemistry.structure", function(v) trace_structure = v end)
-local trace_metapost = false trackers.register("chemistry.metapost", function(v) trace_metapost = v end)
-local trace_textstack = false trackers.register("chemistry.textstack", function(v) trace_textstack = v end)
+-- directive_strictorder: one might set this to off when associated texts are disordered too
+
+local trace_structure = false trackers .register("chemistry.structure", function(v) trace_structure = v end)
+local trace_metapost = false trackers .register("chemistry.metapost", function(v) trace_metapost = v end)
+local trace_textstack = false trackers .register("chemistry.textstack", function(v) trace_textstack = v end)
+local directive_strictorder = true directives.register("chemistry.strictorder", function(v) directive_strictorder = v end)
+local directive_strictindex = false directives.register("chemistry.strictindex", function(v) directive_strictindex = v end)
local report_chemistry = logs.reporter("chemistry")
local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
+local concat, insert, remove, unique, sorted = table.concat, table.insert, table.remove, table.unique, table.sorted
local processor_tostring = typesetters and typesetters.processors.tostring
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_array_with_repeat = utilities.parsers.settings_to_array_with_repeat
local lpegmatch = lpeg.match
-local P, R, S, C, Cs, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc
+local P, R, S, C, Cs, Ct, Cc, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cmt
local variables = interfaces and interfaces.variables
local context = context
+local v_default = variables.default
+local v_small = variables.small
+local v_medium = variables.medium
+local v_big = variables.big
+local v_normal = variables.normal
+local v_fit = variables.fit
+local v_on = variables.on
+
+local mpnamedcolor = attributes.colors.mpnamedcolor
+local topoints = number.topoints
+local todimen = string.todimen
+
chemistry = chemistry or { }
local chemistry = chemistry
@@ -47,39 +63,44 @@ chemistry.format = "metafun"
chemistry.structures = 0
local common_keys = {
- b = "line",
- r = "line",
- sb = "line",
- sr = "line",
- rd = "line",
- rh = "line",
- cc = "line",
- ccd = "line",
- line = "line",
- dash = "line",
- arrow = "line",
- c = "fixed",
- cd = "fixed",
- z = "text",
- zt = "text",
- zlt = "text",
- zrt = "text",
- rz = "text",
- rt = "text",
- lrt = "text",
- rrt = "text",
- zln = "number",
- zrn = "number",
- rn = "number",
- lrn = "number",
- rrn = "number",
- zn = "number",
- mov = "transform",
- mark = "transform",
- move = "transform",
- off = "transform",
- adj = "transform",
- sub = "transform",
+ b = "line",
+ r = "line",
+ sb = "line",
+ sr = "line",
+ rd = "line",
+ rh = "line",
+ rb = "line",
+ rbd = "line",
+ cc = "line",
+ ccd = "line",
+ line = "line",
+ dash = "line",
+ arrow = "line",
+ c = "fixed",
+ cd = "fixed",
+ z = "text",
+ zt = "text",
+ zlt = "text",
+ zrt = "text",
+ rz = "text",
+ rt = "text",
+ lrt = "text",
+ rrt = "text",
+ label = "text",
+ zln = "number",
+ zrn = "number",
+ rn = "number",
+ lrn = "number",
+ rrn = "number",
+ zn = "number",
+ number = "number",
+ mov = "transform",
+ mark = "transform",
+ move = "transform",
+ diff = "transform",
+ off = "transform",
+ adj = "transform",
+ sub = "transform",
}
local front_keys = {
@@ -89,6 +110,14 @@ local front_keys = {
lr = "line",
lsr = "line",
rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ lrb = "line",
+ rrb = "line",
lrz = "text",
rrz = "text",
lsub = "transform",
@@ -99,15 +128,14 @@ local one_keys = {
db = "line",
tb = "line",
bb = "line",
- rb = "line",
dr = "line",
hb = "line",
bd = "line",
bw = "line",
oe = "line",
sd = "line",
- ld = "line",
- rd = "line",
+ rdb = "line",
+ ldb = "line",
ldd = "line",
rdd = "line",
ep = "line",
@@ -130,9 +158,12 @@ local ring_keys = {
rsr = "line",
lrd = "line",
rrd = "line",
- rb = "line",
lrb = "line",
rrb = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
dr = "line",
eb = "line",
er = "line",
@@ -199,7 +230,10 @@ local syntax = {
mp = { direct = '%s', arguments = 1 }, -- backdoor MP code - dangerous!
}
-local definitions = { }
+chemistry.definitions = chemistry.definitions or { }
+local definitions = chemistry.definitions
+
+storage.register("chemistry/definitions",definitions,"chemistry.definitions")
function chemistry.undefine(name)
definitions[lower(name)] = nil
@@ -218,7 +252,7 @@ function chemistry.define(name,spec,text)
}
end
-local metacode, variant, keys, max, txt, pstack, sstack
+local metacode, variant, keys, max, txt, pstack, sstack, align
local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...)
local function fetch(txt)
@@ -260,10 +294,10 @@ local special = (colon * C(other^1)) + Cc("")
local text = (equal * C(P(1)^0)) + Cc(false)
local pattern =
- (amount + Cc(1)) *
- (remapped + Cc("")) *
- Cs(operation/lower) *
- Cs(special/lower) * (
+ (amount + Cc(1))
+ * (remapped + Cc(""))
+ * Cs(operation/lower)
+ * Cs(special/lower) * (
range * Cc(false) * text +
Cc(false) * Cc(false) * set * text +
single * Cc(false) * Cc(false) * text +
@@ -278,43 +312,88 @@ local pattern =
-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x
local t_initialize = 'if unknown context_chem : input mp-chem.mpiv ; fi ;'
-local t_start_structure = 'chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
+local t_start_structure = 'chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
local t_stop_structure = 'chem_stop_structure;'
local t_start_component = 'chem_start_component;'
local t_stop_component = 'chem_stop_component;'
local t_line = 'chem_%s%s(%s,%s,%s,%s,%s);'
local t_set = 'chem_set(%s);'
-local t_number = 'chem_%s(%s,%s,"\\chemicaltext{%s}");'
+local t_number = 'chem_%s%s(%s,%s,"\\chemicaltext{%s}");'
local t_text = t_number
local t_empty_normal = 'chem_%s(%s,%s,"");'
local t_empty_center = 'chem_c%s(%s,%s,"");'
local t_transform = 'chem_%s(%s,%s,%s);'
-local function process(spec,text,n,rulethickness,rulecolor,offset)
- insert(stack,{ spec=spec, text=text, n=n })
+local prepareMPvariable = commands and commands.prepareMPvariable
+
+local function process(level,spec,text,n,rulethickness,rulecolor,offset,default_variant)
+ insert(stack,{ spec = spec, text = text, n = n })
local txt = #stack
local m = #metacode
+ local saved_rulethickness = rulethickness
+ local saved_rulecolor = rulecolor
+ local saved_align = align
+ local current_variant = default_variant or "six"
for i=1,#spec do
local step = spec[i]
local s = lower(step)
- local d = definitions[s]
+ local n = current_variant .. ":" .. s
+ local d = definitions[n]
+ if not d then
+ n = s
+ d = definitions[n]
+ end
if d then
if trace_structure then
- report_chemistry("%s => definition: %s",step,s)
+ report_chemistry("%s > %s => definition: %s (%s snippets)",level,step,n,#d)
end
for i=1,#d do
local di = d[i]
- process(di.spec,di.text,1,rulethickness,rulecolor) -- offset?
+ current_variant = process(level+1,di.spec,di.text,1,rulethickness,rulecolor,offset,current_variant) -- offset?
end
else
- --~local rep, operation, special, index, upto, set, text = lpegmatch(pattern,step)
local factor, osign, operation, special, index, upto, set, text = lpegmatch(pattern,step)
if trace_structure then
local set = set and concat(set," ") or "-"
- report_chemistry("%s => factor: %s, osign: %s operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s",
- step,factor or "",osign or "",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-")
+ report_chemistry("%s > %s => factor: %s, osign: %s operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s",
+ level,step,factor or "",osign or "",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-")
end
- if operation == "pb" then
+ if operation == "rulecolor" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == "" then
+ rulecolor = saved_rulecolor
+ elseif t then
+ rulecolor = mpnamedcolor(t)
+ end
+ elseif operation == "rulethickness" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == t_medium or t == "" then
+ rulethickness = saved_rulethickness
+ elseif t == v_small then
+ rulethickness = topoints(1/1.2 * todimen(saved_rulethickness))
+ elseif t == v_big then
+ rulethickness = topoints(1.2 * todimen(saved_rulethickness))
+ elseif t then
+ -- rulethickness = topoints(todimen(t)) -- mp can't handle sp
+ rulethickness = topoints(tonumber(t) * todimen(saved_rulethickness))
+ end
+ elseif operation == "symalign" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal then
+ align = saved_align
+ elseif t and t ~= "" then
+ align = "." .. t
+ end
+ elseif operation == "pb" then
insert(pstack,variant)
m = m + 1 ; metacode[m] = syntax.pb.direct
if keys[special] == "text" and index then
@@ -330,6 +409,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
keys, max = ss.keys, ss.max
m = m + 1 ; metacode[m] = syntax[operation].direct
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
elseif operation == "save" then
insert(sstack,variant)
m = m + 1 ; metacode[m] = syntax.save.direct
@@ -339,8 +419,52 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
keys, max = ss.keys, ss.max
m = m + 1 ; metacode[m] = syntax[operation].direct
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
elseif operation then
local ss = syntax[operation]
+ local what = keys[operation]
+ local ns = 0
+ if set then
+ local sv = syntax[current_variant]
+ local ms = sv and sv.max
+ set = unique(set)
+ ns = #set
+ if directive_strictorder then
+ if what == "line" then
+ set = sorted(set)
+ end
+ if directive_strictindex and ms then
+ for i=ns,1,-1 do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("%s > operation %s: limited to %s steps, ignoring %s",
+ level,operation,ms,si)
+ set[i] = nil
+ ns = ns - 1
+ else
+ break
+ end
+ end
+ end
+ else
+ if directive_strictindex and ms then
+ local t, nt = { }, 0
+ for i=1,ns do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("%s > operation %s: limited to %s steps, ignoring %s",
+ level,operation,ms,si)
+ set[i] = nil
+ else
+ nt = nt + 1
+ t[nt] = si
+ end
+ end
+ ns = nt
+ set = t
+ end
+ end
+ end
if ss then
local ds = ss.direct
if ds then
@@ -348,7 +472,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if sa == 1 then
local one ; txt, one = fetch(txt)
m = m + 1 ; metacode[m] = format(ds,one or "")
- elseif sa ==2 then
+ elseif sa == 2 then
local one ; txt, one = fetch(txt)
local two ; txt, two = fetch(txt)
m = m + 1 ; metacode[m] = format(ds,one or "",two or "")
@@ -358,118 +482,120 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
elseif ss.keys then
variant, keys, max = s, ss.keys, ss.max
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
end
- else
- local what = keys[operation]
- if what == "line" then
- local s = osign
- if s ~= "" then s = "." .. s end
- if set then
- -- condense consecutive numbers in a set to a range
- -- (numbers modulo max are currently not dealt with...)
- table.sort(set)
- local sf, st = set[1]
- for i=1,#set do
- if i > 1 and set[i] ~= set[i-1]+1 then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
- sf = set[i]
- end
- st = set[i]
+ elseif what == "line" then
+ local s = osign
+ if s ~= "" then
+ s = "." .. s
+ end
+ if set then
+ -- condense consecutive numbers in a set to a range
+ local sf, st = set[1]
+ for i=1,ns do
+ if i > 1 and set[i] ~= set[i-1]+1 then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
+ sf = set[i]
end
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
- elseif upto then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,upto,rulethickness,rulecolor)
- elseif index then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,index,rulethickness,rulecolor)
- else
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,1,max,rulethickness,rulecolor)
+ st = set[i]
end
- elseif what == "number" then
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,si,si)
- end
- elseif upto then
- for i=index,upto do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,si,si)
- end
- elseif index then
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,index,index)
- else
- for i=1,max do
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,i,i)
- end
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
+ elseif upto then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,upto,rulethickness,rulecolor)
+ elseif index then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,index,rulethickness,rulecolor)
+ else
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,1,max,rulethickness,rulecolor)
+ end
+ elseif what == "number" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,si,si)
end
- elseif what == "text" then
- if set then
- for i=1,#set do
- local si = set[i]
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,si,t)
- end
- end
- elseif upto then
- for i=index,upto do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,i,t)
- end
- end
- elseif index == 0 then
+ elseif upto then
+ for i=index,upto do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,si,si)
+ end
+ elseif index then
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,index,index)
+ else
+ for i=1,max do
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,i,i)
+ end
+ end
+ elseif what == "text" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
local t = text
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,index,t)
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,si,t)
end
- elseif index then
+ end
+ elseif upto then
+ for i=index,upto do
local t = text
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,index,t)
- end
- else
- for i=1,max do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,i,t)
- end
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,i,t)
end
end
- elseif what == "transform" then
- if osign == "m" then factor = -factor end
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,si,factor)
- end
- elseif upto then
- for i=index,upto do
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,i,factor)
+ elseif index == 0 then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,index,t)
+ end
+ elseif index then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,index,t)
+ end
+ else
+ for i=1,max do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,i,t)
end
- else
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,index or 1,factor)
end
- elseif what == "fixed" then
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,rulethickness,rulecolor)
- elseif trace_structure then
- report_chemistry("warning: undefined operation %s ignored here", operation or "")
end
+ elseif what == "transform" then
+ if osign == "m" then
+ factor = -factor
+ end
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,si,factor)
+ end
+ elseif upto then
+ for i=index,upto do
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,i,factor)
+ end
+ else
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,index or 1,factor)
+ end
+ elseif what == "fixed" then
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,rulethickness,rulecolor)
+ elseif trace_structure then
+ report_chemistry("%s > warning: undefined operation %s ignored here",
+ level, operation or "")
end
end
end
end
remove(stack)
+ return current_variant
end
-- the size related values are somewhat special but we want to be
@@ -480,19 +606,22 @@ end
function chemistry.start(settings)
chemistry.structures = chemistry.structures + 1
local emwidth, rulethickness, rulecolor, axiscolor = settings.emwidth, settings.rulethickness, settings.rulecolor, settings.framecolor
- local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "normal", settings.offset or 0
+ local width, height, scale, rotation, offset = settings.width or 0, settings.height or 0, settings.scale or "normal", settings.rotation or 0, settings.offset or 0
local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0
--
metacode = { }
--
+ align = settings.symalign or "auto"
if trace_structure then
- report_chemistry("scale: %s, width: %s, height: %s, l: %s, r: %s, t: %s, b: %s", scale, width, height, l, r, t, b)
+ report_chemistry("scale: %s, rotation: %s, width: %s, height: %s, l: %s, r: %s, t: %s, b: %s", scale, rotation, width, height, l, r, t, b)
+ report_chemistry("symalign: %s", align)
end
- if scale == variables.small then
+ if align ~= "" then align = "." .. align end
+ if scale == v_small then
scale = 1/1.2
- elseif scale == variables.normal or scale == variables.medium or scale == 0 then
+ elseif scale == v_normal or scale == v_medium or scale == 0 then
scale = 1
- elseif scale == variables.big then
+ elseif scale == v_big then
scale = 1.2
else
scale = tonumber(scale)
@@ -504,7 +633,7 @@ function chemistry.start(settings)
scale = .01
end
end
- if width == variables.fit then
+ if width == v_fit then
width = true
else
width = tonumber(width) or 0
@@ -529,7 +658,7 @@ function chemistry.start(settings)
end
width = false
end
- if height == variables.fit then
+ if height == v_fit then
height = true
else
height = tonumber(height) or 0
@@ -554,12 +683,13 @@ function chemistry.start(settings)
end
height = false
end
+ rotation = tonumber(rotation) or 0
--
metacode[#metacode+1] = format(t_start_structure,
chemistry.structures,
- l, r, t, b, scale,
+ l, r, t, b, scale, rotation,
tostring(width), tostring(height), tostring(emwidth), tostring(offset),
- tostring(settings.axis == variables.on), tostring(rulethickness), tostring(axiscolor)
+ tostring(settings.axis == v_on), tostring(rulethickness), tostring(axiscolor)
)
--
variant, keys, stack, pstack, sstack = "one", { }, { }, { }, { }
@@ -590,7 +720,7 @@ function chemistry.component(spec,text,settings)
local text = settings_to_array_with_repeat(text,true)
-- inspect(spec)
metacode[#metacode+1] = t_start_component
- process(spec,text,1,rulethickness,rulecolor) -- offset?
+ process(1,spec,text,1,rulethickness,rulecolor) -- offset?
metacode[#metacode+1] = t_stop_component
end
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
index 205675c46..cb840ed80 100644
--- a/tex/context/base/chem-str.mkiv
+++ b/tex/context/base/chem-str.mkiv
@@ -141,6 +141,7 @@
\def\chem_start[#1][#2]%
{\ifmmode\vcenter\else\vbox\fi
\bgroup
+ \synchronizestrut{\chemicalparameter\c!strut}%
\dontcomplain
\settrue\indisplaychemical
\forgetall
@@ -164,6 +165,8 @@
top = \chemicalparameter\c!top,
bottom = \chemicalparameter\c!bottom,
scale = "\chemicalparameter\c!scale",
+ rotation = "\chemicalparameter\c!rotation",
+ symalign = "\chemicalparameter\c!symalign",
axis = "\chemicalparameter\c!axis",
framecolor = "\MPcolor{\chemicalparameter\c!framecolor}",
rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax",
@@ -358,13 +361,28 @@
% \let\chemicalsmashedleft \chemicalleftcentered
% \let\chemicalsmashedright \chemicalrightcentered
-\unexpanded\def\chemicalalignedtext#1#2#3%
+\unexpanded\def\chemicalalignedtext
+ {\ifmmode
+ \expandafter\chem_aligned_text_math
+ \else
+ \expandafter\chem_aligned_text_text
+ \fi}
+
+\def\chem_aligned_text_text#1#2#3%
{\dontleavehmode
\begingroup
\usechemicalstyleandcolor\c!style\c!color
\hbox to \fontcharwd\font`C{\setstrut\strut#1\molecule{#3}#2}%
\endgroup}
+\def\chem_aligned_text_math#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox to \fontcharwd\font`C{\setstrut\strut#1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2}%
+ \endgroup}
+
\unexpanded\def\chemicalcentered {\chemicalalignedtext\hss \hss }
\unexpanded\def\chemicalleftcentered {\chemicalalignedtext\relax\hss }
\unexpanded\def\chemicalrightcentered{\chemicalalignedtext\hss \relax}
@@ -436,18 +454,37 @@
% inline
+% \unexpanded\def\chemical
+% {\ifinformula
+% \expandafter\displaychemical
+% \else
+% \expandafter\inlinechemical
+% \fi}
+
\unexpanded\def\chemical
{\ifinformula
- \expandafter\displaychemical
+ \expandafter\indisplaychemical
\else
\expandafter\inlinechemical
\fi}
+\unexpanded\def\indisplaychemical
+ {\mathstylecommand\displaychemical\inlinechemical\inlinechemical}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\ctxcommand{inlinechemical(\!!bs#1\!!es)}}}%
+ \endgroup}
+
\unexpanded\def\displaychemical
{\dotriplegroupempty\chem_display}
-\def\chem_display#1#2#3% todo:
- {\the\everychemical \everychemical\emptytoks
+\def\chem_display#1#2#3%
+ {\the\everychemical
+ \everychemical\emptytoks
\quad
\vcenter\bgroup
\usechemicalstyleandcolor\c!style\c!color
@@ -644,28 +681,50 @@
\c!offset=\v!overlay,
\c!frame=\v!off]
-\definecolor [lightblue] [h=add8e6] % a nice X11 color
+\definecolor % private color
+ [chemicalframecolor]
+ [r=.75,g=.85,b=.95]
\setupchemical
[\c!frame=,
\c!width=\v!fit, % or unitless number, multiplies scale*EmWidth
\c!height=\v!fit, % or unitless number, multiplies scale*EmWidth
- \c!left=0, % or unitless number, multiplies scale*EmWidth
- \c!right=0, % or unitless number, multiplies scale*EmWidth
- \c!top=0, % or unitless number, multiplies scale*EmWidth
- \c!bottom=0, % or unitless number, multiplies scale*EmWidth
+ \c!left=0, % unitless number, multiplies scale*EmWidth
+ \c!right=0, % unitless number, multiplies scale*EmWidth
+ \c!top=0, % unitless number, multiplies scale*EmWidth
+ \c!bottom=0, % unitless number, multiplies scale*EmWidth
\c!bodyfont=,
- \c!scale=\v!normal, % small, normal or medium, big, unitless number (multiplies EmWidth)
+ \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies EmWidth)
\c!size=\v!medium,
\c!textsize=\v!big, % how is textsize used??
\c!axis=\v!off,
\c!style=\rm,
- \c!location=,
+ \c!rotation=0, % unitless number (interpreted as degrees)
+ \c!symalign=\v!auto,
+ \c!location=, % not yet used (was interaction related in mkii)
\c!offset=.25em,
\c!color=,
- \c!framecolor=lightblue,
+ \c!strut=\v!yes,
+ \c!framecolor=chemicalframecolor,
\c!rulethickness=0.6pt, %1.5\linewidth,
\c!rulecolor=,
\c!factor=1] % how is factor used??
+%D Compatibility:
+
+\definechemical[+R] {\chemical[RR]}
+\definechemical[-R] {\chemical[LR]}
+
+\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]}
+\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]}
+
+\definechemical[NEWMAN] {\chemical[]}
+\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]}
+\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]}
+\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]}
+\definechemical[SIX:FRONT] {\chemical[SIXFRONT]}
+\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]}
+
\protect \endinput
diff --git a/tex/context/base/cldf-bas.mkiv b/tex/context/base/cldf-bas.mkiv
index f2bd05177..f8b5b5d6a 100644
--- a/tex/context/base/cldf-bas.mkiv
+++ b/tex/context/base/cldf-bas.mkiv
@@ -14,5 +14,6 @@
\writestatus{loading}{ConTeXt Lua Documents / Basics}
\registerctxluafile{cldf-bas}{1.001}
+\registerctxluafile{cldf-prs}{1.001}
\endinput
diff --git a/tex/context/base/cldf-com.lua b/tex/context/base/cldf-com.lua
index d9062594e..fa0dbed3e 100644
--- a/tex/context/base/cldf-com.lua
+++ b/tex/context/base/cldf-com.lua
@@ -17,9 +17,8 @@ generics.stoptabulate = "stoptabulate" -- "stop" .. variables.tabulate -- tod
local NC, NR = context.NC, context.NR
local function tabulaterow(how,...)
- local t = { ... }
- for i=1,#t do
- local ti = tostring(t[i])
+ for i=1,select("#",...) do
+ local ti = tostring(select(i,...))
NC()
if how then
context[how](ti)
diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua
index 84ae7314e..b045282b1 100644
--- a/tex/context/base/cldf-ini.lua
+++ b/tex/context/base/cldf-ini.lua
@@ -25,10 +25,10 @@ local tex = tex
context = context or { }
local context = context
-local format, find, gmatch, gsub, validstring = string.format, string.find, string.gmatch, string.gsub, string.valid
+local format, gsub, validstring = string.format, string.gsub, string.valid
local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable
local insert, remove, concat = table.insert, table.remove, table.concat
-local lpegmatch, lpegC, lpegS, lpegP, lpegCc = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc
+local lpegmatch, lpegC, lpegS, lpegP, lpegCc, patterns = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc, lpeg.patterns
local texsprint = tex.sprint
local textprint = tex.tprint
@@ -162,8 +162,8 @@ context.popcatcodes = popcatcodes
--~ content / texsprint
--~ )^0
-local newline = lpeg.patterns.newline
-local space = lpeg.patterns.spacer
+local newline = patterns.newline
+local space = patterns.spacer
local spacing = newline * space^0
local content = lpegC((1-spacing)^1) -- texsprint
local emptyline = space^0 * newline^2 -- texprint("")
@@ -357,6 +357,8 @@ end
-- -- --
+local containseol = patterns.containseol
+
local function writer(parent,command,first,...) -- already optimized before call
local t = { first, ... }
flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
@@ -377,7 +379,7 @@ local function writer(parent,command,first,...) -- already optimized before call
flush(currentcatcodes,"{}")
elseif typ == "string" then
-- is processelines seen ?
- if processlines and find(ti,"[\n\r]") then -- we can check for ti == "\n"
+ if processlines and lpegmatch(containseol,ti) then
flush(currentcatcodes,"{")
local flushlines = parent.__flushlines or flushlines
flushlines(ti)
@@ -529,7 +531,7 @@ local function caller(parent,f,a,...)
if typ == "string" then
if a then
flush(contentcatcodes,format(f,a,...)) -- was currentcatcodes
- elseif processlines and find(f,"[\n\r]") then
+ elseif processlines and lpegmatch(containseol,f) then
local flushlines = parent.__flushlines or flushlines
flushlines(f)
else
@@ -548,10 +550,9 @@ local function caller(parent,f,a,...)
if f then
if a ~= nil then
local flushlines = parent.__flushlines or flushlines
- flushlines(f)
- -- ignore ... maybe some day
+ flushlines(a)
else
- flushdirect(currentcatcodes,"\r")
+ flushdirect(currentcatcodes,"\n") -- no \r, else issues with \startlines ... use context.par() otherwise
end
else
if a ~= nil then
@@ -635,6 +636,11 @@ local currenttrace = nil
local nofwriters = 0
local nofflushes = 0
+local visualizer = lpeg.replacer {
+ { "\n","<<newline>>" },
+ { "\r","<<par>>" },
+}
+
statistics.register("traced context", function()
if nofwriters > 0 or nofflushes > 0 then
return format("writers: %s, flushes: %s, maxstack: %s",nofwriters,nofflushes,_n_f_)
@@ -648,7 +654,7 @@ local tracedwriter = function(parent,...) -- also catcodes ?
local t, n = { "w : - : " }, 1
local traced = function(normal,catcodes,...) -- todo: check for catcodes
local s = concat({...})
- s = gsub(s,"\r","<<newline>>") -- unlikely
+ s = lpegmatch(visualizer,s)
n = n + 1
t[n] = s
normal(catcodes,...)
@@ -676,7 +682,7 @@ local traced = function(normal,one,two,...)
local argtype = type(argument)
c = c + 1
if argtype == "string" then
- collapsed[c] = gsub(argument,"\r","<<newline>>")
+ collapsed[c] = lpegmatch(visualizer,argument)
elseif argtype == "number" then
collapsed[c] = argument
else
@@ -689,7 +695,7 @@ local traced = function(normal,one,two,...)
normal(one)
local argtype = type(one)
if argtype == "string" then
- currenttrace(format("f : - : %s",gsub(one,"\r","<<newline>>")))
+ currenttrace(format("f : - : %s",lpegmatch(visualizer,one)))
elseif argtype == "number" then
currenttrace(format("f : - : %s",one))
else
diff --git a/tex/context/base/cldf-prs.lua b/tex/context/base/cldf-prs.lua
new file mode 100644
index 000000000..42757be19
--- /dev/null
+++ b/tex/context/base/cldf-prs.lua
@@ -0,0 +1,52 @@
+if not modules then modules = { } end modules ['cldf-bas'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs
+local format = string.format
+
+local cpatterns = patterns.context or { }
+patterns.context = cpatterns
+
+local backslash = P("\\")
+local csname = backslash * P(1) * (1-backslash)^0
+local sign = P("+") / "\\textplus "
+ + P("-") / "\\textminus "
+local leftbrace = P("{")
+local rightbrace = P("}")
+local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace }
+local subscript = P("_")
+local superscript = P("^")
+local utf8char = patterns.utf8char
+local cardinal = patterns.cardinal
+
+-- local content = Cs(csname + nested + sign^-1 * (csname + cardinal + utf8char))
+-- local lowfirst = subscript * ( Cc("\\lohi{%s}{%s}") * content * superscript + Cc("\\low{%s}" ) ) * content / format
+-- local highfirst = superscript * ( Cc("\\hilo{%s}{%s}") * content * subscript + Cc("\\high{%s}") ) * content / format
+-- local scripts = Cs(lowfirst + highfirst)
+
+local scripts = P { "start",
+ start = V("csname") + V("lowfirst") + V("highfirst"),
+ csname = csname,
+ content = Cs(V("csname") + nested + sign^-1 * (cardinal + utf8char)),
+ lowfirst = subscript * ( Cc("\\lohi{%s}{%s}") * V("content") * superscript + Cc("\\low{%s}" ) ) * V("content") / format,
+ highfirst = superscript * ( Cc("\\hilo{%s}{%s}") * V("content") * subscript + Cc("\\high{%s}") ) * V("content") / format,
+ }
+
+local scripted = Cs((csname + scripts + utf8char)^0)
+
+cpatterns.scripts = scripts
+cpatterns.csname = csname
+cpatterns.scripted = scripted
+cpatterns.nested = nested
+
+-- inspect(scripted)
+
+-- print(lpegmatch(scripted,"10^-3"))
+-- print(lpegmatch(scripted,"10^-a"))
+
diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua
index 4fdbf4545..1a994b567 100644
--- a/tex/context/base/colo-ini.lua
+++ b/tex/context/base/colo-ini.lua
@@ -38,6 +38,8 @@ local attributes_list = attributes.list
local colorvalues = colors.values
local transparencyvalues = transparencies.values
+local texattribute = tex.attribute
+
colors.sets = colors.sets or { } -- sets are mostly used for
local colorsets = colors.sets -- showing lists of defined
local colorset = { } -- colors
@@ -503,12 +505,17 @@ local function mpcolor(model,ca,ta,default)
end
end
+local function mpnamedcolor(name)
+ return mpcolor(texattribute[a_colorspace],l_color[name] or l_color.black)
+end
+
local function mpoptions(model,ca,ta,default) -- will move to mlib-col
return format("withcolor %s",mpcolor(model,ca,ta,default))
end
-colors.mpcolor = mpcolor
-colors.mpoptions = mpoptions
+colors.mpcolor = mpcolor
+colors.mpnamedcolor = mpnamedcolor
+colors.mpoptions = mpoptions
function colors.formatcolor(ca,separator)
local cv = colorvalues[ca]
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
index 3f5956611..e5cdd0410 100644
--- a/tex/context/base/cont-new.mkii
+++ b/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.12.10 23:20}
+\newcontextversion{2012.12.24 20:08}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index e67181585..4e62d04f2 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.12.10 23:20}
+\newcontextversion{2012.12.24 20:08}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/cont-yes.mkiv b/tex/context/base/cont-yes.mkiv
index 0b7fd621e..5eae3eecb 100644
--- a/tex/context/base/cont-yes.mkiv
+++ b/tex/context/base/cont-yes.mkiv
@@ -20,6 +20,8 @@
-- When a style is loaded there is a good change that we never enter
-- this code.
+ local report = logs.reporter("system")
+
environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
local arguments = environment.arguments
@@ -32,12 +34,16 @@
-- can be part of (any) loaded (sub) file. The \starttext
-- wrapping might go away.
+ report("processing as xml: %s",filename)
+
context.starttext()
context.xmlprocess("main",filename,"")
context.stoptext()
elseif suffix == "cld" or arguments.forcecld then
+ report("processing as cld: %s",filename)
+
context.runfile(filename)
elseif suffix == "lua" or arguments.forcelua then
@@ -45,12 +51,16 @@
-- The wrapping might go away. Why is is it there in the
-- first place.
+ report("processing as lua: %s",filename)
+
context.starttext()
context.ctxlua(string.format('dofile("%s")',filename))
context.stoptext()
elseif suffix == "mp" or arguments.forcemp then
+ report("processing as metapost: %s",filename)
+
context.starttext()
context.processMPfigurefile(filename)
context.stoptext()
@@ -66,6 +76,7 @@
else
+ -- \writestatus{system}{processing as tex}
-- We have a regular tex file so no \starttext yet as we can
-- load fonts.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 73f23e3ab..4feb1ffe5 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png
index fb3daf3d5..882ca4262 100644
--- a/tex/context/base/context-version.png
+++ b/tex/context/base/context-version.png
Binary files differ
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
index dfe757926..d1b87a40f 100644
--- a/tex/context/base/context.mkii
+++ b/tex/context/base/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.12.10 23:20}
+\edef\contextversion{2012.12.24 20:08}
%D For those who want to use this:
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index e47b0e4f1..56e4b0dc1 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.12.10 23:20}
+\edef\contextversion{2012.12.24 20:08}
%D For those who want to use this:
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
index 96f3a00ea..11558102e 100644
--- a/tex/context/base/core-con.lua
+++ b/tex/context/base/core-con.lua
@@ -16,8 +16,6 @@ slower but look nicer this way.</p>
local command, context = commands, context
-local utf = unicode.utf8
-
local floor, date, time, concat = math.floor, os.date, os.time, table.concat
local lower, format, rep, match = string.lower, string.format, string.rep, string.match
local utfchar, utfbyte = utf.char, utf.byte
diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua
index 31f13a0fc..5f00d6fff 100644
--- a/tex/context/base/core-uti.lua
+++ b/tex/context/base/core-uti.lua
@@ -135,6 +135,7 @@ local packlist = {
local jobpacker = packers.new(packlist,1.01)
job.pack = true
+-- job.pack = false
directives.register("job.pack",function(v) pack = v end)
diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua
index f016881b5..2ee25120e 100644
--- a/tex/context/base/data-env.lua
+++ b/tex/context/base/data-env.lua
@@ -24,6 +24,8 @@ resolvers.suffixes = suffixes
resolvers.dangerous = dangerous
resolvers.suffixmap = suffixmap
+local luasuffixes = utilities.lua.suffixes
+
local relations = allocate { -- todo: handlers also here
core = {
ofm = { -- will become obsolete
@@ -109,7 +111,7 @@ local relations = allocate { -- todo: handlers also here
lua = {
names = { "lua" },
variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
+ suffixes = { luasuffixes.lua, luasuffixes.luc, luasuffixes.tma, luasuffixes.tmc },
},
lib = {
names = { "lib" },
diff --git a/tex/context/base/data-ini.lua b/tex/context/base/data-ini.lua
index a952a29bd..37b4f62ca 100644
--- a/tex/context/base/data-ini.lua
+++ b/tex/context/base/data-ini.lua
@@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['data-ini'] = {
}
local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
local next, type = next, type
local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
@@ -98,6 +97,10 @@ do
local args = environment.originalarguments or arg -- this needs a cleanup
+ if not environment.ownmain then
+ environment.ownmain = status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
@@ -214,19 +217,6 @@ end
environment.texroot = file.collapsepath(texroot)
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
if profiler then
directives.register("system.profile",function()
profiler.start("luatex-profile.log")
diff --git a/tex/context/base/data-lua.lua b/tex/context/base/data-lua.lua
index c63851525..de20f4820 100644
--- a/tex/context/base/data-lua.lua
+++ b/tex/context/base/data-lua.lua
@@ -14,6 +14,8 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- -- local mylib = require("libtest")
-- -- local mysql = require("luasql.mysql")
+local searchers = package.searchers or package.loaders
+
local concat = table.concat
local trace_libraries = false
@@ -115,13 +117,9 @@ function package.extraclibpath(...)
end
end
-if not package.loaders then
- package.loaders = package.searchers -- 5.2
-end
-
-if not package.loaders[-2] then
+if not searchers[-2] then
-- use package-path and package-cpath
- package.loaders[-2] = package.loaders[2]
+ searchers[-2] = searchers[2]
end
local function loadedaslib(resolved,rawname)
@@ -132,7 +130,7 @@ local function loadedbylua(name)
if trace_libraries then
report_libraries("! locating %q using normal loader",name)
end
- local resolved = package.loaders[-2](name)
+ local resolved = searchers[-2](name)
end
local function loadedbyformat(name,rawname,suffixes,islib)
@@ -187,7 +185,7 @@ local function notloaded(name)
end
end
-package.loaders[2] = function(name)
+searchers[2] = function(name)
local thename = gsub(name,"%.","/")
local luaname = file.addsuffix(thename,"lua")
local libname = file.addsuffix(thename,os.libsuffix)
@@ -201,7 +199,7 @@ package.loaders[2] = function(name)
or notloaded (name)
end
--- package.loaders[3] = nil
--- package.loaders[4] = nil
+-- searchers[3] = nil
+-- searchers[4] = nil
resolvers.loadlualib = require
diff --git a/tex/context/base/data-pre.lua b/tex/context/base/data-pre.lua
index 8067355d3..e48a5aa8c 100644
--- a/tex/context/base/data-pre.lua
+++ b/tex/context/base/data-pre.lua
@@ -19,10 +19,9 @@ local resolvers = resolvers
local prefixes = utilities.storage.allocate()
resolvers.prefixes = prefixes
-local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local P, S, R, C, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.match
local joinpath, basename, dirname = file.join, file.basename, file.dirname
local getmetatable, rawset, type = getmetatable, rawset, type
@@ -144,6 +143,28 @@ end
-- todo: use an lpeg (see data-lua for !! / stripper)
+-- local function resolve(str) -- use schemes, this one is then for the commandline only
+-- if type(str) == "table" then
+-- local t = { }
+-- for i=1,#str do
+-- t[i] = resolve(str[i])
+-- end
+-- return t
+-- else
+-- local res = resolved[str]
+-- if not res then
+-- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+-- resolved[str] = res
+-- abstract[res] = str
+-- end
+-- return res
+-- end
+-- end
+
+-- home:xx;selfautoparent:xx;
+
+local pattern = Cs((C(R("az")^2) * P(":") * C((1-S(" \"\';,"))^1) / _resolve_ + P(1))^0)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -154,7 +175,7 @@ local function resolve(str) -- use schemes, this one is then for the commandline
else
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
+ res = lpegmatch(pattern,str)
resolved[str] = res
abstract[res] = str
end
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
index 25aaa6c35..41a590228 100644
--- a/tex/context/base/data-res.lua
+++ b/tex/context/base/data-res.lua
@@ -31,6 +31,7 @@ local joinpath = file.joinpath
local allocate = utilities.storage.allocate
local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
+local luasuffixes = utilities.lua.suffixes
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -1607,15 +1608,19 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
+ local engine = environment.ownmain or "luatex"
+ local barename = file.removesuffix(name)
+ local fullname = file.addsuffix(barename,"fmt")
+ local fmtname = caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
+ fmtname = resolvers.findfile(fullname)
fmtname = resolvers.cleanpath(fmtname)
end
if fmtname ~= "" then
local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
+ local luaname = file.addsuffix(barename,luasuffixes.lua)
+ local lucname = file.addsuffix(barename,luasuffixes.luc)
+ local luiname = file.addsuffix(barename,luasuffixes.lui)
if lfs.isfile(luiname) then
return barename, luiname
elseif lfs.isfile(lucname) then
diff --git a/tex/context/base/data-sch.lua b/tex/context/base/data-sch.lua
index 569fa5c94..7eb254557 100644
--- a/tex/context/base/data-sch.lua
+++ b/tex/context/base/data-sch.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['data-sch'] = {
license = "see context related readme files"
}
-local loadstring = loadstring
+local load = load
local gsub, concat, format = string.gsub, table.concat, string.format
local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
@@ -192,7 +192,7 @@ schemes.fetchstring = fetchstring
function schemes.fetchtable(url,data)
local reply = fetchstring(url,data)
if reply then
- local s = loadstring("return " .. reply)
+ local s = load("return " .. reply)
if s then
return s()
end
diff --git a/tex/context/base/data-tex.lua b/tex/context/base/data-tex.lua
index 639bb0ac9..f19b53407 100644
--- a/tex/context/base/data-tex.lua
+++ b/tex/context/base/data-tex.lua
@@ -18,7 +18,7 @@ local resolvers = resolvers
local sequencers = utilities.sequencers
local methodhandler = resolvers.methodhandler
local splitlines = string.splitlines
-local utffiletype = unicode.filetype
+local utffiletype = utf.filetype
-- local fileprocessor = nil
-- local lineprocessor = nil
@@ -75,13 +75,13 @@ function helpers.textopener(tag,filename,filehandle,coding)
report_tex("%s opener, '%s' opened using method '%s'",tag,filename,coding)
end
if coding == "utf-16-be" then
- lines = unicode.utf16_to_utf8_be(lines)
+ lines = utf.utf16_to_utf8_be(lines)
elseif coding == "utf-16-le" then
- lines = unicode.utf16_to_utf8_le(lines)
+ lines = utf.utf16_to_utf8_le(lines)
elseif coding == "utf-32-be" then
- lines = unicode.utf32_to_utf8_be(lines)
+ lines = utf.utf32_to_utf8_be(lines)
elseif coding == "utf-32-le" then
- lines = unicode.utf32_to_utf8_le(lines)
+ lines = utf.utf32_to_utf8_le(lines)
else -- utf8 or unknown (could be a mkvi file)
local runner = textfileactions.runner
if runner then
diff --git a/tex/context/base/data-tmp.lua b/tex/context/base/data-tmp.lua
index f7e64895b..c71002f2b 100644
--- a/tex/context/base/data-tmp.lua
+++ b/tex/context/base/data-tmp.lua
@@ -25,6 +25,7 @@ luatools with a recache feature.</p>
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
+local addsuffix, is_writable, is_readable = file.addsuffix, file.is_writable, file.is_readable
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
@@ -49,8 +50,10 @@ end
-- end of intermezzo
-caches = caches or { }
-local caches = caches
+caches = caches or { }
+local caches = caches
+
+local luasuffixes = utilities.lua.suffixes
caches.base = caches.base or "luatex-cache"
caches.more = caches.more or "context"
@@ -78,18 +81,18 @@ local function identify()
cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
- if file.is_readable(cachepath) then
+ if is_readable(cachepath) then
readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
+ if not writable and is_writable(cachepath) then
writable = cachepath
end
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
+ if is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
+ if isdir(cachepath) and is_writable(cachepath) then
report_caches("created: %s",cachepath)
writable = cachepath
readables[#readables+1] = cachepath
@@ -111,8 +114,8 @@ local function identify()
cachepath = resolvers.resolve(cachepath)
cachepath = resolvers.cleanpath(cachepath)
local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
readables[#readables+1] = cachepath
writable = cachepath
break
@@ -201,7 +204,7 @@ end
local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
+local function getreadablepaths(...)
local tags = { ... }
local hash = concat(tags,"/")
local done = r_cache[hash]
@@ -244,7 +247,7 @@ function caches.getfirstreadablefile(filename,...)
for i=1,#rd do
local path = rd[i]
local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
+ if is_readable(fullname) then
usedreadables[i] = true
return fullname, path
end
@@ -265,7 +268,7 @@ function caches.define(category,subcategory) -- for old times sake
end
function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
+ return format("%s/%s.%s",path,name,luasuffixes.tma), format("%s/%s.%s",path,name,luasuffixes.tmc)
end
function caches.loaddata(readables,name)
@@ -275,7 +278,13 @@ function caches.loaddata(readables,name)
for i=1,#readables do
local path = readables[i]
local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
+ local loader = loadfile(tmcname)
+ if not loader then
+ -- in case we have a different engine
+ utilities.lua.compile(tmaname,tmcname)
+ --
+ loader = loadfile(tmaname)
+ end
if loader then
loader = loader()
collectgarbage("step")
@@ -287,11 +296,15 @@ end
function caches.is_writable(filepath,filename)
local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
+ return is_writable(tmaname)
end
local saveoptions = { compact = true }
+-- add some point we will only use the internal bytecode compiler and
+-- then we can flag success in the tma so that it can trigger a compile
+-- if the other engine
+
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -317,9 +330,9 @@ end
function caches.loadcontent(cachename,dataname)
local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
+ local full, path = caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
+ local blob = loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data = blob()
if data and data.content then
@@ -354,9 +367,10 @@ end
function caches.savecontent(cachename,dataname,content)
local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
+ local full, path = caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
+ local luaname = addsuffix(filename,luasuffixes.lua)
+ local lucname = addsuffix(filename,luasuffixes.luc)
if trace_locating then
report_resolvers("preparing '%s' for '%s'",dataname,cachename)
end
diff --git a/tex/context/base/data-use.lua b/tex/context/base/data-use.lua
index d2a9b7571..fb6798900 100644
--- a/tex/context/base/data-use.lua
+++ b/tex/context/base/data-use.lua
@@ -59,7 +59,7 @@ statistics.register("used cache path", function() return caches.usedpaths() end
function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
local enginebanner = status.list().banner
if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
local luvdata = {
enginebanner = enginebanner,
formatbanner = formatbanner,
@@ -70,10 +70,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname ==
end
end
+-- todo: check this at startup and return (say) 999 as signal that the run
+-- was aborted due to a wrong format in which case mtx-context can trigger
+-- a remake
+
function statistics.checkfmtstatus(texname)
local enginebanner = status.list().banner
if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
+ local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv
if lfs.isfile(luvname) then
local luv = dofile(luvname)
if luv and luv.sourcefile then
diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua
index fda4f27da..f05be5708 100644
--- a/tex/context/base/file-job.lua
+++ b/tex/context/base/file-job.lua
@@ -127,7 +127,7 @@ end
-- moved from tex to lua:
local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
-local luapatterns = { "%s.luc", "%s.lua" }
+local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua" }
local cldpatterns = { "%s.cld" }
local xmlpatterns = { "%s.xml" }
diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua
index 77d7d3e5c..516dffe98 100644
--- a/tex/context/base/font-con.lua
+++ b/tex/context/base/font-con.lua
@@ -6,11 +6,8 @@ if not modules then modules = { } end modules ['font-con'] = {
license = "see context related readme files"
}
-
-- some names of table entries will be changed (no _)
-local utf = unicode.utf8
-
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
local utfbyte = utf.byte
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua
index 03037f1c6..8d4fd25fc 100644
--- a/tex/context/base/font-def.lua
+++ b/tex/context/base/font-def.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['font-def'] = {
-- We can overload some of the definers.functions so we don't local them.
-local concat = table.concat
local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
local tostring, next = tostring, next
local lpegmatch = lpeg.match
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
index 560cf23ee..e23abd701 100644
--- a/tex/context/base/font-ext.lua
+++ b/tex/context/base/font-ext.lua
@@ -6,7 +6,6 @@ if not modules then modules = { } end modules ['font-ext'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
local next, type, byte = next, type, string.byte
local gmatch, concat, format = string.gmatch, table.concat, string.format
local utfchar = utf.char
diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua
index 5b2c3f22a..11615ea8b 100644
--- a/tex/context/base/font-ota.lua
+++ b/tex/context/base/font-ota.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['font-ota'] = {
-- this might become scrp-*.lua
-local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat
+local type = type
if not trackers then trackers = { register = function() end } end
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 9f0fb6657..8e9930a54 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -14,8 +14,6 @@ if not modules then modules = { } end modules ['font-otf'] = {
-- more checking against low level calls of functions
-local utf = unicode.utf8
-
local utfbyte = utf.byte
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -455,32 +453,32 @@ function otf.load(filename,format,sub,featurefile)
starttiming(data)
report_otf("file size: %s", size)
enhancers.apply(data,filename,fontdata)
+ local packtime = { }
if packdata then
if cleanup > 0 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
+ starttiming(packtime)
enhance("pack",data,filename,nil)
+ stoptiming(packtime)
end
report_otf("saving in cache: %s",filename)
data = containers.write(otf.cache, hash, data)
if cleanup > 1 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
stoptiming(data)
if elapsedtime then -- not in generic
- report_otf("preprocessing and caching took %s seconds",elapsedtime(data))
+ report_otf("preprocessing and caching took %s seconds (packtime: %s)",
+ elapsedtime(data),packdata and elapsedtime(packtime) or 0)
end
fontloader.close(fontdata) -- free memory
if cleanup > 3 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
if cleanup > 2 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
else
data = nil
@@ -1058,7 +1056,10 @@ actions["reorganize subtables"] = function(data,filename,raw)
--
local name = gk.name
--
- if features then
+ if not name then
+ -- in fact an error
+ report_otf("skipping weird lookup number %s",k)
+ elseif features then
-- scripts, tag, ismac
local f = { }
for i=1,#features do
@@ -1491,6 +1492,9 @@ actions["merge kern classes"] = function(data,filename,raw)
if type(lookups) ~= "table" then
lookups = { lookups }
end
+ -- if offsets[1] == nil then
+ -- offsets[1] = ""
+ -- end
-- we can check the max in the loop
-- local maxseconds = getn(seconds)
for n, s in next, firsts do
@@ -1511,9 +1515,9 @@ actions["merge kern classes"] = function(data,filename,raw)
if splt then
local extrakerns = { }
local baseoffset = (fk-1) * maxseconds
- -- for sk=2,maxseconds do
- -- local sv = seconds[sk]
- for sk, sv in next, seconds do
+ for sk=2,maxseconds do -- will become 1 based in future luatex
+ local sv = seconds[sk]
+ -- for sk, sv in next, seconds do
local splt = split[sv]
if splt then -- redundant test
local offset = offsets[baseoffset + sk]
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 71027d731..5dba663e4 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -28,6 +28,8 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- handle positions (we need example fonts)
-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
+-- remove some optimizations (when I have a faster machine)
+
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua
index 6c9827de8..fc98b2bdc 100644
--- a/tex/context/base/font-otp.lua
+++ b/tex/context/base/font-otp.lua
@@ -7,11 +7,14 @@ if not modules then modules = { } end modules ['font-otp'] = {
}
-- todo: pack math (but not that much to share)
+-- pitfall 5.2: hashed tables can suddenly become indexed with nil slots
local next, type = next, type
local sort, concat = table.sort, table.concat
+local trace_packing = false trackers.register("otf.packing", function(v) trace_packing = v end)
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
local report_otf = logs.reporter("fonts","otf loading")
-- also used in other scripts so we need to check some tables:
@@ -33,28 +36,68 @@ otf.glists = glists
local criterium = 1
local threshold = 0
-local function tabstr(t)
- local s, n = { }, 0
+local function tabstr_normal(t)
+ local s = { }
+ local n = 0
for k, v in next, t do
n = n + 1
if type(v) == "table" then
- s[n] = k .. "={" .. tabstr(v) .. "}"
+ s[n] = k .. ">" .. tabstr_normal(v)
elseif v == true then
- s[n] = k .. "=true"
+ s[n] = k .. "+" -- "=true"
elseif v then
s[n] = k .. "=" .. v
else
- s[n] = k .. "=false"
+ s[n] = k .. "-" -- "=false"
end
end
- if n == 1 then
+ if n == 0 then
+ return ""
+ elseif n == 1 then
return s[1]
else
- sort(s)
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
return concat(s,",")
end
end
+local function tabstr_flat(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ s[n] = k .. "=" .. v
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
+
+local function tabstr_boolean(t)
+ local s = { }
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
+ if v then
+ s[n] = k .. "+"
+ else
+ s[n] = k .. "-"
+ end
+ end
+ if n == 0 then
+ return ""
+ elseif n == 1 then
+ return s[1]
+ else
+ sort(s) -- costly but needed (occasional wrong hit otherwise)
+ return concat(s,",")
+ end
+end
-- -- saves only a few tens of bytes
--
@@ -74,41 +117,83 @@ local function packdata(data)
local h, t, c = { }, { }, { }
local hh, tt, cc = { }, { }, { }
local nt, ntt = 0, 0
- local function pack_1(v,indexed)
- -- v == table
- local tag = indexed and concat(v," ") or tabstr(v)
+ local function pack_normal(v)
+ local tag = tabstr_normal(v,flat)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_flat(v)
+ local tag = tabstr_flat(v)
local ht = h[tag]
- if not ht then
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
nt = nt + 1
- ht = nt
- t[ht] = v
- h[tag] = ht
- c[ht] = 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_boolean(v)
+ local tag = tabstr_boolean(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+ local function pack_indexed(v)
+ local tag = concat(v," ")
+ local ht = h[tag]
+ if ht then
c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
end
- return ht
end
- local function pack_2(v,indexed)
+ local function pack_final(v)
-- v == number
if c[v] <= criterium then
return t[v]
else
-- compact hash
local hv = hh[v]
- if not hv then
+ if hv then
+ return hv
+ else
ntt = ntt + 1
- hv = ntt
- tt[hv] = t[v]
- hh[v] = hv
- cc[hv] = c[v]
+ tt[ntt] = t[v]
+ hh[v] = ntt
+ cc[ntt] = c[v]
+ return ntt
end
- return hv
end
end
local function success(stage,pass)
if nt == 0 then
- if trace_loading then
+ if trace_loading or trace_packing then
report_otf("pack quality: nothing to pack")
end
return false
@@ -136,35 +221,45 @@ local function packdata(data)
end
data.tables = tt
end
- if trace_loading then
+ if trace_loading or trace_packing then
report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium)
end
return true
else
- if trace_loading then
+ if trace_loading or trace_packing then
report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, nt, threshold)
end
return false
end
end
+ local function packers(pass)
+ if pass == 1 then
+ return pack_normal, pack_indexed, pack_flat, pack_boolean
+ else
+ return pack_final, pack_final, pack_final, pack_final
+ end
+ end
local resources = data.resources
local lookuptypes = resources.lookuptypes
for pass=1,2 do
- local pack = (pass == 1 and pack_1) or pack_2
+ if trace_packing then
+ report_otf("start packing: stage 1, pass %s",pass)
+ end
+ local pack_normal, pack_indexed, pack_flat, pack_boolean = packers(pass)
for unicode, description in next, data.descriptions do
local boundingbox = description.boundingbox
if boundingbox then
- description.boundingbox = pack(boundingbox,true)
+ description.boundingbox = pack_indexed(boundingbox)
end
local slookups = description.slookups
if slookups then
for tag, slookup in next, slookups do
local what = lookuptypes[tag]
if what == "pair" then
- local t = slookup[2] if t then slookup[2] = pack(t,true) end
- local t = slookup[3] if t then slookup[3] = pack(t,true) end
+ local t = slookup[2] if t then slookup[2] = pack_indexed(t) end
+ local t = slookup[3] if t then slookup[3] = pack_indexed(t) end
elseif what ~= "substitution" then
- slookups[tag] = pack(slookup)
+ slookups[tag] = pack_indexed(slookup) -- true is new
end
end
end
@@ -175,12 +270,12 @@ local function packdata(data)
if what == "pair" then
for i=1,#mlookup do
local lookup = mlookup[i]
- local t = lookup[2] if t then lookup[2] = pack(t,true) end
- local t = lookup[3] if t then lookup[3] = pack(t,true) end
+ local t = lookup[2] if t then lookup[2] = pack_indexed(t) end
+ local t = lookup[3] if t then lookup[3] = pack_indexed(t) end
end
elseif what ~= "substitution" then
for i=1,#mlookup do
- mlookup[i] = pack(mlookup[i]) -- true
+ mlookup[i] = pack_indexed(mlookup[i]) -- true is new
end
end
end
@@ -188,7 +283,7 @@ local function packdata(data)
local kerns = description.kerns
if kerns then
for tag, kern in next, kerns do
- kerns[tag] = pack(kern)
+ kerns[tag] = pack_flat(kern)
end
end
local math = description.math
@@ -196,7 +291,7 @@ local function packdata(data)
local kerns = math.kerns
if kerns then
for tag, kern in next, kerns do
- kerns[tag] = pack(kern)
+ kerns[tag] = pack_normal(kern)
end
end
end
@@ -206,12 +301,14 @@ local function packdata(data)
if what == "baselig" then
for _, a in next, anchor do
for k=1,#a do
- a[k] = pack(a[k])
+-- a[k] = pack_normal(a[k])
+ a[k] = pack_indexed(a[k])
end
end
else
for k, v in next, anchor do
- anchor[k] = pack(v)
+-- anchor[k] = pack_normal(v)
+ anchor[k] = pack_indexed(v)
end
end
end
@@ -224,11 +321,11 @@ local function packdata(data)
if rules then
for i=1,#rules do -- was next loop
local rule = rules[i]
- local r = rule.before if r then for i=1,#r do r[i] = pack(r[i]) end end
- local r = rule.after if r then for i=1,#r do r[i] = pack(r[i]) end end
- local r = rule.current if r then for i=1,#r do r[i] = pack(r[i]) end end
- local r = rule.replacements if r then rule.replacements = pack(r) end
- local r = rule.lookups if r then rule.lookups = pack(r) end
+ local r = rule.before if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.after if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.current if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
+ local r = rule.replacements if r then rule.replacements = pack_boolean(r) end
+ local r = rule.lookups if r then rule.lookups = pack_boolean(r) end
end
end
end
@@ -236,13 +333,13 @@ local function packdata(data)
local anchor_to_lookup = resources.anchor_to_lookup
if anchor_to_lookup then
for anchor, lookup in next, anchor_to_lookup do
- anchor_to_lookup[anchor] = pack(lookup)
+ anchor_to_lookup[anchor] = pack_normal(lookup)
end
end
local lookup_to_anchor = resources.lookup_to_anchor
if lookup_to_anchor then
for lookup, anchor in next, lookup_to_anchor do
- lookup_to_anchor[lookup] = pack(anchor)
+ lookup_to_anchor[lookup] = pack_normal(anchor)
end
end
local sequences = resources.sequences
@@ -250,16 +347,16 @@ local function packdata(data)
for feature, sequence in next, sequences do
local flags = sequence.flags
if flags then
- sequence.flags = pack(flags)
+ sequence.flags = pack_normal(flags)
end
local subtables = sequence.subtables
if subtables then
- sequence.subtables = pack(subtables)
+ sequence.subtables = pack_normal(subtables)
end
local features = sequence.features
if features then
for script, feature in next, features do
- features[script] = pack(feature)
+ features[script] = pack_normal(feature)
end
end
end
@@ -269,11 +366,11 @@ local function packdata(data)
for name, lookup in next, lookups do
local flags = lookup.flags
if flags then
- lookup.flags = pack(flags)
+ lookup.flags = pack_normal(flags)
end
local subtables = lookup.subtables
if subtables then
- lookup.subtables = pack(subtables)
+ lookup.subtables = pack_normal(subtables)
end
end
end
@@ -283,7 +380,7 @@ local function packdata(data)
local list = features[what]
if list then
for feature, spec in next, list do
- list[feature] = pack(spec)
+ list[feature] = pack_normal(spec)
end
end
end
@@ -294,27 +391,30 @@ local function packdata(data)
end
if nt > 0 then
for pass=1,2 do
- local pack = (pass == 1 and pack_1) or pack_2
+ if trace_packing then
+ report_otf("start packing: stage 2, pass %s",pass)
+ end
+ local pack_normal, pack_indexed, pack_flat, pack_boolean = packers(pass)
for unicode, description in next, data.descriptions do
local kerns = description.kerns
if kerns then
- description.kerns = pack(kerns)
+ description.kerns = pack_normal(kerns)
end
local math = description.math
if math then
local kerns = math.kerns
if kerns then
- math.kerns = pack(kerns)
+ math.kerns = pack_normal(kerns)
end
end
local anchors = description.anchors
if anchors then
- description.anchors = pack(anchors)
+ description.anchors = pack_normal(anchors)
end
local mlookups = description.mlookups
if mlookups then
for tag, mlookup in next, mlookups do
- mlookups[tag] = pack(mlookup)
+ mlookups[tag] = pack_normal(mlookup)
end
end
end
@@ -325,9 +425,9 @@ local function packdata(data)
if rules then
for i=1,#rules do -- was next loop
local rule = rules[i]
- local r = rule.before if r then rule.before = pack(r) end
- local r = rule.after if r then rule.after = pack(r) end
- local r = rule.current if r then rule.current = pack(r) end
+ local r = rule.before if r then rule.before = pack_normal(r) end
+ local r = rule.after if r then rule.after = pack_normal(r) end
+ local r = rule.current if r then rule.current = pack_normal(r) end
end
end
end
@@ -335,7 +435,7 @@ local function packdata(data)
local sequences = resources.sequences
if sequences then
for feature, sequence in next, sequences do
- sequence.features = pack(sequence.features)
+ sequence.features = pack_normal(sequence.features)
end
end
if not success(2,pass) then
@@ -344,15 +444,15 @@ local function packdata(data)
end
for pass=1,2 do
- local pack = (pass == 1 and pack_1) or pack_2
+ local pack_normal, pack_indexed, pack_flat, pack_boolean = packers(pass)
for unicode, description in next, data.descriptions do
local slookups = description.slookups
if slookups then
- description.slookups = pack(slookups)
+ description.slookups = pack_normal(slookups)
end
local mlookups = description.mlookups
if mlookups then
- description.mlookups = pack(mlookups)
+ description.mlookups = pack_normal(mlookups)
end
end
end
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index 9be307099..3f90da91b 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['font-syn'] = {
-- todo: subs in lookups requests
-local utf = unicode.utf8
local next, tonumber = next, tonumber
local sub, gsub, lower, match, find, lower, upper = string.sub, string.gsub, string.lower, string.match, string.find, string.lower, string.upper
local find, gmatch = string.find, string.gmatch
diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua
index 01d5289f8..34d74d93f 100644
--- a/tex/context/base/font-vf.lua
+++ b/tex/context/base/font-vf.lua
@@ -7,10 +7,13 @@ if not modules then modules = { } end modules ['font-vf'] = {
}
--[[ldx--
-<p>This is very experimental code! Not yet adapted to recent
-changes. This will change.</p>
+<p>This is very experimental code! Not yet adapted to recent changes. This will change.</p>
--ldx]]--
+-- present in the backend but unspecified:
+--
+-- vf.rule vf.special vf.right vf.push vf.down vf.char vf.node vf.fontid vf.pop vf.image vf.nop
+
local next = next
local allocate = utilities.storage.allocate
diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua
index 3deb660ce..0568bcfb5 100644
--- a/tex/context/base/l-dir.lua
+++ b/tex/context/base/l-dir.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-dir'] = {
-- dir.expandname will be merged with cleanpath and collapsepath
-local type = type
+local type, select = type, select
local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
@@ -261,15 +261,15 @@ local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
if onwindows then
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
end
end
local first, middle, last
@@ -329,9 +329,9 @@ if onwindows then
else
function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
if s and s ~= "" then -- we catch nil and false
if str ~= "" then
str = str .. "/" .. s
diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua
index d1ec753b1..f34bed5fd 100644
--- a/tex/context/base/l-file.lua
+++ b/tex/context/base/l-file.lua
@@ -36,25 +36,25 @@ local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = C((noslashes^0 * slashes^1)^1)
local function pathpart(name,default)
- return lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
end
local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
local function basename(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
local function nameonly(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
local function suffixonly(name)
- return lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
end
file.pathpart = pathpart
@@ -85,7 +85,9 @@ local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra capture
local pattern_d = path * rest
function file.splitname(str,splitdrive)
- if splitdrive then
+ if not str then
+ -- error
+ elseif splitdrive then
return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
else
return lpegmatch(pattern_b,str) -- returns path, base, suffix
@@ -93,34 +95,36 @@ function file.splitname(str,splitdrive)
end
function file.splitbase(str)
- return lpegmatch(pattern_d,str) -- returns path, base+suffix
+ return str and lpegmatch(pattern_d,str) -- returns path, base+suffix
end
function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
- else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
end
local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1)
function file.removesuffix(name)
- return lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
end
-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
@@ -137,8 +141,8 @@ end
local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
return filename
elseif criterium == true then
return filename .. "." .. suffix
@@ -184,7 +188,7 @@ local suffix = period * (1-period-slashes)^1 * -1
local pattern = Cs((1-suffix)^0)
function file.replacesuffix(name,suffix)
- if suffix and suffix ~= "" then
+ if name and suffix and suffix ~= "" then
return lpegmatch(pattern,name) .. "." .. suffix
else
return name
@@ -193,10 +197,10 @@ end
--
-local reslasher = lpeg.replacer(S("\\"),"/")
+local reslasher = lpeg.replacer(P("\\"),"/")
function file.reslash(str)
- return lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
end
-- We should be able to use:
@@ -212,7 +216,9 @@ end
-- variant:
function file.is_writable(name)
- if lfs.isdir(name) then
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
local f = io.open(name,"wb")
if f then
@@ -240,24 +246,32 @@ end
local readable = P("r") * Cc(true)
function file.is_readable(name)
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
function file.size(name)
- local a = attributes(name)
- return a and a.size or 0
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
end
function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
- return checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
end
function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
local stripper = Cs(P(fwslash)^0/"" * reslasher)
@@ -265,14 +279,23 @@ local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
-function file.join(...) -- rather dirty
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
return one .. "/" .. two
elseif lpegmatch(isroot,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
return two
else
@@ -281,7 +304,7 @@ function file.join(...) -- rather dirty
elseif one == "" then
return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(reslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat(lst,"/"))
end
end
@@ -310,6 +333,9 @@ local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * C
local absolute = fwslash
function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
if anchor and not lpegmatch(anchors,str) then
str = getcurrentdir() .. "/" .. str
end
@@ -319,7 +345,6 @@ function file.collapsepath(str,anchor)
return lpegmatch(reslasher,str)
end
local starter, oldelements = lpegmatch(splitstarter,str)
--- inspect(oldelements)
local newelements = { }
local i = #oldelements
while i > 0 do
@@ -373,11 +398,13 @@ local whatever = P("-")^0 / ""
local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
function file.robustname(str,strict)
- str = lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
- else
- return str
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
end
end
@@ -385,7 +412,9 @@ file.readdata = io.loaddata
file.savedata = io.savedata
function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+ if oldname and newname then
+ file.savedata(newname,io.loaddata(oldname))
+ end
end
-- also rewrite previous
@@ -406,11 +435,11 @@ lpeg.patterns.rootbased = rootbased
-- ./name ../name /name c: :// name/name
function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+ return filename and lpegmatch(qualified,filename) ~= nil
end
function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
+ return filename and lpegmatch(rootbased,filename) ~= nil
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -432,8 +461,10 @@ end
-- for myself:
function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
end
-- local debuglist = {
diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua
index ec628b5e0..e7bc23642 100644
--- a/tex/context/base/l-io.lua
+++ b/tex/context/base/l-io.lua
@@ -328,7 +328,7 @@ function io.readstring(f,n,m)
f:seek("set",n)
n = m
end
- local str = gsub(f:read(n),"%z","")
+ local str = gsub(f:read(n),"\000","")
return str
end
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
index a5fdec765..b00d02f9f 100644
--- a/tex/context/base/l-lpeg.lua
+++ b/tex/context/base/l-lpeg.lua
@@ -6,9 +6,11 @@ if not modules then modules = { } end modules ['l-lpeg'] = {
license = "see context related readme files"
}
-
-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
+
local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
@@ -60,12 +62,9 @@ local byte, char, gmatch, format = string.byte, string.char, string.gmatch, stri
lpeg.patterns = lpeg.patterns or { } -- so that we can share
local patterns = lpeg.patterns
-local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
local lpegtype, lpegmatch = lpeg.type, lpeg.match
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
local anything = P(1)
local endofstring = P(-1)
local alwaysmatched = P(true)
@@ -91,9 +90,12 @@ local utfbom_8 = P('\239\187\191')
local utfbom = utfbom_32_be + utfbom_32_le
+ utfbom_16_be + utfbom_16_le
+ utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
local utf8next = R("\128\191")
@@ -103,6 +105,7 @@ patterns.utf8three = R("\224\239") * utf8next * utf8next
patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
patterns.utfbom = utfbom
patterns.utftype = utftype
+patterns.utfoffset = utfoffset
local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
@@ -115,6 +118,22 @@ patterns.validutf8char = validutf8char
local eol = S("\n\r")
local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * P(-1) / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
+
+patterns.stripper = stripper
+patterns.collapser = collapser
patterns.digit = digit
patterns.sign = sign
@@ -137,13 +156,8 @@ patterns.letter = patterns.lowercase + patterns.uppercase
patterns.space = space
patterns.tab = P("\t")
patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = eol
-patterns.spacer = spacer
-patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - spacer
-patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
patterns.commaspacer = P(",") * spacer^0
@@ -156,8 +170,8 @@ patterns.squote = squote
patterns.dquote = dquote
patterns.nosquote = (escaped + (1-squote))^0
patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
@@ -165,16 +179,11 @@ patterns.singlequoted = squote * patterns.nosquote * squote
patterns.doublequoted = dquote * patterns.nodquote * dquote
patterns.quoted = patterns.doublequoted + patterns.singlequoted
+patterns.propername = R("AZ","az","__") * R("09","AZ","az", "__")^0 * P(-1)
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
local function anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) }
end
@@ -237,10 +246,10 @@ function string.splitup(str,separator)
return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
---~ local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
---~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
---~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
---~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
local cache = { }
@@ -273,12 +282,6 @@ local content = (empty + nonempty)^1
patterns.textline = content
---~ local linesplitter = Ct(content^0)
---~
---~ function string.splitlines(str)
---~ return lpegmatch(linesplitter,str)
---~ end
-
local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
@@ -287,66 +290,7 @@ function string.splitlines(str)
return lpegmatch(linesplitter,str)
end
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return lpegmatch(utflinesplitter,str or "")
-end
-
-local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
-local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
-
-function string.utfsplit(str,ignorewhitespace) -- new
- if ignorewhitespace then
- return lpegmatch(utfcharsplitter_iws,str or "")
- else
- return lpegmatch(utfcharsplitter_ows,str or "")
- end
-end
-
--- inspect(string.utfsplit("a b c d"))
--- inspect(string.utfsplit("a b c d",true))
-
--- -- alternative 1: 0.77
---
--- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
---
--- function string.utflength(str)
--- return #lpegmatch(utfcharcounter,str or "")
--- end
---
--- -- alternative 2: 1.70
---
--- local n = 0
---
--- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
---
--- function string.utflength(str)
--- n = 0
--- lpegmatch(utfcharcounter,str or "")
--- return n
--- end
---
--- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
-
-local n = 0
-
-local utfcharcounter = utfbom^-1 * Cs ( (
- Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
- + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
- + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
- + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
-)^0 )
-
-function string.utflength(str)
- n = 0
- lpegmatch(utfcharcounter,str or "")
- return n
-end
-
---~ lpeg.splitters = cache -- no longer public
+-- lpeg.splitters = cache -- no longer public
local cache = { }
@@ -372,7 +316,7 @@ function string.checkedsplit(str,separator)
return lpegmatch(c,str)
end
---~ from roberto's site:
+-- from roberto's site:
local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
@@ -430,8 +374,11 @@ end
-- Just for fun I looked at the used bytecode and
-- p = (p and p + pp) or pp gets one more (testset).
-function lpeg.replacer(one,two,makefunction)
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
local pattern
+ local u = isutf and utf8char or 1
if type(one) == "table" then
local no = #one
local p = P(false)
@@ -439,24 +386,21 @@ function lpeg.replacer(one,two,makefunction)
for k, v in next, one do
p = p + P(k) / v
end
- pattern = Cs((p + 1)^0)
+ pattern = Cs((p + u)^0)
elseif no == 1 then
local o = one[1]
one, two = P(o[1]), o[2]
-- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two + 1)^0)
+ pattern = Cs((one/two + u)^0)
else
for i=1,no do
local o = one[i]
p = p + P(o[1]) / o[2]
end
- pattern = Cs((p + 1)^0)
+ pattern = Cs((p + u)^0)
end
else
- one = P(one)
- two = two or ""
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two +1)^0)
+ pattern = Cs((P(one)/(two or "") + u)^0)
end
if makefunction then
return function(str)
@@ -470,14 +414,20 @@ end
function lpeg.finder(lst,makefunction)
local pattern
if type(lst) == "table" then
- local p = P(false)
- for i=1,#lst do
- p = p + P(lst[i])
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
end
- pattern = (p + 1)^0
else
- pattern = (P(lst) + 1)^0
+ pattern = P(lst)
end
+ pattern = (1-pattern)^0 * pattern
if makefunction then
return function(str)
return lpegmatch(pattern,str)
@@ -518,21 +468,21 @@ function lpeg.balancer(left,right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
---~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
---~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
---~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
---~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
---~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
---~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
---~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
---~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
-
---~ -- slower:
---~
---~ function lpeg.counter(pattern)
---~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
---~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
---~ end
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
local nany = utf8char/""
@@ -543,65 +493,12 @@ function lpeg.counter(pattern)
end
end
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #lpegmatch(p,str)
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and s or p,str)
-end
-
-- utf extensies
+local utfcharacters = utf and utf.characters or string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+local utfchar = utf and utf.char or (unicode and unicode.utf8 and unicode.utf8.char)
+
lpeg.UP = lpeg.P
if utfcharacters then
@@ -640,8 +537,6 @@ end
local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
function lpeg.UR(str,more)
local first, last
if type(str) == "number" then
@@ -672,16 +567,16 @@ end
-- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
---~ lpeg.print(lpeg.R("ab","cd","gh"))
---~ lpeg.print(lpeg.P("a","b","c"))
---~ lpeg.print(lpeg.S("a","b","c"))
+-- lpeg.print(lpeg.R("ab","cd","gh"))
+-- lpeg.print(lpeg.P("a","b","c"))
+-- lpeg.print(lpeg.S("a","b","c"))
---~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
---~ print(lpeg.count("äáàa",lpeg.UP("áà")))
---~ print(lpeg.count("äáàa",lpeg.US("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR("aá")))
---~ print(lpeg.count("äáàa",lpeg.UR("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
function lpeg.is_lpeg(p)
return p and lpegtype(p) == "pattern"
@@ -703,12 +598,30 @@ end
-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
-- loop back from the end cq. prepend.
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
function lpeg.append(list,pp,delayed,checked)
local p = pp
if #list > 0 then
- local keys = fastcopy(list)
+ local keys = copyindexed(list)
sort(keys)
for i=#keys,1,-1 do
local k = keys[i]
@@ -805,8 +718,10 @@ end
local function make(t)
local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = t[k]
if not p then
if next(v) then
p = P(k) * make(v)
@@ -824,7 +739,7 @@ local function make(t)
return p
end
-function lpeg.utfchartabletopattern(list)
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
local tree = { }
for i=1,#list do
local t = tree
@@ -856,20 +771,8 @@ end
-- utfchar(0x205F), -- math thinspace
-- } )
--- handy from within tex:
-
-local lpegmatch = lpeg.match
-
-local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
-
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-
--- strips leading and trailing spaces and collapsed all other spaces
-
-local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
-function string.collapsespaces(str)
- return lpegmatch(pattern,str)
-end
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
diff --git a/tex/context/base/l-lua.lua b/tex/context/base/l-lua.lua
new file mode 100644
index 000000000..8ac351417
--- /dev/null
+++ b/tex/context/base/l-lua.lua
@@ -0,0 +1,107 @@
+if not modules then modules = { } end modules ['l-lua'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- compatibility hacks ... try to avoid usage
+
+local major, minor = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+
+_MAJORVERSION = tonumber(major) or 5
+_MINORVERSION = tonumber(minor) or 1
+
+-- basics:
+
+if loadstring then
+
+ local loadnormal = load
+
+ function load(first,...)
+ if type(first) == "string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+
+else
+
+ loadstring = load
+
+end
+
+-- table:
+
+-- Starting with version 5.2 Lua no longer provide ipairs, which makes
+-- sense. As we already used the for loop and # in most places the
+-- impact on ConTeXt was not that large; the remaining ipairs already
+-- have been replaced. In a similar fashion we also hardly used pairs.
+--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- The unpack function has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+
+ table.unpack = _G.unpack
+
+elseif not unpack then
+
+ _G.unpack = table.unpack
+
+end
+
+-- package:
+
+-- if not package.seachers then
+--
+-- package.searchers = package.loaders -- 5.2
+--
+-- elseif not package.loaders then
+--
+-- package.loaders = package.searchers
+--
+-- end
+
+if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type
+
+ package.loaders = package.searchers
+
+end
diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua
index a4dbe3bdf..f974f2582 100644
--- a/tex/context/base/l-number.lua
+++ b/tex/context/base/l-number.lua
@@ -16,10 +16,129 @@ local lpegmatch = lpeg.match
number = number or { }
local number = number
--- a,b,c,d,e,f = number.toset(100101)
+if bit32 then
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p)
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ }
+
+ function number.tobitstring(b,m)
+ -- if really needed we can speed this one up
+ -- because small numbers need less extraction
+ local n = 32
+ for i=0,31 do
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
end
function number.toevenhex(n)
@@ -31,104 +150,57 @@ function number.toevenhex(n)
end
end
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
--
-- for i=1,1000000 do
-- local a,b,c,d,e,f,g,h = number.toset(12345678)
-- local a,b,c,d = number.toset(1234)
-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
-- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-local one = lpeg.C(1-lpeg.S(''))^1
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
function number.toset(n)
return lpegmatch(one,tostring(n))
end
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
local m = n % 2
+ local n = floor(n/2)
if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
- end
- return t
-end
-
---~ http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
-
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
-
-function number.setbit(x, p)
- return (x % (p + p) >= p) and x or x + p
-end
-
-function number.clearbit(x, p)
- return (x % (p + p) >= p) and x - p or x
-end
-
---~ function number.tobitstring(n)
---~ if n == 0 then
---~ return "0"
---~ else
---~ local t = { }
---~ while n > 0 do
---~ insert(t,1,n % 2 > 0 and 1 or 0)
---~ n = floor(n/2)
---~ end
---~ return concat(t)
---~ end
---~ end
-
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+ return bits(n, i+1, i, ...)
else
- return "00000000"
+ return bits(n, i+1, ...)
end
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ return ...
end
end
---~ print(number.tobitstring(8))
---~ print(number.tobitstring(14))
---~ print(number.tobitstring(66))
---~ print(number.tobitstring(0x00))
---~ print(number.tobitstring(0xFF))
---~ print(number.tobitstring(46260767936,8))
---~ print(#number.tobitstring(46260767936,6))
-
-function number.valid(str,default)
- return tonumber(str) or default or nil
+function number.bits(n)
+ return { bits(n,1) }
end
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index 857acb019..597ce3462 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -7,40 +7,46 @@ if not modules then modules = { } end modules ['l-string'] = {
}
local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-
--- some functions may disappear as they are not used anywhere
-
-if not string.split then
-
- -- this will be overloaded by a faster lpeg variant
-
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
- end
- end
- return t
- end
-
-end
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
+
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
+
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
+
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
+
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+ return lpegmatch(unquoted,str) or str
end
---~ function stringunquoted(str)
---~ if find(str,"^[\'\"]") then
---~ return sub(str,2,-2)
---~ else
---~ return str
---~ end
---~ end
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function string.quoted(str)
return format("%q",str) -- always "
@@ -63,65 +69,112 @@ function string.limit(str,n,sentinel) -- not utf proof
end
end
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+local stripper = patterns.stripper
+local collapser = patterns.collapser
function string.strip(str)
return lpegmatch(stripper,str) or ""
end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1)
+
function string.is_empty(str)
- return not find(str,"%S")
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
if str == "" then
return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
- end
- if strict then
- return "^" .. str .. "$"
- else
- return str
- end
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
end
end
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
function string.valid(str,default)
return (type(str) == "string" and str ~= "" and str) or default or nil
end
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
-
-- handy fallback
string.itself = function(s) return s end
@@ -133,3 +186,16 @@ local pattern = Ct(C(1)^0) -- string and not utf !
function string.totable(str)
return lpegmatch(pattern,str)
end
+
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 62e0cae14..b668281a8 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -6,68 +6,23 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
local table, string = table, string
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local getinfo = debug.getinfo
-
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Hm, actually ipairs was retained, but we no longer use it anyway.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
-
-if not ipairs then
-
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
-
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
-
- function ipairs(a)
- return iterate, a, 0
- end
-
-end
-
-if not pairs then
-
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
-
- function pairs(t)
- return next, t -- , nil
- end
-
-end
-
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
-
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local floor = math.floor
-- extra functions, some might go (when not used)
+local stripper = patterns.stripper
+
function table.strip(tab)
local lst, l = { }, 0
for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
-- skip this one
else
@@ -176,7 +131,7 @@ local function sortedhash(t)
end
table.sortedhash = sortedhash
-table.sortedpairs = sortedhash
+table.sortedpairs = sortedhash -- obsolete
function table.append(t,list)
local n = #t
@@ -200,31 +155,63 @@ function table.prepend(t, list)
return t
end
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
t[k] = v
end
end
return t
end
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
function table.merged(...)
- local tmp, lst = { }, { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
- tmp[k] = v
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
end
end
- return tmp
+ return t
end
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
function table.imerge(t, ...)
- local lst, nt = { ... }, #t
- for i=1,#lst do
- local nst = lst[i]
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
nt = nt + 1
t[nt] = nst[j]
@@ -233,10 +220,22 @@ function table.imerge(t, ...)
return t
end
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
function table.imerged(...)
- local tmp, ntmp, lst = { }, 0, {...}
- for i=1,#lst do
- local nst = lst[i]
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
ntmp = ntmp + 1
tmp[ntmp] = nst[j]
@@ -248,7 +247,7 @@ end
local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
- for k,v in next, old do
+ for k, v in next, old do
if type(v) == "table" then
new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
@@ -302,7 +301,7 @@ end
table.fastcopy = fastcopy
table.copy = copy
-function table.derive(parent)
+function table.derive(parent) -- for the moment not public
local child = { }
if parent then
setmetatable(child,{ __index = parent })
@@ -383,6 +382,13 @@ end
-- problem: there no good number_to_string converter with the best resolution
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
local function dummy() end
local function do_serialize(root,name,depth,level,indexed)
@@ -392,14 +398,14 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s{",depth))
else
local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
+ if tn == "number" then
if hexify then
handle(format("%s[0x%04X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
handle(format("%s%s={",depth,name))
else
handle(format("%s[%q]={",depth,name))
@@ -425,7 +431,6 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
--- if not root[k] then
if root[k] == nil then
last = k - 1
break
@@ -473,7 +478,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
+ handle(format('%s load(%q),',depth,dump(v)))
else
handle(format('%s "function",',depth))
end
@@ -485,7 +490,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s __p__=nil,",depth))
end
elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
else
@@ -497,7 +502,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%04X,",depth,k,v))
else
@@ -512,7 +517,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "string" then
if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,v))
else
@@ -520,13 +525,13 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,v))
else
@@ -534,7 +539,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
handle(format("%s [%q]=%q,",depth,k,v))
@@ -542,7 +547,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "table" then
if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={},",depth,k))
else
@@ -550,7 +555,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
handle(format("%s [%q]={},",depth,k))
@@ -558,15 +563,15 @@ local function do_serialize(root,name,depth,level,indexed)
elseif inline then
local st = simple_table(v)
if st then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
@@ -578,15 +583,15 @@ local function do_serialize(root,name,depth,level,indexed)
do_serialize(v,k,depth,level+1)
end
elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%s,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%s,",depth,k,tostring(v)))
@@ -595,30 +600,30 @@ local function do_serialize(root,name,depth,level,indexed)
if functions then
local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
@@ -699,14 +704,14 @@ local function serialize(_handle,root,name,specification) -- handle wins
handle("}")
end
---~ name:
---~
---~ true : return { }
---~ false : { }
---~ nil : t = { }
---~ string : string = { }
---~ 'return' : return { }
---~ number : [number] = { }
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
function table.serialize(root,name,specification)
local t, n = { }, 0
@@ -795,7 +800,7 @@ table.flattened = flattened
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
- f = { }
+ f = { } -- this one can become obsolete
end
for i=1,#t do
local v = t[i]
@@ -824,7 +829,7 @@ local function are_equal(a,b,n,m) -- indexed
local ai, bi = a[i], b[i]
if ai==bi then
-- same
- elseif type(ai)=="table" and type(bi)=="table" then
+ elseif type(ai) == "table" and type(bi) == "table" then
if not are_equal(ai,bi) then
return false
end
@@ -859,10 +864,10 @@ table.are_equal = are_equal
-- maybe also make a combined one
-function table.compact(t)
+function table.compact(t) -- remove empty tables, assumes subtables
if t then
- for k,v in next, t do
- if not next(v) then
+ for k, v in next, t do
+ if not next(v) then -- no type checking
t[k] = nil
end
end
@@ -901,7 +906,7 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirror(t) -- hash
+function table.mirrored(t) -- hash
local n = { }
for k, v in next, t do
n[v] = k
@@ -924,6 +929,17 @@ function table.reversed(t)
end
end
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
function table.sequenced(t,sep) -- hash only
if t then
local s, n = { }, 0
diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua
index 7fd380b88..7c452ef8f 100644
--- a/tex/context/base/l-unicode.lua
+++ b/tex/context/base/l-unicode.lua
@@ -10,29 +10,45 @@ if not modules then modules = { } end modules ['l-unicode'] = {
-- todo: utf.sub replacement (used in syst-aux)
-local concat = table.concat
+-- we put these in the utf namespace:
+
+utf = utf or (unicode and unicode.utf8) or { }
+
+utf.characters = utf.characters or string.utfcharacters
+utf.values = utf.values or string.utfvalues
+
+-- string.utfvalues
+-- string.utfcharacters
+-- string.characters
+-- string.characterpairs
+-- string.bytes
+-- string.bytepairs
+
local type = type
-local P, C, R, Cs, Ct, Cmt = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt
+local char, byte, format, sub = string.char, string.byte, string.format, string.sub
+local concat = table.concat
+local P, C, R, Cs, Ct, Cmt, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local utftype = patterns.utftype
-local char, byte, find, bytepairs, utfvalues, format, sub = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format, string.sub
-local utfsplitlines = string.utfsplitlines
-if not unicode then
+local bytepairs = string.bytepairs
- unicode = { }
+local finder = lpeg.finder
+local replacer = lpeg.replacer
-end
-
-local unicode = unicode
+local utfvalues = utf.values
+local utfgmatch = utf.gmatch -- not always present
-utf = utf or unicode.utf8
+local p_utftype = patterns.utftype
+local p_utfoffset = patterns.utfoffset
+local p_utf8char = patterns.utf8char
+local p_utf8byte = patterns.utf8byte
+local p_utfbom = patterns.utfbom
+local p_newline = patterns.newline
+local p_whitespace = patterns.whitespace
-if not utf then
+if not unicode then
- utf8 = { }
- unicode.utf8 = utf8
- utf = utf8
+ unicode = { utf = utf } -- for a while
end
@@ -89,64 +105,13 @@ if not utf.byte then
end
-if not utf.sub then
-
- local utf8char = patterns.utf8char
-
- -- inefficient as lpeg just copies ^n
-
- -- local function sub(str,start,stop)
- -- local pattern = utf8char^-(start-1) * C(utf8char^-(stop-start+1))
- -- inspect(pattern)
- -- return lpegmatch(pattern,str) or ""
- -- end
-
- local b, e, n, first, last = 0, 0, 0, 0, 0
-
- local function slide(s,p)
- n = n + 1
- if n == first then
- b = p
- if not last then
- return nil
- end
- end
- if n == last then
- e = p
- return nil
- else
- return p
- end
- end
-
- local pattern = Cmt(utf8char,slide)^0
-
- function utf.sub(str,start,stop) -- todo: from the end
- if not start then
- return str
- end
- b, e, n, first, last = 0, 0, 0, start, stop
- lpegmatch(pattern,str)
- if not stop then
- return sub(str,b)
- else
- return sub(str,b,e)
- end
- end
-
- -- print(utf.sub("Hans Hagen is my name"))
- -- print(utf.sub("Hans Hagen is my name",5))
- -- print(utf.sub("Hans Hagen is my name",5,10))
-
-end
-
local utfchar, utfbyte = utf.char, utf.byte
-- As we want to get rid of the (unmaintained) utf library we implement our own
-- variants (in due time an independent module):
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
end
local toentities = Cs (
@@ -257,7 +222,7 @@ local pattern = P("\254\255") * Cs( (
+ one
)^1 )
-function string.toutf(s)
+function string.toutf(s) -- in string namespace
return lpegmatch(pattern,s) or s -- todo: utf32
end
@@ -273,26 +238,269 @@ local validatedutf = Cs (
patterns.validatedutf = validatedutf
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.is_valid(str)
+ return type(str) == "string" and lpegmatch(validatedutf,str) or false
end
+if not utf.len then
-utf.length = string.utflength
-utf.split = string.utfsplit
-utf.splitines = string.utfsplitlines
-utf.valid = string.validutf
+ -- -- alternative 1: 0.77
+ --
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ --
+ -- function utf.len(str)
+ -- return #lpegmatch(utfcharcounter,str or "")
+ -- end
+ --
+ -- -- alternative 2: 1.70
+ --
+ -- local n = 0
+ --
+ -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ --
+ -- function utf.length(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+ --
+ -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+ -- local n = 0
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * (
+ -- -- patterns.utf8one ^1 * Cc(1)
+ -- -- + patterns.utf8two ^1 * Cc(2)
+ -- -- + patterns.utf8three^1 * Cc(3)
+ -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end
+ -- -- )^0 ) -- just as many captures as below
+ --
+ -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( (
+ -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end))
+ -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end))
+ -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end))
+ -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end))
+ -- -- )^0 ) -- not interesting as it creates strings but sometimes faster
+ --
+ -- -- The best so far:
+ --
+ -- local utfcharcounter = utfbom^-1 * P ( (
+ -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+ -- )^0 )
+
+ -- function utf.len(str)
+ -- n = 0
+ -- lpegmatch(utfcharcounter,str or "")
+ -- return n
+ -- end
+
+ local n, f = 0, 1
+
+ local utfcharcounter = patterns.utfbom^-1 * Cmt (
+ Cc(1) * patterns.utf8one ^1
+ + Cc(2) * patterns.utf8two ^1
+ + Cc(3) * patterns.utf8three^1
+ + Cc(4) * patterns.utf8four ^1,
+ function(_,t,d) -- due to Cc no string captures, so faster
+ n = n + (t - f)/d
+ f = t
+ return true
+ end
+ )^0
+
+ function utf.len(str)
+ n, f = 0, 1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
-if not utf.len then
- utf.len = utf.length
end
--- a replacement for simple gsubs:
+utf.length = utf.len
+
+if not utf.sub then
+
+ -- inefficient as lpeg just copies ^n
+
+ -- local function sub(str,start,stop)
+ -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1))
+ -- inspect(pattern)
+ -- return lpegmatch(pattern,str) or ""
+ -- end
+
+ -- local b, e, n, first, last = 0, 0, 0, 0, 0
+ --
+ -- local function slide(s,p)
+ -- n = n + 1
+ -- if n == first then
+ -- b = p
+ -- if not last then
+ -- return nil
+ -- end
+ -- end
+ -- if n == last then
+ -- e = p
+ -- return nil
+ -- else
+ -- return p
+ -- end
+ -- end
+ --
+ -- local pattern = Cmt(p_utf8char,slide)^0
+ --
+ -- function utf.sub(str,start,stop) -- todo: from the end
+ -- if not start then
+ -- return str
+ -- end
+ -- b, e, n, first, last = 0, 0, 0, start, stop
+ -- lpegmatch(pattern,str)
+ -- if not stop then
+ -- return sub(str,b)
+ -- else
+ -- return sub(str,b,e-1)
+ -- end
+ -- end
+
+ -- print(utf.sub("Hans Hagen is my name"))
+ -- print(utf.sub("Hans Hagen is my name",5))
+ -- print(utf.sub("Hans Hagen is my name",5,10))
+
+ local utflength = utf.length
+
+ -- also negative indices, upto 10 times slower than a c variant
+
+ local b, e, n, first, last = 0, 0, 0, 0, 0
+
+ local function slide_zero(s,p)
+ n = n + 1
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_one(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ end
+ if n >= last then
+ e = p - 1
+ else
+ return p
+ end
+ end
+
+ local function slide_two(s,p)
+ n = n + 1
+ if n == first then
+ b = p
+ else
+ return true
+ end
+ end
+
+ local pattern_zero = Cmt(p_utf8char,slide_zero)^0
+ local pattern_one = Cmt(p_utf8char,slide_one )^0
+ local pattern_two = Cmt(p_utf8char,slide_two )^0
+
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start == 0 then
+ start = 1
+ end
+ if not stop then
+ if start < 0 then
+ local l = utflength(str) -- we can inline this function if needed
+ start = l + start
+ else
+ start = start - 1
+ end
+ b, n, first = 0, 0, start
+ lpegmatch(pattern_two,str)
+ if n >= first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start < 0 or stop < 0 then
+ local l = utf.length(str)
+ if start < 0 then
+ start = l + start
+ if start <= 0 then
+ start = 1
+ else
+ start = start + 1
+ end
+ end
+ if stop < 0 then
+ stop = l + stop
+ if stop == 0 then
+ stop = 1
+ else
+ stop = stop + 1
+ end
+ end
+ end
+ if start > stop then
+ return ""
+ elseif start > 1 then
+ b, e, n, first, last = 0, 0, 0, start - 1, stop
+ lpegmatch(pattern_one,str)
+ if n >= first and e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ else
+ b, e, n, last = 1, 0, 0, stop
+ lpegmatch(pattern_zero,str)
+ if e == 0 then
+ e = #str
+ end
+ return sub(str,b,e)
+ end
+ end
-local utf8char = patterns.utf8char
+ -- local n = 100000
+ -- local str = string.rep("123456àáâãäå",100)
+ --
+ -- for i=-15,15,1 do
+ -- for j=-15,15,1 do
+ -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then
+ -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j))
+ -- end
+ -- end
+ -- if utf.xsub(str,i) ~= utf.sub(str,i) then
+ -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i))
+ -- end
+ -- end
+
+ -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7))
+ -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7))
+ -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9))
+ -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 ))
+ -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 ))
+ -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0))
+ -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4))
+ -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0))
+ -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0))
+ -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3))
+ -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3))
+ -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 ))
+
+end
+
+-- a replacement for simple gsubs:
function utf.remapper(mapping)
- local pattern = Cs((utf8char/mapping)^0)
+ local pattern = Cs((p_utf8char/mapping)^0)
return function(str)
if not str or str == "" then
return ""
@@ -305,158 +513,113 @@ end
-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
-- print(remap("abcd 1234 abcd"))
+--
+
+function utf.replacer(t) -- no precheck, always string builder
+ local r = replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+
+function utf.subtituter(t) -- with precheck and no building if no match
+ local f = finder (t)
+ local r = replacer(t,false,false,true)
+ return function(str)
+ local i = lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i > #str then
+ return str
+ else
+ -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower
+ return lpegmatch(r,str)
+ end
+ end
+end
+
+-- inspect(utf.split("a b c d"))
+-- inspect(utf.split("a b c d",true))
+
+local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0)
+local utfcharsplitter_raw = Ct(C(p_utf8char)^0)
+
+patterns.utflinesplitter = utflinesplitter
+
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+function utf.split(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+function utf.totable(str) -- keeps bom
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
-- 2 FE FF UTF-16-big-endian
-- 3 FF FE 00 00 UTF-32-little-endian
-- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
-}
-
+--
-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
- else
- f:seek('set')
- return 0
+-- utf.name = {
+-- [0] = 'utf-8',
+-- [1] = 'utf-16-le',
+-- [2] = 'utf-16-be',
+-- [3] = 'utf-32-le',
+-- [4] = 'utf-32-be'
+-- }
+--
+-- function utf.magic(f)
+-- local str = f:read(4)
+-- if not str then
+-- f:seek('set')
+-- return 0
+-- -- elseif find(str,"^%z%z\254\255") then -- depricated
+-- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+-- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+-- return 4
+-- -- elseif find(str,"^\255\254%z%z") then -- depricated
+-- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+-- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+-- return 3
+-- elseif find(str,"^\254\255") then
+-- f:seek('set',2)
+-- return 2
+-- elseif find(str,"^\255\254") then
+-- f:seek('set',2)
+-- return 1
+-- elseif find(str,"^\239\187\191") then
+-- f:seek('set',3)
+-- return 0
+-- else
+-- f:seek('set')
+-- return 0
+-- end
+-- end
+
+function utf.magic(f) -- not used
+ local str = f:read(4) or ""
+ local off = lpegmatch(p_utfoffset,str)
+ if off < 4 then
+ f:seek('set',off)
end
+ return lpegmatch(p_utftype,str)
end
---~ function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
---~ local result, tmp, n, m, p, r, t = { }, { }, 0, 0, 0, 0, 0 -- we reuse tmp
---~ -- lf | cr | crlf / (cr:13, lf:10)
---~ local function doit() -- inline this
---~ if n == 10 then
---~ if p ~= 13 then
---~ if t > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t)
---~ t = 0
---~ end
---~ p = 0
---~ end
---~ elseif n == 13 then
---~ if t > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t)
---~ t = 0
---~ end
---~ p = n
---~ else
---~ t = t + 1
---~ tmp[t] = utfchar(n)
---~ p = 0
---~ end
---~ end
---~ for l,r in bytepairs(str) do
---~ if r then
---~ if endian then -- maybe make two loops
---~ n = 256*l + r
---~ else
---~ n = 256*r + l
---~ end
---~ if m > 0 then
---~ n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
---~ m = 0
---~ doit()
---~ elseif n >= 0xD800 and n <= 0xDBFF then
---~ m = n
---~ else
---~ doit()
---~ end
---~ end
---~ end
---~ if t > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t) -- we reused tmp, hence t
---~ end
---~ return result
---~ end
-
---~ function unicode.utf32_to_utf8(str, endian)
---~ local result, tmp, n, m, p, r, t = { }, { }, 0, -1, 0, 0, 0
---~ -- lf | cr | crlf / (cr:13, lf:10)
---~ local function doit() -- inline this
---~ if n == 10 then
---~ if p ~= 13 then
---~ if t > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t)
---~ t = 0
---~ end
---~ p = 0
---~ end
---~ elseif n == 13 then
---~ if t > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t)
---~ t = 0
---~ end
---~ p = n
---~ else
---~ t = t + 1
---~ tmp[t] = utfchar(n)
---~ p = 0
---~ end
---~ end
---~ for a,b in bytepairs(str) do
---~ if a and b then
---~ if m < 0 then
---~ if endian then -- maybe make two loops
---~ m = 256*256*256*a + 256*256*b
---~ else
---~ m = 256*b + a
---~ end
---~ else
---~ if endian then -- maybe make two loops
---~ n = m + 256*a + b
---~ else
---~ n = m + 256*256*256*b + 256*256*a
---~ end
---~ m = -1
---~ doit()
---~ end
---~ else
---~ break
---~ end
---~ end
---~ if #tmp > 0 then
---~ r = r + 1
---~ result[r] = concat(tmp,"",1,t) -- we reused tmp, hence t
---~ end
---~ return result
---~ end
-
local function utf16_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -484,7 +647,7 @@ end
local function utf16_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -512,7 +675,7 @@ end
local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -537,7 +700,7 @@ end
local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(t)
+ t = lpegmatch(utflinesplitter,t)
end
local result = { } -- we reuse result
for i=1,#t do
@@ -560,20 +723,20 @@ local function utf32_to_utf8_le(t)
return t
end
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
+utf.utf32_to_utf8_be = utf32_to_utf8_be
+utf.utf32_to_utf8_le = utf32_to_utf8_le
+utf.utf16_to_utf8_be = utf16_to_utf8_be
+utf.utf16_to_utf8_le = utf16_to_utf8_le
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+function utf.utf8_to_utf8(t)
+ return type(t) == "string" and lpegmatch(utflinesplitter,t) or t
end
-function unicode.utf16_to_utf8(t,endian)
+function utf.utf16_to_utf8(t,endian)
return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
end
-function unicode.utf32_to_utf8(t,endian)
+function utf.utf32_to_utf8(t,endian)
return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
end
@@ -599,7 +762,7 @@ local function big(c)
end
end
--- function unicode.utf8_to_utf16(str,littleendian)
+-- function utf.utf8_to_utf16(str,littleendian)
-- if littleendian then
-- return char(255,254) .. utfgsub(str,".",little)
-- else
@@ -610,7 +773,7 @@ end
local _, l_remap = utf.remapper(little)
local _, b_remap = utf.remapper(big)
-function unicode.utf8_to_utf16(str,littleendian)
+function utf.utf8_to_utf16(str,littleendian)
if littleendian then
return char(255,254) .. lpegmatch(l_remap,str)
else
@@ -618,27 +781,67 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+-- function utf.tocodes(str,separator) -- can be sped up with an lpeg
+-- local t, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- t[n] = format("0x%04X",u)
+-- end
+-- return concat(t,separator or " ")
+-- end
+
+local pattern = Cs (
+ (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) *
+ (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
end
-function unicode.ustring(s)
+function utf.ustring(s)
return format("U+%05X",type(s) == "number" and s or utfbyte(s))
end
-function unicode.xstring(s)
+function utf.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
--
-local pattern = Ct(C(patterns.utf8char)^0)
+local p_nany = p_utf8char / ""
+
+if utfgmatch then
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function utf.count(str,what)
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + p_nany)^0)
+ cache[p] = p
+ end
+ return #lpegmatch(p,str)
+ else -- 4 times slower but still faster than / function
+ return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
+ end
+ end
-function utf.totable(str)
- return lpegmatch(pattern,str)
end
+
+-- maybe also register as string.utf*
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index eaedcd69a..02a33c181 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -17,7 +17,6 @@ if not modules then modules = { } end modules ['lang-ini'] = {
--~ lang:hyphenation(string) string = lang:hyphenation() lang:clear_hyphenation()
local type, tonumber = type, tonumber
-local utf = unicode.utf8
local utfbyte = utf.byte
local format, gsub = string.format, string.gsub
local concat, sortedkeys, sortedpairs = table.concat, table.sortedkeys, table.sortedpairs
diff --git a/tex/context/base/lang-url.lua b/tex/context/base/lang-url.lua
index 3b354216a..35381e672 100644
--- a/tex/context/base/lang-url.lua
+++ b/tex/context/base/lang-url.lua
@@ -6,10 +6,7 @@ if not modules then modules = { } end modules ['lang-url'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
-local utfbyte, utfchar = utf.byte, utf.char
+local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char
context = context
diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua
index c5bc75ca2..84d6107d4 100644
--- a/tex/context/base/lang-wrd.lua
+++ b/tex/context/base/lang-wrd.lua
@@ -6,8 +6,8 @@ if not modules then modules = { } end modules ['lang-wrd'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-local lower, utfchar = string.lower, utf.char
+local lower = string.lower
+local utfchar = utf.char
local concat = table.concat
local lpegmatch = lpeg.match
local P, S, Cs = lpeg.P, lpeg.S, lpeg.Cs
diff --git a/tex/context/base/lpdf-epa.lua b/tex/context/base/lpdf-epa.lua
index 03a36f2dc..93e494a31 100644
--- a/tex/context/base/lpdf-epa.lua
+++ b/tex/context/base/lpdf-epa.lua
@@ -12,6 +12,8 @@ if not modules then modules = { } end modules ['lpdf-epa'] = {
local type, tonumber = type, tonumber
local format, gsub = string.format, string.gsub
+----- lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
local report_link = logs.reporter("backend","merging")
@@ -20,6 +22,9 @@ local backends, lpdf = backends, lpdf
local variables = interfaces.variables
local codeinjections = backends.pdf.codeinjections
+----- urlescaper = lpegpatterns.urlescaper
+----- utftohigh = lpegpatterns.utftohigh
+local escapetex = characters.filters.utf.private.escape
local layerspec = { -- predefining saves time
"epdflinks"
@@ -53,19 +58,22 @@ local function add_link(x,y,w,h,destination,what)
end
local function link_goto(x,y,w,h,document,annotation,pagedata,namespace)
- local destination = annotation.A.D -- [ 18 0 R /Fit ]
- local what = "page"
- if type(destination) == "string" then
- local destinations = document.destinations
- local wanted = destinations[destination]
- destination = wanted and wanted.D
- if destination then what = "named" end
- end
- local pagedata = destination and destination[1]
- if pagedata then
- local destinationpage = pagedata.number
- if destinationpage then
- add_link(x,y,w,h,namespace .. destinationpage,what)
+ local a = annotation.A
+ if a then
+ local destination = a.D -- [ 18 0 R /Fit ]
+ local what = "page"
+ if type(destination) == "string" then
+ local destinations = document.destinations
+ local wanted = destinations[destination]
+ destination = wanted and wanted.D
+ if destination then what = "named" end
+ end
+ local pagedata = destination and destination[1]
+ if pagedata then
+ local destinationpage = pagedata.number
+ if destinationpage then
+ add_link(x,y,w,h,namespace .. destinationpage,what)
+ end
end
end
end
@@ -73,24 +81,31 @@ end
local function link_uri(x,y,w,h,document,annotation)
local url = annotation.A.URI
if url then
+ -- url = lpegmatch(urlescaper,url)
+ -- url = lpegmatch(utftohigh,url)
+ url = escapetex(url)
add_link(x,y,w,h,format("url(%s)",url),"url")
end
end
local function link_file(x,y,w,h,document,annotation)
- local filename = annotation.A.F
- if filename then
- local destination = annotation.A.D
- if not destination then
- add_link(x,y,w,h,format("file(%s)",filename),"file")
- elseif type(destination) == "string" then
- add_link(x,y,w,h,format("%s::%s",filename,destination),"file (named)")
- else
- destination = destination[1] -- array
- if tonumber(destination) then
- add_link(x,y,w,h,format("%s::page(%s)",filename,destination),"file (page)")
- else
+ local a = annotation.A
+ if a then
+ local filename = a.F
+ if filename then
+ filename = escapetex(filename)
+ local destination = a.D
+ if not destination then
add_link(x,y,w,h,format("file(%s)",filename),"file")
+ elseif type(destination) == "string" then
+ add_link(x,y,w,h,format("%s::%s",filename,destination),"file (named)")
+ else
+ destination = destination[1] -- array
+ if tonumber(destination) then
+ add_link(x,y,w,h,format("%s::page(%s)",filename,destination),"file (page)")
+ else
+ add_link(x,y,w,h,format("file(%s)",filename),"file")
+ end
end
end
end
@@ -110,41 +125,50 @@ function codeinjections.mergereferences(specification)
local yscale = specification.yscale or 1
local size = specification.size or "crop" -- todo
local pagedata = document.pages[pagenumber]
- local annotations = pagedata.Annots
+ local annotations = pagedata and pagedata.Annots
if annotations and annotations.n > 0 then
- local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname)))
- local reference = namespace .. pagenumber
+ local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname)))
+ local reference = namespace .. pagenumber
local mediabox = pagedata.MediaBox
local llx, lly, urx, ury = mediabox[1], mediabox[2], mediabox[3], mediabox[4]
local width, height = xscale * (urx - llx), yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
context.definelayer( { "epdflinks" }, { height = height.."bp" , width = width.."bp" })
for i=1,annotations.n do
local annotation = annotations[i]
- local subtype = annotation.Subtype
- local rectangle = annotation.Rect
- local a_llx, a_lly, a_urx, a_ury = rectangle[1], rectangle[2], rectangle[3], rectangle[4]
- local x, y = xscale * (a_llx - llx), yscale * (a_lly - lly)
- local w, h = xscale * (a_urx - a_llx), yscale * (a_ury - a_lly)
- if subtype == "Link" then
- local linktype = annotation.A.S
- if linktype == "GoTo" then
- link_goto(x,y,w,h,document,annotation,pagedata,namespace)
- elseif linktype == "GoToR" then
- link_file(x,y,w,h,document,annotation)
- elseif linktype == "URI" then
- link_uri(x,y,w,h,document,annotation)
+ if annotation then
+ local subtype = annotation.Subtype
+ local rectangle = annotation.Rect
+ local a_llx, a_lly, a_urx, a_ury = rectangle[1], rectangle[2], rectangle[3], rectangle[4]
+ local x, y = xscale * (a_llx - llx), yscale * (a_lly - lly)
+ local w, h = xscale * (a_urx - a_llx), yscale * (a_ury - a_lly)
+ if subtype == "Link" then
+ local a = annotation.A
+ if a then
+ local linktype = a.S
+ if linktype == "GoTo" then
+ link_goto(x,y,w,h,document,annotation,pagedata,namespace)
+ elseif linktype == "GoToR" then
+ link_file(x,y,w,h,document,annotation)
+ elseif linktype == "URI" then
+ link_uri(x,y,w,h,document,annotation)
+ elseif trace_links then
+ report_link("unsupported link annotation %q",linktype)
+ end
+ else
+ report_link("mising link annotation")
+ end
elseif trace_links then
- report_link("unsupported link annotation '%s'",linktype)
+ report_link("unsupported annotation %q",subtype)
end
elseif trace_links then
- report_link("unsupported annotation '%s'",subtype)
+ report_link("broken annotation, index: %i",i)
end
end
context.flushlayer { "epdflinks" }
-- context("\\gdef\\figurereference{%s}",reference) -- global
context.setgvalue("figurereference",reference) -- global
if trace_links then
- report_link("setting figure reference to '%s'",reference)
+ report_link("setting figure reference to %q",reference)
end
specification.reference = reference
return namespace
@@ -171,19 +195,24 @@ function codeinjections.mergeviewerlayers(specification)
local layers = document.layers
if layers then
for i=1,layers.n do
- local tag = namespace .. gsub(layers[i]," ",":")
- local title = tag
- if trace_links then
- report_link("using layer '%s'",tag)
+ local layer = layers[i]
+ if layer then
+ local tag = namespace .. gsub(layer," ",":")
+ local title = tag
+ if trace_links then
+ report_link("using layer %q",tag)
+ end
+ attributes.viewerlayers.define { -- also does some cleaning
+ tag = tag, -- todo: #3A or so
+ title = title,
+ visible = variables.start,
+ editable = variables.yes,
+ printable = variables.yes,
+ }
+ codeinjections.useviewerlayer(tag)
+ elseif trace_links then
+ report_link("broken layer, index: %i",i)
end
- attributes.viewerlayers.define { -- also does some cleaning
- tag = tag, -- todo: #3A or so
- title = title,
- visible = variables.start,
- editable = variables.yes,
- printable = variables.yes,
- }
- codeinjections.useviewerlayer(tag)
end
end
end
diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua
index 1c4b4b5c5..b9f8cfc7c 100644
--- a/tex/context/base/lpdf-epd.lua
+++ b/tex/context/base/lpdf-epd.lua
@@ -27,6 +27,8 @@ local lower, match, char, find, sub = string.lower, string.match, string.char, s
local concat = table.concat
local toutf = string.toutf
+local report_epdf = logs.reporter("epdf")
+
-- a bit of protection
local limited = false
@@ -59,9 +61,7 @@ local function prepare(document,d,t,n,k)
for i=1,n do
local v = d:getVal(i)
local r = d:getValNF(i)
- if r:getTypeName() ~= "ref" then
- t[d:getKey(i)] = checked_access[v:getTypeName()](v,document)
- else
+ if r:getTypeName() == "ref" then
r = r:getRef().num
local c = document.cache[r]
if c then
@@ -74,6 +74,8 @@ local function prepare(document,d,t,n,k)
end
end
t[d:getKey(i)] = c
+ else
+ t[d:getKey(i)] = checked_access[v:getTypeName()](v,document)
end
end
getmetatable(t).__index = nil
@@ -95,9 +97,9 @@ local function prepare(document,a,t,n,k)
for i=1,n do
local v = a:get(i)
local r = a:getNF(i)
- if r:getTypeName() ~= "ref" then
- t[i] = checked_access[v:getTypeName()](v,document)
- else
+ if v:getTypeName() == "null" then
+ -- TH: weird, but appears possible
+ elseif r:getTypeName() == "ref" then
r = r:getRef().num
local c = document.cache[r]
if c then
@@ -108,6 +110,8 @@ local function prepare(document,a,t,n,k)
document.xrefs[c] = r
end
t[i] = c
+ else
+ t[i] = checked_access[v:getTypeName()](v,document)
end
end
getmetatable(t).__index = nil
@@ -267,10 +271,14 @@ local function getpages(document)
for pagenumber=1,nofpages do
local pagereference = cata:getPageRef(pagenumber).num
local pagedata = some_dictionary(xref:fetch(pagereference,0):getDict(),document,pagereference)
- pagedata.number = pagenumber
- pages[pagenumber] = pagedata
- xrefs[pagedata] = pagereference
- cache[pagereference] = pagedata
+ if pagedata then
+ pagedata.number = pagenumber
+ pages[pagenumber] = pagedata
+ xrefs[pagedata] = pagereference
+ cache[pagereference] = pagedata
+ else
+ report_epdf("missing pagedata at slot %i",i)
+ end
end
pages.n = nofpages
return pages
diff --git a/tex/context/base/lpdf-ini.lua b/tex/context/base/lpdf-ini.lua
index 1591d6da1..c1b742949 100644
--- a/tex/context/base/lpdf-ini.lua
+++ b/tex/context/base/lpdf-ini.lua
@@ -8,8 +8,7 @@ if not modules then modules = { } end modules ['lpdf-ini'] = {
local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset
local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch
-local utfvalues = string.utfvalues
-local utfchar = utf.char
+local utfchar, utfvalues = utf.char, utf.values
local sind, cosd = math.sind, math.cosd
local lpegmatch, P, C, R, S, Cc, Cs = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs
diff --git a/tex/context/base/lpdf-swf.lua b/tex/context/base/lpdf-swf.lua
index 4bbec8dbe..d3c2b41da 100644
--- a/tex/context/base/lpdf-swf.lua
+++ b/tex/context/base/lpdf-swf.lua
@@ -108,7 +108,7 @@ local function insertswf(spec)
local names = configuration.Assets.Names
local prefix = false
if root ~= "" and root ~= "." then
- prefix = format("^%s/",string.escapedpattern(root,true))
+ prefix = format("^%s/",string.topattern(root))
end
if prefix and trace_swf then
report_swf("using strip pattern '%s'",prefix)
diff --git a/tex/context/base/luat-bas.mkiv b/tex/context/base/luat-bas.mkiv
index 4d6f6d03b..e24568b0a 100644
--- a/tex/context/base/luat-bas.mkiv
+++ b/tex/context/base/luat-bas.mkiv
@@ -13,10 +13,11 @@
\writestatus{loading}{ConTeXt Lua Macros / Basic Lua Libraries}
+\registerctxluafile{l-lua} {1.001}
+\registerctxluafile{l-lpeg} {1.001}
\registerctxluafile{l-function}{1.001}
\registerctxluafile{l-string} {1.001}
\registerctxluafile{l-table} {1.001}
-\registerctxluafile{l-lpeg} {1.001}
\registerctxluafile{l-boolean} {1.001}
\registerctxluafile{l-number} {1.001}
\registerctxluafile{l-math} {1.001}
diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua
index 07a5d51f2..e574bf428 100644
--- a/tex/context/base/luat-cnf.lua
+++ b/tex/context/base/luat-cnf.lua
@@ -30,22 +30,22 @@ texconfig.param_size = 25000 -- 60
texconfig.save_size = 50000 -- 4000
texconfig.stack_size = 10000 -- 300
---~ local function initialize()
---~ local t, variable = allocate(), resolvers.variable
---~ for name, default in next, variablenames do
---~ local name = variablenames[i]
---~ local value = variable(name)
---~ value = tonumber(value)
---~ if not value or value == "" or value == 0 then
---~ value = default
---~ end
---~ texconfig[name], t[name] = value, value
---~ end
---~ initialize = nil
---~ return t
---~ end
-
---~ luatex.variables = initialize()
+-- local function initialize()
+-- local t, variable = allocate(), resolvers.variable
+-- for name, default in next, variablenames do
+-- local name = variablenames[i]
+-- local value = variable(name)
+-- value = tonumber(value)
+-- if not value or value == "" or value == 0 then
+-- value = default
+-- end
+-- texconfig[name], t[name] = value, value
+-- end
+-- initialize = nil
+-- return t
+-- end
+--
+-- luatex.variables = initialize()
local stub = [[
@@ -71,9 +71,9 @@ function texconfig.init()
local builtin, globals = { }, { }
- libraries = { -- we set it her as we want libraries also 'indexed'
+ libraries = { -- we set it here as we want libraries also 'indexed'
basiclua = {
- "string", "table", "coroutine", "debug", "file", "io", "lpeg", "math", "os", "package",
+ "string", "table", "coroutine", "debug", "file", "io", "lpeg", "math", "os", "package", "bit32",
},
basictex = { -- noad
"callback", "font", "img", "lang", "lua", "node", "pdf", "status", "tex", "texconfig", "texio", "token",
@@ -88,6 +88,14 @@ function texconfig.init()
"fontforge", -- can be filled by luat-log
"kpse",
},
+ functions = {
+ "assert", "pcall", "xpcall", "error", "collectgarbage",
+ "dofile", "load","loadfile", "require", "module",
+ "getmetatable", "setmetatable",
+ "ipairs", "pairs", "rawequal", "rawget", "rawset", "next",
+ "tonumber", "tostring",
+ "type", "unpack", "select", "print",
+ },
builtin = builtin, -- to be filled
globals = globals, -- to be filled
}
@@ -96,27 +104,33 @@ function texconfig.init()
globals[k] = tostring(v)
end
- local function collect(t)
+ local function collect(t,fnc)
local lib = { }
for k, v in next, t do
- local keys = { }
- local gv = _G[v]
- if type(gv) == "table" then
- for k, v in next, gv do
- keys[k] = tostring(v) -- true -- by tostring we cannot call overloades functions (security)
+ if fnc then
+ lib[v] = _G[v]
+ else
+ local keys = { }
+ local gv = _G[v]
+ local tv = type(gv)
+ if tv == "table" then
+ for k, v in next, gv do
+ keys[k] = tostring(v) -- true -- by tostring we cannot call overloades functions (security)
+ end
end
+ lib[v] = keys
+ builtin[v] = keys
end
- lib[v] = keys
- builtin[v] = keys
end
return lib
end
- libraries.basiclua = collect(libraries.basiclua)
- libraries.basictex = collect(libraries.basictex)
- libraries.extralua = collect(libraries.extralua)
- libraries.extratex = collect(libraries.extratex)
- libraries.obsolete = collect(libraries.obsolete)
+ libraries.basiclua = collect(libraries.basiclua)
+ libraries.basictex = collect(libraries.basictex)
+ libraries.extralua = collect(libraries.extralua)
+ libraries.extratex = collect(libraries.extratex)
+ libraries.functions = collect(libraries.functions,true)
+ libraries.obsolete = collect(libraries.obsolete)
-- shortcut and helper
@@ -150,7 +164,6 @@ end)
-- done, from now on input and callbacks are internal
]]
-
local variablenames = {
"error_line", "half_error_line",
"expand_depth", "hash_extra", "nest_size",
diff --git a/tex/context/base/luat-cod.mkiv b/tex/context/base/luat-cod.mkiv
index beb631844..9ce6161c3 100644
--- a/tex/context/base/luat-cod.mkiv
+++ b/tex/context/base/luat-cod.mkiv
@@ -67,7 +67,7 @@
%D Reporting the version of \LUA\ that we use is done as follows:
-\edef\luaversion{\ctxwrite{_VERSION}} % no context luaded yet
+\edef\luaversion{\ctxwrite{_VERSION}}
\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}}
\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}}
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
index 4d58897a0..7bce0052d 100644
--- a/tex/context/base/luat-env.lua
+++ b/tex/context/base/luat-env.lua
@@ -22,6 +22,10 @@ local format, sub, match, gsub, find = string.format, string.sub, string.match,
local unquoted, quoted = string.unquoted, string.quoted
local concat, insert, remove = table.concat, table.insert, table.remove
local loadedluacode = utilities.lua.loadedluacode
+local luasuffixes = utilities.lua.suffixes
+
+environment = environment or { }
+local environment = environment
-- precautions
@@ -31,9 +35,29 @@ function os.setlocale()
-- no way you can mess with it
end
--- dirty tricks
+-- dirty tricks (we will replace the texlua call by luatex --luaonly)
+
+local validengines = allocate {
+ ["luatex"] = true,
+ ["luajittex"] = true,
+ -- ["luatex.exe"] = true,
+ -- ["luajittex.exe"] = true,
+}
+
+local basicengines = allocate {
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex",
+ ["texluac"] = "luatex",
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex",
+ -- ["texlua.exe"] = "luatex",
+ -- ["texluajit.exe"] = "luajittex",
+}
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+environment.validengines = validengines
+environment.basicengines = basicengines
+
+if arg and validengines[file.removesuffix(arg[0])] and arg[1] == "--luaonly" then
arg[-1] = arg[0]
arg[ 0] = arg[2]
for k=3,#arg do
@@ -65,9 +89,6 @@ end
-- environment
-environment = environment or { }
-local environment = environment
-
environment.arguments = allocate()
environment.files = allocate()
environment.sortedflags = nil
@@ -123,7 +144,7 @@ function environment.initializearguments(arg)
end
end
end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
+ environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
function environment.setargument(name,value)
@@ -204,22 +225,22 @@ function environment.reconstructcommandline(arg,noquote)
end
end
---~ -- to be tested:
---~
---~ function environment.reconstructcommandline(arg,noquote)
---~ arg = arg or environment.originalarguments
---~ if noquote and #arg == 1 then
---~ return unquoted(resolvers.resolve(arg[1]))
---~ elseif #arg > 0 then
---~ local result = { }
---~ for i=1,#arg do
---~ result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
---~ end
---~ return concat(result," ")
---~ else
---~ return ""
---~ end
---~ end
+-- -- to be tested:
+--
+-- function environment.reconstructcommandline(arg,noquote)
+-- arg = arg or environment.originalarguments
+-- if noquote and #arg == 1 then
+-- return unquoted(resolvers.resolve(arg[1]))
+-- elseif #arg > 0 then
+-- local result = { }
+-- for i=1,#arg do
+-- result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
+-- end
+-- return concat(result," ")
+-- else
+-- return ""
+-- end
+-- end
if arg then
@@ -314,9 +335,11 @@ function environment.loadluafile(filename, version)
local lucname, luaname, chunk
local basename = file.removesuffix(filename)
if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
+ luaname = fiule.addsuffix(basename,luasuffixes.lua)
+ lucname = fiule.addsuffix(basename,luasuffixes.luc)
else
- lucname, luaname = nil, basename -- forced suffix
+ luaname = basename -- forced suffix
+ lucname = nil
end
-- when not overloaded by explicit suffix we look for a luc file first
local fullname = (lucname and environment.luafile(lucname)) or ""
diff --git a/tex/context/base/luat-exe.lua b/tex/context/base/luat-exe.lua
index 0d5cb5abc..a57a5a006 100644
--- a/tex/context/base/luat-exe.lua
+++ b/tex/context/base/luat-exe.lua
@@ -10,6 +10,7 @@ if not modules then modules = { } end modules ['luat-exe'] = {
local match, find, gmatch = string.match, string.find, string.gmatch
local concat = table.concat
+local select = select
local report_executers = logs.reporter("system","executers")
@@ -29,20 +30,20 @@ local spawn = osspawn
local popen = iopopen
local function register(...)
- local t = { ... }
- for k=1,#t do
- local v = t[k]
- permitted[#permitted+1] = (v == "*" and ".*") or v
+ for k=1,select("#",...) do
+ local v = select(k,...)
+ permitted[#permitted+1] = v == "*" and ".*" or v
end
end
local function prepare(...)
-- todo: make more clever first split
local t = { ... }
+ local n = #n
local one = t[1]
- if #t == 1 then
+ if n == 1 then
if type(one) == 'table' then
- return one, concat(t," ",2,#t)
+ return one, concat(t," ",2,n)
else
local name, arguments = match(one,"^(.-)%s+(.+)$")
if name and arguments then
@@ -52,7 +53,7 @@ local function prepare(...)
end
end
else
- return one, concat(t," ",2,#t)
+ return one, concat(t," ",2,n)
end
end
diff --git a/tex/context/base/luat-fio.lua b/tex/context/base/luat-fio.lua
index 8e7988c4e..0af9cb6fc 100644
--- a/tex/context/base/luat-fio.lua
+++ b/tex/context/base/luat-fio.lua
@@ -81,6 +81,9 @@ if not resolvers.instance then
register('find_write_file' , function(id,name) return name end, true)
register('find_format_file' , function(name) return name end, true)
+ register('find_cidmap_file' , function(name) return findbinfile(name,"cidmap") end, true)
+ -- register('read_cidmap_file' , function(file) return loadbinfile(file,"cidmap") end, true)
+
end
end
diff --git a/tex/context/base/luat-fmt.lua b/tex/context/base/luat-fmt.lua
index 37b0f5166..2d2614ecb 100644
--- a/tex/context/base/luat-fmt.lua
+++ b/tex/context/base/luat-fmt.lua
@@ -8,13 +8,11 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
local format = string.format
+local quoted = string.quoted
+local luasuffixes = utilities.lua.suffixes
local report_format = logs.reporter("resolvers","formats")
--- helper for mtxrun
-
-local quoted = string.quoted
-
local function primaryflags() -- not yet ok
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
@@ -29,13 +27,14 @@ local function primaryflags() -- not yet ok
end
function environment.make_format(name)
+ local engine = environment.ownmain or "luatex"
-- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
+ local olddir = dir.current()
+ local path = caches.getwritablepath("formats",engine) or "" -- maybe platform
if path ~= "" then
lfs.chdir(path)
end
- report_format("format path: %s",lfs.currentdir())
+ report_format("format path: %s",dir.current())
-- check source file
local texsourcename = file.addsuffix(name,"mkiv")
local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
@@ -72,13 +71,12 @@ function environment.make_format(name)
elseif type(usedlualibs) == "table" then
report_format("using stub specification: %s",fullspecificationname)
local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
+ local luastubname = file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname = file.addsuffix(texbasename,luasuffixes.luc)
-- pack libraries in stub
report_format("creating initialization file: %s",luastubname)
utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
-- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
report_format("using compiled initialization file: %s",lucstubname)
usedluastub = lucstubname
@@ -92,7 +90,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -111,8 +109,9 @@ end
function environment.run_format(name,data,more)
if name and name ~= "" then
+ local engine = environment.ownmain or "luatex"
local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
+ local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
if fmtname == "" then
fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
end
@@ -129,7 +128,7 @@ function environment.run_format(name,data,more)
report_format("using format name: %s",fmtname)
report_format("no luc/lua with name: %s",barename)
else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
+ local command = format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
report_format("running command: %s",command)
os.spawn(command)
end
diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua
index 0b8c5d951..587214b93 100644
--- a/tex/context/base/luat-ini.lua
+++ b/tex/context/base/luat-ini.lua
@@ -6,15 +6,16 @@ if not modules then modules = { } end modules ['luat-ini'] = {
license = "see context related readme files"
}
--- rather experimental down here ... will change with lua 5.2 --
+-- rather experimental down here ... adapted to lua 5.2 ... but still
+-- experimental
local debug = require("debug")
local string, table, lpeg, math, io, system = string, table, lpeg, math, io, system
-local next, setfenv = next, setfenv or debug.setfenv
+local rawset, rawget, next, setmetatable = rawset, rawget, next, setmetatable
--[[ldx--
-<p>We cannot load anything yet. However what we will do us reserve a fewtables.
+<p>We cannot load anything yet. However what we will do us reserve a few tables.
These can be used for runtime user data or third party modules and will not be
cluttered by macro package code.</p>
--ldx]]--
@@ -38,115 +39,168 @@ thirddata['tricks' ] = { }
--ldx]]--
--[[ldx--
-<p>We could cook up a readonly model for global tables but it
-makes more sense to invite users to use one of the predefined
-namespaces. One can redefine the protector. After all, it's
-just a lightweight suggestive system, not a watertight
-one.</p>
+<p>We could cook up a readonly model for global tables but it makes more sense
+to invite users to use one of the predefined namespaces. One can redefine the
+protector. After all, it's just a lightweight suggestive system, not a
+watertight one.</p>
--ldx]]--
--- this will change when we move on to lua 5.2+
-
-local global = _G
-
+local global = _G
global.global = global
---~ rawset(global,"global",global)
local dummy = function() end
--- another approach is to freeze tables by using a metatable, this will be
--- implemented stepwise
-
-local protected = {
- -- global table
- global = global,
- -- user tables
- -- moduledata = moduledata,
- userdata = userdata,
- thirddata = thirddata,
- documentdata = documentdata,
- -- reserved
- protect = dummy,
- unprotect = dummy,
- -- luatex
- tex = tex,
- -- lua
- string = string,
- table = table,
- lpeg = lpeg,
- math = math,
- io = io,
- --
- -- maybe other l-*, xml etc
-}
+--[[ldx--
+<p>Another approach is to freeze tables by using a metatable, this will be
+implemented stepwise.</p>
+--ldx]]--
-- moduledata : no need for protection (only for developers)
-- isolatedata : full protection
-- userdata : protected
-- thirddata : protected
-userdata, thirddata = nil, nil
-
--- we could have a metatable that automaticaly creates a top level namespace
+--[[ldx--
+<p>We could have a metatable that automaticaly creates a top level namespace.</p>
+--ldx]]--
-if not setfenv then
- texio.write_nl("warning: we need to fix setfenv by using 'load in' or '_ENV'")
-end
+local luanames = lua.name -- luatex itself
+
+lua.numbers = lua.numbers or { } local numbers = lua.numbers
+lua.messages = lua.messages or { } local messages = lua.messages
+
+storage.register("lua/numbers", numbers, "lua.numbers" )
+storage.register("lua/messages", messages, "lua.messages")
+
+local setfenv = setfenv or debug.setfenv -- < 5.2
+
+if setfenv then
+
+ local protected = {
+ -- global table
+ global = global,
+ -- user tables
+ -- moduledata = moduledata,
+ userdata = userdata,
+ thirddata = thirddata,
+ documentdata = documentdata,
+ -- reserved
+ protect = dummy,
+ unprotect = dummy,
+ -- luatex
+ tex = tex,
+ -- lua
+ string = string,
+ table = table,
+ lpeg = lpeg,
+ math = math,
+ io = io,
+ file = file,
+ bit32 = bit32,
+ --
+ context = context,
+ }
+
+ local protect_full = function(name)
+ local t = { }
+ for k, v in next, protected do
+ t[k] = v
+ end
+ return t
+ end
-local function protect_full(name)
- local t = { }
- for k, v in next, protected do
- t[k] = v
+ local protect_part = function(name) -- adds
+ local t = rawget(global,name)
+ if not t then
+ t = { }
+ for k, v in next, protected do
+ t[k] = v
+ end
+ rawset(global,name,t)
+ end
+ return t
end
- return t
-end
-local function protect_part(name)
---~ local t = global[name]
- local t = rawget(global,name)
- if not t then
- t = { }
- for k, v in next, protected do
- t[k] = v
+ protect = function(name)
+ if name == "isolateddata" then
+ setfenv(2,protect_full(name))
+ else
+ setfenv(2,protect_part(name or "shareddata"))
end
---~ global[name] = t
- rawset(global,name,t)
end
- return t
-end
-function protect(name)
- if name == "isolateddata" then
- setfenv(2,protect_full(name))
- else
- setfenv(2,protect_part(name or "shareddata"))
+ function lua.registername(name,message)
+ local lnn = lua.numbers[name]
+ if not lnn then
+ lnn = #messages + 1
+ messages[lnn] = message
+ numbers[name] = lnn
+ end
+ luanames[lnn] = message
+ context(lnn)
+ -- initialize once
+ if name ~= "isolateddata" then
+ protect_full(name or "shareddata")
+ end
end
-end
-lua.numbers = { }
-lua.messages = { }
+elseif libraries then -- assume >= 5.2
+
+ local shared
+
+ protect = function(name)
+ if not shared then
+ -- e.g. context is not yet known
+ local public = {
+ global = global,
+ -- moduledata = moduledata,
+ userdata = userdata,
+ thirddata = thirddata,
+ documentdata = documentdata,
+ protect = dummy,
+ unprotect = dummy,
+ context = context,
+ }
+ --
+ for k, v in next, libraries.builtin do public[k] = v end
+ for k, v in next, libraries.functions do public[k] = v end
+ for k, v in next, libraries.obsolete do public[k] = nil end
+ --
+ shared = { __index = public }
+ protect = function(name)
+ local t = global[name] or { }
+ setmetatable(t,shared) -- set each time
+ return t
+ end
+ end
+ return protect(name)
+ end
-function lua.registername(name,message)
- local lnn = lua.numbers[name]
- if not lnn then
- lnn = #lua.messages + 1
- lua.messages[lnn] = message
- lua.numbers[name] = lnn
+ function lua.registername(name,message)
+ local lnn = lua.numbers[name]
+ if not lnn then
+ lnn = #messages + 1
+ messages[lnn] = message
+ numbers[name] = lnn
+ end
+ luanames[lnn] = message
+ context(lnn)
end
- lua.name[lnn] = message
- context(lnn)
- -- initialize once
- if name ~= "isolateddata" then
- protect_full(name or "shareddata")
+
+else
+
+ protect = dummy
+
+ function lua.registername(name,message)
+ local lnn = lua.numbers[name]
+ if not lnn then
+ lnn = #messages + 1
+ messages[lnn] = message
+ numbers[name] = lnn
+ end
+ luanames[lnn] = message
+ context(lnn)
end
-end
---~ function lua.checknames()
---~ lua.name[0] = "ctx"
---~ for k, v in next, lua.messages do
---~ lua.name[k] = v
---~ end
---~ end
+end
-storage.register("lua/numbers", lua.numbers, "lua.numbers")
-storage.register("lua/messages", lua.messages, "lua.messages")
diff --git a/tex/context/base/luat-ini.mkiv b/tex/context/base/luat-ini.mkiv
index 8ce5e80fd..a3a590311 100644
--- a/tex/context/base/luat-ini.mkiv
+++ b/tex/context/base/luat-ini.mkiv
@@ -27,14 +27,14 @@
%D A few more goodies:
-\unexpanded\def\startlua {\luat_start_lua } \let\stoplua \relax % tex catcodes
-\unexpanded\def\startluacode{\luat_start_lua_code} \let\stopluacode\relax % lua catcodes
+\let\stoplua \relax % tex catcodes
+\let\stopluacode\relax % lua catcodes
% It might makes sense to have a \type {\directelua} so that we can avoid
% the \type {\normalexpanded} around \type {\directlua}. Something to discuss
% in the team.
-\def\luat_start_lua
+\unexpanded\def\startlua % \stoplua
{\begingroup
\obeylualines
\luat_start_lua_indeed}
@@ -42,7 +42,7 @@
\def\luat_start_lua_indeed#1\stoplua
{\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default
-\def\luat_start_lua_code
+\unexpanded\def\startluacode % \stopluacode
{\begingroup
\obeylualines
\obeyluatokens
@@ -62,42 +62,46 @@
\newtoks\everyluacode
-\edef\lualetterbackslash{\string\\}
-\edef\lualetterbar {\string\|} \edef\lualetterdash {\string\-}
-\edef\lualetterlparent {\string\(} \edef\lualetterrparent {\string\)}
-\edef\lualetterlbrace {\string\{} \edef\lualetterrbrace {\string\}}
-\edef\lualettersquote {\string\'} \edef\lualetterdquote {\string\"}
-\edef\lualettern {\string\n} \edef\lualetterr {\string\r}
-\edef\lualetterf {\string\f} \edef\lualettert {\string\t}
-\edef\lualettera {\string\a} \edef\lualetterb {\string\b}
-\edef\lualetterv {\string\v} \edef\lualetters {\string\s}
-\edef\lualetterone {\string\1} \edef\lualettertwo {\string\2}
-\edef\lualetterthree {\string\3} \edef\lualetterfour {\string\4}
-\edef\lualetterfive {\string\5} \edef\lualettersix {\string\6}
-\edef\lualetterseven {\string\7} \edef\lualettereight {\string\8}
-\edef\lualetternine {\string\9} \edef\lualetterzero {\string\0}
+\edef\lua_letter_backslash{\string\\}
+\edef\lua_letter_bar {\string\|} \edef\lua_letter_dash {\string\-}
+\edef\lua_letter_lparent {\string\(} \edef\lua_letter_rparent {\string\)}
+\edef\lua_letter_lbrace {\string\{} \edef\lua_letter_rbrace {\string\}}
+\edef\lua_letter_squote {\string\'} \edef\lua_letter_dquote {\string\"}
+\edef\lua_letter_n {\string\n} \edef\lua_letter_r {\string\r}
+\edef\lua_letter_f {\string\f} \edef\lua_letter_t {\string\t}
+\edef\lua_letter_a {\string\a} \edef\lua_letter_b {\string\b}
+\edef\lua_letter_v {\string\v} \edef\lua_letter_s {\string\s}
+\edef\lua_letter_one {\string\1} \edef\lua_letter_two {\string\2}
+\edef\lua_letter_three {\string\3} \edef\lua_letter_four {\string\4}
+\edef\lua_letter_five {\string\5} \edef\lua_letter_six {\string\6}
+\edef\lua_letter_seven {\string\7} \edef\lua_letter_eight {\string\8}
+\edef\lua_letter_nine {\string\9} \edef\lua_letter_zero {\string\0}
\appendtoks
- \let\\\lualetterbackslash
- \let\|\lualetterbar \let\-\lualetterdash
- \let\(\lualetterlparent \let\)\lualetterrparent
- \let\{\lualetterlbrace \let\}\lualetterrbrace
- \let\'\lualettersquote \let\"\lualetterdquote
- \let\n\lualettern \let\r\lualetterr
- \let\f\lualetterf \let\t\lualettert
- \let\a\lualettera \let\b\lualetterb
- \let\v\lualetterv \let\s\lualetters
- \let\1\lualetterone \let\2\lualettertwo
- \let\3\lualetterthree \let\4\lualetterfour
- \let\5\lualetterfive \let\6\lualettersix
- \let\7\lualetterseven \let\8\lualettereight
- \let\9\lualetternine \let\0\lualetterzero
+ \let\\\lua_letter_backslash
+ \let\|\lua_letter_bar \let\-\lua_letter_dash
+ \let\(\lua_letter_lparent \let\)\lua_letter_rparent
+ \let\{\lua_letter_lbrace \let\}\lua_letter_rbrace
+ \let\'\lua_letter_squote \let\"\lua_letter_dquote
+ \let\n\lua_letter_n \let\r\lua_letter_r
+ \let\f\lua_letter_f \let\t\lua_letter_t
+ \let\a\lua_letter_a \let\b\lua_letter_b
+ \let\v\lua_letter_v \let\s\lua_letter_s
+ \let\1\lua_letter_one \let\2\lua_letter_two
+ \let\3\lua_letter_three \let\4\lua_letter_four
+ \let\5\lua_letter_five \let\6\lua_letter_six
+ \let\7\lua_letter_seven \let\8\lua_letter_eight
+ \let\9\lua_letter_nine \let\0\lua_letter_zero
\to \everyluacode
-\def\obeyluatokens
+\unexpanded\def\obeyluatokens
{\setcatcodetable\luacatcodes
\the\everyluacode}
+
+\edef\luamajorversion{\ctxwrite{_MINORVERSION}}
+\edef\luaminorversion{\ctxwrite{_MAJORVERSION}}
+
%D \macros
%D {definenamedlua}
%D
@@ -110,19 +114,20 @@
\installcorenamespace{luacode}
-\def\luat_start_named_lua_code#1%
+\unexpanded\def\luat_start_named_lua_code#1%
{\begingroup
\obeylualines
\obeyluatokens
\csname\??luacode#1\endcsname}
-\unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet
+\unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet / we could use numbers instead (more efficient)
{\ifcsname\??luacode#1\endcsname \else
\scratchcounter\ctxlua{lua.registername("#1","#3")}%
- \normalexpanded{\edef\csname\??luacode#1\endcsname##1\csname\e!stop#1\v!code\endcsname}%
- {\endgroup\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
- \expandafter\def \csname\e!start#1\v!code\endcsname {\luat_start_named_lua_code{#1}}%
- \expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
+ \normalexpanded{\xdef\csname\??luacode#1\endcsname##1\csname\e!stop#1\v!code\endcsname}%
+ %{\endgroup\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}%
+ {\noexpand\normalexpanded{\endgroup\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}}%
+ \expandafter\edef\csname\e!start#1\v!code\endcsname {\luat_start_named_lua_code{#1}}%
+ \expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}%
\fi}
%D We predefine a few.
@@ -142,12 +147,25 @@
%D
%D \startusercode
%D global.context("USER 1")
+%D context.par()
%D context("USER 2")
+%D context.par()
%D if characters then
-%D context("ACCESS")
+%D context("ACCESS directly")
+%D elseif global.characters then
+%D context("ACCESS via global")
+%D else
+%D context("NO ACCESS at all")
+%D end
+%D context.par()
+%D if bogus then
+%D context("ACCESS directly")
+%D elseif global.bogus then
+%D context("ACCESS via global")
%D else
-%D context("NO ACCESS")
+%D context("NO ACCESS at all")
%D end
+%D context.par()
%D \stopusercode
%D \stopbuffer
%D
diff --git a/tex/context/base/lxml-ent.lua b/tex/context/base/lxml-ent.lua
index be69dec00..14b758f1c 100644
--- a/tex/context/base/lxml-ent.lua
+++ b/tex/context/base/lxml-ent.lua
@@ -7,9 +7,8 @@ if not modules then modules = { } end modules ['lxml-ent'] = {
}
local type, next, tonumber = type, next, tonumber
-local utf = unicode.utf8
local byte, format = string.byte, string.format
-local utfupper, utfchar = utf.upper, utf.char
+local utfchar = utf.char
local lpegmatch = lpeg.match
--[[ldx--
diff --git a/tex/context/base/lxml-inf.lua b/tex/context/base/lxml-inf.lua
index 834d152fd..8f1157c7d 100644
--- a/tex/context/base/lxml-inf.lua
+++ b/tex/context/base/lxml-inf.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['lxml-inf'] = {
-- This file will be loaded runtime by x-pending.tex.
+local concat = table.concat
+
local xmlwithelements = xml.withelements
local getid = lxml.getid
diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua
index 0c10998a0..4e84930f1 100644
--- a/tex/context/base/lxml-lpt.lua
+++ b/tex/context/base/lxml-lpt.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['lxml-lpt'] = {
-- todo: B/C/[get first match]
local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local type, next, tonumber, tostring, setmetatable, load, select = type, next, tonumber, tostring, setmetatable, load, select
local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
@@ -682,7 +682,7 @@ end
local function register_expression(expression)
local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
+ local runner = load(format(template_e,converted))
runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
end
@@ -690,9 +690,9 @@ end
local function register_finalizer(protocol,name,arguments)
local runner
if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ runner = load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
+ runner = load(format(template_f_n,protocol or xml.defaultprotocol,name))
end
runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
@@ -1116,6 +1116,7 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
+
expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
return pattern and (collected and #collected) or 0
@@ -1123,13 +1124,30 @@ end
-- external
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+-- expressions.oneof = function(s,...)
+-- local t = {...}
+-- for i=1,#t do
+-- if s == t[i] then
+-- return true
+-- end
+-- end
+-- return false
+-- end
+
+expressions.oneof = function(s,...)
+ for i=1,select("#",...) do
+ if s == select(i,...) then
+ return true
+ end
+ end
+ return false
end
+
expressions.error = function(str)
xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
+
expressions.undefined = function(s)
return s == nil
end
diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua
index 21c7561e8..04b4192c0 100644
--- a/tex/context/base/lxml-tab.lua
+++ b/tex/context/base/lxml-tab.lua
@@ -39,7 +39,6 @@ local xml = xml
--~ local xml = xml
-local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua
index 6ff96bf05..8a57ed54e 100644
--- a/tex/context/base/lxml-tex.lua
+++ b/tex/context/base/lxml-tex.lua
@@ -10,12 +10,10 @@ if not modules then modules = { } end modules ['lxml-tex'] = {
-- interface and not the context one. If we ever do that there will
-- be an cldf-xml helper library.
-local utf = unicode.utf8
-
-local utfchar, utfupper = utf.char, utf.upper
+local utfchar = utf.char
local concat, insert, remove = table.concat, table.insert, table.remove
local format, sub, gsub, find, gmatch, match = string.format, string.sub, string.gsub, string.find, string.gmatch, string.match
-local type, next, tonumber, tostring = type, next, tonumber, tostring
+local type, next, tonumber, tostring, select = type, next, tonumber, tostring, select
local lpegmatch = lpeg.match
local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
@@ -125,7 +123,7 @@ function lxml.resolvedentity(str)
end
context(err)
else
- local tag = utfupper(str)
+ local tag = upperchars(str)
if trace_entities then
report_xml("passing entity '%s' to \\xmle using tag '%s'",str,tag)
end
@@ -841,10 +839,32 @@ function lxml.installsetup(what,document,setup,where)
end
end
+-- function lxml.flushsetups(id,...)
+-- local done, list = { }, { ... }
+-- for i=1,#list do
+-- local document = list[i]
+-- local sd = setups[document]
+-- if sd then
+-- for k=1,#sd do
+-- local v= sd[k]
+-- if not done[v] then
+-- if trace_loading then
+-- report_lxml("applying setup %02i = %s to %s",k,v,document)
+-- end
+-- contextsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
+-- done[v] = true
+-- end
+-- end
+-- elseif trace_loading then
+-- report_lxml("no setups for %s",document)
+-- end
+-- end
+-- end
+
function lxml.flushsetups(id,...)
- local done, list = { }, { ... }
- for i=1,#list do
- local document = list[i]
+ local done = { }
+ for i=1,select("#",...) do
+ local document = select(i,...)
local sd = setups[document]
if sd then
for k=1,#sd do
diff --git a/tex/context/base/m-database.lua b/tex/context/base/m-database.lua
index b9ec3aa36..caa40f8f6 100644
--- a/tex/context/base/m-database.lua
+++ b/tex/context/base/m-database.lua
@@ -20,12 +20,16 @@ local report_database = logs.reporter("database")
buffers.database = buffers.database or { }
+local l_tab = lpegpatterns.tab
+local l_space = lpegpatterns.space
+local l_comma = lpegpatterns.comma
+
local separators = { -- not interfaced
- tab = lpegpatterns.tab,
- tabs = lpegpatterns.tab^1,
- comma = lpegpatterns.comma,
- space = lpegpatterns.space,
- spaces = lpegpatterns.space^1,
+ tab = l_tab,
+ tabs = l_tab^1,
+ comma = l_comma,
+ space = l_space,
+ spaces = l_space^1,
}
function buffers.database.process(settings)
@@ -54,7 +58,7 @@ function buffers.database.process(settings)
local quotedata = nil
for chr in gmatch(quotechar,".") do
local quotechar = lpegP(chr)
- local quoteword = quotechar * lpeg.C((1 - quotechar)^0) * quotechar
+ local quoteword = l_space^0 * quotechar * lpegC((1 - quotechar)^0) * quotechar * l_space^0
if quotedata then
quotedata = quotedata + quoteword
else
diff --git a/tex/context/base/m-morse.mkvi b/tex/context/base/m-morse.mkvi
index 6082d588a..a2c20dff7 100644
--- a/tex/context/base/m-morse.mkvi
+++ b/tex/context/base/m-morse.mkvi
@@ -100,16 +100,22 @@ local codes = {
morse.codes = codes
-setmetatable(codes, { __index = function(t,k)
+local fallbackself = false
+
+local function codefallback(t,k)
if k then
local u = ucchars[k]
local v = rawget(t,u) or rawget(t,shchars[u]) or false
t[k] = v
return v
+ elseif fallbackself then
+ return k
else
return false
end
-end })
+end
+
+table.setmetatableindex(codes,codefallback)
local MorseBetweenWords = context.MorseBetweenWords
local MorseBetweenCharacters = context.MorseBetweenCharacters
@@ -228,16 +234,19 @@ end
\def\MorseSpace {\hskip7\dimexpr\MorseWidth\relax}
\def\MorseUnknown #text{[\detokenize{#text}]}
-\unexpanded\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}}
-\unexpanded\def\MorseString#text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}}
-\unexpanded\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}}
-\unexpanded\def\MorseTable {\ctxlua{moduledata.morse.showtable()}}
+\unexpanded\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}}
+\unexpanded\def\MorseString #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}}
+\unexpanded\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}}
+\unexpanded\def\MorseTable {\ctxlua{moduledata.morse.showtable()}}
\let\Morse \MorseString
+%def\MorseShort {·}
+%def\MorseLong {—}
+
\protect
-\continueifinputfile{m-morse.mkiv}
+\continueifinputfile{m-morse.mkvi}
\starttext
diff --git a/tex/context/base/m-timing.mkiv b/tex/context/base/m-timing.mkiv
index 18646cfae..5502768f6 100644
--- a/tex/context/base/m-timing.mkiv
+++ b/tex/context/base/m-timing.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifx\ShowNamedUsage\undefined \else \endinput \fi
+\ifdefined\ShowNamedUsage \endinput \fi
%D Written at the end of 2007, this module is dedicated to Taco. Reaching this
%D point in \LUATEX\ was a non trivial effort. By visualizing a bit what happens
@@ -55,12 +55,13 @@ end
\stopnotmode
\unexpanded\def\ShowNamedUsage#1#2#3%
- {\setbox\scratchbox\vbox\bgroup\startMPcode
+ {\setbox\scratchbox\vbox\bgroup
+ \startMPcode
begingroup ; save p, q, b, h, w ;
path p, q, b ; numeric h, w ;
p := \cldcontext{moduledata.progress.path("#1","#2")} ;
% p := p shifted -llcorner p ;
- if bbwidth(p) > 1 :
+ if bbwidth(p) > 0 :
h := 100 ; w := 2 * h ;
w := \the\textwidth-3pt ; % correct for pen
p := p xstretched w ;
@@ -79,7 +80,8 @@ end
fi ;
fi ;
endgroup ;
- \stopMPcode\egroup
+ \stopMPcode
+ \egroup
\scratchdimen\wd\scratchbox
\ifdim\scratchdimen>\zeropoint
\startlinecorrection
diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
index c83bac309..46c366c3e 100644
--- a/tex/context/base/math-ini.lua
+++ b/tex/context/base/math-ini.lua
@@ -11,7 +11,8 @@ if not modules then modules = { } end modules ['math-ini'] = {
--
-- isn't characters.data loaded already ... shortcut it here
-local format, utfchar, utfbyte = string.format, utf.char, utf.byte
+local format = string.format
+local utfchar, utfbyte = utf.char, utf.byte
local setmathcode, setdelcode = tex.setmathcode, tex.setdelcode
local texattribute = tex.attribute
local floor = math.floor
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 3de4c808f..1e78ff492 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -1082,6 +1082,18 @@
\textface
\fi}
+\def\mathstylecommand#1#2#3%
+ {\ifcase\normalmathstyle
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#1\or
+ \expandafter#2\or
+ \expandafter#2\or
+ \expandafter#3\or
+ \expandafter#3\else
+ \expandafter#1\fi}
+
%D A plain inheritance:
\def\mathpalette#1#2%
diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua
index e9cf79590..3c67d26a2 100644
--- a/tex/context/base/math-noa.lua
+++ b/tex/context/base/math-noa.lua
@@ -18,8 +18,6 @@ if not modules then modules = { } end modules ['math-noa'] = {
-- 20D6 -> 2190
-- 20D7 -> 2192
-local utf = unicode.utf8
-
local utfchar, utfbyte = utf.char, utf.byte
local format, rep = string.format, string.rep
local concat = table.concat
diff --git a/tex/context/base/meta-fun.lua b/tex/context/base/meta-fun.lua
index 7594d0c78..78ee25baf 100644
--- a/tex/context/base/meta-fun.lua
+++ b/tex/context/base/meta-fun.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['meta-fun'] = {
-- very experimental, actually a joke ... see metafun manual for usage
-local format, loadstring, type = string.format, loadstring, type
+local format, load, type = string.format, load, type
local metapost = metapost
@@ -39,7 +39,7 @@ function metafun.interpolate(f,b,e,s,c)
local done = false
context("(")
for i=b,e,(e-b)/s do
- local d = loadstring(format("return function(x) return %s end",f))
+ local d = load(format("return function(x) return %s end",f))
if d then
d = d()
if done then
diff --git a/tex/context/base/meta-imp-dum.mkiv b/tex/context/base/meta-imp-dum.mkiv
index 83fe12f09..05d40b70b 100644
--- a/tex/context/base/meta-imp-dum.mkiv
+++ b/tex/context/base/meta-imp-dum.mkiv
@@ -120,6 +120,7 @@
\c!height=\figureheight,
\c!frame=\v!off,
\c!strut=\v!no,
+ \c!align={\v!middle,\v!lohi},
\c!background=figure:placeholder:graphic,
\c!foregroundcolor=\s!white]%
\doifelse{\externalfigureparameter\c!text}\v!yes
diff --git a/tex/context/base/meta-ini.lua b/tex/context/base/meta-ini.lua
index 8b6fd22a2..928048776 100644
--- a/tex/context/base/meta-ini.lua
+++ b/tex/context/base/meta-ini.lua
@@ -7,7 +7,9 @@ if not modules then modules = { } end modules ['meta-ini'] = {
}
local tonumber = tonumber
-local format, gmatch, match, gsub = string.format, string.gmatch, string.match, string.gsub
+local format = string.format
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, Cs, R, S, C, Cc = lpeg.P, lpeg.Cs, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc
local context = context
@@ -45,46 +47,94 @@ end
local colorhash = attributes.list[attributes.private('color')]
-local validdimen = lpeg.patterns.validdimen * lpeg.P(-1)
-
-local lpegmatch = lpeg.match
local textype = tex.type
local MPcolor = context.MPcolor
+-- local validdimen = lpegpatterns.validdimen * P(-1)
+--
+-- function commands.prepareMPvariable(v) -- slow but ok
+-- if v == "" then
+-- MPcolor("black")
+-- else
+-- local typ, var = match(v,"(.):(.*)")
+-- if not typ then
+-- -- parse
+-- if colorhash[v] then
+-- MPcolor(v)
+-- elseif tonumber(v) then
+-- context(v)
+-- elseif lpegmatch(validdimen,v) then
+-- return context("\\the\\dimexpr %s",v)
+-- else
+-- for s in gmatch(v,"\\([a-zA-Z]+)") do -- can have trailing space
+-- local t = textype(s)
+-- if t == "dimen" then
+-- return context("\\the\\dimexpr %s",v)
+-- elseif t == "count" then
+-- return context("\\the\\numexpr %s",v)
+-- end
+-- end
+-- context("\\number %s",v) -- 0.4 ...
+-- end
+-- elseif typ == "d" then -- to be documented
+-- -- dimension
+-- context("\\the\\dimexpr %s",var)
+-- elseif typ == "n" then -- to be documented
+-- -- number
+-- context("\\the\\numexpr %s",var)
+-- elseif typ == "s" then -- to be documented
+-- -- string
+-- context(var)
+-- elseif typ == "c" then -- to be documented
+-- -- color
+-- MPcolor(var)
+-- else
+-- context(var)
+-- end
+-- end
+-- end
+
+-- we can actually get the dimen/count values here
+
+local dimenorname =
+ lpegpatterns.validdimen / function(s)
+ context("\\the\\dimexpr %s",s)
+ end
+ + (C(lpegpatterns.float) + Cc(1)) * lpegpatterns.space^0 * P("\\") * C(lpegpatterns.letter^1) / function(f,s)
+ local t = textype(s)
+ if t == "dimen" then
+ context("\\the\\dimexpr %s\\%s",f,s)
+ elseif t == "count" then
+ context("\\the\\numexpr \\%s * %s\\relax",s,f) -- <n>\scratchcounter is not permitted
+ end
+ end
+
+local splitter = lpeg.splitat(":",true)
+
function commands.prepareMPvariable(v) -- slow but ok
if v == "" then
MPcolor("black")
else
- local typ, var = match(v,"(.):(.*)")
- if not typ then
+ local typ, var = lpegmatch(splitter,v)
+ if not var then
-- parse
if colorhash[v] then
MPcolor(v)
elseif tonumber(v) then
context(v)
- elseif lpegmatch(validdimen,v) then
- return context("\\the\\dimexpr %s",v)
- else
- for s in gmatch(v,"\\(.-)") do
- local t = textype(s)
- if t == "dimen" then
- return context("\\the\\dimexpr %s",v)
- elseif t == "count" then
- return context("\\the\\numexpr %s",v)
- end
- end
- return context("\\number %s",v) -- 0.4 ...
+ elseif not lpegmatch(dimenorname,v) then
+ context("\\number %s",v) -- 0.4 ...
end
- elseif typ == "d" then
+ elseif typ == "d" then -- to be documented
-- dimension
context("\\the\\dimexpr %s",var)
- elseif typ == "n" then
+ elseif typ == "n" then -- to be documented
-- number
context("\\the\\numexpr %s",var)
- elseif typ == "s" then
+ elseif typ == "s" then -- to be documented
-- string
context(var)
- elseif typ == "c" then
+ elseif typ == "c" then -- to be documented
-- color
MPcolor(var)
else
@@ -93,12 +143,19 @@ function commands.prepareMPvariable(v) -- slow but ok
end
end
-function metapost.formatnumber(f,n) -- just lua format
- f = gsub(f,"@(%d)","%%.%1")
- f = gsub(f,"@","%%")
- f = format(f,tonumber(n) or 0)
- f = gsub(f,"e([%+%-%d]+)",function(s)
- return format("\\times10^{%s}",tonumber(s) or s) -- strips leading zeros
- end)
- context.mathematics(f)
+-- function metapost.formatnumber(f,n) -- just lua format
+-- f = gsub(f,"@(%d)","%%.%1")
+-- f = gsub(f,"@","%%")
+-- f = format(f,tonumber(n) or 0)
+-- f = gsub(f,"e([%+%-%d]+)",function(s)
+-- return format("\\times10^{%s}",tonumber(s) or s) -- strips leading zeros
+-- end)
+-- context.mathematics(f)
+-- end
+
+local one = Cs((P("@")/"%%." * (R("09")^1) + P("@")/"%%" + 1)^0)
+local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1)/function(s) return format("\\times10^{%s}",tonumber(s) or s) end) + 1)^1)
+
+function metapost.formatnumber(fmt,n) -- just lua format
+ context.mathematics(lpegmatch(two,format(lpegmatch(one,fmt),n)))
end
diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv
index e731d26e0..5ac7908d5 100644
--- a/tex/context/base/meta-ini.mkiv
+++ b/tex/context/base/meta-ini.mkiv
@@ -395,15 +395,10 @@
%D \setupMPvariables[meta:button][size=20pt]
%D \stoptyping
-% \startlines
-% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
-% \stoplines
-
+% \lineheight 2pt 2 \scratchcounter red 0.4 .5\bodyfontsize
+%
+% see cont-loc for test code
+%
% currently the inheritance of backgrounds does not work and
% we might drop it anyway (too messy)
diff --git a/tex/context/base/meta-pag.mkiv b/tex/context/base/meta-pag.mkiv
index ef53d4753..7124902e7 100644
--- a/tex/context/base/meta-pag.mkiv
+++ b/tex/context/base/meta-pag.mkiv
@@ -38,6 +38,8 @@
% todo: ColumnDistance
\stopMPinitializations
+% maybe always set as frozen anyway
+
\startMPinitializations
def LoadPageState =
OnRightPage:=\MPonrightpage;
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
index c68350a96..307779b16 100644
--- a/tex/context/base/meta-pdf.lua
+++ b/tex/context/base/meta-pdf.lua
@@ -195,6 +195,7 @@ end
function mps.setdash(...) -- can be made faster, operate on t = { ... }
local n = select("#",...)
mpscode("[" .. concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d")
+ -- mpscode("[" .. concat({select(1,n-1)}," ") .. "] " .. select(n,...) .. " d")
end
function mps.resetdash()
diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua
index 88f26e755..e22e3af30 100644
--- a/tex/context/base/mlib-pdf.lua
+++ b/tex/context/base/mlib-pdf.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['mlib-pdf'] = {
license = "see context related readme files",
}
+-- maybe %s is better than %f
+
local format, concat, gsub = string.format, table.concat, string.gsub
local abs, sqrt, round = math.abs, math.sqrt, math.round
local setmetatable = setmetatable
@@ -356,7 +358,7 @@ function metapost.flush(result,flusher,askedfig)
end
local dl = object.dash
if dl then
- local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
+ local d = format("[%s] %f d",concat(dl.dashes or {}," "),dl.offset)
if d ~= dashed then
dashed = d
t[#t+1] = dashed
diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua
index 5e702245d..6a23fe316 100644
--- a/tex/context/base/mlib-run.lua
+++ b/tex/context/base/mlib-run.lua
@@ -243,7 +243,7 @@ if mplibone then
-- mpsformat = mpsformat .. "-" .. mpsbase
-- end
-- mpsformat = file.addsuffix(mpsformat, "mem")
- -- local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or ""
+ -- local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats","metapost") or ""
-- if mpsformatfullname ~= "" then
-- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
-- local mpx, result = metapost.load(mpsformatfullname)
diff --git a/tex/context/base/mtx-context-copy.tex b/tex/context/base/mtx-context-copy.tex
new file mode 100644
index 000000000..b798b3f8d
--- /dev/null
+++ b/tex/context/base/mtx-context-copy.tex
@@ -0,0 +1,151 @@
+% engine=luatex
+
+%D \module
+%D [ file=mtx-context-copy,
+%D version=2008.11.10, % about that time i started playing with this
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Copying Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=copy [options] list-of-files
+%
+% --interaction : add hyperlinks
+%
+% end help
+
+\input mtx-context-common.tex
+
+\doif {\getdocumentargument{interaction}} {yes} {
+ \setupinteraction
+ [state=start]
+ \setupexternalfigures
+ [interaction=yes]
+}
+
+\setupexternalfigures
+ [directory=]
+
+\definepapersize
+ [fit]
+ [width=\figurewidth,
+ height=\figureheight]
+
+\setuplayout
+ [page]
+
+% this will be an option to \copypages
+
+\unexpanded\def\CopyPages[#1]%
+ {\dorecurse
+ {\noffigurepages}
+ {\startTEXpage
+ \externalfigure[#1][page=\recurselevel]%
+ \stopTEXpage}}
+
+\starttext
+
+\startluacode
+
+ if #document.files == 0 then
+ context("no files given")
+ else
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ logs.report("copy",filename)
+ context.getfiguredimensions
+ { filename }
+ context.setuppapersize
+ { "fit" }
+ context.CopyPages
+ { filename }
+ end
+ end
+ end
+
+\stopluacode
+
+\stoptext
+
+
+% def copyoutput
+% copyortrim(false,'copy')
+% end
+
+% def trimoutput
+% copyortrim(true,'trim')
+% end
+
+% def copyortrim(trim=false,what='unknown')
+% if job = TEX.new(logger) then
+% prepare(job)
+% job.cleanuptemprunfiles
+% files = if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+% if files.length > 0 then
+% if f = File.open(job.tempfilename('tex'),'w') then
+% scale = @commandline.checkedoption('scale')
+% begin
+% scale = (scale.to_f * 1000.0).to_i if scale.to_i < 10
+% rescue
+% scale = 1000
+% end
+% scale = scale.to_i
+% paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+% f << "\\starttext\n"
+% files.each do |filename|
+% result = @commandline.checkedoption('result','texexec')
+% begin
+% if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
+% report("copying file: #{filename}")
+% f << "\\getfiguredimensions\n"
+% f << " [#{filename}]\n"
+% f << " [scale=#{scale},\n"
+% f << " page=1,\n"
+% f << " size=trimbox\n" if trim
+% f << "]\n"
+% f << "\\definepapersize\n"
+% f << " [copy]\n"
+% f << " [width=\\figurewidth,\n"
+% f << " height=\\figureheight]\n"
+% f << "\\setuppapersize\n"
+% f << " [copy][copy]\n"
+% f << "\\setuplayout\n"
+% f << " [page]\n"
+% f << "\\setupexternalfigures\n"
+% f << " [directory=]\n"
+% f << "\\copypages\n"
+% f << " [#{filename}]\n"
+% f << " [scale=#{scale},\n"
+% f << " marking=on,\n" if @commandline.option('markings')
+% f << " size=trimbox,\n" if trim
+% f << " offset=#{paperoffset}]\n"
+% end
+% rescue
+% report("wrong specification")
+% end
+% end
+% f << "\\stoptext\n"
+% f.close
+% job.setvariable('interface','english')
+% job.setvariable('simplerun',true)
+% # job.setvariable('nooptionfile',true)
+% job.setvariable('files',[job.tempfilename])
+% job.processtex
+% else
+% report("no files to #{what}")
+% end
+% else
+% report("no files to #{what}")
+% end
+% job.cleanuptemprunfiles
+% end
+% end
diff --git a/tex/context/base/mtx-context-select.tex b/tex/context/base/mtx-context-select.tex
index 7d6535119..2f63f5955 100644
--- a/tex/context/base/mtx-context-select.tex
+++ b/tex/context/base/mtx-context-select.tex
@@ -4,7 +4,7 @@
%D [ file=mtx-context-select,
%D version=2008.11.10, % about that time i started playing with this
%D title=\CONTEXT\ Extra Trickry,
-%D subtitle=Listing Files,
+%D subtitle=Selecting Files,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -94,6 +94,7 @@
end
for _, filename in ipairs(document.files) do
if not string.find(filename,"^mtx%-context%-") then
+ logs.report("select",filename)
context.filterpages (
{ filename },
{ selection },
diff --git a/tex/context/base/mtx-context-timing.tex b/tex/context/base/mtx-context-timing.tex
index 2fd9cb807..c545c768f 100644
--- a/tex/context/base/mtx-context-timing.tex
+++ b/tex/context/base/mtx-context-timing.tex
@@ -35,9 +35,13 @@
\starttext
- \doifsomething {\getdocumentfilename{1}} {
+
+ \doifsomethingelse {\getdocumentfilename{1}} {
+ \writestatus{system}{processing timings of \getdocumentfilename{1}}
\LoadUsage{\getdocumentfilename{1}-luatex-progress}
\ShowUsage{\getdocumentfilename{1}-luatex-progress}
+ } {
+ \writestatus{system}{no filename given for timings}
}
\stoptext
diff --git a/tex/context/base/mult-de.mkii b/tex/context/base/mult-de.mkii
index ce34b6a5b..99a5944b0 100644
--- a/tex/context/base/mult-de.mkii
+++ b/tex/context/base/mult-de.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{switchtorawfont}
\setinterfacecommand{sym}{sym}
\setinterfacecommand{symbol}{symbol}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{synchronisationsbalken}
\setinterfacecommand{synchronize}{synchronisieren}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua
index 26b2b8529..9c7b4f767 100644
--- a/tex/context/base/mult-def.lua
+++ b/tex/context/base/mult-def.lua
@@ -5889,6 +5889,10 @@ return {
["pe"]="نم",
["ro"]="sim",
},
+ ["symoffset"]={
+ ["en"]="symoffset",
+ ["nl"]="symoffset",
+ },
["symbol"]={
["cs"]="symbol",
["de"]="symbol",
diff --git a/tex/context/base/mult-en.mkii b/tex/context/base/mult-en.mkii
index 860060247..24bf6c074 100644
--- a/tex/context/base/mult-en.mkii
+++ b/tex/context/base/mult-en.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{switchtorawfont}
\setinterfacecommand{sym}{sym}
\setinterfacecommand{symbol}{symbol}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{synchronizationbar}
\setinterfacecommand{synchronize}{synchronize}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/mult-fr.mkii b/tex/context/base/mult-fr.mkii
index f52a761d2..0640cbecb 100644
--- a/tex/context/base/mult-fr.mkii
+++ b/tex/context/base/mult-fr.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{changepolicebrute}
\setinterfacecommand{sym}{sym}
\setinterfacecommand{symbol}{symbole}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{barresynchronisation}
\setinterfacecommand{synchronize}{synchronise}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/mult-it.mkii b/tex/context/base/mult-it.mkii
index b91e3ee5b..f4d02ad46 100644
--- a/tex/context/base/mult-it.mkii
+++ b/tex/context/base/mult-it.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{passaafontgrezzo}
\setinterfacecommand{sym}{sim}
\setinterfacecommand{symbol}{simbolo}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{barrasincronizzazione}
\setinterfacecommand{synchronize}{sincronizza}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua
index 8338d41eb..287e2c9c1 100644
--- a/tex/context/base/mult-low.lua
+++ b/tex/context/base/mult-low.lua
@@ -114,6 +114,8 @@ return {
"constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument",
--
"continueifinputfile",
+ --
+ "luastringsep", "!!bs", "!!es",
},
["helpers"] = {
--
@@ -215,7 +217,9 @@ return {
--
"removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to",
--
- "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace",
+ "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace",
+ "obeyspaces", "obeylines", "obeyedspace", "obeyedline",
+ "normalspace",
--
"executeifdefined",
--
@@ -227,6 +231,8 @@ return {
--
"setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure",
--
+ "installcorenamespace",
+ --
"getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue",
"resetvalue", "undefinevalue", "ignorevalue",
"setuvalue", "setuevalue", "setugvalue", "setuxvalue",
@@ -306,6 +312,18 @@ return {
"startimath", "stopimath", "normalstartimath", "normalstopimath",
"startdmath", "stopdmath", "normalstartdmath", "normalstopdmath",
--
- "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathstyleface",
+ "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathstyleface", "mathstylecommand",
+ --
+ "luaexpr", "expdoifelse", "expdoif", "expdoifnot", "expdoifcommonelse", "expdoifinsetelse",
+ --
+ "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport",
+ "ctxlua", "luacode", "lateluacode", "directluacode",
+ "registerctxluafile", "ctxloadluafile",
+ "luaversion", "luamajorversion", "luaminorversion",
+ "ctxluacode", "luaconditional", "luaexpanded",
+ "startluaparameterset", "stopluaparameterset", "luaparameterset",
+ "definenamedlua",
+ "obeylualines", "obeyluatokens",
+ "startluacode", "stopluacode", "startlua", "stoplua",
}
}
diff --git a/tex/context/base/mult-nl.mkii b/tex/context/base/mult-nl.mkii
index dbce41d85..9247f7ebf 100644
--- a/tex/context/base/mult-nl.mkii
+++ b/tex/context/base/mult-nl.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{switchtorawfont}
\setinterfacecommand{sym}{sym}
\setinterfacecommand{symbol}{symbool}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{synchronisatiebalk}
\setinterfacecommand{synchronize}{synchroniseer}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/mult-pe.mkii b/tex/context/base/mult-pe.mkii
index 58d3ff527..82f7abcd9 100644
--- a/tex/context/base/mult-pe.mkii
+++ b/tex/context/base/mult-pe.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{تغییربه‌قلم‌خام}
\setinterfacecommand{sym}{نم}
\setinterfacecommand{symbol}{نماد}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{میله‌تطابق}
\setinterfacecommand{synchronize}{تطابق}
\setinterfacecommand{tab}{تب}
diff --git a/tex/context/base/mult-ro.mkii b/tex/context/base/mult-ro.mkii
index adc811188..01ffe9fbe 100644
--- a/tex/context/base/mult-ro.mkii
+++ b/tex/context/base/mult-ro.mkii
@@ -1699,6 +1699,7 @@
\setinterfacecommand{switchtorawfont}{trecilafontraw}
\setinterfacecommand{sym}{sim}
\setinterfacecommand{symbol}{simbol}
+\setinterfacecommand{symoffset}{symoffset}
\setinterfacecommand{synchronizationbar}{barasincronizare}
\setinterfacecommand{synchronize}{sincronizeaza}
\setinterfacecommand{tab}{tab}
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua
index 03a8789f7..466b7991d 100644
--- a/tex/context/base/node-aux.lua
+++ b/tex/context/base/node-aux.lua
@@ -12,7 +12,7 @@ local type, tostring = type, tostring
local nodes, node = nodes, node
-local utfvalues = string.utfvalues
+local utfvalues = utf.values
local nodecodes = nodes.nodecodes
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index 66cd9916f..543f64acb 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -219,5 +219,166 @@ function handlers.characters(head)
return head, true
end
+-- function handlers.xcharacters(head)
+-- -- either next or not, but definitely no already processed list
+-- starttiming(nodes)
+-- local usedfonts, attrfonts, done = { }, { }, false
+-- local a, u, prevfont, prevattr = 0, 0, nil, nil
+-- local ap = 0
+-- if trace_fontrun then
+-- run = run + 1
+-- report_fonts()
+-- report_fonts("checking node list, run %s",run)
+-- report_fonts()
+-- local n = head
+-- while n do
+-- if n.id == glyph_code then
+-- local font = n.font
+-- local attr = has_attribute(n,0) or 0
+-- report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char))
+-- else
+-- report_fonts("[%s]",nodecodes[n.id])
+-- end
+-- n = n.next
+-- end
+-- end
+-- for n in traverse_id(glyph_code,head) do
+-- -- if n.subtype<256 then
+-- local font = n.font
+-- local attr = n.attr
+-- if attr ~= prevattr then
+-- local an = has_attribute(n,0) or 0
+-- if ap ~= an and an > 0 then
+-- local used = attrfonts[font]
+-- if not used then
+-- used = { }
+-- attrfonts[font] = used
+-- end
+-- if not used[an] then
+-- local sd = setfontdynamics[font]
+-- if sd then -- always true ?
+-- local d = sd(font,an) -- can we cache this one?
+-- if d then
+-- used[an] = d
+-- a = a + 1
+-- else
+-- -- can't happen ... otherwise best use nil/false distinction
+-- end
+-- end
+-- end
+-- elseif font ~= prevfont then
+-- local used = usedfonts[font]
+-- if not used then
+-- local fp = fontprocesses[font]
+-- if fp then
+-- usedfonts[font] = fp
+-- u = u + 1
+-- else
+-- -- can't happen ... otherwise best use nil/false distinction
+-- end
+-- end
+-- end
+-- prevfont = font
+-- prevattr = attr
+-- ap = an
+-- elseif font ~= prevfont then
+-- local used = usedfonts[font]
+-- if not used then
+-- local fp = fontprocesses[font]
+-- if fp then
+-- usedfonts[font] = fp
+-- u = u + 1
+-- else
+-- -- can't happen ... otherwise best use nil/false distinction
+-- end
+-- end
+-- prevfont = font
+-- end
+-- -- end
+-- end
+-- if trace_fontrun then
+-- report_fonts()
+-- report_fonts("statics : %s",(u > 0 and concat(keys(usedfonts)," ")) or "none")
+-- report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none")
+-- report_fonts()
+-- end
+-- -- we could combine these and just make the attribute nil
+-- if u == 1 then
+-- local font, processors = next(usedfonts)
+-- local n = #processors
+-- if n > 0 then
+-- local h, d = processors[1](head,font,0)
+-- head = h or head
+-- done = done or d
+-- if n > 1 then
+-- for i=2,n do
+-- local h, d = processors[i](head,font,0)
+-- head = h or head
+-- done = done or d
+-- end
+-- end
+-- end
+-- elseif u > 0 then
+-- for font, processors in next, usedfonts do
+-- local n = #processors
+-- local h, d = processors[1](head,font,0)
+-- head = h or head
+-- done = done or d
+-- if n > 1 then
+-- for i=2,n do
+-- local h, d = processors[i](head,font,0)
+-- head = h or head
+-- done = done or d
+-- end
+-- end
+-- end
+-- end
+-- if a == 1 then
+-- local font, dynamics = next(attrfonts)
+-- for attribute, processors in next, dynamics do -- attr can switch in between
+-- local n = #processors
+-- if n == 0 then
+-- report_fonts("no processors associated with dynamic %s",attribute)
+-- else
+-- local h, d = processors[1](head,font,attribute)
+-- head = h or head
+-- done = done or d
+-- if n > 1 then
+-- for i=2,n do
+-- local h, d = processors[i](head,font,attribute)
+-- head = h or head
+-- done = done or d
+-- end
+-- end
+-- end
+-- end
+-- elseif a > 0 then
+-- for font, dynamics in next, attrfonts do
+-- for attribute, processors in next, dynamics do -- attr can switch in between
+-- local n = #processors
+-- if n == 0 then
+-- report_fonts("no processors associated with dynamic %s",attribute)
+-- else
+-- local h, d = processors[1](head,font,attribute)
+-- head = h or head
+-- done = done or d
+-- if n > 1 then
+-- for i=2,n do
+-- local h, d = processors[i](head,font,attribute)
+-- head = h or head
+-- done = done or d
+-- end
+-- end
+-- end
+-- end
+-- end
+-- end
+-- stoptiming(nodes)
+-- if trace_characters then
+-- nodes.report(head,done)
+-- end
+-- return head, true
+-- end
+
handlers.protectglyphs = node.protect_glyphs
handlers.unprotectglyphs = node.unprotect_glyphs
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index e654d9e0f..a294643b2 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -13,7 +13,6 @@ modules.</p>
-- this module is being reconstructed
-local utf = unicode.utf8
local next, type = next, type
local format, match, gsub = string.format, string.match, string.gsub
local concat, remove = table.concat, table.remove
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
index 4e0824fe9..33eaa6eb1 100644
--- a/tex/context/base/node-inj.lua
+++ b/tex/context/base/node-inj.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['node-inj'] = {
-- This is very experimental (this will change when we have luatex > .50 and
-- a few pending thingies are available. Also, Idris needs to make a few more
-- test fonts. Btw, future versions of luatex will have extended glyph properties
--- that can be of help.
+-- that can be of help. Some optimizations can go away when we have faster machines.
local next = next
diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua
index d30ad49a9..42c6a8543 100644
--- a/tex/context/base/node-pro.lua
+++ b/tex/context/base/node-pro.lua
@@ -6,7 +6,6 @@ if not modules then modules = { } end modules ['node-pro'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
local utfchar = utf.char
local format, concat = string.format, table.concat
diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua
index 754b398c4..6e1a31643 100644
--- a/tex/context/base/node-typ.lua
+++ b/tex/context/base/node-typ.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['node-typ'] = {
license = "see context related readme files"
}
-local utfvalues = string.utfvalues
+local utfvalues = utf.values
local currentfont = font.current
local fontparameters = fonts.hashes.parameters
diff --git a/tex/context/base/phys-dim.mkiv b/tex/context/base/phys-dim.mkiv
index 934985399..910ab9524 100644
--- a/tex/context/base/phys-dim.mkiv
+++ b/tex/context/base/phys-dim.mkiv
@@ -408,6 +408,10 @@
\newtoks \everyunits % we keep the old \units command so we need a longer one
\appendtoks
+ \disablemathpunctuation
+\to \everyunits
+
+\appendtoks
\setuevalue\currentunit{\phys_units_direct{\currentunit}}
\to \everydefineunit
diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex
index 500caa4b3..019a7b2fb 100644
--- a/tex/context/base/s-abr-01.tex
+++ b/tex/context/base/s-abr-01.tex
@@ -53,6 +53,7 @@
\logo [CCODE] {C}
\logo [CPLUSPLUS] {C\high{++}}
\logo [CALCMATH] {CalcMath}
+\logo [CLD] {cld}
\logo [CD] {cd}
\logo [CPU] {cpu}
\logo [CDROM] {cdrom}
diff --git a/tex/context/base/s-abr-04.tex b/tex/context/base/s-abr-04.tex
index ab3dc94cd..bcc2c8265 100644
--- a/tex/context/base/s-abr-04.tex
+++ b/tex/context/base/s-abr-04.tex
@@ -46,6 +46,7 @@
\logo [CCODE] {c}
\logo [CALCMATH] {CalcMath}
\logo [CD] {cd}
+\logo [CLD] {cld}
\logo [CPU] {cpu}
\logo [CDROM] {cdrom}
\logo [CID] {cid}
diff --git a/tex/context/base/s-inf-03.mkiv b/tex/context/base/s-inf-03.mkiv
index 0f4f82543..822173d00 100644
--- a/tex/context/base/s-inf-03.mkiv
+++ b/tex/context/base/s-inf-03.mkiv
@@ -4,11 +4,11 @@
% There is a loop somewhere ... todo.
% \stoptext
-\enablemode[ipad] % whatever that means
+\enablemode[tablet] % whatever that means
\setupbodyfont[dejavu]
-\doifmodeelse {ipad} {
+\doifmodeelse {tablet} {
\setuppapersize
[S6,landscape]
@@ -90,21 +90,21 @@ local extralua = libraries.extralua
local obsolete = libraries.obsolete
local find = string.find
-local color, goto = context.color, context.goto
+local color, gotolocation = context.color, context["goto"]
for k, v in table.sortedpairs(_G) do
if obsolete[k] or find(k,"_") or k == "arg" or k == "utf" then
--
elseif basiclua[k] then
- goto(function() color( { "darkred" }, k) end, { k } )
+ gotolocation(function() color( { "darkred" }, k) end, { k } )
elseif extralua[k] then
- goto(function() color( { "darkgreen" }, k) end, { k } )
+ gotolocation(function() color( { "darkgreen" }, k) end, { k } )
elseif basictex[k] then
- goto(function() color( { "darkblue" }, k) end, { k } )
+ gotolocation(function() color( { "darkblue" }, k) end, { k } )
elseif extratex[k] then
- goto(function() color( { "darkyellow" }, k) end, { k } )
+ gotolocation(function() color( { "darkyellow" }, k) end, { k } )
elseif type(v) == "table" then
- goto(function() color( { "white" }, k) end, { k } )
+ gotolocation(function() color( { "white" }, k) end, { k } )
end
context(" ")
end
@@ -156,16 +156,19 @@ local byte = string.byte
local upper = string.upper
local skipglobal = table.tohash {
- "_G", "context", "modules", "global", "arg", "utf", 1,
+ "_G", "_M", "_ENV", "",
+ "context", "modules", "global", "arg", "utf", 1,
"_ptbs_", "_pcol_", "_plib_", "_clib_", "_tlib_",
- "_M", "kpse",
+ "kpse",
}
local skipkeys = table.tohash {
"_pcol_", "_plib_", "_clib_", "_tlib_", "_bpnf_", "_ptbs_",
"_cldf_", "_cldn_",
"_clmb_", "_clme_", "_clmm_", "_clmn_", "_clma_", "_clmh_",
- "_G", "_M", "_VERSION", "_COPYRIGHT", "_DESCRIPTION", "_NAME", "_PACKAGE", "__unload",
+ "_G", "_M", "_ENV", "",
+ "_VERSION", "_COPYRIGHT", "_DESCRIPTION", "_NAME", "_PACKAGE", "__unload",
+
}
local sameglobal = {
@@ -229,7 +232,7 @@ end
local NC, NR = context.NC, context.NR
local overstrike, rlap, bf = context.overstrike, context.rlap, context.bf
-local color, goto = context.color, context.goto
+local color, gotolocation = context.color, context["goto"]
local function cleanup(s)
return "\\char" ..byte(s) .. " "
@@ -295,19 +298,19 @@ local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mar
NC() bf()
if inlib then
if not mark and t == "table" then
- goto(function() color( { libcolor }, kstr) end, { k } )
+ gotolocation(function() color( { libcolor }, kstr) end, { k } )
else
color( { libcolor }, kstr)
end
elseif inglo then
if not mark and t == "table" then
- goto(function() color( { glocolor }, kstr) end, { k } )
+ gotolocation(function() color( { glocolor }, kstr) end, { k } )
else
color( { glocolor }, kstr)
end
else
if not mark and t == "table" then
- goto(k, { kstr } )
+ gotolocation(k, { kstr } )
else
context(kstr)
end
diff --git a/tex/context/base/s-mod-01.mkiv b/tex/context/base/s-mod-01.mkiv
index ae119a7ee..6946bef69 100644
--- a/tex/context/base/s-mod-01.mkiv
+++ b/tex/context/base/s-mod-01.mkiv
@@ -25,6 +25,9 @@
%D him when you run into problems. Bugs in this style can be sent to
%D Hans.
+\usemodule
+ [abr-00]
+
\setvariables
[document]
[ file=\jobname,
diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua
index aa3caff96..99eebf0a2 100644
--- a/tex/context/base/sort-ini.lua
+++ b/tex/context/base/sort-ini.lua
@@ -43,11 +43,8 @@ with any demand so nothing here is frozen.</p>
have language etc properties that then can be used.</p>
]]--
-
-local utf = unicode.utf8
local gsub, rep, sub, sort, concat = string.gsub, string.rep, string.sub, table.sort, table.concat
-local utfbyte, utfchar = utf.byte, utf.char
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local utfbyte, utfchar, utfcharacters, utfvalues = utf.byte, utf.char, utf.characters, utf.values
local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset
local allocate = utilities.storage.allocate
@@ -246,7 +243,7 @@ local function preparetables(data)
local b = utfbyte(k)
n = decomposed[b] or { b }
if trace_tests then
- report_sorters(" 6 split: %s",utf.string(b))
+ report_sorters(" 6 split: %s",utf.tostring(b))
end
end
if n then
diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv
index eb05f66dc..0b280c149 100644
--- a/tex/context/base/spac-ver.mkiv
+++ b/tex/context/base/spac-ver.mkiv
@@ -949,17 +949,19 @@
{\dosingleempty\spac_struts_setup}
\def\spac_struts_setup[#1]%
- {\ifcsname\??struts#1\endcsname
- \csname\??struts#1\endcsname % these are defined later
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \csname\??struts\m_strut\endcsname % these are defined later
\else
- \setcharstrut{#1}%
+ \setcharstrut\m_strut
\fi}
-\def\synchronizestrut#1% no [] parsing, faster for internal
- {\ifcsname\??struts#1\endcsname
- \csname\??struts#1\endcsname
+\unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal
+ {\edef\m_strut{#1}%
+ \ifcsname\??struts\m_strut\endcsname
+ \csname\??struts\m_strut\endcsname
\else
- \setcharstrut{#1}%
+ \setcharstrut\m_strut
\fi}
\unexpanded\def\showstruts
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 2819a3f4b..53465a6bc 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index 2371c0934..55b0cb780 100644
--- a/tex/context/base/status-lua.pdf
+++ b/tex/context/base/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/status-mkiv.tex b/tex/context/base/status-mkiv.tex
index 7ca394a19..8685c97ad 100644
--- a/tex/context/base/status-mkiv.tex
+++ b/tex/context/base/status-mkiv.tex
@@ -86,6 +86,15 @@
\stoptitle
+\starttitle[title=To keep an eye on]
+
+\startitemize[packed]
+ \startitem Currently lpeg replacements interpret the percent sign so we need to escape it. \stopitem
+ \startitem Currently numbers and strings are cast in comparisons bu tthat might change in the future. \stopitem
+\stopitemize
+
+\stoptitle
+
\definehighlight[notabenered] [color=darkred, style=bold]
\definehighlight[notabeneblue] [color=darkblue, style=bold]
\definehighlight[notabeneyellow] [color=darkyellow, style=bold]
diff --git a/tex/context/base/strc-bkm.lua b/tex/context/base/strc-bkm.lua
index 4eb9551a9..dbb7d3853 100644
--- a/tex/context/base/strc-bkm.lua
+++ b/tex/context/base/strc-bkm.lua
@@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['strc-bkm'] = {
-- we should hook the placement into everystoptext ... needs checking
local format, concat, gsub = string.format, table.concat, string.gsub
-local utfvalues = string.utfvalues
+local utfvalues = utf.values
local settings_to_hash = utilities.parsers.settings_to_hash
local codeinjections = backends.codeinjections
diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua
index 7275534b7..d6b4cc96b 100644
--- a/tex/context/base/strc-doc.lua
+++ b/tex/context/base/strc-doc.lua
@@ -15,7 +15,7 @@ if not modules then modules = { } end modules ['strc-doc'] = {
-- in section titles by default a zero aborts, so there we need: sectionset=bagger with \definestructureprefixset [bagger] [section-2,section-4] []
-- in lists however zero's are ignored, so there numbersegments=2:4 gives result
-local next, type, tonumber = next, type, tonumber
+local next, type, tonumber, select = next, type, tonumber, select
local format, gsub, find, gmatch, match = string.format, string.gsub, string.find, string.gmatch, string.match
local concat, fastcopy = table.concat, table.fastcopy
local max, min = math.max, math.min
@@ -596,9 +596,8 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
local set = ""
local segments = ""
local criterium = ""
- local dataset = { ... }
- for d=1,#dataset do
- local data = dataset[d] -- can be multiple parametersets
+ for d=1,select("#",...) do
+ local data = select(d,...) -- can be multiple parametersets
if data then
if separatorset == "" then separatorset = data.separatorset or "" end
if conversionset == "" then conversionset = data.conversionset or "" end
diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua
index 3f0a8768f..790899a21 100644
--- a/tex/context/base/strc-ini.lua
+++ b/tex/context/base/strc-ini.lua
@@ -20,10 +20,10 @@ but it does not make sense to store all processdata.
]]--
-local format, concat = string.format, table.concat
+local format = string.format
local lpegmatch = lpeg.match
local count = tex.count
-local type, next, tonumber = type, next, tonumber
+local type, next, tonumber, select = type, next, tonumber, select
local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -169,9 +169,9 @@ end
helpers.simplify = simplify
function helpers.merged(...)
- local h, t = { ... }, { }
- for k=1, #h do
- local v = h[k]
+ local t = { }
+ for k=1, select("#",...) do
+ local v = select(k,...)
if v and v ~= "" and not t[k] then
t[k] = v
end
diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua
index 06a70cc28..0fd8fcd93 100644
--- a/tex/context/base/strc-ref.lua
+++ b/tex/context/base/strc-ref.lua
@@ -1780,7 +1780,7 @@ end
function filters.generic.number(data,what,prefixspec) -- todo: spec and then no stopper
if data then
- local numberdata = data.numberdata
+ numberdata = lists.reordered(data) -- data.numberdata
if numberdata then
helpers.prefix(data,prefixspec)
sections.typesetnumber(numberdata,"number",numberdata)
diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi
index 2ace41c90..edbeded68 100644
--- a/tex/context/base/strc-ref.mkvi
+++ b/tex/context/base/strc-ref.mkvi
@@ -562,7 +562,7 @@
\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}}
\def\doifreferencefoundelse#labels#yes#nop%
- {\ctxcommand{doifelsereference("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
+ {\ctxcommand{doifelsereference("\referenceprefix",\!!bs#labels\!!es,\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
{\expandtexincurrentreference
#yes}%
{#nop}}
@@ -1544,7 +1544,7 @@
{\dotripleargument\strc_references_define_program}
\def\strc_references_define_program[#name][#program][#description]%
- {\ctxcommand{defineprogram("#name","#program","#description")}}
+ {\ctxcommand{defineprogram("#name",\!!bs#program\!!es,\!!bs#description\!!es)}}
\def\program[#name]% incompatible, more consistent, hardy used anyway
{\dontleavehmode
diff --git a/tex/context/base/syst-aux.lua b/tex/context/base/syst-aux.lua
index cda340cb6..b0fb8483b 100644
--- a/tex/context/base/syst-aux.lua
+++ b/tex/context/base/syst-aux.lua
@@ -14,7 +14,6 @@ if not modules then modules = { } end modules ['syst-aux'] = {
local commands, context = commands, context
local settings_to_array = utilities.parsers.settings_to_array
-local concat = table.concat
local format = string.format
local utfsub = utf.sub
local P, C, Carg, lpegmatch, utf8char = lpeg.P, lpeg.C, lpeg.Carg, lpeg.match, lpeg.patterns.utf8char
diff --git a/tex/context/base/syst-con.lua b/tex/context/base/syst-con.lua
index ae9d15a26..3a9b966ca 100644
--- a/tex/context/base/syst-con.lua
+++ b/tex/context/base/syst-con.lua
@@ -14,7 +14,7 @@ the top of <l n='luatex'/>'s char range but outside the unicode range.</p>
--ldx]]--
local tonumber = tonumber
-local utfchar = unicode.utf8.char
+local utfchar = utf.char
local gsub, format = string.gsub, string.format
function converters.hexstringtonumber(n) tonumber(n,16) end
diff --git a/tex/context/base/syst-lua.mkiv b/tex/context/base/syst-lua.mkiv
index bca6ab3a2..88a8c246e 100644
--- a/tex/context/base/syst-lua.mkiv
+++ b/tex/context/base/syst-lua.mkiv
@@ -19,7 +19,7 @@
\def\expdoif #1#2{\ctxcommand{doif (\!!bs#1\!!es==\!!bs#2\!!es)}}
\def\expdoifnot #1#2{\ctxcommand{doifnot (\!!bs#1\!!es==\!!bs#2\!!es)}}
-% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3
+% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3
% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5
\def\expdoifcommonelse#1#2{\ctxcommand{doifcommonelse("#1","#2")}}
@@ -34,10 +34,14 @@
\unexpanded\def\writestatus#1#2{\ctxcommand{writestatus(\!!bs#1\!!es,\!!bs#2\!!es)}}
-% a handy helper (we can probably omit the tex.ctxcatcodes here as nowadays we seldom
-% change the regime at the tex end
+% A handy helper:
-\def\luaexpr#1{\ctxlua{context(tostring(#1))}}
+% \def\luaexpr#1{\ctxlua{context(tostring(#1))}} % more efficient:
+
+% We can omit the tex.ctxcatcodes here as nowadays we seldom
+% change the regime at the \TEX\ end:
+
+\def\luaexpr#1{\directlua{tex.print(tostring(#1))}}
% helpers:
diff --git a/tex/context/base/toks-ini.lua b/tex/context/base/toks-ini.lua
index 1f4d48466..f88e0fcb5 100644
--- a/tex/context/base/toks-ini.lua
+++ b/tex/context/base/toks-ini.lua
@@ -5,8 +5,7 @@ if not modules then modules = { } end modules ['toks-ini'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-local utfbyte, utfchar = utf.byte, utf.char
+local utfbyte, utfchar, utfvalues = utf.byte, utf.char, utf.values
local format, gsub = string.format, string.gsub
--[[ldx--
@@ -56,7 +55,7 @@ tokens.other = function(chr) return createtoken(utfbyte(chr), 12) end
tokens.letters = function(str)
local t, n = { }, 0
- for chr in string.utfvalues(str) do
+ for chr in utfvalues(str) do
n = n + 1
t[n] = createtoken(chr, 11)
end
diff --git a/tex/context/base/trac-log.lua b/tex/context/base/trac-log.lua
index 44de8ebe6..6c8213099 100644
--- a/tex/context/base/trac-log.lua
+++ b/tex/context/base/trac-log.lua
@@ -14,9 +14,9 @@ if not modules then modules = { } end modules ['trac-log'] = {
local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
local format, gmatch, find = string.format, string.gmatch, string.find
local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
+local topattern = string.topattern
local texcount = tex and tex.count
-local next, type = next, type
+local next, type, select = next, type, select
local setmetatableindex = table.setmetatableindex
@@ -330,7 +330,7 @@ local function setblocked(category,value)
if data[c] then
v.state = value
else
- c = escapedpattern(c,true)
+ c = topattern(c,true,true)
for k, v in next, data do
if find(k,c) then
v.state = value
@@ -548,10 +548,10 @@ local function reporthelp(t,...)
if type(helpinfo) == "string" then
reportlines(t,helpinfo)
elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
+ local n = select("#",...)
+ for i=1,n do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i < n then
t.report()
end
end
diff --git a/tex/context/base/trac-set.lua b/tex/context/base/trac-set.lua
index 8c842f542..ddbd94825 100644
--- a/tex/context/base/trac-set.lua
+++ b/tex/context/base/trac-set.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
+local format, find, lower, gsub, topattern = string.format, string.find, string.lower, string.gsub, string.topattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -98,7 +98,7 @@ local function set(t,what,newvalue)
else
value = is_boolean(value,value)
end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
+ w = topattern(w,true,true)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
@@ -152,7 +152,8 @@ function setters.register(t,what,...)
end
end
local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
+ for i=1,select("#",...) do
+ local fnc = select(i,...)
local typ = type(fnc)
if typ == "string" then
if trace_initialize then
@@ -221,7 +222,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
end
end
t.report()
@@ -245,17 +246,29 @@ local function report(setter,...)
end
end
-function setters.new(name)
+local function default(setter,name)
+ local d = setter.data[name]
+ return d and d.default
+end
+
+local function value(setter,name)
+ local d = setter.data[name]
+ return d and (d.value or d.default)
+end
+
+function setters.new(name) -- we could use foo:bar syntax (but not used that often)
local setter -- we need to access it in setter itself
setter = {
data = allocate(), -- indexed, but also default and value fields
name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
+ report = function(...) report (setter,...) end,
+ enable = function(...) enable (setter,...) end,
+ disable = function(...) disable (setter,...) end,
+ register = function(...) register(setter,...) end,
+ list = function(...) list (setter,...) end,
+ show = function(...) show (setter,...) end,
+ default = function(...) return default (setter,...) end,
+ value = function(...) return value (setter,...) end,
}
data[name] = setter
return setter
diff --git a/tex/context/base/trac-tim.lua b/tex/context/base/trac-tim.lua
index 66ac518bb..e76882afc 100644
--- a/tex/context/base/trac-tim.lua
+++ b/tex/context/base/trac-tim.lua
@@ -14,6 +14,8 @@ moduledata = moduledata or { }
local progress = moduledata.progress or { }
moduledata.progress = progress
+local report_timing = logs.reporter("timing")
+
progress.parameters = nodes.snapshots.getparameters
progress.defaultfilename = ((tex and tex.jobname) or "whatever") .. "-luatex-progress"
@@ -24,7 +26,9 @@ function progress.store()
end
function progress.save(name)
- table.save((name or progress.defaultfilename) .. ".lut",nodes.snapshots.getsamples())
+ local filename = (name or progress.defaultfilename) .. ".lut"
+ report_timing("saving data in %q",filename)
+ table.save(filename,nodes.snapshots.getsamples())
nodes.snapshots.resetsamples()
end
diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua
index 13c0aec97..ee9407074 100644
--- a/tex/context/base/typo-dir.lua
+++ b/tex/context/base/typo-dir.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['typo-dir'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-
local next, type = next, type
local format, insert, sub, find, match = string.format, table.insert, string.sub, string.find, string.match
local utfchar = utf.char
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index e9b9f1f45..cd2639c67 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['typo-krn'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-
local next, type, tonumber = next, type, tonumber
local utfchar = utf.char
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua
index 9e653ad55..d40aed579 100644
--- a/tex/context/base/typo-spa.lua
+++ b/tex/context/base/typo-spa.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['typo-spa'] = {
license = "see context related readme files"
}
-local utf = unicode.utf8
-
local next, type = next, type
local utfchar = utf.char
diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua
index df69bba0e..b496880b2 100644
--- a/tex/context/base/util-lua.lua
+++ b/tex/context/base/util-lua.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['util-lua'] = {
}
local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
-local loadstring, loadfile, type = loadstring, loadfile, type
+local load, loadfile, type = load, loadfile, type
utilities = utilities or {}
utilities.lua = utilities.lua or { }
@@ -25,11 +25,23 @@ luautilities.nofstrippedbytes = 0
local strippedchunks = { } -- allocate()
luautilities.strippedchunks = strippedchunks
+luautilities.suffixes = {
+ tma = "tma",
+ tmc = jit and "tmb" or "tmc",
+ lua = "lua",
+ luc = jit and "lub" or "luc",
+ lui = "lui",
+ luv = "luv",
+ luj = "luj",
+ tua = "tua",
+ tuc = "tuc",
+}
+
local function fatalerror(name)
utilities.report(format("fatal error in %q",name or "unknown"))
end
-if jit then
+if jit or status.luatex_version >= 74 then
local function register(name)
if tracestripping then
@@ -42,7 +54,7 @@ if jit then
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if code then
code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
if code and code ~= "" then
@@ -74,13 +86,13 @@ if jit then
end
if forcestrip or luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
elseif luautilities.alwaysstripcode then
register(name)
- return loadstring(dump(code,true)), 0
+ return load(dump(code,true)), 0
else
return code, 0
end
@@ -88,14 +100,14 @@ if jit then
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
register(name)
code = dump(code,true)
end
- return loadstring(code), 0
+ return load(code), 0
end
function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
@@ -136,67 +148,79 @@ else
return delta
end
- local function strip_code_pc(dump,name)
- local before = #dump
- local version, format, endian, int, size, ins, num = byte(dump,5,11)
- local subint
- if endian == 1 then
- subint = function(dump, i, l)
- local val = 0
- for n = l, 1, -1 do
- val = val * 256 + byte(dump,i + n - 1)
+ local strip_code_pc
+
+ if _MAJORVERSION == 5 and _MINORVERSION == 1 then
+
+ strip_code_pc = function(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
- return val, i + l
- end
- else
- subint = function(dump, i, l)
- local val = 0
- for n = 1, l, 1 do
- val = val * 256 + byte(dump,i + n - 1)
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
- return val, i + l
end
- end
- local strip_function
- strip_function = function(dump)
- local count, offset = subint(dump, 1, size)
- local stripped, dirty = rep("\0", size), offset + count
- offset = offset + count + int * 2 + 4
- offset = offset + int + subint(dump, offset, int) * ins
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- local t
- t, offset = subint(dump, offset, 1)
- if t == 1 then
- offset = offset + 1
- elseif t == 4 then
- offset = offset + size + subint(dump, offset, size)
- elseif t == 3 then
- offset = offset + num
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
end
- count, offset = subint(dump, offset, int)
- stripped = stripped .. sub(dump,dirty, offset - 1)
- for n = 1, count do
- local proto, off = strip_function(sub(dump,offset, -1))
- stripped, offset = stripped .. proto, offset + off - 1
- end
- offset = offset + subint(dump, offset, int) * int + int
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size + int * 2
- end
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size
- end
- stripped = stripped .. rep("\0", int * 3)
- return stripped, offset
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = register(name,before,after)
+ return dump, delta
end
- dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
- local after = #dump
- local delta = register(name,before,after)
- return dump, delta
+
+ else
+
+ strip_code_pc = function(dump,name)
+ return dump, 0
+ end
+
end
-- ... end of borrowed code.
@@ -216,14 +240,14 @@ else
end
if forcestrip then
local code, n = strip_code_pc(dump(code),name)
- return loadstring(code), n
+ return load(code), n
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
elseif luautilities.alwaysstripcode then
- return loadstring(strip_code_pc(dump(code),name))
+ return load(strip_code_pc(dump(code),name))
else
return code, 0
end
@@ -232,20 +256,20 @@ else
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
local n = 0
if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror(name)
end
code, n = strip_code_pc(dump(code),name)
end
- return loadstring(code), n
+ return load(code), n
end
local function stupidcompile(luafile,lucfile,strip)
local code = io.loaddata(luafile)
local n = 0
if code and code ~= "" then
- code = loadstring(code)
+ code = load(code)
if not code then
fatalerror()
end
@@ -285,6 +309,7 @@ else
utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
end
cleanup = false -- better see how bad it is
+ done = true -- hm
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
diff --git a/tex/context/base/util-pck.lua b/tex/context/base/util-pck.lua
index d964c7a23..7937ff557 100644
--- a/tex/context/base/util-pck.lua
+++ b/tex/context/base/util-pck.lua
@@ -10,6 +10,7 @@ if not modules then modules = { } end modules ['util-pck'] = {
local next, tostring, type = next, tostring, type
local sort, concat = table.sort, table.concat
+local sortedhashkeys, sortedkeys = table.sortedhashkeys, table.sortedkeys
utilities = utilities or { }
utilities.packers = utilities.packers or { }
@@ -43,27 +44,19 @@ end
packers.hashed = hashed
packers.simplehashed = simplehashed
---~ local function pack(t,keys,hash,index)
---~ for k,v in next, t do
---~ if type(v) == "table" then
---~ pack(v,keys,hash,index)
---~ end
---~ if keys[k] and type(v) == "table" then
---~ local h = hashed(v)
---~ local i = hash[h]
---~ if not i then
---~ i = #index + 1
---~ index[i] = v
---~ hash[h] = i
---~ end
---~ t[k] = i
---~ end
---~ end
---~ end
+-- In luatex < 0.74 (lua 5.1) a next chain was the same for each run so no sort was needed,
+-- but in the latest greatest versions (lua 5.2) we really need to sort the keys in order
+-- not to get endless runs due to a difference in tuc files.
local function pack(t,keys,hash,index)
if t then
- for k,v in next, t do
+ -- for k, v in next, t do
+ -- local sk = sortedkeys(t)
+ local sk = sortedhashkeys(t)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = t[k]
+ --
if type(v) == "table" then
pack(v,keys,hash,index)
if keys[k] then
diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua
index 506497875..6f16af666 100644
--- a/tex/context/base/util-prs.lua
+++ b/tex/context/base/util-prs.lua
@@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['util-prs'] = {
}
local lpeg, table, string = lpeg, table, string
-
local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
@@ -425,3 +424,42 @@ function parsers.rfc4180splitter(specification)
end
end
+-- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- utilities.parsers.stepper("1-3,7,8,9")
+-- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- utilities.parsers.stepper(" 1 : 3, ,7 ")
+-- utilities.parsers.stepper("1:4,9:13,24:*",30)
+
+local function ranger(first,last,n,action)
+ if not first then
+ -- forget about it
+ elseif last == true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+
+local cardinal = patterns.cardinal / tonumber
+local spacers = patterns.spacer^0
+local endofstring = patterns.endofstring
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1
+
+local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) )
+ * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring)
+
+function utilities.parsers.stepper(str,n,action)
+ if type(n) == "function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
diff --git a/tex/context/base/util-seq.lua b/tex/context/base/util-seq.lua
index c3361b7be..711424a2c 100644
--- a/tex/context/base/util-seq.lua
+++ b/tex/context/base/util-seq.lua
@@ -18,7 +18,7 @@ use locals to refer to them when compiling the chain.</p>
-- todo: protect groups (as in tasks)
local format, gsub, concat, gmatch = string.format, string.gsub, table.concat, string.gmatch
-local type, loadstring = type, loadstring
+local type, load = type, load
utilities = utilities or { }
local tables = utilities.tables
@@ -257,7 +257,7 @@ compile = function(t,compiler,n) -- already referred to in sequencers.new
if compiled == "" then
runner = false
else
- runner = compiled and loadstring(compiled)()
+ runner = compiled and load(compiled)()
end
t.runner = runner
return runner
diff --git a/tex/context/base/util-sql-users.lua b/tex/context/base/util-sql-users.lua
index 4bf5057b5..5b6d0906a 100644
--- a/tex/context/base/util-sql-users.lua
+++ b/tex/context/base/util-sql-users.lua
@@ -13,7 +13,7 @@ if not modules then modules = { } end modules ['util-sql-users'] = {
local sql = require("util-sql")
local md5 = require("md5")
-local format, upper, find, gsub, escapedpattern = string.format, string.upper, string.find, string.gsub, string.escapedpattern
+local format, upper, find, gsub, topattern = string.format, string.upper, string.find, string.gsub, string.topattern
local sumhexa = md5.sumhexa
local booleanstring = string.booleanstring
@@ -52,7 +52,7 @@ end
local function validaddress(address,addresses)
if address and addresses and address ~= "" and addresses ~= "" then
- if find(address,"^" .. escapedpattern(addresses,true)) then -- simple escapes
+ if find(address,topattern(addresses,true,true)) then
return true, "valid remote address"
end
return false, "invalid remote address"
diff --git a/tex/context/base/util-sql.lua b/tex/context/base/util-sql.lua
index fc460b984..5310ea699 100644
--- a/tex/context/base/util-sql.lua
+++ b/tex/context/base/util-sql.lua
@@ -60,7 +60,7 @@ if not modules then modules = { } end modules ['util-sql'] = {
local format, match = string.format, string.match
local random = math.random
-local rawset, setmetatable, getmetatable, loadstring, type = rawset, setmetatable, getmetatable, loadstring, type
+local rawset, setmetatable, getmetatable, load, type = rawset, setmetatable, getmetatable, load, type
local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
local concat = table.concat
@@ -149,7 +149,7 @@ local function makeconverter(entries,celltemplate,wraptemplate)
end
end
local code = format(wraptemplate,concat(shortcuts,"\n"),concat(assignments,"\n "))
- local func = loadstring(code)
+ local func = load(code)
return func and func()
end
diff --git a/tex/context/base/util-sta.lua b/tex/context/base/util-sta.lua
index f94c1acdf..1a61ec4e6 100644
--- a/tex/context/base/util-sta.lua
+++ b/tex/context/base/util-sta.lua
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['util-sta'] = {
local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
local format = string.format
+local select, tostring = select, tostring
local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end)
@@ -90,9 +91,8 @@ function stacker.new(name)
local hashing = true
local function push(...)
- local t = { ... }
- for i=1,#t do
- insert(stack,t[i])
+ for i=1,select("#",...) do
+ insert(stack,(select(i,...))) -- watch the ()
end
if hashing then
local c = concat(stack,"|")
diff --git a/tex/context/base/util-sto.lua b/tex/context/base/util-sto.lua
index 42ee6cf00..147f17ea9 100644
--- a/tex/context/base/util-sto.lua
+++ b/tex/context/base/util-sto.lua
@@ -12,9 +12,11 @@ utilities = utilities or { }
utilities.storage = utilities.storage or { }
local storage = utilities.storage
+local report = texio and texio.write_nl or print
+
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage cannot be marked")
+ report("fatal error: storage cannot be marked")
return -- os.exit()
end
local m = getmetatable(t)
@@ -44,36 +46,36 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage has not been allocated")
+ report("fatal error: storage has not been allocated")
return -- os.exit()
end
return t
end
---~ function utilities.storage.delay(parent,name,filename)
---~ local m = getmetatable(parent)
---~ m.__list[name] = filename
---~ end
---~
---~ function utilities.storage.predefine(parent)
---~ local list = { }
---~ local m = getmetatable(parent) or {
---~ __list = list,
---~ __index = function(t,k)
---~ local l = require(list[k])
---~ t[k] = l
---~ return l
---~ end
---~ }
---~ setmetatable(parent,m)
---~ end
---~
---~ bla = { }
---~ utilities.storage.predefine(bla)
---~ utilities.storage.delay(bla,"test","oepsoeps")
---~ local t = bla.test
---~ table.print(t)
---~ print(t.a)
+-- function utilities.storage.delay(parent,name,filename)
+-- local m = getmetatable(parent)
+-- m.__list[name] = filename
+-- end
+--
+-- function utilities.storage.predefine(parent)
+-- local list = { }
+-- local m = getmetatable(parent) or {
+-- __list = list,
+-- __index = function(t,k)
+-- local l = require(list[k])
+-- t[k] = l
+-- return l
+-- end
+-- }
+-- setmetatable(parent,m)
+-- end
+--
+-- bla = { }
+-- utilities.storage.predefine(bla)
+-- utilities.storage.delay(bla,"test","oepsoeps")
+-- local t = bla.test
+-- table.print(t)
+-- print(t.a)
function storage.setinitializer(data,initialize)
local m = getmetatable(data) or { }
@@ -98,12 +100,14 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_table (t,k) local v = { } t[k] = v return v end
+local function f_ignore() end -- t,k,v
local t_empty = { __index = f_empty }
local t_self = { __index = f_self }
+local t_table = { __index = f_table }
local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
@@ -113,6 +117,8 @@ function table.setmetatableindex(t,f)
m.__index = f_empty
elseif f == "key" then
m.__index = f_self
+ elseif f == "table" then
+ m.__index = f_table
else
m.__index = f
end
@@ -121,6 +127,8 @@ function table.setmetatableindex(t,f)
setmetatable(t, t_empty)
elseif f == "key" then
setmetatable(t, t_self)
+ elseif f == "table" then
+ setmetatable(t, t_table)
else
setmetatable(t,{ __index = f })
end
diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua
index c547d5b3e..e3d6a9f7d 100644
--- a/tex/context/base/util-tab.lua
+++ b/tex/context/base/util-tab.lua
@@ -13,24 +13,10 @@ local tables = utilities.tables
local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local type, next, rawset, tonumber, load, select = type, next, rawset, tonumber, load, select
local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
local serialize = table.serialize
--- function tables.definetable(target) -- defines undefined tables
--- local composed, t, n = nil, { }, 0
--- for name in gmatch(target,"([^%.]+)") do
--- n = n + 1
--- if composed then
--- composed = composed .. "." .. name
--- else
--- composed = name
--- end
--- t[n] = format("%s = %s or { }",composed,composed)
--- end
--- return concat(t,"\n")
--- end
-
local splitter = lpeg.tsplitat(".")
function tables.definetable(target,nofirst,nolast) -- defines undefined tables
@@ -59,13 +45,13 @@ end
-- local t = tables.definedtable("a","b","c","d")
function tables.definedtable(...)
- local l = { ... }
local t = _G
- for i=1,#l do
- local tl = t[l[i]]
+ for i=1,select("#",...) do
+ local li = select(i,...)
+ local tl = t[li]
if not tl then
tl = { }
- t[l[i]] = tl
+ t[li] = tl
end
t = tl
end
@@ -258,7 +244,7 @@ function table.deserialize(str)
if not str or str == "" then
return
end
- local code = loadstring(str)
+ local code = load(str)
if not code then
return
end
@@ -275,7 +261,7 @@ function table.load(filename)
if filename then
local t = io.loaddata(filename)
if t and t ~= "" then
- t = loadstring(t)
+ t = load(t)
if type(t) == "function" then
t = t()
if type(t) == "table" then
diff --git a/tex/context/base/x-mathml.lua b/tex/context/base/x-mathml.lua
index 430122786..f35251d37 100644
--- a/tex/context/base/x-mathml.lua
+++ b/tex/context/base/x-mathml.lua
@@ -9,13 +9,11 @@ if not modules then modules = { } end modules ['x-mathml'] = {
-- This needs an upgrade to the latest greatest mechanisms.
local type, next = type, next
-local utf = unicode.utf8
local format, lower, find, gsub = string.format, string.lower, string.find, string.gsub
local strip = string.strip
-local utfchar = utf.char
local xmlsprint, xmlcprint, xmltext, xmlcontent = xml.sprint, xml.cprint, xml.text, xml.content
local getid = lxml.getid
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local utfchar. utfcharacters, utfvalues = utf.char, utf.characters, utf.values
local lpegmatch = lpeg.match
local mathml = { }
diff --git a/tex/context/interface/keys-cs.xml b/tex/context/interface/keys-cs.xml
index 0fe7f4b4d..05c9fdf1d 100644
--- a/tex/context/interface/keys-cs.xml
+++ b/tex/context/interface/keys-cs.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='switchtorawfont'/>
<cd:command name='sym' value='sym'/>
<cd:command name='symbol' value='symbol'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='synchronizacnilista'/>
<cd:command name='synchronize' value='synchronizovat'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml
index c14f7c526..31a48c2a2 100644
--- a/tex/context/interface/keys-de.xml
+++ b/tex/context/interface/keys-de.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='switchtorawfont'/>
<cd:command name='sym' value='sym'/>
<cd:command name='symbol' value='symbol'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='synchronisationsbalken'/>
<cd:command name='synchronize' value='synchronisieren'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml
index d981143b0..57475e65b 100644
--- a/tex/context/interface/keys-en.xml
+++ b/tex/context/interface/keys-en.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='switchtorawfont'/>
<cd:command name='sym' value='sym'/>
<cd:command name='symbol' value='symbol'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='synchronizationbar'/>
<cd:command name='synchronize' value='synchronize'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml
index 3d25240bf..7fb90a042 100644
--- a/tex/context/interface/keys-fr.xml
+++ b/tex/context/interface/keys-fr.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='changepolicebrute'/>
<cd:command name='sym' value='sym'/>
<cd:command name='symbol' value='symbole'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='barresynchronisation'/>
<cd:command name='synchronize' value='synchronise'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml
index cc08f1e3e..336930e16 100644
--- a/tex/context/interface/keys-it.xml
+++ b/tex/context/interface/keys-it.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='passaafontgrezzo'/>
<cd:command name='sym' value='sim'/>
<cd:command name='symbol' value='simbolo'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='barrasincronizzazione'/>
<cd:command name='synchronize' value='sincronizza'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml
index 039d6e882..4e0797424 100644
--- a/tex/context/interface/keys-nl.xml
+++ b/tex/context/interface/keys-nl.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='switchtorawfont'/>
<cd:command name='sym' value='sym'/>
<cd:command name='symbol' value='symbool'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='synchronisatiebalk'/>
<cd:command name='synchronize' value='synchroniseer'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/context/interface/keys-pe.xml b/tex/context/interface/keys-pe.xml
index 6615a3488..014a138ac 100644
--- a/tex/context/interface/keys-pe.xml
+++ b/tex/context/interface/keys-pe.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='تغییربه‌قلم‌خام'/>
<cd:command name='sym' value='نم'/>
<cd:command name='symbol' value='نماد'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='میله‌تطابق'/>
<cd:command name='synchronize' value='تطابق'/>
<cd:command name='tab' value='تب'/>
diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml
index fb827945e..77209d4bb 100644
--- a/tex/context/interface/keys-ro.xml
+++ b/tex/context/interface/keys-ro.xml
@@ -1711,6 +1711,7 @@
<cd:command name='switchtorawfont' value='trecilafontraw'/>
<cd:command name='sym' value='sim'/>
<cd:command name='symbol' value='simbol'/>
+ <cd:command name='symoffset' value='symoffset'/>
<cd:command name='synchronizationbar' value='barasincronizare'/>
<cd:command name='synchronize' value='sincronizeaza'/>
<cd:command name='tab' value='tab'/>
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 1f402cd4f..2b1f94b14 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,789 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 12/10/12 23:20:34
+-- merge date : 12/24/12 20:08:31
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+-- move utf -> l-unicode
+-- move string -> l-string or keep it here
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+-- some code will move to unicode and string
+
+local report = texio and texio.write_nl or print
+
+-- local lpmatch = lpeg.match
+-- local lpprint = lpeg.print
+-- local lpp = lpeg.P
+-- local lpr = lpeg.R
+-- local lps = lpeg.S
+-- local lpc = lpeg.C
+-- local lpb = lpeg.B
+-- local lpv = lpeg.V
+-- local lpcf = lpeg.Cf
+-- local lpcb = lpeg.Cb
+-- local lpcg = lpeg.Cg
+-- local lpct = lpeg.Ct
+-- local lpcs = lpeg.Cs
+-- local lpcc = lpeg.Cc
+-- local lpcmt = lpeg.Cmt
+-- local lpcarg = lpeg.Carg
+
+-- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+-- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+-- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+-- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+-- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+-- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+-- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+-- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+-- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+-- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+-- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+-- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+-- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+-- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+-- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ + utfbom_8 * Cc(3) + Cc(0)
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+patterns.utfoffset = utfoffset
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+local nonspacer = 1 - spacer
+local nonwhitespace = 1 - whitespace
+
+patterns.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
+patterns.nonspacer = nonspacer
+patterns.nonwhitespace = nonwhitespace
+
+local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto
+
+----- collapser = Cs(spacer^0/"" * ((spacer^1 * P(-1) / "") + (spacer^1/" ") + P(1))^0)
+local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
+
+patterns.stripper = stripper
+patterns.collapser = collapser
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.unsigned = digit^0 * P('.') * digit^1
+patterns.float = sign^0 * patterns.unsigned
+patterns.cunsigned = digit^0 * P(',') * digit^1
+patterns.cfloat = sign^0 * patterns.cunsigned
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
+patterns.propername = R("AZ","az","__") * R("09","AZ","az", "__")^0 * P(-1)
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
+end
+
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+-- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+-- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.split(str,separator)
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+
+-- lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+end
+
+-- from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+--~ local str = " a b c d "
+
+--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]")
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(anything^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * endofstring)^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+-- todo: cache when string
+
+function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys
+ local pattern
+ local u = isutf and utf8char or 1
+ if type(one) == "table" then
+ local no = #one
+ local p = P(false)
+ if no == 0 then
+ for k, v in next, one do
+ p = p + P(k) / v
+ end
+ pattern = Cs((p + u)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ -- pattern = Cs(((1-one)^1 + one/two)^0)
+ pattern = Cs((one/two + u)^0)
+ else
+ for i=1,no do
+ local o = one[i]
+ p = p + P(o[1]) / o[2]
+ end
+ pattern = Cs((p + u)^0)
+ end
+ else
+ pattern = Cs((P(one)/(two or "") + u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst) == "table" then
+ pattern = P(false)
+ if #lst == 0 then
+ for k, v in next, lst do
+ pattern = pattern + P(k) -- ignore key, so we can use a replacer table
+ end
+ else
+ for i=1,#lst do
+ pattern = pattern + P(lst[i])
+ end
+ end
+ else
+ pattern = P(lst)
+ end
+ pattern = (1-pattern)^0 * pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+-- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+-- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+-- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+-- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+-- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+-- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+-- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+-- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
+
+-- -- slower:
+--
+-- function lpeg.counter(pattern)
+-- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+-- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+-- end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+
+-- utf extensies
+
+local utfcharacters = utf and utf.characters or string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+local utfchar = utf and utf.char or (unicode and unicode.utf8 and unicode.utf8.char)
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfcharacters(str) do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfgmatch(str,".") do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p = P(false)
+ local f = function(uc)
+ p = p + P(uc)
+ end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
+ local p = P(false)
+ for i=first,last do
+ p = p + P(utfchar(i))
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ -- tricky, these nested captures
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+-- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
+
+-- lpeg.print(lpeg.R("ab","cd","gh"))
+-- lpeg.print(lpeg.P("a","b","c"))
+-- lpeg.print(lpeg.S("a","b","c"))
+
+-- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.count("äáàa",lpeg.UP("áà")))
+-- print(lpeg.count("äáàa",lpeg.US("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR("aá")))
+-- print(lpeg.count("äáàa",lpeg.UR("àá")))
+-- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- table.sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort = table.sort
+
+local function copyindexed(old)
+ local new = { }
+ for i=1,#old do
+ new[i] = old
+ end
+ return new
+end
+
+local function sortedkeys(tab)
+ local keys, s = { }, 0
+ for key,_ in next, tab do
+ s = s + 1
+ keys[s] = key
+ end
+ sort(keys)
+ return keys
+end
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = t[k]
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
+-- a few handy ones:
+--
+-- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3
+
+patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol
+
+end -- closure
do -- begin closure to overcome local limits and interference
@@ -29,40 +812,46 @@ if not modules then modules = { } end modules ['l-string'] = {
}
local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-
--- some functions may disappear as they are not used anywhere
+local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs
-if not string.split then
+-- Some functions are already defined in l-lpeg and maybe some from here will
+-- move there (unless we also expose caches).
- -- this will be overloaded by a faster lpeg variant
+-- if not string.split then
+--
+-- function string.split(str,pattern)
+-- local t = { }
+-- if #str > 0 then
+-- local n = 1
+-- for s in gmatch(str..pattern,"(.-)"..pattern) do
+-- t[n] = s
+-- n = n + 1
+-- end
+-- end
+-- return t
+-- end
+--
+-- end
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
- end
- end
- return t
- end
+-- function string.unquoted(str)
+-- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern
+-- end
-end
+local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote
+ + patterns.dquote * C(patterns.nodquote) * patterns.dquote
function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+ return lpegmatch(unquoted,str) or str
end
---~ function stringunquoted(str)
---~ if find(str,"^[\'\"]") then
---~ return sub(str,2,-2)
---~ else
---~ return str
---~ end
---~ end
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function string.quoted(str)
return format("%q",str) -- always "
@@ -85,65 +874,112 @@ function string.limit(str,n,sentinel) -- not utf proof
end
end
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+local stripper = patterns.stripper
+local collapser = patterns.collapser
function string.strip(str)
return lpegmatch(stripper,str) or ""
end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+
+-- function string.is_empty(str)
+-- return not find(str,"%S")
+-- end
+
+local pattern = P(" ")^0 * P(-1)
+
function string.is_empty(str)
- return not find(str,"%S")
+ if str == "" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
+-- if not string.escapedpattern then
+--
+-- local patterns_escapes = {
+-- ["%"] = "%%",
+-- ["."] = "%.",
+-- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+-- ["["] = "%[", ["]"] = "%]",
+-- ["("] = "%(", [")"] = "%)",
+-- -- ["{"] = "%{", ["}"] = "%}"
+-- -- ["^"] = "%^", ["$"] = "%$",
+-- }
+--
+-- local simple_escapes = {
+-- ["-"] = "%-",
+-- ["."] = "%.",
+-- ["?"] = ".",
+-- ["*"] = ".*",
+-- }
+--
+-- function string.escapedpattern(str,simple)
+-- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+-- end
+--
+-- function string.topattern(str,lowercase,strict)
+-- if str == "" then
+-- return ".*"
+-- else
+-- str = gsub(str,".",simple_escapes)
+-- if lowercase then
+-- str = lower(str)
+-- end
+-- if strict then
+-- return "^" .. str .. "$"
+-- else
+-- return str
+-- end
+-- end
+-- end
+--
+-- end
+
+--- needs checking
+
+local anything = patterns.anything
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+
+local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
+local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
if str == "" then
return ".*"
+ elseif strict then
+ str = lpegmatch(pattern_c,str)
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
- end
- if strict then
- return "^" .. str .. "$"
- else
- return str
- end
+ str = lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
end
end
+-- print(string.escapedpattern("12+34*.tex",false))
+-- print(string.escapedpattern("12+34*.tex",true))
+-- print(string.topattern ("12+34*.tex",false,false))
+-- print(string.topattern ("12+34*.tex",false,true))
function string.valid(str,default)
return (type(str) == "string" and str ~= "" and str) or default or nil
end
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
-
-- handy fallback
string.itself = function(s) return s end
@@ -156,6 +992,19 @@ function string.totable(str)
return lpegmatch(pattern,str)
end
+-- handy from within tex:
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -168,68 +1017,23 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select
local table, string = table, string
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local getinfo = debug.getinfo
-
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Hm, actually ipairs was retained, but we no longer use it anyway.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
-
-if not ipairs then
-
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
-
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
-
- function ipairs(a)
- return iterate, a, 0
- end
-
-end
-
-if not pairs then
-
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
-
- function pairs(t)
- return next, t -- , nil
- end
-
-end
-
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
-
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local floor = math.floor
-- extra functions, some might go (when not used)
+local stripper = patterns.stripper
+
function table.strip(tab)
local lst, l = { }, 0
for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
-- skip this one
else
@@ -338,7 +1142,7 @@ local function sortedhash(t)
end
table.sortedhash = sortedhash
-table.sortedpairs = sortedhash
+table.sortedpairs = sortedhash -- obsolete
function table.append(t,list)
local n = #t
@@ -362,31 +1166,63 @@ function table.prepend(t, list)
return t
end
+-- function table.merge(t, ...) -- first one is target
+-- t = t or { }
+-- local lst = { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- t[k] = v
+-- end
+-- end
+-- return t
+-- end
+
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
t[k] = v
end
end
return t
end
+-- function table.merged(...)
+-- local tmp, lst = { }, { ... }
+-- for i=1,#lst do
+-- for k, v in next, lst[i] do
+-- tmp[k] = v
+-- end
+-- end
+-- return tmp
+-- end
+
function table.merged(...)
- local tmp, lst = { }, { ... }
- for i=1,#lst do
- for k, v in next, lst[i] do
- tmp[k] = v
+ local t = { }
+ for i=1,select("#",...) do
+ for k, v in next, (select(i,...)) do
+ t[k] = v
end
end
- return tmp
+ return t
end
+-- function table.imerge(t, ...)
+-- local lst, nt = { ... }, #t
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- nt = nt + 1
+-- t[nt] = nst[j]
+-- end
+-- end
+-- return t
+-- end
+
function table.imerge(t, ...)
- local lst, nt = { ... }, #t
- for i=1,#lst do
- local nst = lst[i]
+ local nt = #t
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
nt = nt + 1
t[nt] = nst[j]
@@ -395,10 +1231,22 @@ function table.imerge(t, ...)
return t
end
+-- function table.imerged(...)
+-- local tmp, ntmp, lst = { }, 0, {...}
+-- for i=1,#lst do
+-- local nst = lst[i]
+-- for j=1,#nst do
+-- ntmp = ntmp + 1
+-- tmp[ntmp] = nst[j]
+-- end
+-- end
+-- return tmp
+-- end
+
function table.imerged(...)
- local tmp, ntmp, lst = { }, 0, {...}
- for i=1,#lst do
- local nst = lst[i]
+ local tmp, ntmp = { }, 0
+ for i=1,select("#",...) do
+ local nst = select(i,...)
for j=1,#nst do
ntmp = ntmp + 1
tmp[ntmp] = nst[j]
@@ -410,7 +1258,7 @@ end
local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
- for k,v in next, old do
+ for k, v in next, old do
if type(v) == "table" then
new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
@@ -464,7 +1312,7 @@ end
table.fastcopy = fastcopy
table.copy = copy
-function table.derive(parent)
+function table.derive(parent) -- for the moment not public
local child = { }
if parent then
setmetatable(child,{ __index = parent })
@@ -545,6 +1393,13 @@ end
-- problem: there no good number_to_string converter with the best resolution
+-- probably using .. is faster than format
+-- maybe split in a few cases (yes/no hexify)
+
+-- todo: %g faster on numbers than %s
+
+local propername = patterns.propername -- was find(name,"^%a[%w%_]*$")
+
local function dummy() end
local function do_serialize(root,name,depth,level,indexed)
@@ -554,14 +1409,14 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s{",depth))
else
local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
+ if tn == "number" then
if hexify then
handle(format("%s[0x%04X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
handle(format("%s%s={",depth,name))
else
handle(format("%s[%q]={",depth,name))
@@ -587,7 +1442,6 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
--- if not root[k] then
if root[k] == nil then
last = k - 1
break
@@ -635,7 +1489,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
+ handle(format('%s load(%q),',depth,dump(v)))
else
handle(format('%s "function",',depth))
end
@@ -647,7 +1501,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s __p__=nil,",depth))
end
elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
else
@@ -659,7 +1513,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%04X,",depth,k,v))
else
@@ -674,7 +1528,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "string" then
if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,v))
else
@@ -682,13 +1536,13 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,v))
else
@@ -696,7 +1550,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
handle(format("%s [%q]=%q,",depth,k,v))
@@ -704,7 +1558,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "table" then
if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={},",depth,k))
else
@@ -712,7 +1566,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
handle(format("%s [%q]={},",depth,k))
@@ -720,15 +1574,15 @@ local function do_serialize(root,name,depth,level,indexed)
elseif inline then
local st = simple_table(v)
if st then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
@@ -740,15 +1594,15 @@ local function do_serialize(root,name,depth,level,indexed)
do_serialize(v,k,depth,level+1)
end
elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%s,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%s,",depth,k,tostring(v)))
@@ -757,30 +1611,30 @@ local function do_serialize(root,name,depth,level,indexed)
if functions then
local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
- if tk == "number" then -- or find(k,"^%d+$") then
+ if tk == "number" then
if hexify then
handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
+ elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
@@ -861,14 +1715,14 @@ local function serialize(_handle,root,name,specification) -- handle wins
handle("}")
end
---~ name:
---~
---~ true : return { }
---~ false : { }
---~ nil : t = { }
---~ string : string = { }
---~ 'return' : return { }
---~ number : [number] = { }
+-- name:
+--
+-- true : return { }
+-- false : { }
+-- nil : t = { }
+-- string : string = { }
+-- "return" : return { }
+-- number : [number] = { }
function table.serialize(root,name,specification)
local t, n = { }, 0
@@ -957,7 +1811,7 @@ table.flattened = flattened
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
- f = { }
+ f = { } -- this one can become obsolete
end
for i=1,#t do
local v = t[i]
@@ -986,7 +1840,7 @@ local function are_equal(a,b,n,m) -- indexed
local ai, bi = a[i], b[i]
if ai==bi then
-- same
- elseif type(ai)=="table" and type(bi)=="table" then
+ elseif type(ai) == "table" and type(bi) == "table" then
if not are_equal(ai,bi) then
return false
end
@@ -1021,10 +1875,10 @@ table.are_equal = are_equal
-- maybe also make a combined one
-function table.compact(t)
+function table.compact(t) -- remove empty tables, assumes subtables
if t then
- for k,v in next, t do
- if not next(v) then
+ for k, v in next, t do
+ if not next(v) then -- no type checking
t[k] = nil
end
end
@@ -1063,7 +1917,7 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirror(t) -- hash
+function table.mirrored(t) -- hash
local n = { }
for k, v in next, t do
n[v] = k
@@ -1086,6 +1940,17 @@ function table.reversed(t)
end
end
+function table.reverse(t)
+ if t then
+ local n = #t
+ for i=1,floor(n/2) do
+ local j = n - i + 1
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+ end
+end
+
function table.sequenced(t,sep) -- hash only
if t then
local s, n = { }, 0
@@ -1172,886 +2037,6 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
--- some code will move to unicode and string
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type, next = type, next
-local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
-local lpegtype, lpegmatch = lpeg.type, lpeg.match
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-local eol = S("\n\r")
-local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-local whitespace = eol + spacer
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.unsigned = digit^0 * P('.') * digit^1
-patterns.float = sign^0 * patterns.unsigned
-patterns.cunsigned = digit^0 * P(',') * digit^1
-patterns.cfloat = sign^0 * patterns.cunsigned
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = eol
-patterns.spacer = spacer
-patterns.whitespace = whitespace
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - spacer
-patterns.nonwhitespace = 1 - whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.singlequoted = squote * patterns.nosquote * squote
-patterns.doublequoted = dquote * patterns.nodquote * dquote
-patterns.quoted = patterns.doublequoted + patterns.singlequoted
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-local function anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) }
-end
-
-lpeg.anywhere = anywhere
-
-function lpeg.instringchecker(p)
- p = anywhere(p)
- return function(str)
- return lpegmatch(p,str) and true or false
- end
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return lpegmatch(splitters_m[separator] or splitat(separator),str)
-end
-
---~ local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
---~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
---~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
---~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.split(str,separator)
- if separator then
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return lpegmatch(c,str)
- else
- return { str }
- end
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
---~ local linesplitter = Ct(content^0)
---~
---~ function string.splitlines(str)
---~ return lpegmatch(linesplitter,str)
---~ end
-
-local linesplitter = tsplitat(newline)
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return lpegmatch(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return lpegmatch(utflinesplitter,str or "")
-end
-
-local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
-local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
-
-function string.utfsplit(str,ignorewhitespace) -- new
- if ignorewhitespace then
- return lpegmatch(utfcharsplitter_iws,str or "")
- else
- return lpegmatch(utfcharsplitter_ows,str or "")
- end
-end
-
--- inspect(string.utfsplit("a b c d"))
--- inspect(string.utfsplit("a b c d",true))
-
--- -- alternative 1: 0.77
---
--- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
---
--- function string.utflength(str)
--- return #lpegmatch(utfcharcounter,str or "")
--- end
---
--- -- alternative 2: 1.70
---
--- local n = 0
---
--- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
---
--- function string.utflength(str)
--- n = 0
--- lpegmatch(utfcharcounter,str or "")
--- return n
--- end
---
--- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
-
-local n = 0
-
-local utfcharcounter = utfbom^-1 * Cs ( (
- Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
- + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
- + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
- + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
-)^0 )
-
-function string.utflength(str)
- n = 0
- lpegmatch(utfcharcounter,str or "")
- return n
-end
-
---~ lpeg.splitters = cache -- no longer public
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return lpegmatch(c,str)
-end
-
---~ from roberto's site:
-
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
---~ local str = " a b c d "
-
---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
---~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]")
---~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]")
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(anything^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * endofstring)^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two,makefunction)
- local pattern
- if type(one) == "table" then
- local no = #one
- local p = P(false)
- if no == 0 then
- for k, v in next, one do
- p = p + P(k) / v
- end
- pattern = Cs((p + 1)^0)
- elseif no == 1 then
- local o = one[1]
- one, two = P(o[1]), o[2]
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two + 1)^0)
- else
- for i=1,no do
- local o = one[i]
- p = p + P(o[1]) / o[2]
- end
- pattern = Cs((p + 1)^0)
- end
- else
- one = P(one)
- two = two or ""
- -- pattern = Cs(((1-one)^1 + one/two)^0)
- pattern = Cs((one/two +1)^0)
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
-function lpeg.finder(lst,makefunction)
- local pattern
- if type(lst) == "table" then
- local p = P(false)
- for i=1,#lst do
- p = p + P(lst[i])
- end
- pattern = (p + 1)^0
- else
- pattern = (P(lst) + 1)^0
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-
--- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
--- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
--- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
---~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
---~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
---~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
---~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
---~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
---~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
---~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
---~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
-
---~ -- slower:
---~
---~ function lpeg.counter(pattern)
---~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
---~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
---~ end
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #lpegmatch(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #lpegmatch(p,str)
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfcharacters(str) do
- p = p + P(uc)
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfgmatch(str,".") do
- p = p + P(uc)
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p = P(false)
- local f = function(uc)
- p = p + P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
- local p = P(false)
- for i=first,last do
- p = p + P(utfchar(i))
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- -- tricky, these nested captures
- return utf8byte / f -- nil when invalid range
- end
-end
-
--- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
-
---~ lpeg.print(lpeg.R("ab","cd","gh"))
---~ lpeg.print(lpeg.P("a","b","c"))
---~ lpeg.print(lpeg.S("a","b","c"))
-
---~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
---~ print(lpeg.count("äáàa",lpeg.UP("áà")))
---~ print(lpeg.count("äáàa",lpeg.US("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR("aá")))
---~ print(lpeg.count("äáàa",lpeg.UR("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- table.sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
-
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
-
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
-
--- experiment:
-
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
-end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
- end
- return make(tree)
-end
-
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
--- handy from within tex:
-
-local lpegmatch = lpeg.match
-
-local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
-
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-
--- strips leading and trailing spaces and collapsed all other spaces
-
-local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
-
-function string.collapsespaces(str)
- return lpegmatch(pattern,str)
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
if not modules then modules = { } end modules ['l-boolean'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -2205,25 +2190,25 @@ local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = C((noslashes^0 * slashes^1)^1)
local function pathpart(name,default)
- return lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
end
local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1
local function basename(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0
local function nameonly(name)
- return lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
end
local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
local function suffixonly(name)
- return lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
end
file.pathpart = pathpart
@@ -2254,7 +2239,9 @@ local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra capture
local pattern_d = path * rest
function file.splitname(str,splitdrive)
- if splitdrive then
+ if not str then
+ -- error
+ elseif splitdrive then
return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
else
return lpegmatch(pattern_b,str) -- returns path, base, suffix
@@ -2262,34 +2249,36 @@ function file.splitname(str,splitdrive)
end
function file.splitbase(str)
- return lpegmatch(pattern_d,str) -- returns path, base+suffix
+ return str and lpegmatch(pattern_d,str) -- returns path, base+suffix
end
function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
- else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ if str then
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
end
local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1)
function file.removesuffix(name)
- return lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
end
-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1
@@ -2306,8 +2295,8 @@ end
local suffix = period/"" * (1-period-slashes)^1 * -1
local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix)
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix == "" then
return filename
elseif criterium == true then
return filename .. "." .. suffix
@@ -2353,7 +2342,7 @@ local suffix = period * (1-period-slashes)^1 * -1
local pattern = Cs((1-suffix)^0)
function file.replacesuffix(name,suffix)
- if suffix and suffix ~= "" then
+ if name and suffix and suffix ~= "" then
return lpegmatch(pattern,name) .. "." .. suffix
else
return name
@@ -2362,10 +2351,10 @@ end
--
-local reslasher = lpeg.replacer(S("\\"),"/")
+local reslasher = lpeg.replacer(P("\\"),"/")
function file.reslash(str)
- return lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
end
-- We should be able to use:
@@ -2381,7 +2370,9 @@ end
-- variant:
function file.is_writable(name)
- if lfs.isdir(name) then
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
local f = io.open(name,"wb")
if f then
@@ -2409,24 +2400,32 @@ end
local readable = P("r") * Cc(true)
function file.is_readable(name)
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
function file.size(name)
- local a = attributes(name)
- return a and a.size or 0
+ if name then
+ local a = attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
end
function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split)
- return checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
end
function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+ return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
local stripper = Cs(P(fwslash)^0/"" * reslasher)
@@ -2434,14 +2433,23 @@ local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
-function file.join(...) -- rather dirty
+local deslasher = lpeg.replacer(S("\\/")^1,"/")
+
+-- If we have a network or prefix then there is a change that we end up with two
+-- // in the middle ... we could prevent this if we (1) expand prefixes: and (2)
+-- split and rebuild as url. Of course we could assume no network paths (which
+-- makes sense) adn assume either mapped drives (windows) or mounts (unix) but
+-- then we still have to deal with urls ... anyhow, multiple // are never a real
+-- problem but just ugly.
+
+function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
return one .. "/" .. two
elseif lpegmatch(isroot,one) then
- local two = lpegmatch(reslasher,concat(lst,"/",2))
+ local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
return two
else
@@ -2450,7 +2458,7 @@ function file.join(...) -- rather dirty
elseif one == "" then
return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(reslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat(lst,"/"))
end
end
@@ -2479,6 +2487,9 @@ local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * C
local absolute = fwslash
function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
if anchor and not lpegmatch(anchors,str) then
str = getcurrentdir() .. "/" .. str
end
@@ -2488,7 +2499,6 @@ function file.collapsepath(str,anchor)
return lpegmatch(reslasher,str)
end
local starter, oldelements = lpegmatch(splitstarter,str)
--- inspect(oldelements)
local newelements = { }
local i = #oldelements
while i > 0 do
@@ -2542,11 +2552,13 @@ local whatever = P("-")^0 / ""
local pattern_b = Cs(whatever * (1 - whatever * -1)^1)
function file.robustname(str,strict)
- str = lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
- else
- return str
+ if str then
+ str = lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking)
+ else
+ return str
+ end
end
end
@@ -2554,7 +2566,9 @@ file.readdata = io.loaddata
file.savedata = io.savedata
function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+ if oldname and newname then
+ file.savedata(newname,io.loaddata(oldname))
+ end
end
-- also rewrite previous
@@ -2575,11 +2589,11 @@ lpeg.patterns.rootbased = rootbased
-- ./name ../name /name c: :// name/name
function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+ return filename and lpegmatch(qualified,filename) ~= nil
end
function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
+ return filename and lpegmatch(rootbased,filename) ~= nil
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2601,8 +2615,10 @@ end
-- for myself:
function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ if name then
+ local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
+ return a ~= "" and a or name
+ end
end
-- local debuglist = {
@@ -2954,7 +2970,7 @@ function io.readstring(f,n,m)
f:seek("set",n)
n = m
end
- local str = gsub(f:read(n),"%z","")
+ local str = gsub(f:read(n),"\000","")
return str
end
@@ -3544,11 +3560,8 @@ if not modules then modules = { } end modules ['font-con'] = {
license = "see context related readme files"
}
-
-- some names of table entries will be changed (no _)
-local utf = unicode.utf8
-
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
local utfbyte = utf.byte
@@ -5651,8 +5664,6 @@ if not modules then modules = { } end modules ['font-otf'] = {
-- more checking against low level calls of functions
-local utf = unicode.utf8
-
local utfbyte = utf.byte
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -6092,32 +6103,32 @@ function otf.load(filename,format,sub,featurefile)
starttiming(data)
report_otf("file size: %s", size)
enhancers.apply(data,filename,fontdata)
+ local packtime = { }
if packdata then
if cleanup > 0 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
+ starttiming(packtime)
enhance("pack",data,filename,nil)
+ stoptiming(packtime)
end
report_otf("saving in cache: %s",filename)
data = containers.write(otf.cache, hash, data)
if cleanup > 1 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
stoptiming(data)
if elapsedtime then -- not in generic
- report_otf("preprocessing and caching took %s seconds",elapsedtime(data))
+ report_otf("preprocessing and caching took %s seconds (packtime: %s)",
+ elapsedtime(data),packdata and elapsedtime(packtime) or 0)
end
fontloader.close(fontdata) -- free memory
if cleanup > 3 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
if cleanup > 2 then
collectgarbage("collect")
---~ lua.collectgarbage()
end
else
data = nil
@@ -6695,7 +6706,10 @@ actions["reorganize subtables"] = function(data,filename,raw)
--
local name = gk.name
--
- if features then
+ if not name then
+ -- in fact an error
+ report_otf("skipping weird lookup number %s",k)
+ elseif features then
-- scripts, tag, ismac
local f = { }
for i=1,#features do
@@ -7128,6 +7142,9 @@ actions["merge kern classes"] = function(data,filename,raw)
if type(lookups) ~= "table" then
lookups = { lookups }
end
+ -- if offsets[1] == nil then
+ -- offsets[1] = ""
+ -- end
-- we can check the max in the loop
-- local maxseconds = getn(seconds)
for n, s in next, firsts do
@@ -7148,9 +7165,9 @@ actions["merge kern classes"] = function(data,filename,raw)
if splt then
local extrakerns = { }
local baseoffset = (fk-1) * maxseconds
- -- for sk=2,maxseconds do
- -- local sv = seconds[sk]
- for sk, sv in next, seconds do
+ for sk=2,maxseconds do -- will become 1 based in future luatex
+ local sv = seconds[sk]
+ -- for sk, sv in next, seconds do
local splt = split[sv]
if splt then -- redundant test
local offset = offsets[baseoffset + sk]
@@ -8377,7 +8394,7 @@ if not modules then modules = { } end modules ['node-inj'] = {
-- This is very experimental (this will change when we have luatex > .50 and
-- a few pending thingies are available. Also, Idris needs to make a few more
-- test fonts. Btw, future versions of luatex will have extended glyph properties
--- that can be of help.
+-- that can be of help. Some optimizations can go away when we have faster machines.
local next = next
@@ -8864,7 +8881,7 @@ if not modules then modules = { } end modules ['font-ota'] = {
-- this might become scrp-*.lua
-local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat
+local type = type
if not trackers then trackers = { register = function() end } end
@@ -9249,6 +9266,8 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- handle positions (we need example fonts)
-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
+-- remove some optimizations (when I have a faster machine)
+
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
@@ -12601,7 +12620,6 @@ if not modules then modules = { } end modules ['font-def'] = {
-- We can overload some of the definers.functions so we don't local them.
-local concat = table.concat
local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
local tostring, next = tostring, next
local lpegmatch = lpeg.match
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index dd2c902cd..6b502cd24 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -22,7 +22,7 @@ if not modules then modules = { } end modules ['luatex-fonts'] = {
--
-- Todo: all global namespaces in called modules will get local shortcuts.
-utf = unicode.utf8
+utf = utf or unicode.utf8
if not generic_context then
@@ -132,10 +132,10 @@ else
-- mess up ConTeXt code for the sake of general generality. Around
-- version 1.0 there will be an official api defined.
+ loadmodule('l-lpeg.lua')
loadmodule('l-function.lua')
loadmodule('l-string.lua')
loadmodule('l-table.lua')
- loadmodule('l-lpeg.lua')
loadmodule('l-boolean.lua')
loadmodule('l-math.lua')
loadmodule('l-file.lua')