diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
commit | d7ccb42582f85acf30568913610ccf4d602023fb (patch) | |
tree | 7292e3545a420676878e7451b68892d360c62cb6 /Master/texmf-dist/tex/context/base/l-file.lua | |
parent | 2d62a6fe9b80def59c392268022f1f9a2d6e358f (diff) |
commit context 2011.05.18
git-svn-id: svn://tug.org/texlive/trunk@22719 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/l-file.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/l-file.lua | 279 |
1 files changed, 154 insertions, 125 deletions
diff --git a/Master/texmf-dist/tex/context/base/l-file.lua b/Master/texmf-dist/tex/context/base/l-file.lua index 212318fb751..c3199f0229e 100644 --- a/Master/texmf-dist/tex/context/base/l-file.lua +++ b/Master/texmf-dist/tex/context/base/l-file.lua @@ -8,47 +8,93 @@ if not modules then modules = { } end modules ['l-file'] = { -- needs a cleanup -file = file or { } +file = file or { } +local file = file -local concat = table.concat -local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char +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 lpegmatch = lpeg.match +local getcurrentdir, attributes = lfs.currentdir, lfs.attributes -function file.removesuffix(filename) - return (gsub(filename,"%.[%a%d]+$","")) +local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc + +local function dirname(name,default) + return match(name,"^(.+)[/\\].-$") or (default or "") end -function file.addsuffix(filename, suffix) - if not suffix or suffix == "" then - return filename - elseif not find(filename,"%.[%a%d]+$") then - return filename .. "." .. suffix - else - return filename - end +local function basename(name) + return match(name,"^.+[/\\](.-)$") or name end -function file.replacesuffix(filename, suffix) - return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix +local function nameonly(name) + return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) end -function file.dirname(name,default) - return match(name,"^(.+)[/\\].-$") or (default or "") +local function extname(name,default) + return match(name,"^.+%.([^/\\]-)$") or default or "" end -function file.basename(name) - return match(name,"^.+[/\\](.-)$") or name +local function splitname(name) + local n, s = match(name,"^(.+)%.([^/\\]-)$") + return n or name, s or "" end -function file.nameonly(name) - return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) +file.basename = basename +file.dirname = dirname +file.nameonly = nameonly +file.extname = extname +file.suffix = extname + +function file.removesuffix(filename) + return (gsub(filename,"%.[%a%d]+$","")) end -function file.extname(name,default) - return match(name,"^.+%.([^/\\]-)$") or default or "" +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) + if not s or s == "" then + return filename .. "." .. suffix + else + return filename + end + else + local n, s = splitname(filename) + if s and s ~= "" then + local t = type(criterium) + if t == "table" then + -- keep if in criterium + for i=1,#criterium do + if s == criterium[i] then + return filename + end + end + elseif t == "string" then + -- keep if criterium + if s == criterium then + return filename + end + end + end + return n .. "." .. suffix + end end -file.suffix = file.extname +--~ 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 --~ function file.join(...) --~ local pth = concat({...},"/") @@ -100,50 +146,59 @@ end --~ print(file.join("http:///a","/y")) --~ print(file.join("//nas-1","/y")) -function file.iswritable(name) - local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) +function file.is_writable(name) + local a = attributes(name) or attributes(dirname(name,".")) return a and sub(a.permissions,2,2) == "w" end -function file.isreadable(name) - local a = lfs.attributes(name) +function file.is_readable(name) + local a = attributes(name) return a and sub(a.permissions,1,1) == "r" end -file.is_readable = file.isreadable -file.is_writable = file.iswritable +file.isreadable = file.is_readable -- depricated +file.iswritable = file.is_writable -- depricated --- todo: lpeg - ---~ function file.split_path(str) ---~ local t = { } ---~ str = gsub(str,"\\", "/") ---~ str = gsub(str,"(%a):([;/])", "%1\001%2") ---~ for name in gmatch(str,"([^;:]+)") do ---~ if name ~= "" then ---~ t[#t+1] = gsub(name,"\001",":") ---~ end ---~ end ---~ return t ---~ end +-- todo: lpeg \\ / .. does not save much local checkedsplit = string.checkedsplit -function file.split_path(str,separator) +function file.splitpath(str,separator) -- string str = gsub(str,"\\","/") return checkedsplit(str,separator or io.pathseparator) end -function file.join_path(tab) - return concat(tab,io.pathseparator) -- can have trailing // +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 thinsg like sys://. -local insert = table.insert - -function file.collapse_path(str,anchor) +function file.collapsepath(str,anchor) if anchor and not find(str,"^/") and not find(str,"^%a:") then str = getcurrentdir() .. "/" .. str end @@ -197,64 +252,26 @@ function file.collapse_path(str,anchor) return concat(newelements, '/') end end -function file.xcollapse_path(str) - print('collapse', str) - if str == "" or str =="." then - return "." - elseif find(str,"^%.%.") then - return str - elseif not find(str,"%.") then - return str - end - str = gsub(str,"^%./",lfs.currentdir() .. "/") -- ./xx in qualified - str = gsub(str,"\\","/") - local oldelements = checkedsplit(str,"/") - local newelements = { } - local i = #oldelements - while i > 0 do - local element = oldelements[i] - if element == '.' then - -- do nothing - elseif element == '..' then - local n = i -1 - while n > 0 do - local element = oldelements[n] - if element ~= '..' and element ~= '.' then - oldelements[n] = '.' - break - else - n = n - 1 - end - end - if n<1 then - insert(newelements,1,'..') - end - elseif element ~= "" then - insert(newelements,1,element) - end - i = i - 1 - end - if #newelements == 0 then - return "." - elseif find(str,"^/") then - return "/" .. concat(newelements,'/') + +--~ local function test(str) +--~ print(string.format("%-20s %-15s %-15s",str,file.collapsepath(str),file.collapsepath(str,true))) +--~ end +--~ test("a/b.c/d") test("b.c/d") test("b.c/..") +--~ test("/") test("c:/..") test("sys://..") +--~ test("") test("./") test(".") test("..") test("./..") test("../..") +--~ test("a") test("./a") test("/a") test("a/../..") +--~ 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/../..") + +function file.robustname(str,strict) + str = gsub(str,"[^%a%d%/%-%.\\]+","-") + if strict then + return lower(gsub(str,"^%-*(.-)%-*$","%1")) else - return concat(newelements, '/') + return str end end ---~ print(file.collapse_path("/a")) ---~ print(file.collapse_path("a/./b/..")) ---~ print(file.collapse_path("a/aa/../b/bb")) ---~ print(file.collapse_path("a/../..")) ---~ print(file.collapse_path("a/.././././b/..")) ---~ print(file.collapse_path("a/./././b/..")) ---~ print(file.collapse_path("a/b/c/../..")) - -function file.robustname(str) - return (gsub(str,"[^%a%d%/%-%.\\]+","-")) -end - file.readdata = io.loaddata file.savedata = io.savedata @@ -264,31 +281,31 @@ end -- lpeg variants, slightly faster, not always ---~ local period = lpeg.P(".") ---~ local slashes = lpeg.S("\\/") +--~ 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 * lpeg.C(noperiod^1) * -1 +--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 --~ function file.extname(name) --~ return lpegmatch(pattern,name) or "" --~ end ---~ local pattern = lpeg.Cs(((period * noperiod^1 * -1)/"" + 1)^1) +--~ local pattern = Cs(((period * noperiod^1 * -1)/"" + 1)^1) --~ function file.removesuffix(name) --~ return lpegmatch(pattern,name) --~ end ---~ local pattern = (noslashes^0 * slashes)^1 * lpeg.C(noslashes^1) * -1 +--~ local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 --~ function file.basename(name) --~ return lpegmatch(pattern,name) or name --~ end ---~ local pattern = (noslashes^0 * slashes)^1 * lpeg.Cp() * noslashes^1 * -1 +--~ local pattern = (noslashes^0 * slashes)^1 * Cp() * noslashes^1 * -1 --~ function file.dirname(name) --~ local p = lpegmatch(pattern,name) @@ -299,7 +316,7 @@ end --~ end --~ end ---~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1 +--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 --~ function file.addsuffix(name, suffix) --~ local p = lpegmatch(pattern,name) @@ -310,7 +327,7 @@ end --~ end --~ end ---~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1 +--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 --~ function file.replacesuffix(name,suffix) --~ local p = lpegmatch(pattern,name) @@ -321,7 +338,7 @@ end --~ end --~ end ---~ local pattern = (noslashes^0 * slashes)^0 * lpeg.Cp() * ((noperiod^1 * period)^1 * lpeg.Cp() + lpeg.P(true)) * noperiod^1 * -1 +--~ local pattern = (noslashes^0 * slashes)^0 * Cp() * ((noperiod^1 * period)^1 * Cp() + P(true)) * noperiod^1 * -1 --~ function file.nameonly(name) --~ local a, b = lpegmatch(pattern,name) @@ -353,11 +370,14 @@ end -- also rewrite previous -local letter = lpeg.R("az","AZ") + lpeg.S("_-+") -local separator = lpeg.P("://") +local letter = R("az","AZ") + S("_-+") +local separator = P("://") -local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator + letter^1 * lpeg.P("/") -local rootbased = lpeg.P("/") + letter*lpeg.P(":") +local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/") +local rootbased = P("/") + letter*P(":") + +lpeg.patterns.qualified = qualified +lpeg.patterns.rootbased = rootbased -- ./name ../name /name c: :// name/name @@ -369,14 +389,16 @@ function file.is_rootbased_path(filename) return lpegmatch(rootbased,filename) ~= nil end -local slash = lpeg.S("\\/") -local period = lpeg.P(".") -local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":") -local path = lpeg.C(((1-slash)^0 * slash)^0) -local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1)) -local base = lpeg.C((1-suffix)^0) +-- 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 pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc("")) +local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc("")) function file.splitname(str) -- returns drive, path, base, suffix return lpegmatch(pattern,str) @@ -392,8 +414,15 @@ end --~ -- todo: --~ --~ if os.type == "windows" then ---~ local currentdir = lfs.currentdir ---~ function lfs.currentdir() +--~ local currentdir = getcurrentdir +--~ function getcurrentdir() --~ return (gsub(currentdir(),"\\","/")) --~ end --~ end + +-- for myself: + +function file.strip(name,dir) + local b, a = match(name,"^(.-)" .. dir .. "(.*)$") + return a ~= "" and a or name +end |