diff options
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 Binary files differindex 73f23e3ab..4feb1ffe5 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex fb3daf3d5..882ca4262 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png 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 Binary files differindex 2819a3f4b..53465a6bc 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex 2371c0934..55b0cb780 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf 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') |