summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/l-file.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/l-file.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/l-file.lua280
1 files changed, 186 insertions, 94 deletions
diff --git a/Master/texmf-dist/tex/context/base/l-file.lua b/Master/texmf-dist/tex/context/base/l-file.lua
index f49add5456b..0782ac67634 100644
--- a/Master/texmf-dist/tex/context/base/l-file.lua
+++ b/Master/texmf-dist/tex/context/base/l-file.lua
@@ -1,19 +1,24 @@
--- filename : l-file.lua
--- comment : split off from luat-lib
--- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
--- copyright: PRAGMA ADE / ConTeXt Development Team
--- license : see context related readme files
+if not modules then modules = { } end modules ['l-file'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
-if not versions then versions = { } end versions['l-file'] = 1.001
+-- needs a cleanup
-if not file then file = { } end
+file = file or { }
+
+local concat = table.concat
+local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
function file.removesuffix(filename)
- return filename:gsub("%.[%a%d]+$", "")
+ return (gsub(filename,"%.[%a%d]+$",""))
end
function file.addsuffix(filename, suffix)
- if not filename:find("%.[%a%d]+$") then
+ if not find(filename,"%.[%a%d]+$") then
return filename .. "." .. suffix
else
return filename
@@ -21,43 +26,27 @@ function file.addsuffix(filename, suffix)
end
function file.replacesuffix(filename, suffix)
- if not filename:find("%.[%a%d]+$") then
- return filename .. "." .. suffix
- else
- return (filename:gsub("%.[%a%d]+$","."..suffix))
- end
+ return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
end
-function file.dirname(name)
- return name:match("^(.+)[/\\].-$") or ""
+function file.dirname(name,default)
+ return match(name,"^(.+)[/\\].-$") or (default or "")
end
function file.basename(name)
- return name:match("^.+[/\\](.-)$") or name
+ return match(name,"^.+[/\\](.-)$") or name
end
function file.nameonly(name)
- return ((name:match("^.+[/\\](.-)$") or name):gsub("%..*$",""))
+ return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$",""))
end
function file.extname(name)
- return name:match("^.+%.([^/\\]-)$") or ""
+ return match(name,"^.+%.([^/\\]-)$") or ""
end
file.suffix = file.extname
-function file.stripsuffix(name)
- return (name:gsub("%.[%a%d]+$",""))
-end
-
---~ function file.join(...)
---~ local t = { ... }
---~ for i=1,#t do
---~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
---~ end
---~ return table.concat(t,"/")
---~ end
-
--~ print(file.join("x/","/y"))
--~ print(file.join("http://","/y"))
--~ print(file.join("http://a","/y"))
@@ -65,97 +54,73 @@ end
--~ print(file.join("//nas-1","/y"))
function file.join(...)
- local pth = table.concat({...},"/")
- pth = pth:gsub("\\","/")
- local a, b = pth:match("^(.*://)(.*)$")
+ local pth = concat({...},"/")
+ pth = gsub(pth,"\\","/")
+ local a, b = match(pth,"^(.*://)(.*)$")
if a and b then
- return a .. b:gsub("//+","/")
+ return a .. gsub(b,"//+","/")
end
- a, b = pth:match("^(//)(.*)$")
+ a, b = match(pth,"^(//)(.*)$")
if a and b then
- return a .. b:gsub("//+","/")
+ return a .. gsub(b,"//+","/")
end
- return (pth:gsub("//+","/"))
+ return (gsub(pth,"//+","/"))
end
-function file.is_writable(name)
- local f = io.open(name, 'w')
- if f then
- f:close()
- return true
- else
- return false
- end
+function file.iswritable(name)
+ local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,"."))
+ return a and a.permissions:sub(2,2) == "w"
end
-function file.is_readable(name)
- local f = io.open(name,'r')
- if f then
- f:close()
- return true
- else
- return false
- end
+function file.isreadable(name)
+ local a = lfs.attributes(name)
+ return a and a.permissions:sub(1,1) == "r"
end
---~ function file.split_path(str)
---~ if str:find(';') then
---~ return str:splitchr(";")
---~ else
---~ return str:splitchr(io.pathseparator)
---~ end
---~ end
+file.is_readable = file.isreadable
+file.is_writable = file.iswritable
-- todo: lpeg
function file.split_path(str)
local t = { }
- str = str:gsub("\\", "/")
- str = str:gsub("(%a):([;/])", "%1\001%2")
- for name in str:gmatch("([^;:]+)") do
+ str = gsub(str,"\\", "/")
+ str = gsub(str,"(%a):([;/])", "%1\001%2")
+ for name in gmatch(str,"([^;:]+)") do
if name ~= "" then
- name = name:gsub("\001",":")
- t[#t+1] = name
+ t[#t+1] = gsub(name,"\001",":")
end
end
return t
end
function file.join_path(tab)
- return table.concat(tab,io.pathseparator) -- can have trailing //
-end
-
---~ print('test' .. " == " .. file.collapse_path("test"))
---~ print("test/test" .. " == " .. file.collapse_path("test/test"))
---~ print("test/test/test" .. " == " .. file.collapse_path("test/test/test"))
---~ print("test/test" .. " == " .. file.collapse_path("test/../test/test"))
---~ print("test" .. " == " .. file.collapse_path("test/../test"))
---~ print("../test" .. " == " .. file.collapse_path("../test"))
---~ print("../test/" .. " == " .. file.collapse_path("../test/"))
---~ print("a/a" .. " == " .. file.collapse_path("a/b/c/../../a"))
-
---~ function file.collapse_path(str)
---~ local ok, n = false, 0
---~ while not ok do
---~ ok = true
---~ str, n = str:gsub("[^%./]+/%.%./", function(s)
---~ ok = false
---~ return ""
---~ end)
---~ end
---~ return (str:gsub("/%./","/"))
---~ end
+ return concat(tab,io.pathseparator) -- can have trailing //
+end
function file.collapse_path(str)
- local n = 1
- while n > 0 do
- str, n = str:gsub("([^/%.]+/%.%./)","")
+ str = gsub(str,"/%./","/")
+ local n, m = 1, 1
+ while n > 0 or m > 0 do
+ str, n = gsub(str,"[^/%.]+/%.%.$","")
+ str, m = gsub(str,"[^/%.]+/%.%./","")
end
- return (str:gsub("/%./","/"))
+ str = gsub(str,"([^/])/$","%1")
+ str = gsub(str,"^%./","")
+ str = gsub(str,"/%.$","")
+ if str == "" then str = "." end
+ return str
end
+--~ 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 (str:gsub("[^%a%d%/%-%.\\]+","-"))
+ return (gsub(str,"[^%a%d%/%-%.\\]+","-"))
end
file.readdata = io.loaddata
@@ -164,3 +129,130 @@ file.savedata = io.savedata
function file.copy(oldname,newname)
file.savedata(newname,io.loaddata(oldname))
end
+
+-- lpeg variants, slightly faster, not always
+
+--~ local period = lpeg.P(".")
+--~ local slashes = lpeg.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
+
+--~ function file.extname(name)
+--~ return pattern:match(name) or ""
+--~ end
+
+--~ local pattern = lpeg.Cs(((period * noperiod^1 * -1)/"" + 1)^1)
+
+--~ function file.removesuffix(name)
+--~ return pattern:match(name)
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.C(noslashes^1) * -1
+
+--~ function file.basename(name)
+--~ return pattern:match(name) or name
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.Cp() * noslashes^1 * -1
+
+--~ function file.dirname(name)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name:sub(1,p-2)
+--~ else
+--~ return ""
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.addsuffix(name, suffix)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.replacesuffix(name,suffix)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name:sub(1,p-2) .. "." .. suffix
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * lpeg.Cp() * ((noperiod^1 * period)^1 * lpeg.Cp() + lpeg.P(true)) * noperiod^1 * -1
+
+--~ function file.nameonly(name)
+--~ local a, b = pattern:match(name)
+--~ if b then
+--~ return name:sub(a,b-2)
+--~ elseif a then
+--~ return name:sub(a)
+--~ else
+--~ return name
+--~ end
+--~ end
+
+--~ local test = file.extname
+--~ 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 = lpeg.R("az","AZ") + lpeg.S("_-+")
+local separator = lpeg.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(":")
+
+-- ./name ../name /name c: :// name/name
+
+function file.is_qualified_path(filename)
+ return qualified:match(filename)
+end
+
+function file.is_rootbased_path(filename)
+ return rootbased:match(filename)
+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)
+
+local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc(""))
+
+function file.splitname(str) -- returns drive, path, base, suffix
+ return pattern:match(str)
+end
+
+-- function test(t) for k, v in pairs(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" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- 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" }