From 1c36d2cc9c25d74a806ee74c0ee28da32d5e84ba Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 11 Dec 2012 00:40:14 +0200 Subject: beta 2012.12.10 23:20 --- tex/context/base/char-ent.lua | 3 +- tex/context/base/chem-str.lua | 47 +- tex/context/base/chem-str.mkiv | 9 + tex/context/base/cont-new.mkii | 2 +- tex/context/base/cont-new.mkiv | 2 +- tex/context/base/context-version.pdf | Bin 4146 -> 4089 bytes tex/context/base/context-version.png | Bin 40530 -> 40551 bytes tex/context/base/context.mkii | 2 +- tex/context/base/context.mkiv | 2 +- tex/context/base/font-def.lua | 4 +- tex/context/base/l-file.lua | 539 +++++++++----------- tex/context/base/l-lpeg.lua | 26 +- tex/context/base/l-url.lua | 35 +- tex/context/base/lang-lab.lua | 2 +- tex/context/base/lxml-tex.lua | 19 +- tex/context/base/math-frc.mkiv | 28 +- tex/context/base/math-ini.lua | 100 +++- tex/context/base/math-ini.mkiv | 6 +- tex/context/base/meta-ini.mkiv | 79 +-- tex/context/base/mlib-ctx.lua | 44 +- tex/context/base/mlib-pps.lua | 61 ++- tex/context/base/mlib-run.lua | 30 +- tex/context/base/mult-def.mkiv | 3 + tex/context/base/mult-fun.lua | 2 + tex/context/base/mult-low.lua | 5 + tex/context/base/ppchtex.mkii | 3 +- tex/context/base/s-mod-00.mkiv | 8 +- tex/context/base/s-mod-02.mkiv | 8 +- tex/context/base/status-files.pdf | Bin 24548 -> 24378 bytes tex/context/base/status-lua.pdf | Bin 199334 -> 199955 bytes tex/context/base/syst-con.lua | 20 +- tex/context/base/util-prs.lua | 14 +- tex/context/base/x-mathml.mkiv | 60 +-- tex/generic/context/luatex/luatex-fonts-merged.lua | 567 ++++++++++----------- 34 files changed, 915 insertions(+), 815 deletions(-) (limited to 'tex') diff --git a/tex/context/base/char-ent.lua b/tex/context/base/char-ent.lua index ef55be7e4..58ee9472c 100644 --- a/tex/context/base/char-ent.lua +++ b/tex/context/base/char-ent.lua @@ -567,7 +567,8 @@ local entities = utilities.storage.allocate { ["Ugr"] = "Υ", -- U+003A5 ["Ugrave"] = "Ù", -- U+000D9 ["Umacr"] = "Ū", -- U+0016A - ["UnderBar"] = "_", -- U+0005F + -- ["UnderBar"] = "_", -- U+0005F + ["UnderBar"] = "‾", -- U+0203E ["UnderBrace"] = "⏟", -- U+023DF ["UnderBracket"] = "⎵", -- U+023B5 ["UnderParenthesis"] = "⏝", -- U+023DD diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua index 0ca82d2e1..dc4bd746f 100644 --- a/tex/context/base/chem-str.lua +++ b/tex/context/base/chem-str.lua @@ -62,22 +62,35 @@ local common_keys = { 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", } local front_keys = { bb = "line", + eb = "line", rr = "line", lr = "line", lsr = "line", rsr = "line", lrz = "text", rrz = "text", - -- rz = "text", -- no lsub = "transform", rsub = "transform", } @@ -101,17 +114,11 @@ local one_keys = { es = "line", ed = "line", et = "line", - zlt = "text", - zln = "number", - zrt = "text", - zrn = "number", - rz = "text", cz = "text", rot = "transform", dir = "transform", rm = "transform", mir = "transform", - sub = "transform", } local ring_keys = { @@ -137,24 +144,12 @@ local ring_keys = { mid = "line", mids = "line", midz = "text", - zlt = "text", - zln = "number", - zrt = "text", - zrn = "number", - rz = "text", lrz = "text", rrz = "text", crz = "text", - rt = "text", - lrt = "text", - rrt = "text", - rn = "number", - lrn = "number", - rrn = "number", rot = "transform", mir = "transform", adj = "transform", - sub = "transform", lsub = "transform", rsub = "transform", rm = "transform", @@ -182,6 +177,7 @@ local syntax = { six = { max = 6, keys = ring_keys, }, seven = { max = 7, keys = ring_keys, }, eight = { max = 8, keys = ring_keys, }, + nine = { max = 9, keys = ring_keys, }, fivefront = { max = 5, keys = front_keys, }, sixfront = { max = 6, keys = front_keys, }, chair = { max = 6, keys = front_keys, }, @@ -217,7 +213,7 @@ function chemistry.define(name,spec,text) definitions[name] = dn end dn[#dn+1] = { - spec = settings_to_array_with_repeat(lower(spec),true), + spec = settings_to_array_with_repeat(spec,true), text = settings_to_array_with_repeat(text,true), } end @@ -228,6 +224,7 @@ local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser local function fetch(txt) local st = stack[txt] local t = st.text[st.n] +-- inspect(stack) while not t and txt > 1 do txt = txt - 1 st = stack[txt] @@ -338,9 +335,6 @@ local function process(spec,text,n,rulethickness,rulecolor,offset) m = m + 1 ; metacode[m] = syntax.save.direct elseif operation == "restore" then variant = remove(sstack) - if variant and #sstack == 0 then - insert(sstack,variant) -- allow multiple restores at the bottom of the stack. - end local ss = syntax[variant] keys, max = ss.keys, ss.max m = m + 1 ; metacode[m] = syntax[operation].direct @@ -580,7 +574,12 @@ function chemistry.stop() if metapost.instance(chemistry.instance) then t_initialize = "" end - metapost.graphic(chemistry.instance,chemistry.format,mpcode,"","",t_initialize) + metapost.graphic { + instance = chemistry.instance, + format = chemistry.format, + data = mpcode, + definitions = t_initialize, + } t_initialize = "" metacode = nil end diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv index 2d4449a25..205675c46 100644 --- a/tex/context/base/chem-str.mkiv +++ b/tex/context/base/chem-str.mkiv @@ -388,7 +388,15 @@ \unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6} \unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7} +\unexpanded\def\chemicalbar + {\hbox \!!spread .5\emwidth \bgroup + \hss + \vrule \!!height .9\strutht \!!depth .65\strutdp \!!width .1\exheight + \hss + \egroup} + \appendtoks + \let|\chemicalbar % \SR{N|NH} \let \+\chemicaloxidationplus \let \-\chemicaloxidationminus \let \[\chemicalforeveropen @@ -419,6 +427,7 @@ \let\SM\chemicalsmashedmiddle \let\SR\chemicalsmashedright \to \everychemical + % Should these also be defined in lower case, so as to be case independent? \appendtoks diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 749ec9477..3f5956611 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.06 22:36} +\newcontextversion{2012.12.10 23:20} %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 952d14da1..e67181585 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.06 22:36} +\newcontextversion{2012.12.10 23:20} %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/context-version.pdf b/tex/context/base/context-version.pdf index afeae25e9..73f23e3ab 100644 Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png index 7002ba4ae..fb3daf3d5 100644 Binary files a/tex/context/base/context-version.png and b/tex/context/base/context-version.png differ diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 71a16df3a..dfe757926 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.06 22:36} +\edef\contextversion{2012.12.10 23:20} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 387888068..e47b0e4f1 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.06 22:36} +\edef\contextversion{2012.12.10 23:20} %D For those who want to use this: diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index f50e57113..03037f1c6 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -48,7 +48,9 @@ local internalized = allocate() -- internal tex numbers (private) local loadedfonts = constructors.loadedfonts local designsizes = constructors.designsizes -local resolvefile = fontgoodies.filenames.resolve +-- not in generic (some day I'll make two defs, one for context, one for generic) + +local resolvefile = fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end --[[ldx--

We hardly gain anything when we cache the final (pre scaled) diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index 03323d29e..d1ec753b1 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -12,66 +12,145 @@ file = file or { } local file = file local insert, concat = table.insert, table.concat -local find, gmatch, match, gsub, sub, char, lower = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char, string.lower +local match = string.match local lpegmatch = lpeg.match local getcurrentdir, attributes = lfs.currentdir, lfs.attributes +local checkedsplit = string.checkedsplit + +-- local patterns = file.patterns or { } +-- file.patterns = patterns + +local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct + +local colon = P(":") +local period = P(".") +local periods = P("..") +local fwslash = P("/") +local bwslash = P("\\") +local slashes = S("\\/") +local noperiod = 1-period +local noslashes = 1-slashes +local name = noperiod^1 +local suffix = period/"" * (1-period-slashes)^1 * -1 -local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc +local pattern = C((noslashes^0 * slashes^1)^1) -local function dirname(name,default) - return match(name,"^(.+)[/\\].-$") or (default or "") +local function pathpart(name,default) + return lpegmatch(pattern,name) or default or "" end +local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 + local function basename(name) - return match(name,"^.+[/\\](.-)$") or name + return lpegmatch(pattern,name) or name end --- local function nameonly(name) --- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) --- end +local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0 local function nameonly(name) - return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$","")) + return lpegmatch(pattern,name) or name end -local function suffixonly(name,default) - return match(name,"^.+%.([^/\\]-)$") or default or "" -end +local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 -local function splitname(name) - local n, s = match(name,"^(.+)%.([^/\\]-)$") - return n or name, s or "" +local function suffixonly(name) + return lpegmatch(pattern,name) or "" end +file.pathpart = pathpart file.basename = basename - -file.pathpart = dirname -file.dirname = dirname - file.nameonly = nameonly - file.suffixonly = suffixonly -file.extname = suffixonly -- obsolete file.suffix = suffixonly -function file.removesuffix(filename) - return (gsub(filename,"%.[%a%d]+$","")) +file.dirname = pathpart -- obsolete +file.extname = suffixonly -- obsolete + +-- actually these are schemes + +local drive = C(R("az","AZ")) * colon +local path = C(((1-slashes)^0 * slashes)^0) +local suffix = period * C(P(1-period)^0 * P(-1)) +local base = C((1-suffix)^0) +local rest = C(P(1)^0) + +drive = drive + Cc("") +path = path + Cc("") +base = base + Cc("") +suffix = suffix + Cc("") + +local pattern_a = drive * path * base * suffix +local pattern_b = path * base * suffix +local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures +local pattern_d = path * rest + +function file.splitname(str,splitdrive) + if splitdrive then + return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix + else + return lpegmatch(pattern_b,str) -- returns path, base, suffix + end +end + +function file.splitbase(str) + return 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, + } + end +end + +local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1) + +function file.removesuffix(name) + return lpegmatch(pattern,name) +end + +-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 +-- +-- function file.addsuffix(name, suffix) +-- local p = lpegmatch(pattern,name) +-- if p then +-- return name +-- else +-- return name .. "." .. suffix +-- end +-- 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 return filename elseif criterium == true then return filename .. "." .. suffix elseif not criterium then - local n, s = splitname(filename) + local n, s = lpegmatch(pattern,filename) if not s or s == "" then return filename .. "." .. suffix else return filename end else - local n, s = splitname(filename) + local n, s = lpegmatch(pattern,filename) if s and s ~= "" then local t = type(criterium) if t == "table" then @@ -88,96 +167,49 @@ function file.addsuffix(filename, suffix, criterium) end end end - return n .. "." .. suffix + return (n or filename) .. "." .. suffix end end ---~ print("1 " .. file.addsuffix("name","new") .. " -> name.new") ---~ print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") ---~ print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") ---~ print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") ---~ print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") ---~ print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") ---~ print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") ---~ print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") - -function file.replacesuffix(filename, suffix) - return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix -end - -local trick_1 = char(1) -local trick_2 = "^" .. trick_1 .. "/+" - -function file.join(...) -- rather dirty - local lst = { ... } - local a, b = lst[1], lst[2] - if not a or a == "" then -- not a added - lst[1] = trick_1 - elseif b and find(a,"^/+$") and find(b,"^/") then - lst[1] = "" - lst[2] = gsub(b,"^/+","") - end - local pth = concat(lst,"/") - pth = gsub(pth,"\\","/") - local a, b = match(pth,"^(.*://)(.*)$") - if a and b then - return a .. gsub(b,"//+","/") - end - a, b = match(pth,"^(//)(.*)$") - if a and b then - return a .. gsub(b,"//+","/") +-- print("1 " .. file.addsuffix("name","new") .. " -> name.new") +-- print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") +-- print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") +-- print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") +-- print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") +-- print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") +-- print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") +-- print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") + +local suffix = period * (1-period-slashes)^1 * -1 +local pattern = Cs((1-suffix)^0) + +function file.replacesuffix(name,suffix) + if suffix and suffix ~= "" then + return lpegmatch(pattern,name) .. "." .. suffix + else + return name end - pth = gsub(pth,trick_2,"") - return (gsub(pth,"//+","/")) end --- local slash = P("/") --- local colon = P(":") - --- local replacer = lpeg.replacer(S("\\/")^1,"/") --- local stripper = Cs(P(slash)^0/"" * replacer) --- local isnetwork = slash * slash * (1-slash) + (1-slash-colon)^1 * colon --- local isroot = slash^1 * -1 --- local hasroot = slash^1 - --- function file.newjoin(...) -- rather dirty --- local lst = { ... } --- local one = lst[1] --- if lpegmatch(isnetwork,one) then --- local two = lpegmatch(replacer,concat(lst,"/",2)) --- return one .. two --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(replacer,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- elseif one == "" then --- return lpegmatch(stripper,concat(lst,"/",2)) --- else --- return lpegmatch(replacer,concat(lst,"/")) --- end --- end +-- --- print(file.join("//","/y")) --- print(file.join("/","/y")) --- print(file.join("","/y")) --- print(file.join("/x/","/y")) --- print(file.join("x/","/y")) --- print(file.join("http://","/y")) --- print(file.join("http://a","/y")) --- print(file.join("http:///a","/y")) --- print(file.join("//nas-1","/y")) +local reslasher = lpeg.replacer(S("\\"),"/") + +function file.reslash(str) + return lpegmatch(reslasher,str) +end -- We should be able to use: -- +-- local writable = P(1) * P("w") * Cc(true) +-- -- function file.is_writable(name) --- local a = attributes(name) or attributes(dirname(name,".")) --- return a and sub(a.permissions,2,2) == "w" +-- local a = attributes(name) or attributes(pathpart(name,".")) +-- return a and lpegmatch(writable,a.permissions) or false -- end -- --- But after some testing Taco and I came up with: +-- But after some testing Taco and I came up with the more robust +-- variant: function file.is_writable(name) if lfs.isdir(name) then @@ -205,9 +237,11 @@ function file.is_writable(name) return false end +local readable = P("r") * Cc(true) + function file.is_readable(name) local a = attributes(name) - return a and sub(a.permissions,1,1) == "r" + return a and lpegmatch(readable,a.permissions) or false end file.isreadable = file.is_readable -- depricated @@ -218,64 +252,74 @@ function file.size(name) return a and a.size or 0 end --- todo: lpeg \\ / .. does not save much - -local checkedsplit = string.checkedsplit - -function file.splitpath(str,separator) -- string - str = gsub(str,"\\","/") - return checkedsplit(str,separator or io.pathseparator) +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) end function file.joinpath(tab,separator) -- table return concat(tab,separator or io.pathseparator) -- can have trailing // end --- we can hash them weakly - ---~ function file.collapsepath(str) -- fails on b.c/.. ---~ str = gsub(str,"\\","/") ---~ if find(str,"/") then ---~ str = gsub(str,"^%./",(gsub(getcurrentdir(),"\\","/")) .. "/") -- ./xx in qualified ---~ str = gsub(str,"/%./","/") ---~ local n, m = 1, 1 ---~ while n > 0 or m > 0 do ---~ str, n = gsub(str,"[^/%.]+/%.%.$","") ---~ str, m = gsub(str,"[^/%.]+/%.%./","") ---~ end ---~ str = gsub(str,"([^/])/$","%1") ---~ -- str = gsub(str,"^%./","") -- ./xx in qualified ---~ str = gsub(str,"/%.$","") ---~ end ---~ if str == "" then str = "." end ---~ return str ---~ end ---~ ---~ The previous one fails on "a.b/c" so Taco came up with a split based ---~ variant. After some skyping we got it sort of compatible with the old ---~ one. After that the anchoring to currentdir was added in a better way. ---~ Of course there are some optimizations too. Finally we had to deal with ---~ windows drive prefixes and things like sys://. +local stripper = Cs(P(fwslash)^0/"" * reslasher) +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 lst = { ... } + local one = lst[1] + if lpegmatch(isnetwork,one) then + local two = lpegmatch(reslasher,concat(lst,"/",2)) + return one .. "/" .. two + elseif lpegmatch(isroot,one) then + local two = lpegmatch(reslasher,concat(lst,"/",2)) + if lpegmatch(hasroot,two) then + return two + else + return "/" .. two + end + elseif one == "" then + return lpegmatch(stripper,concat(lst,"/",2)) + else + return lpegmatch(reslasher,concat(lst,"/")) + end +end + +-- print(file.join("c:/whatever","name")) +-- print(file.join("//","/y")) +-- print(file.join("/","/y")) +-- print(file.join("","/y")) +-- print(file.join("/x/","/y")) +-- print(file.join("x/","/y")) +-- print(file.join("http://","/y")) +-- print(file.join("http://a","/y")) +-- print(file.join("http:///a","/y")) +-- print(file.join("//nas-1","/y")) + +-- The previous one fails on "a.b/c" so Taco came up with a split based +-- variant. After some skyping we got it sort of compatible with the old +-- one. After that the anchoring to currentdir was added in a better way. +-- Of course there are some optimizations too. Finally we had to deal with +-- windows drive prefixes and things like sys://. Eventually gsubs and +-- finds were replaced by lpegs. + +local drivespec = R("az","AZ")^1 * colon +local anchors = fwslash + drivespec +local untouched = periods + (1-period)^1 * P(-1) +local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * Ct(lpeg.splitat(S("/\\")^1)) +local absolute = fwslash function file.collapsepath(str,anchor) - if anchor and not find(str,"^/") and not find(str,"^%a:") then + if anchor and not lpegmatch(anchors,str) then str = getcurrentdir() .. "/" .. str end if str == "" or str =="." then return "." - elseif find(str,"^%.%.") then - str = gsub(str,"\\","/") - return str - elseif not find(str,"%.") then - str = gsub(str,"\\","/") - return str - end - str = gsub(str,"\\","/") - local starter, rest = match(str,"^(%a+:/*)(.-)$") - if starter then - str = rest + elseif lpegmatch(untouched,str) then + return lpegmatch(reslasher,str) end - local oldelements = checkedsplit(str,"/") + local starter, oldelements = lpegmatch(splitstarter,str) +-- inspect(oldelements) local newelements = { } local i = #oldelements while i > 0 do @@ -305,7 +349,7 @@ function file.collapsepath(str,anchor) return starter or "." elseif starter then return starter .. concat(newelements, '/') - elseif find(str,"^/") then + elseif lpegmatch(absolute,str) then return "/" .. concat(newelements,'/') else return concat(newelements, '/') @@ -322,29 +366,21 @@ end -- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..") -- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..") +local validchars = R("az","09","AZ","--","..") +local pattern_a = lpeg.replacer(1-validchars) +local pattern_a = Cs((validchars + P(1)/"-")^1) +local whatever = P("-")^0 / "" +local pattern_b = Cs(whatever * (1 - whatever * -1)^1) + function file.robustname(str,strict) - str = gsub(str,"[^%a%d%/%-%.\\]+","-") + str = lpegmatch(pattern_a,str) or str if strict then - return lower(gsub(str,"^%-*(.-)%-*$","%1")) + return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking) else return str end end --- local pattern_a = lpeg.replacer(1-R("az","09","AZ","--","..")) --- local pattern_a = Cs((R("az","09","AZ","--","..") + P(1)/"-")^1) --- 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 --- end --- end - file.readdata = io.loaddata file.savedata = io.savedata @@ -352,92 +388,17 @@ function file.copy(oldname,newname) file.savedata(newname,io.loaddata(oldname)) end --- lpeg variants, slightly faster, not always - --- local period = P(".") --- local slashes = S("\\/") --- local noperiod = 1-period --- local noslashes = 1-slashes --- local name = noperiod^1 - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 - --- function file.suffixonly(name) --- return lpegmatch(pattern,name) or "" --- end - --- local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1) - --- function file.removesuffix(name) --- return lpegmatch(pattern,name) --- end - --- local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 - --- function file.basename(name) --- return lpegmatch(pattern,name) or name --- end - --- local pattern = Cs ((1 - slashes * noslashes^1 * -1)^1) - --- function file.dirname(name) --- return lpegmatch(pattern,name) or "" --- end - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 - --- function file.addsuffix(name, suffix) --- local p = lpegmatch(pattern,name) --- if p then --- return name --- else --- return name .. "." .. suffix --- end --- end - --- local suffix = period * (1-period-slashes)^1 * -1 --- local pattern = Cs((1-suffix)^1) - --- function file.replacesuffix(name,suffix) --- if suffix and suffix ~= "" then --- return lpegmatch(pattern,name) .. "." .. suffix --- else --- return name --- end --- end - --- local path = noslashes^0 * slashes^1 --- local suffix = period * (1-period-slashes)^1 * -1 --- local pattern = path^0 * Cs((1-suffix)^1) * suffix^0 - --- function file.nameonly(name) --- return lpegmatch(pattern,name) or name --- end - --- local test = file.suffixonly --- local test = file.basename --- local test = file.dirname --- local test = file.addsuffix --- local test = file.replacesuffix --- local test = file.nameonly - --- print(1,test("./a/b/c/abd.def.xxx","!!!")) --- print(2,test("./../b/c/abd.def.xxx","!!!")) --- print(3,test("a/b/c/abd.def.xxx","!!!")) --- print(4,test("a/b/c/def.xxx","!!!")) --- print(5,test("a/b/c/def","!!!")) --- print(6,test("def","!!!")) --- print(7,test("def.xxx","!!!")) - --- local tim = os.clock() for i=1,250000 do local ext = test("abd.def.xxx","!!!") end print(os.clock()-tim) - -- also rewrite previous local letter = R("az","AZ") + S("_-+") local separator = P("://") -local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/") -local rootbased = P("/") + letter*P(":") +local qualified = period^0 * fwslash + + letter * colon + + letter^1 * separator + + letter^1 * fwslash +local rootbased = fwslash + + letter * colon lpeg.patterns.qualified = qualified lpeg.patterns.rootbased = rootbased @@ -452,61 +413,6 @@ function file.is_rootbased_path(filename) return lpegmatch(rootbased,filename) ~= nil end --- actually these are schemes - -local slash = S("\\/") -local period = P(".") -local drive = C(R("az","AZ")) * P(":") -local path = C(((1-slash)^0 * slash)^0) -local suffix = period * C(P(1-period)^0 * P(-1)) -local base = C((1-suffix)^0) -local rest = C(P(1)^0) - -drive = drive + Cc("") -path = path + Cc("") -base = base + Cc("") -suffix = suffix + Cc("") - -local pattern_a = drive * path * base * suffix -local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures -local pattern_d = path * rest - -function file.splitname(str,splitdrive) - if splitdrive then - return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix - else - return lpegmatch(pattern_b,str) -- returns path, base, suffix - end -end - -function file.splitbase(str) - return 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, - } - end -end - --- print(file.splitbase("a/b/c.txt")) - -- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end -- -- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } @@ -514,14 +420,14 @@ end -- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } -- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } ---~ -- todo: ---~ ---~ if os.type == "windows" then ---~ local currentdir = getcurrentdir ---~ function getcurrentdir() ---~ return (gsub(currentdir(),"\\","/")) ---~ end ---~ end +-- -- maybe: +-- +-- if os.type == "windows" then +-- local currentdir = getcurrentdir +-- function getcurrentdir() +-- return lpegmatch(reslasher,currentdir()) +-- end +-- end -- for myself: @@ -529,3 +435,18 @@ function file.strip(name,dir) local b, a = match(name,"^(.-)" .. dir .. "(.*)$") return a ~= "" and a or name end + +-- local debuglist = { +-- "pathpart", "basename", "nameonly", "suffixonly", "suffix", "dirname", "extname", +-- "addsuffix", "removesuffix", "replacesuffix", "join", +-- "strip","collapsepath", "joinpath", "splitpath", +-- } + +-- for i=1,#debuglist do +-- local name = debuglist[i] +-- local f = file[name] +-- file[name] = function(...) +-- print(name,f(...)) +-- return f(...) +-- end +-- end diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index c461df1ce..a5fdec765 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -443,7 +443,8 @@ function lpeg.replacer(one,two,makefunction) 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(((1-one)^1 + one/two)^0) + pattern = Cs((one/two + 1)^0) else for i=1,no do local o = one[i] @@ -454,7 +455,28 @@ function lpeg.replacer(one,two,makefunction) else one = P(one) two = two or "" - pattern = Cs(((1-one)^1 + one/two)^0) + -- 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) diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua index ab5002881..4624a0507 100644 --- a/tex/context/base/l-url.lua +++ b/tex/context/base/l-url.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['l-url'] = { license = "see context related readme files" } -local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find +local char, format, byte = string.char, string.format, string.byte local concat = table.concat local tonumber, type = tonumber, type local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V @@ -45,6 +45,8 @@ local nothing = Cc("") local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar local escaped = (plus / " ") + escapedchar +local noslash = P("/") / "" + -- we assume schemes with more than 1 character (in order to avoid problems with windows disks) -- we also assume that when we have a scheme, we also have an authority -- @@ -233,29 +235,23 @@ function url.construct(hash) -- dodo: we need to escape ! return lpegmatch(escaper,concat(fullurl)) end -function url.filename(filename) -- why no lpeg here ? - local t = hashed(filename) - return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename +local pattern = Cs(noslash * R("az","AZ") * (S(":|")/":") * noslash * P(1)^0) + +function url.filename(filename) + local spec = hashed(filename) + local path = spec.path + return (spec.scheme == "file" and path and lpegmatch(pattern,path)) or filename end +-- print(url.filename("/c|/test")) +-- print(url.filename("/c/test")) + local function escapestring(str) return lpegmatch(escaper,str) end url.escape = escapestring --- function url.query(str) -- separator could be an option --- if type(str) == "string" then --- local t = { } --- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do --- t[k] = v --- end --- return t --- else --- return str --- end --- end - function url.query(str) if type(str) == "string" then return lpegmatch(splitquery,str) or "" @@ -283,14 +279,19 @@ end -- /test/ | /test | test/ | test => test +local pattern = Cs(noslash^0 * (1 - noslash * P(-1))^0) + function url.barepath(path) if not path or path == "" then return "" else - return (gsub(path,"^/?(.-)/?$","%1")) + return lpegmatch(pattern,path) end end +-- print(url.barepath("/test"),url.barepath("test/"),url.barepath("/test/"),url.barepath("test")) +-- print(url.barepath("/x/yz"),url.barepath("x/yz/"),url.barepath("/x/yz/"),url.barepath("x/yz")) + --~ print(url.filename("file:///c:/oeps.txt")) --~ print(url.filename("c:/oeps.txt")) --~ print(url.filename("file:///oeps.txt")) diff --git a/tex/context/base/lang-lab.lua b/tex/context/base/lang-lab.lua index 755f236cf..568964251 100644 --- a/tex/context/base/lang-lab.lua +++ b/tex/context/base/lang-lab.lua @@ -170,7 +170,7 @@ commands.definelabels = labels.define -- text : "a,b,c" -- separators : "{, },{ and }" -function commands.concat(settings) -- it's too easy to forget that this one is there +function commands.concatcommalist(settings) -- it's too easy to forget that this one is there local list = settings.list or settings_to_array(settings.text or "") local size = #list local command = settings.command and context[settings.command] or context diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua index 3f1ec8254..6ff96bf05 100644 --- a/tex/context/base/lxml-tex.lua +++ b/tex/context/base/lxml-tex.lua @@ -1401,18 +1401,6 @@ function lxml.raw(id,pattern) -- the content, untouched by commands end end -function lxml.context(id,pattern) -- the content, untouched by commands - if not pattern then - local collected = getid(id) - ctx_text(collected.dt[1]) - else - local collected = xmlapplylpath(getid(id),pattern) or getid(id) - if collected and #collected > 0 then - contextsprint(ctxcatcodes,collected[1].dt) - end - end -end - function lxml.context(id,pattern) -- the content, untouched by commands if pattern then local collected = xmlapplylpath(getid(id),pattern) or getid(id) @@ -1421,8 +1409,11 @@ function lxml.context(id,pattern) -- the content, untouched by commands end else local collected = getid(id) - if collected and #collected > 0 then - ctx_text(collected.dt[1]) + if collected then + local dt = collected.dt + if #dt > 0 then + ctx_text(dt[1]) + end end end end diff --git a/tex/context/base/math-frc.mkiv b/tex/context/base/math-frc.mkiv index 59bd588c0..17879cbe0 100644 --- a/tex/context/base/math-frc.mkiv +++ b/tex/context/base/math-frc.mkiv @@ -68,8 +68,30 @@ %D So we stick to the next definitions (watch the local %D overloading of \type {\xfrac}). -\def\math_fractions_forced#1#2#3{\relax\mathematics{\Ustack{{#1{#2}}\normalover{#1{#3}}}}} -\def\math_fractions_auto #1#2{\relax\mathematics{\Ustack{{#1}\normalover{#2}}}} +% \def\math_fractions_forced#1#2#3{\relax\mathematics{\Ustack{{#1{#2}}\normalover{#1{#3}}}}} +% \def\math_fractions_auto #1#2{\relax\mathematics{\Ustack{{#1}\normalover{#2}}}} + +\def\math_fractions_forced#1#2#3% + {\vcenter\expandafter\bgroup + \expandafter\hbox\expandafter\bgroup\expandafter + \startimath + \triggermathstyle\normalmathstyle + \Ustack{{#1{#2}}\normalover{#1{#3}}}% + \stopimath + \egroup + \egroup} + +\def\math_fractions_auto#1#2% + {\vcenter\expandafter\bgroup + \expandafter\hbox\expandafter\bgroup\expandafter + \startimath + \triggermathstyle\normalmathstyle + \Ustack{{#1}\normalover{#2}}% + \stopimath + \egroup + \egroup} + +% \def\math_fractions_auto{\math_fractions_forced\firstofoneargument} % $\mathfracmode0 \frac{1}{2}$ % $\mathfracmode1 \frac{1}{2}$ @@ -82,7 +104,7 @@ \setnewconstant\mathfracmode\zerocount -\unexpanded\def\frac % overloaded later on +\unexpanded\def\frac {\ifcase\mathfracmode \expandafter\math_fractions_auto \or diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 632bd0bbc..c83bac309 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -304,26 +304,98 @@ end -- needed for mathml analysis +-- we could cache + local function utfmathclass(chr, default) local cd = chardata[utfbyte(chr)] - return (cd and cd.mathclass) or default or "unknown" + return cd and cd.mathclass or default or "unknown" end -local function utfmathaccent(chr, default) +local function utfmathaccent(chr,default,asked) local cd = chardata[utfbyte(chr)] - local mc = cd and cd.mathclass or "unknown" - return mc and accents[mc] or false + if not cd then + return default or false + end + if asked then + local mc = cd.mathclass + if mc and mc == asked then + return true + end + local ms = cd.mathspec + if ms then + for i=1,#ms do + local msi = ms[i] + local mc = msi.class + if mc and mc == asked then + return true + end + end + end + else + local mc = cd.mathclass + if mc then + return accents[mc] or default or false + end + local ms = cd.mathspec + if ms then + for i=1,#ms do + local msi = ms[i] + local mc = msi.class + if mc then + return accents[mc] or default or false + end + end + end + end + return default or false end local function utfmathstretch(chr, default) -- "h", "v", "b", "" local cd = chardata[utfbyte(chr)] - return (cd and cd.mathstretch) or default or "" + return cd and cd.mathstretch or default or "" end -local function utfmathcommand(chr, default) +local function utfmathcommand(chr,default,asked) +-- local cd = chardata[utfbyte(chr)] +-- local cmd = cd and cd.mathname +-- return cmd or default or "" local cd = chardata[utfbyte(chr)] - local cmd = cd and cd.mathname - return cmd or default or "" + if not cd then + return default or "" + end + if asked then + local mn = cd.mathname + local mc = cd.mathclass + if mn and mc and mc == asked then + return mn + end + local ms = cd.mathspec + if ms then + for i=1,#ms do + local msi = ms[i] + local mn = msi.name + if mn and msi.class == asked then + return mn + end + end + end + else + local mn = cd.mathname + if mn then + return mn + end + local ms = cd.mathspec + if ms then + for i=1,#ms do + local msi = ms[i] + local mn = msi.name + if mn then + return mn + end + end + end + end + return default or "" end local function utfmathfiller(chr, default) @@ -339,13 +411,13 @@ mathematics.utfmathfiller = utfmathfiller -- interfaced -function commands.utfmathclass (chr) context(utfmathclass (chr)) end -function commands.utfmathstretch(chr) context(utfmathstretch(chr)) end -function commands.utfmathcommand(chr) context(utfmathcommand(chr)) end -function commands.utfmathfiller (chr) context(utfmathfiller (chr)) end +function commands.utfmathclass (...) context(utfmathclass (...)) end +function commands.utfmathstretch(...) context(utfmathstretch(...)) end +function commands.utfmathcommand(...) context(utfmathcommand(...)) end +function commands.utfmathfiller (...) context(utfmathfiller (...)) end -function commands.doifelseutfmathaccent(chr) - commands.doifelse(utfmathaccent(chr)) +function commands.doifelseutfmathaccent(chr,asked) + commands.doifelse(utfmathaccent(chr,nil,asked)) end -- helpers diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv index ebe8ea709..3de4c808f 100644 --- a/tex/context/base/math-ini.mkiv +++ b/tex/context/base/math-ini.mkiv @@ -250,7 +250,11 @@ \def\utfmathcommand#1{\ctxcommand{utfmathcommand(\!!bs#1\!!es)}} \def\utfmathfiller #1{\ctxcommand{utfmathfiller (\!!bs#1\!!es)}} -\unexpanded\def\doifelseutfmathaccent#1{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es)}} +\def\utfmathclassfiltered #1#2{\ctxcommand{utfmathclass (\!!bs#1\!!es,nil,"#2")}} +\def\utfmathcommandfiltered#1#2{\ctxcommand{utfmathcommand(\!!bs#1\!!es,nil,"#2")}} + +\unexpanded\def\doifelseutfmathaccent #1{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es)}} +\unexpanded\def\doifelseutfmathaccentfiltered#1#2{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es,"#2")}} %D Not used that much: diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv index fec3a64f9..e731d26e0 100644 --- a/tex/context/base/meta-ini.mkiv +++ b/tex/context/base/meta-ini.mkiv @@ -51,7 +51,7 @@ \ifx\currentMPinstance\empty \let\currentMPinstance\defaultMPinstance \fi - \global\t_meta_instance\expandafter{\the\t_meta_instance#2}% + \global\t_meta_definitions\expandafter{\the\t_meta_definitions#2}% \let\currentMPinstance\m_meta_saved_instance} \let\stopMPdefinitions\relax @@ -95,7 +95,7 @@ \edef\currentwidth {\the\hsize \space}% \edef\currentheight {\the\vsize \space}} -\def\t_meta_instance{\csname\??mpinstancetokens\currentMPinstance\endcsname} % token register +\def\t_meta_definitions{\csname\??mpinstancetokens\currentMPinstance\endcsname} % token register \installcommandhandler \??mpinstance {MPinstance} \??mpinstance @@ -103,6 +103,7 @@ [\s!format=metafun, \s!extensions=\v!no, \s!initializations=\v!no, + \c!method=\s!default, \c!textstyle=, \c!textcolor=] @@ -110,7 +111,7 @@ \ifcsname\??mpinstancetokens\currentMPinstance\endcsname \else \expandafter\newtoks\csname\??mpinstancetokens\currentMPinstance\endcsname \fi - \t_meta_instance\emptytoks % in case we redefine + \t_meta_definitions\emptytoks % in case we redefine \to \everydefineMPinstance \unexpanded\def\resetMPinstance[#1]% @@ -134,11 +135,13 @@ \def\currentMPinstance{\defaultMPinstance} \def\currentMPformat {\currentMPinstance} -\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] -\defineMPinstance[extrafun][\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] -\defineMPinstance[mprun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] -\defineMPinstance[metapost][\s!format=mpost] -\defineMPinstance[nofun] [\s!format=mpost] +\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double] +\defineMPinstance[decimalfun][\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!decimal] +\defineMPinstance[mprun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[metapost] [\s!format=mpost] +\defineMPinstance[nofun] [\s!format=mpost] \newconditional\c_meta_include_extensions \newconditional\c_meta_include_initializations @@ -154,18 +157,28 @@ \def\meta_flush_current_initializations {\ifconditional\c_meta_include_initializations - \the\t_meta_initializations;% + \the\t_meta_initializations \fi \theMPrandomseed;} -\def\meta_flush_current_preamble +% \def\meta_flush_current_preamble +% {\ifconditional\c_meta_include_extensions +% \the\t_meta_extensions +% \the\t_meta_userinclusions +% \fi} + +\def\meta_flush_current_extensions + {\ifconditional\c_meta_include_extensions + \the\t_meta_extensions + \fi} + +\def\meta_flush_current_userinclusions {\ifconditional\c_meta_include_extensions - \the\t_meta_extensions;% - \the\t_meta_userinclusions;% + \the\t_meta_userinclusions \fi} -\def\meta_flush_current_instance - {\the\t_meta_instance;} +\def\meta_flush_current_definitions + {\the\t_meta_definitions} \def\meta_reset_current_preamble {\ifconditional\c_meta_include_extensions @@ -199,7 +212,7 @@ \useMPinstancestyleandcolor\c!textstyle\c!textcolor} \def\meta_stop_current_graphic - {\global\t_meta_instance\emptytoks + {\global\t_meta_definitions\emptytoks \endgroup} \def\meta_process_graphic_start @@ -213,15 +226,17 @@ {\meta_start_current_graphic \forgetall \meta_process_graphic_start - \normalexpanded{\noexpand\ctxlua{metapost.graphic( - "\currentMPinstance", - "\currentMPformat", - \!!bs#1;\!!es, - \!!bs\meta_flush_current_initializations;\!!es, - \!!bs\meta_flush_current_preamble;\!!es, - \!!bs\meta_flush_current_instance;\!!es, - "\MPaskedfigure" - )}}% + \normalexpanded{\noexpand\ctxlua{metapost.graphic { + instance = "\currentMPinstance", + format = "\currentMPformat", + data = \!!bs#1;\!!es, + initializations = \!!bs\meta_flush_current_initializations\!!es, + extensions = \!!bs\meta_flush_current_extensions\!!es, + inclusions = \!!bs\meta_flush_current_userinclusions\!!es, + definitions = \!!bs\meta_flush_current_definitions\!!es, + figure = "\MPaskedfigure", + method = "\MPinstanceparameter\c!method", + }}}% \meta_process_graphic_stop \meta_reset_current_preamble \meta_stop_current_graphic} @@ -319,13 +334,15 @@ \edef\height{#3\space}\let\overlayheight\height \ifcsname\??mpclip#1\endcsname \meta_start_current_graphic - \xdef\MPclippath{\normalexpanded{\noexpand\ctxlua{metapost.theclippath( - "\currentMPinstance", - "\currentMPformat", - \!!bs\getvalue{\??mpclip#1}\!!es, - \!!bs\meta_flush_current_initializations\!!es, - \!!bs\meta_flush_current_preamble\!!es - )}}}% + \xdef\MPclippath{\normalexpanded{\noexpand\ctxlua{metapost.theclippath { + instance = "\currentMPinstance", + format = "\currentMPformat", + data = \!!bs\getvalue{\??mpclip#1}\!!es, + initializations = \!!bs\meta_flush_current_initializations\!!es, + extensions = \!!bs\meta_flush_current_extensions\!!es, + inclusions = \!!bs\meta_flush_current_userinclusions\!!es, + method = "\MPinstanceparameter\c!method", + }}}}% \meta_stop_current_graphic \meta_reset_current_preamble \ifx\MPclippath\empty diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua index 4b1a5035d..5a3becd7a 100644 --- a/tex/context/base/mlib-ctx.lua +++ b/tex/context/base/mlib-ctx.lua @@ -19,19 +19,47 @@ local mplib = mplib metapost = metapost or {} local metapost = metapost -metapost.defaultformat = "metafun" +metapost.defaultformat = "metafun" +metapost.defaultinstance = "metafun" +metapost.defaultmethod = "default" + +local function setmpsformat(specification) + local instance = specification.instance + local format = specification.format + local method = specification.method + if not instance or instance == "" then + instance = metapost.defaultinstance + specification.instance = instance + end + if not format or format == "" then + format = metapost.defaultformat + specification.format = format + end + if not method or method == "" then + method = metapost.defaultmethod + specification.method = method + end + specification.mpx = metapost.format(instance,format,method) +end -function metapost.graphic(instance,mpsformat,str,initializations,preamble,definitions,askedfig) - local mpx = metapost.format(instance,mpsformat or metapost.defaultformat) - metapost.graphic_base_pass(mpx,str,initializations,preamble,definitions,askedfig) +function metapost.graphic(specification) + setmpsformat(specification) + metapost.graphic_base_pass(specification) end -function metapost.getclippath(instance,mpsformat,data,initializations,preamble) - local mpx = metapost.format(instance,mpsformat or metapost.defaultformat) - if mpx and data then +function metapost.getclippath(specification) + setmpsformat(specification) + local mpx = specification.mpx + local data = specification.data or "" + if mpx and data ~= "" then starttiming(metapost) starttiming(metapost.exectime) - local result = mpx:execute(format("%s;beginfig(1);%s;%s;endfig;",preamble or "",initializations or "",data)) + local result = mpx:execute ( format ( "%s;%s;beginfig(1);%s;%s;endfig;", + specification.extensions or "", + specification.inclusions or "", + specification.initializations or "", + data + ) ) stoptiming(metapost.exectime) if result.status > 0 then report_metapost("%s: %s", result.status, result.error or result.term or result.log) diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index dfa475b68..21b6657de 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -512,36 +512,67 @@ local function checkaskedfig(askedfig) -- return askedfig, wrappit end end -function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,definitions,askedfig) +function metapost.graphic_base_pass(specification) + local mpx = specification.mpx -- mandate + local data = specification.data or "" + local definitions = specification.definitions or "" + local extensions = specification.extensions or "" + local inclusions = specification.inclusions or "" + local initializations = specification.initializations or "" + local askedfig = specification.figure -- no default else no wrapper + -- nofruns = nofruns + 1 local askedfig, wrappit = checkaskedfig(askedfig) - local done_1, done_2, forced_1, forced_2 - str, done_1, forced_1 = checktexts(str) - if not preamble or preamble == "" then - preamble, done_2, forced_2 = "", false, false + local done_1, done_2, done_3, forced_1, forced_2, forced_3 + data, done_1, forced_1 = checktexts(data) + -- we had preamble = extensions + inclusions + if extensions == "" then + extensions, done_2, forced_2 = "", false, false else - preamble, done_2, forced_2 = checktexts(preamble) + extensions, done_2, forced_2 = checktexts(extensions) + end + if inclusions == "" then + inclusions, done_3, forced_3 = "", false, false + else + inclusions, done_3, forced_3 = checktexts(inclusions) end metapost.intermediate.needed = false metapost.multipass = false -- no needed here - current_format = mpsformat - current_graphic = str - current_initializations = initializations or "" - if metapost.method == 1 or (metapost.method == 2 and (done_1 or done_2)) then + current_format = mpx + current_graphic = data + current_initializations = initializations + local method = metapost.method + if trace_runs then + if method == 1 then + report_metapost("forcing two runs due to library configuration") + elseif method ~= 2 then + report_metapost("ignoring run due to library configuration") + elseif not (done_1 or done_2 or done_3) then + report_metapost("forcing one run only due to analysis") + elseif done_1 then + report_metapost("forcing at max two runs due to main code") + elseif done_2 then + report_metapost("forcing at max two runs due to extensions") + else + report_metapost("forcing at max two runs due to inclusions") + end + end + if method == 1 or (method == 2 and (done_1 or done_2 or done_3)) then if trace_runs then report_metapost("first run of job %s (asked: %s)",nofruns,tostring(askedfig)) end -- first true means: trialrun, second true means: avoid extra run if no multipass - local flushed = metapost.process(mpsformat, { + local flushed = metapost.process(mpx, { definitions, - preamble, + extensions, + inclusions, wrappit and do_begin_fig or "", do_trial_run, current_initializations, do_safeguard, current_graphic, wrappit and do_end_fig or "", - }, true, nil, not (forced_1 or forced_2), false, askedfig) + }, true, nil, not (forced_1 or forced_2 or forced_3), false, askedfig) if metapost.intermediate.needed then for _, action in next, metapost.intermediate.actions do action() @@ -556,7 +587,7 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,defin if trace_runs then report_metapost("running job %s (asked: %s)",nofruns,tostring(askedfig)) end - metapost.process(mpsformat, { + metapost.process(mpx, { preamble, wrappit and do_begin_fig or "", no_trial_run, @@ -564,7 +595,7 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,defin do_safeguard, current_graphic, wrappit and do_end_fig or "", - }, false, nil, false, false, askedfig ) + }, false, nil, false, false, askedfig) end end diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua index 62203e95e..5e702245d 100644 --- a/tex/context/base/mlib-run.lua +++ b/tex/context/base/mlib-run.lua @@ -284,11 +284,17 @@ else input "%s" ; ]] - function metapost.load(name) + local methods = { + double = "double", + decimal = false, -- for the moment + } + + function metapost.load(name,method) starttiming(mplib) local mpx = mplib.new { ini_version = true, - find_file = finder, + find_file = finder, + math_mode = method and methods[method] or nil, } local result if not mpx then @@ -301,7 +307,7 @@ else return mpx, result end - function metapost.checkformat(mpsinput) + function metapost.checkformat(mpsinput,method) local mpsversion = environment.version or "unset version" local mpsinput = mpsinput or "metafun" local foundfile = "" @@ -320,8 +326,8 @@ else if foundfile == "" then report_metapost("loading '%s' fails, format not found",mpsinput) else - report_metapost("loading '%s': %s",mpsinput,foundfile) - local mpx, result = metapost.load(foundfile) + report_metapost("loading '%s': %s, using method: %s",mpsinput,foundfile,method or "default") + local mpx, result = metapost.load(foundfile,method) if mpx then return mpx else @@ -343,12 +349,15 @@ end local mpxformats = { } -function metapost.format(instance,name) +function metapost.format(instance,name,method) + if not instance or instance == "" then + instance = "metafun" -- brrr + end name = name or instance local mpx = mpxformats[instance] if not mpx then report_metapost("initializing instance '%s' using format '%s'",instance,name) - mpx = metapost.checkformat(name) + mpx = metapost.checkformat(name,method) mpxformats[instance] = mpx end return mpx @@ -401,6 +410,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end if type(data) == "table" then -- this hack is needed because the library currently barks on \n\n + -- eventually we can text for "" in the next loop local n = 0 local nofsnippets = #data for i=1,nofsnippets do @@ -427,11 +437,15 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, if trace_tracingall then mpx:execute("tracingall;") end +-- table.insert(data,2,"") for i=1,#data do local d = data[i] +-- d = string.gsub(d,"\r","") if d then if trace_graphics then + mp_inp[mpx]:write(format("\n%% begin snippet %s\n",i)) mp_inp[mpx]:write(d) + mp_inp[mpx]:write(format("\n%% end snippet %s\n",i)) end starttiming(metapost.exectime) result = mpx:execute(d) @@ -484,7 +498,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, metapost.lastlog = metapost.lastlog .. "\n" .. result.term report_metapost("info: %s",result.term or "no-term") end - if result.fig then + if result.fig then converted = metapost.convert(result, trialrun, flusher, multipass, askedfig) end end diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv index ceb15de90..eb4624ee8 100644 --- a/tex/context/base/mult-def.mkiv +++ b/tex/context/base/mult-def.mkiv @@ -73,6 +73,9 @@ \def\s!integral {integral} \def\s!insert {insert} % maybe insertclass +\def\s!double {double} +\def\s!decimal {decimal} + \def\c!HL {HL} \def\c!VL {VL} \def\c!NL {NL} diff --git a/tex/context/base/mult-fun.lua b/tex/context/base/mult-fun.lua index 260497f52..f7a7792e5 100644 --- a/tex/context/base/mult-fun.lua +++ b/tex/context/base/mult-fun.lua @@ -10,6 +10,7 @@ return { -- "originlength", "tickstep ", "ticklength", -- "autoarrows", "ahfactor", -- "angleoffset", anglelength", anglemethod", + "metapostversion", }, commands = { -- @@ -45,6 +46,7 @@ return { "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", + "property", "properties", "withproperties", "asgroup", "infont", -- redefined usign textext -- "property", "withproperties", "properties", -- not yet diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua index 863ee3860..8338d41eb 100644 --- a/tex/context/base/mult-low.lua +++ b/tex/context/base/mult-low.lua @@ -302,5 +302,10 @@ return { "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", -- "normalreqno", + -- + "startimath", "stopimath", "normalstartimath", "normalstopimath", + "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", + -- + "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathstyleface", } } diff --git a/tex/context/base/ppchtex.mkii b/tex/context/base/ppchtex.mkii index d1209cd97..07ca9789a 100644 --- a/tex/context/base/ppchtex.mkii +++ b/tex/context/base/ppchtex.mkii @@ -2130,7 +2130,8 @@ \def\RB{\chemicalrightbottom}% \def\SL{\chemicalsmashedleft}% \def\SM{\chemicalsmashedmiddle}% - \def\SR{\chemicalsmashedright}} + \def\SR{\chemicalsmashedright}% +} % \reversechemical#1#2#3 % diff --git a/tex/context/base/s-mod-00.mkiv b/tex/context/base/s-mod-00.mkiv index 94f6edcb6..7af56dc2d 100644 --- a/tex/context/base/s-mod-00.mkiv +++ b/tex/context/base/s-mod-00.mkiv @@ -13,6 +13,12 @@ \unprotect -% gone +\startmode[nocode] + + % \definieerbuffer[definition] % ignore + + \def\startdefinition#1\stopdefinition{} + +\stopmode \protect \endinput diff --git a/tex/context/base/s-mod-02.mkiv b/tex/context/base/s-mod-02.mkiv index 032ace8a6..37e3d2f14 100644 --- a/tex/context/base/s-mod-02.mkiv +++ b/tex/context/base/s-mod-02.mkiv @@ -13,6 +13,12 @@ \unprotect -% gone +\startmode[nocode] + + % \definieerbuffer[definition] % ignore + + \def\startdefinition#1\stopdefinition{} + +\stopmode \protect \endinput diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf index 84c7adbe3..2819a3f4b 100644 Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf index 9b7fd7ee5..2371c0934 100644 Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ diff --git a/tex/context/base/syst-con.lua b/tex/context/base/syst-con.lua index f3f1b98cf..ae9d15a26 100644 --- a/tex/context/base/syst-con.lua +++ b/tex/context/base/syst-con.lua @@ -43,10 +43,18 @@ end local cosd, sind, tand = math.cosd, math.sind, math.tand local cos, sin, tan = math.cos, math.sin, math.tan -function commands.sind(n) context("%0.6f",sind(n)) end -function commands.cosd(n) context("%0.6f",cosd(n)) end -function commands.tand(n) context("%0.6f",tand(n)) end +-- function commands.sind(n) context("%0.6f",sind(n)) end +-- function commands.cosd(n) context("%0.6f",cosd(n)) end +-- function commands.tand(n) context("%0.6f",tand(n)) end -function commands.sin(n) context("%0.6f",sin(n)) end -function commands.cos(n) context("%0.6f",cos(n)) end -function commands.tan(n) context("%0.6f",tan(n)) end +-- function commands.sin (n) context("%0.6f",sin (n)) end +-- function commands.cos (n) context("%0.6f",cos (n)) end +-- function commands.tan (n) context("%0.6f",tan (n)) end + +function commands.sind(n) context(sind(n)) end +function commands.cosd(n) context(cosd(n)) end +function commands.tand(n) context(tand(n)) end + +function commands.sin (n) context(sin (n)) end +function commands.cos (n) context(cos (n)) end +function commands.tan (n) context(tan (n)) end diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua index dc1526df7..506497875 100644 --- a/tex/context/base/util-prs.lua +++ b/tex/context/base/util-prs.lua @@ -232,8 +232,8 @@ end -- for chem (currently one level) local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + C(digit^1 * lparent * (noparent + nestedparents)^0 * rparent) - + C((nestedbraces + (1-comma))^0) + + C(digit^1 * lparent * (noparent + nestedparents)^1 * rparent) + + C((nestedbraces + (1-comma))^1) local pattern_a = spaces * Ct(value*(separator*value)^0) local function repeater(n,str) @@ -257,15 +257,15 @@ local function repeater(n,str) end local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + (C(digit^1)/tonumber * lparent * Cs((noparent + nestedparents)^0) * rparent) / repeater - + C((nestedbraces + (1-comma))^0) + + (C(digit^1)/tonumber * lparent * Cs((noparent + nestedparents)^1) * rparent) / repeater + + C((nestedbraces + (1-comma))^1) local pattern_b = spaces * Ct(value*(separator*value)^0) -function parsers.settings_to_array_with_repeat(str,expand) +function parsers.settings_to_array_with_repeat(str,expand) -- beware: "" => { } if expand then - return lpegmatch(pattern_b,str) + return lpegmatch(pattern_b,str) or { } else - return lpegmatch(pattern_a,str) + return lpegmatch(pattern_a,str) or { } end end diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv index d461bf149..cf861cd7b 100644 --- a/tex/context/base/x-mathml.mkiv +++ b/tex/context/base/x-mathml.mkiv @@ -1681,7 +1681,7 @@ \ifdefined\asciimath \expanded{\asciimath{\xmlflush{#1}}} \else - \hbox{\tt no am loaded}% + \hbox{\tt no am loaded} \fi } { \xmlall{#1}{../!mml:annotation} @@ -2182,33 +2182,27 @@ {\csname#1\endcsname}} \startxmlsetups mml:mover -% \mathop { - \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelseutfmathaccent\mmlovertoken { - \edef\mmlovercommand{\utfmathcommand\mmlovertoken} - \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}} - } { - \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}} - \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken} - \edef\mmlovercommand{\utfmathfiller\mmlovertoken} -% todo: proper math mode/size - \vbox { - \mathsurround\zeropoint \ialign { -% \hss##\hss -\hss$##$\hss - \crcr - \noalign{\kern3\onepoint}% -% \mmlexecuteifdefined\mmlovercommand{\mathematics{\mmlsecond{#1}}} -\mmlexecuteifdefined\mmlovercommand{\mmlsecond{#1}} - \crcr - \noalign{\kern3\onepoint\nointerlineskip}% -% \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}} -\mmlexecuteifdefined\mmlbasecommand{\mmlfirst{#1}} - \crcr - } + \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}} + \doifelseutfmathaccentfiltered\mmlovertoken{topaccent} { + \edef\mmlovercommand{\utfmathcommandfiltered\mmlovertoken{topaccent}} + \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}} + } { + \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}} + \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken} + \edef\mmlovercommand{\utfmathfiller\mmlovertoken} + \vbox { + \mathsurround\zeropoint \ialign { + \hss$##$\hss + \crcr + \noalign{\kern3\onepoint}% + \mmlexecuteifdefined\mmlovercommand{\mmlsecond{#1}} + \crcr + \noalign{\kern3\onepoint\nointerlineskip}% + \mmlexecuteifdefined\mmlbasecommand{\mmlfirst{#1}} + \crcr } } -% } + } % \limits % spoils spacing \stopxmlsetups @@ -2217,25 +2211,21 @@ \startxmlsetups mml:munder % \mathop { \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelseutfmathaccent\mmlundertoken { - \edef\mmlundercommand{\utfmathcommand\mmlundertoken} + \doifelseutfmathaccentfiltered\mmlundertoken{botaccent} { + \edef\mmlundercommand{\utfmathcommandfiltered\mmlundertoken{botaccent}} \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}} } { \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}} \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken} \edef\mmlundercommand{\utfmathfiller\mmlundertoken} -% todo: proper math mode/size \vtop { \mathsurround\zeropoint \ialign { -% \hss##\hss -\hss$##$\hss + \hss$##$\hss \crcr -% \mmlexecuteifdefined\mmlbasecommand {\mathematics{\mmlfirst{#1}}} -\mmlexecuteifdefined\mmlbasecommand {\mmlfirst{#1}} + \mmlexecuteifdefined\mmlbasecommand {\mmlfirst{#1}} \crcr \noalign{\kern3\onepoint\nointerlineskip}% -% \mmlexecuteifdefined\mmlundercommand{\mathematics{\mmlsecond{#1}}} -\mmlexecuteifdefined\mmlundercommand{\mmlsecond{#1}} + \mmlexecuteifdefined\mmlundercommand{\mmlsecond{#1}} \crcr \noalign{\kern3\onepoint} } diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 4b5d60492..1f402cd4f 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 12/06/12 22:36:49 +-- merge date : 12/10/12 23:20:34 do -- begin closure to overcome local limits and interference @@ -1617,7 +1617,8 @@ function lpeg.replacer(one,two,makefunction) 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(((1-one)^1 + one/two)^0) + pattern = Cs((one/two + 1)^0) else for i=1,no do local o = one[i] @@ -1628,7 +1629,28 @@ function lpeg.replacer(one,two,makefunction) else one = P(one) two = two or "" - pattern = Cs(((1-one)^1 + one/two)^0) + -- 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) @@ -2159,66 +2181,145 @@ file = file or { } local file = file local insert, concat = table.insert, table.concat -local find, gmatch, match, gsub, sub, char, lower = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char, string.lower +local match = string.match local lpegmatch = lpeg.match local getcurrentdir, attributes = lfs.currentdir, lfs.attributes +local checkedsplit = string.checkedsplit + +-- local patterns = file.patterns or { } +-- file.patterns = patterns -local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc +local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct -local function dirname(name,default) - return match(name,"^(.+)[/\\].-$") or (default or "") +local colon = P(":") +local period = P(".") +local periods = P("..") +local fwslash = P("/") +local bwslash = P("\\") +local slashes = S("\\/") +local noperiod = 1-period +local noslashes = 1-slashes +local name = noperiod^1 +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 "" end +local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 + local function basename(name) - return match(name,"^.+[/\\](.-)$") or name + return lpegmatch(pattern,name) or name end --- local function nameonly(name) --- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) --- end +local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0 local function nameonly(name) - return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$","")) + return lpegmatch(pattern,name) or name end -local function suffixonly(name,default) - return match(name,"^.+%.([^/\\]-)$") or default or "" -end +local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 -local function splitname(name) - local n, s = match(name,"^(.+)%.([^/\\]-)$") - return n or name, s or "" +local function suffixonly(name) + return lpegmatch(pattern,name) or "" end +file.pathpart = pathpart file.basename = basename - -file.pathpart = dirname -file.dirname = dirname - file.nameonly = nameonly - file.suffixonly = suffixonly -file.extname = suffixonly -- obsolete file.suffix = suffixonly -function file.removesuffix(filename) - return (gsub(filename,"%.[%a%d]+$","")) +file.dirname = pathpart -- obsolete +file.extname = suffixonly -- obsolete + +-- actually these are schemes + +local drive = C(R("az","AZ")) * colon +local path = C(((1-slashes)^0 * slashes)^0) +local suffix = period * C(P(1-period)^0 * P(-1)) +local base = C((1-suffix)^0) +local rest = C(P(1)^0) + +drive = drive + Cc("") +path = path + Cc("") +base = base + Cc("") +suffix = suffix + Cc("") + +local pattern_a = drive * path * base * suffix +local pattern_b = path * base * suffix +local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures +local pattern_d = path * rest + +function file.splitname(str,splitdrive) + if splitdrive then + return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix + else + return lpegmatch(pattern_b,str) -- returns path, base, suffix + end +end + +function file.splitbase(str) + return 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, + } + end +end + +local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1) + +function file.removesuffix(name) + return lpegmatch(pattern,name) +end + +-- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 +-- +-- function file.addsuffix(name, suffix) +-- local p = lpegmatch(pattern,name) +-- if p then +-- return name +-- else +-- return name .. "." .. suffix +-- end +-- 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 return filename elseif criterium == true then return filename .. "." .. suffix elseif not criterium then - local n, s = splitname(filename) + local n, s = lpegmatch(pattern,filename) if not s or s == "" then return filename .. "." .. suffix else return filename end else - local n, s = splitname(filename) + local n, s = lpegmatch(pattern,filename) if s and s ~= "" then local t = type(criterium) if t == "table" then @@ -2235,96 +2336,49 @@ function file.addsuffix(filename, suffix, criterium) end end end - return n .. "." .. suffix + return (n or filename) .. "." .. suffix end end ---~ print("1 " .. file.addsuffix("name","new") .. " -> name.new") ---~ print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") ---~ print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") ---~ print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") ---~ print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") ---~ print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") ---~ print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") ---~ print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") +-- print("1 " .. file.addsuffix("name","new") .. " -> name.new") +-- print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") +-- print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") +-- print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") +-- print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") +-- print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") +-- print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") +-- print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") + +local suffix = period * (1-period-slashes)^1 * -1 +local pattern = Cs((1-suffix)^0) -function file.replacesuffix(filename, suffix) - return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix +function file.replacesuffix(name,suffix) + if suffix and suffix ~= "" then + return lpegmatch(pattern,name) .. "." .. suffix + else + return name + end end -local trick_1 = char(1) -local trick_2 = "^" .. trick_1 .. "/+" +-- -function file.join(...) -- rather dirty - local lst = { ... } - local a, b = lst[1], lst[2] - if not a or a == "" then -- not a added - lst[1] = trick_1 - elseif b and find(a,"^/+$") and find(b,"^/") then - lst[1] = "" - lst[2] = gsub(b,"^/+","") - end - local pth = concat(lst,"/") - pth = gsub(pth,"\\","/") - local a, b = match(pth,"^(.*://)(.*)$") - if a and b then - return a .. gsub(b,"//+","/") - end - a, b = match(pth,"^(//)(.*)$") - if a and b then - return a .. gsub(b,"//+","/") - end - pth = gsub(pth,trick_2,"") - return (gsub(pth,"//+","/")) -end - --- local slash = P("/") --- local colon = P(":") - --- local replacer = lpeg.replacer(S("\\/")^1,"/") --- local stripper = Cs(P(slash)^0/"" * replacer) --- local isnetwork = slash * slash * (1-slash) + (1-slash-colon)^1 * colon --- local isroot = slash^1 * -1 --- local hasroot = slash^1 - --- function file.newjoin(...) -- rather dirty --- local lst = { ... } --- local one = lst[1] --- if lpegmatch(isnetwork,one) then --- local two = lpegmatch(replacer,concat(lst,"/",2)) --- return one .. two --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(replacer,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- elseif one == "" then --- return lpegmatch(stripper,concat(lst,"/",2)) --- else --- return lpegmatch(replacer,concat(lst,"/")) --- end --- end +local reslasher = lpeg.replacer(S("\\"),"/") --- print(file.join("//","/y")) --- print(file.join("/","/y")) --- print(file.join("","/y")) --- print(file.join("/x/","/y")) --- print(file.join("x/","/y")) --- print(file.join("http://","/y")) --- print(file.join("http://a","/y")) --- print(file.join("http:///a","/y")) --- print(file.join("//nas-1","/y")) +function file.reslash(str) + return lpegmatch(reslasher,str) +end -- We should be able to use: -- +-- local writable = P(1) * P("w") * Cc(true) +-- -- function file.is_writable(name) --- local a = attributes(name) or attributes(dirname(name,".")) --- return a and sub(a.permissions,2,2) == "w" +-- local a = attributes(name) or attributes(pathpart(name,".")) +-- return a and lpegmatch(writable,a.permissions) or false -- end -- --- But after some testing Taco and I came up with: +-- But after some testing Taco and I came up with the more robust +-- variant: function file.is_writable(name) if lfs.isdir(name) then @@ -2352,9 +2406,11 @@ function file.is_writable(name) return false end +local readable = P("r") * Cc(true) + function file.is_readable(name) local a = attributes(name) - return a and sub(a.permissions,1,1) == "r" + return a and lpegmatch(readable,a.permissions) or false end file.isreadable = file.is_readable -- depricated @@ -2365,64 +2421,74 @@ function file.size(name) return a and a.size or 0 end --- todo: lpeg \\ / .. does not save much - -local checkedsplit = string.checkedsplit - -function file.splitpath(str,separator) -- string - str = gsub(str,"\\","/") - return checkedsplit(str,separator or io.pathseparator) +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) end function file.joinpath(tab,separator) -- table return concat(tab,separator or io.pathseparator) -- can have trailing // end --- we can hash them weakly +local stripper = Cs(P(fwslash)^0/"" * reslasher) +local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon +local isroot = fwslash^1 * -1 +local hasroot = fwslash^1 ---~ function file.collapsepath(str) -- fails on b.c/.. ---~ str = gsub(str,"\\","/") ---~ if find(str,"/") then ---~ str = gsub(str,"^%./",(gsub(getcurrentdir(),"\\","/")) .. "/") -- ./xx in qualified ---~ str = gsub(str,"/%./","/") ---~ local n, m = 1, 1 ---~ while n > 0 or m > 0 do ---~ str, n = gsub(str,"[^/%.]+/%.%.$","") ---~ str, m = gsub(str,"[^/%.]+/%.%./","") ---~ end ---~ str = gsub(str,"([^/])/$","%1") ---~ -- str = gsub(str,"^%./","") -- ./xx in qualified ---~ str = gsub(str,"/%.$","") ---~ end ---~ if str == "" then str = "." end ---~ return str ---~ end ---~ ---~ The previous one fails on "a.b/c" so Taco came up with a split based ---~ variant. After some skyping we got it sort of compatible with the old ---~ one. After that the anchoring to currentdir was added in a better way. ---~ Of course there are some optimizations too. Finally we had to deal with ---~ windows drive prefixes and things like sys://. +function file.join(...) -- rather dirty + local lst = { ... } + local one = lst[1] + if lpegmatch(isnetwork,one) then + local two = lpegmatch(reslasher,concat(lst,"/",2)) + return one .. "/" .. two + elseif lpegmatch(isroot,one) then + local two = lpegmatch(reslasher,concat(lst,"/",2)) + if lpegmatch(hasroot,two) then + return two + else + return "/" .. two + end + elseif one == "" then + return lpegmatch(stripper,concat(lst,"/",2)) + else + return lpegmatch(reslasher,concat(lst,"/")) + end +end + +-- print(file.join("c:/whatever","name")) +-- print(file.join("//","/y")) +-- print(file.join("/","/y")) +-- print(file.join("","/y")) +-- print(file.join("/x/","/y")) +-- print(file.join("x/","/y")) +-- print(file.join("http://","/y")) +-- print(file.join("http://a","/y")) +-- print(file.join("http:///a","/y")) +-- print(file.join("//nas-1","/y")) + +-- The previous one fails on "a.b/c" so Taco came up with a split based +-- variant. After some skyping we got it sort of compatible with the old +-- one. After that the anchoring to currentdir was added in a better way. +-- Of course there are some optimizations too. Finally we had to deal with +-- windows drive prefixes and things like sys://. Eventually gsubs and +-- finds were replaced by lpegs. + +local drivespec = R("az","AZ")^1 * colon +local anchors = fwslash + drivespec +local untouched = periods + (1-period)^1 * P(-1) +local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * Ct(lpeg.splitat(S("/\\")^1)) +local absolute = fwslash function file.collapsepath(str,anchor) - if anchor and not find(str,"^/") and not find(str,"^%a:") then + if anchor and not lpegmatch(anchors,str) then str = getcurrentdir() .. "/" .. str end if str == "" or str =="." then return "." - elseif find(str,"^%.%.") then - str = gsub(str,"\\","/") - return str - elseif not find(str,"%.") then - str = gsub(str,"\\","/") - return str - end - str = gsub(str,"\\","/") - local starter, rest = match(str,"^(%a+:/*)(.-)$") - if starter then - str = rest + elseif lpegmatch(untouched,str) then + return lpegmatch(reslasher,str) end - local oldelements = checkedsplit(str,"/") + local starter, oldelements = lpegmatch(splitstarter,str) +-- inspect(oldelements) local newelements = { } local i = #oldelements while i > 0 do @@ -2452,7 +2518,7 @@ function file.collapsepath(str,anchor) return starter or "." elseif starter then return starter .. concat(newelements, '/') - elseif find(str,"^/") then + elseif lpegmatch(absolute,str) then return "/" .. concat(newelements,'/') else return concat(newelements, '/') @@ -2469,29 +2535,21 @@ end -- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..") -- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..") +local validchars = R("az","09","AZ","--","..") +local pattern_a = lpeg.replacer(1-validchars) +local pattern_a = Cs((validchars + P(1)/"-")^1) +local whatever = P("-")^0 / "" +local pattern_b = Cs(whatever * (1 - whatever * -1)^1) + function file.robustname(str,strict) - str = gsub(str,"[^%a%d%/%-%.\\]+","-") + str = lpegmatch(pattern_a,str) or str if strict then - return lower(gsub(str,"^%-*(.-)%-*$","%1")) + return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking) else return str end end --- local pattern_a = lpeg.replacer(1-R("az","09","AZ","--","..")) --- local pattern_a = Cs((R("az","09","AZ","--","..") + P(1)/"-")^1) --- 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 --- end --- end - file.readdata = io.loaddata file.savedata = io.savedata @@ -2499,92 +2557,17 @@ function file.copy(oldname,newname) file.savedata(newname,io.loaddata(oldname)) end --- lpeg variants, slightly faster, not always - --- local period = P(".") --- local slashes = S("\\/") --- local noperiod = 1-period --- local noslashes = 1-slashes --- local name = noperiod^1 - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 - --- function file.suffixonly(name) --- return lpegmatch(pattern,name) or "" --- end - --- local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1) - --- function file.removesuffix(name) --- return lpegmatch(pattern,name) --- end - --- local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 - --- function file.basename(name) --- return lpegmatch(pattern,name) or name --- end - --- local pattern = Cs ((1 - slashes * noslashes^1 * -1)^1) - --- function file.dirname(name) --- return lpegmatch(pattern,name) or "" --- end - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 - --- function file.addsuffix(name, suffix) --- local p = lpegmatch(pattern,name) --- if p then --- return name --- else --- return name .. "." .. suffix --- end --- end - --- local suffix = period * (1-period-slashes)^1 * -1 --- local pattern = Cs((1-suffix)^1) - --- function file.replacesuffix(name,suffix) --- if suffix and suffix ~= "" then --- return lpegmatch(pattern,name) .. "." .. suffix --- else --- return name --- end --- end - --- local path = noslashes^0 * slashes^1 --- local suffix = period * (1-period-slashes)^1 * -1 --- local pattern = path^0 * Cs((1-suffix)^1) * suffix^0 - --- function file.nameonly(name) --- return lpegmatch(pattern,name) or name --- end - --- local test = file.suffixonly --- local test = file.basename --- local test = file.dirname --- local test = file.addsuffix --- local test = file.replacesuffix --- local test = file.nameonly - --- print(1,test("./a/b/c/abd.def.xxx","!!!")) --- print(2,test("./../b/c/abd.def.xxx","!!!")) --- print(3,test("a/b/c/abd.def.xxx","!!!")) --- print(4,test("a/b/c/def.xxx","!!!")) --- print(5,test("a/b/c/def","!!!")) --- print(6,test("def","!!!")) --- print(7,test("def.xxx","!!!")) - --- local tim = os.clock() for i=1,250000 do local ext = test("abd.def.xxx","!!!") end print(os.clock()-tim) - -- also rewrite previous local letter = R("az","AZ") + S("_-+") local separator = P("://") -local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/") -local rootbased = P("/") + letter*P(":") +local qualified = period^0 * fwslash + + letter * colon + + letter^1 * separator + + letter^1 * fwslash +local rootbased = fwslash + + letter * colon lpeg.patterns.qualified = qualified lpeg.patterns.rootbased = rootbased @@ -2599,61 +2582,6 @@ function file.is_rootbased_path(filename) return lpegmatch(rootbased,filename) ~= nil end --- actually these are schemes - -local slash = S("\\/") -local period = P(".") -local drive = C(R("az","AZ")) * P(":") -local path = C(((1-slash)^0 * slash)^0) -local suffix = period * C(P(1-period)^0 * P(-1)) -local base = C((1-suffix)^0) -local rest = C(P(1)^0) - -drive = drive + Cc("") -path = path + Cc("") -base = base + Cc("") -suffix = suffix + Cc("") - -local pattern_a = drive * path * base * suffix -local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures -local pattern_d = path * rest - -function file.splitname(str,splitdrive) - if splitdrive then - return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix - else - return lpegmatch(pattern_b,str) -- returns path, base, suffix - end -end - -function file.splitbase(str) - return 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, - } - end -end - --- print(file.splitbase("a/b/c.txt")) - -- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end -- -- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } @@ -2661,14 +2589,14 @@ end -- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } -- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } ---~ -- todo: ---~ ---~ if os.type == "windows" then ---~ local currentdir = getcurrentdir ---~ function getcurrentdir() ---~ return (gsub(currentdir(),"\\","/")) ---~ end ---~ end +-- -- maybe: +-- +-- if os.type == "windows" then +-- local currentdir = getcurrentdir +-- function getcurrentdir() +-- return lpegmatch(reslasher,currentdir()) +-- end +-- end -- for myself: @@ -2677,6 +2605,21 @@ function file.strip(name,dir) return a ~= "" and a or name end +-- local debuglist = { +-- "pathpart", "basename", "nameonly", "suffixonly", "suffix", "dirname", "extname", +-- "addsuffix", "removesuffix", "replacesuffix", "join", +-- "strip","collapsepath", "joinpath", "splitpath", +-- } + +-- for i=1,#debuglist do +-- local name = debuglist[i] +-- local f = file[name] +-- file[name] = function(...) +-- print(name,f(...)) +-- return f(...) +-- end +-- end + end -- closure do -- begin closure to overcome local limits and interference @@ -12698,7 +12641,9 @@ local internalized = allocate() -- internal tex numbers (private) local loadedfonts = constructors.loadedfonts local designsizes = constructors.designsizes -local resolvefile = fontgoodies.filenames.resolve +-- not in generic (some day I'll make two defs, one for context, one for generic) + +local resolvefile = fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end --[[ldx--

We hardly gain anything when we cache the final (pre scaled) -- cgit v1.2.3