diff options
| author | Philipp Gesang <philipp.gesang@alumni.uni-heidelberg.de> | 2012-10-19 19:38:46 +0200 | 
|---|---|---|
| committer | Philipp Gesang <philipp.gesang@alumni.uni-heidelberg.de> | 2012-10-19 19:38:46 +0200 | 
| commit | 7932ae95cb4506822cb76ce7cc4f5491652db60d (patch) | |
| tree | 8db9fdafaeaec9c6648d2ee7d7c0f5bf10673f72 | |
| parent | eddad3cd039618fcb6a147686bb69906ecd5662c (diff) | |
| download | lualibs-7932ae95cb4506822cb76ce7cc4f5491652db60d.tar.gz | |
update l-dir.lua
| -rw-r--r-- | lualibs-dir.lua | 284 | 
1 files changed, 183 insertions, 101 deletions
| diff --git a/lualibs-dir.lua b/lualibs-dir.lua index 1b9bcbc..3deb660 100644 --- a/lualibs-dir.lua +++ b/lualibs-dir.lua @@ -6,35 +6,91 @@ if not modules then modules = { } end modules ['l-dir'] = {      license   = "see context related readme files"  } --- dir.expand_name will be merged with cleanpath and collapsepath +-- dir.expandname will be merged with cleanpath and collapsepath  local type = type  local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub +local concat, insert, remove = table.concat, table.insert, table.remove  local lpegmatch = lpeg.match +local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V +  dir = dir or { } +local dir = dir +local lfs = lfs + +local attributes = lfs.attributes +local walkdir    = lfs.dir +local isdir      = lfs.isdir +local isfile     = lfs.isfile +local currentdir = lfs.currentdir + +-- in case we load outside luatex + +if not isdir then +    function isdir(name) +        local a = attributes(name) +        return a and a.mode == "directory" +    end +    lfs.isdir = isdir +end + +if not isfile then +    function isfile(name) +        local a = attributes(name) +        return a and a.mode == "file" +    end +    lfs.isfile = isfile +end  -- handy  function dir.current() -    return (gsub(lfs.currentdir(),"\\","/")) +    return (gsub(currentdir(),"\\","/"))  end --- optimizing for no string.find (*) does not save time +-- optimizing for no find (*) does not save time + +--~ local function globpattern(path,patt,recurse,action) -- fails in recent luatex due to some change in lfs +--~     local ok, scanner +--~     if path == "/" then +--~         ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe +--~     else +--~         ok, scanner = xpcall(function() return walkdir(path)      end, function() end) -- kepler safe +--~     end +--~     if ok and type(scanner) == "function" then +--~         if not find(path,"/$") then path = path .. '/' end +--~         for name in scanner do +--~             local full = path .. name +--~             local mode = attributes(full,'mode') +--~             if mode == 'file' then +--~                 if find(full,patt) then +--~                     action(full) +--~                 end +--~             elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then +--~                 globpattern(full,patt,recurse,action) +--~             end +--~         end +--~     end +--~ end + +local lfsisdir = isdir + +local function isdir(path) +    path = gsub(path,"[/\\]+$","") +    return lfsisdir(path) +end -local attributes = lfs.attributes -local walkdir    = lfs.dir +lfs.isdir = isdir -local function glob_pattern(path,patt,recurse,action) -    local ok, scanner, dirobj +local function globpattern(path,patt,recurse,action)      if path == "/" then -        ok, scanner, dirobj = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe -    else -        ok, scanner, dirobj = xpcall(function() return walkdir(path)      end, function() end) -- kepler safe +        path = path .. "." +    elseif not find(path,"/$") then +        path = path .. '/'      end -    if ok and type(scanner) == "function" then -        if not find(path,"/$") then path = path .. '/' end -        for name in scanner, dirobj do +    if isdir(path) then -- lfs.isdir does not like trailing / +        for name in walkdir(path) do -- lfs.dir accepts trailing /              local full = path .. name              local mode = attributes(full,'mode')              if mode == 'file' then @@ -42,25 +98,25 @@ local function glob_pattern(path,patt,recurse,action)                      action(full)                  end              elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then -                glob_pattern(full,patt,recurse,action) +                globpattern(full,patt,recurse,action)              end          end      end  end -dir.glob_pattern = glob_pattern +dir.globpattern = globpattern -local function collect_pattern(path,patt,recurse,result) -    local ok, scanner, dirobj +local function collectpattern(path,patt,recurse,result) +    local ok, scanner      result = result or { }      if path == "/" then -        ok, scanner, dirobj = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe +        ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe      else -        ok, scanner, dirobj = xpcall(function() return walkdir(path)      end, function() end) -- kepler safe +        ok, scanner, first = xpcall(function() return walkdir(path)      end, function() end) -- kepler safe      end      if ok and type(scanner) == "function" then          if not find(path,"/$") then path = path .. '/' end -        for name in scanner, dirobj do +        for name in scanner, first do              local full = path .. name              local attr = attributes(full)              local mode = attr.mode @@ -69,7 +125,7 @@ local function collect_pattern(path,patt,recurse,result)                      result[name] = attr                  end              elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then -                attr.list = collect_pattern(full,patt,recurse) +                attr.list = collectpattern(full,patt,recurse)                  result[name] = attr              end          end @@ -77,9 +133,7 @@ local function collect_pattern(path,patt,recurse,result)      return result  end -dir.collect_pattern = collect_pattern - -local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V +dir.collectpattern = collectpattern  local pattern = Ct {      [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3), @@ -103,16 +157,16 @@ local function glob(str,t)              for s=1,#str do                  glob(str[s],t)              end -        elseif lfs.isfile(str) then +        elseif isfile(str) then              t(str)          else -            local split = lpegmatch(pattern,str) +            local split = lpegmatch(pattern,str) -- we could use the file splitter              if split then                  local root, path, base = split[1], split[2], split[3]                  local recurse = find(base,"%*%*")                  local start = root .. path                  local result = lpegmatch(filter,start .. base) -                glob_pattern(start,result,recurse,t) +                globpattern(start,result,recurse,t)              end          end      else @@ -122,12 +176,15 @@ local function glob(str,t)                  glob(str[s],t)              end              return t -        elseif lfs.isfile(str) then -            local t = t or { } -            t[#t+1] = str -            return t +        elseif isfile(str) then +            if t then +                t[#t+1] = str +                return t +            else +                return { str } +            end          else -            local split = lpegmatch(pattern,str) +            local split = lpegmatch(pattern,str) -- we could use the file splitter              if split then                  local t = t or { }                  local action = action or function(name) t[#t+1] = name end @@ -135,7 +192,7 @@ local function glob(str,t)                  local recurse = find(base,"%*%*")                  local start = root .. path                  local result = lpegmatch(filter,start .. base) -                glob_pattern(start,result,recurse,action) +                globpattern(start,result,recurse,action)                  return t              else                  return { } @@ -154,10 +211,11 @@ dir.glob = glob  local function globfiles(path,recurse,func,files) -- func == pattern or function      if type(func) == "string" then -        local s = func -- alas, we need this indirect way +        local s = func          func = function(name) return find(name,s) end      end      files = files or { } +    local noffiles = #files      for name in walkdir(path) do          if find(name,"^%.") then              --- skip @@ -168,12 +226,9 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function                      globfiles(path .. "/" .. name,recurse,func,files)                  end              elseif mode == "file" then -                if func then -                    if func(name) then -                        files[#files+1] = path .. "/" .. name -                    end -                else -                    files[#files+1] = path .. "/" .. name +                if not func or func(name) then +                    noffiles = noffiles + 1 +                    files[noffiles] = path .. "/" .. name                  end              end          end @@ -191,7 +246,7 @@ dir.globfiles = globfiles  -- print(dir.ls("*.tex"))  function dir.ls(pattern) -    return table.concat(glob(pattern),"\n") +    return concat(glob(pattern),"\n")  end  --~ mkdirs("temp") @@ -201,7 +256,9 @@ end  local make_indeed = true -- false -if string.find(os.getenv("PATH"),";") then -- os.type == "windows" +local onwindows = os.type == "windows" or find(os.getenv("PATH"),";") + +if onwindows then      function dir.mkdirs(...)          local str, pth, t = "", "", { ... } @@ -250,56 +307,24 @@ if string.find(os.getenv("PATH"),";") then -- os.type == "windows"              else                  pth = pth .. "/" .. s              end -            if make_indeed and not lfs.isdir(pth) then +            if make_indeed and not isdir(pth) then                  lfs.mkdir(pth)              end          end -        return pth, (lfs.isdir(pth) == true) +        return pth, (isdir(pth) == true)      end ---~         print(dir.mkdirs("","","a","c")) ---~         print(dir.mkdirs("a")) ---~         print(dir.mkdirs("a:")) ---~         print(dir.mkdirs("a:/b/c")) ---~         print(dir.mkdirs("a:b/c")) ---~         print(dir.mkdirs("a:/bbb/c")) ---~         print(dir.mkdirs("/a/b/c")) ---~         print(dir.mkdirs("/aaa/b/c")) ---~         print(dir.mkdirs("//a/b/c")) ---~         print(dir.mkdirs("///a/b/c")) ---~         print(dir.mkdirs("a/bbb//ccc/")) - -    function dir.expand_name(str) -- will be merged with cleanpath and collapsepath -        local first, nothing, last = match(str,"^(//)(//*)(.*)$") -        if first then -            first = dir.current() .. "/" -        end -        if not first then -            first, last = match(str,"^(//)/*(.*)$") -        end -        if not first then -            first, last = match(str,"^([a-zA-Z]:)(.*)$") -            if first and not find(last,"^/") then -                local d = lfs.currentdir() -                if lfs.chdir(first) then -                    first = dir.current() -                end -                lfs.chdir(d) -            end -        end -        if not first then -            first, last = dir.current(), str -        end -        last = gsub(last,"//","/") -        last = gsub(last,"/%./","/") -        last = gsub(last,"^/*","") -        first = gsub(first,"/*$","") -        if last == "" then -            return first -        else -            return first .. "/" .. last -        end -    end +    --~ print(dir.mkdirs("","","a","c")) +    --~ print(dir.mkdirs("a")) +    --~ print(dir.mkdirs("a:")) +    --~ print(dir.mkdirs("a:/b/c")) +    --~ print(dir.mkdirs("a:b/c")) +    --~ print(dir.mkdirs("a:/bbb/c")) +    --~ print(dir.mkdirs("/a/b/c")) +    --~ print(dir.mkdirs("/aaa/b/c")) +    --~ print(dir.mkdirs("//a/b/c")) +    --~ print(dir.mkdirs("///a/b/c")) +    --~ print(dir.mkdirs("a/bbb//ccc/"))  else @@ -307,7 +332,7 @@ else          local str, pth, t = "", "", { ... }          for i=1,#t do              local s = t[i] -            if s ~= "" then +            if s and s ~= "" then -- we catch nil and false                  if str ~= "" then                      str = str .. "/" .. s                  else @@ -325,7 +350,7 @@ else                  else                      pth = pth .. "/" .. s                  end -                if make_indeed and not first and not lfs.isdir(pth) then +                if make_indeed and not first and not isdir(pth) then                      lfs.mkdir(pth)                  end              end @@ -333,31 +358,88 @@ else              pth = "."              for s in gmatch(str,"[^/]+") do                  pth = pth .. "/" .. s -                if make_indeed and not lfs.isdir(pth) then +                if make_indeed and not isdir(pth) then                      lfs.mkdir(pth)                  end              end          end -        return pth, (lfs.isdir(pth) == true) +        return pth, (isdir(pth) == true) +    end + +    --~ print(dir.mkdirs("","","a","c")) +    --~ print(dir.mkdirs("a")) +    --~ print(dir.mkdirs("/a/b/c")) +    --~ print(dir.mkdirs("/aaa/b/c")) +    --~ print(dir.mkdirs("//a/b/c")) +    --~ print(dir.mkdirs("///a/b/c")) +    --~ print(dir.mkdirs("a/bbb//ccc/")) + +end + +dir.makedirs = dir.mkdirs + +-- we can only define it here as it uses dir.current + +if onwindows then + +    function dir.expandname(str) -- will be merged with cleanpath and collapsepath +        local first, nothing, last = match(str,"^(//)(//*)(.*)$") +        if first then +            first = dir.current() .. "/" +        end +        if not first then +            first, last = match(str,"^(//)/*(.*)$") +        end +        if not first then +            first, last = match(str,"^([a-zA-Z]:)(.*)$") +            if first and not find(last,"^/") then +                local d = currentdir() +                if lfs.chdir(first) then +                    first = dir.current() +                end +                lfs.chdir(d) +            end +        end +        if not first then +            first, last = dir.current(), str +        end +        last = gsub(last,"//","/") +        last = gsub(last,"/%./","/") +        last = gsub(last,"^/*","") +        first = gsub(first,"/*$","") +        if last == "" or last == "." then +            return first +        else +            return first .. "/" .. last +        end      end ---~         print(dir.mkdirs("","","a","c")) ---~         print(dir.mkdirs("a")) ---~         print(dir.mkdirs("/a/b/c")) ---~         print(dir.mkdirs("/aaa/b/c")) ---~         print(dir.mkdirs("//a/b/c")) ---~         print(dir.mkdirs("///a/b/c")) ---~         print(dir.mkdirs("a/bbb//ccc/")) +else -    function dir.expand_name(str) -- will be merged with cleanpath and collapsepath +    function dir.expandname(str) -- will be merged with cleanpath and collapsepath          if not find(str,"^/") then -            str = lfs.currentdir() .. "/" .. str +            str = currentdir() .. "/" .. str          end          str = gsub(str,"//","/")          str = gsub(str,"/%./","/") +        str = gsub(str,"(.)/%.$","%1")          return str      end  end -dir.makedirs = dir.mkdirs +file.expandname = dir.expandname -- for convenience + +local stack = { } + +function dir.push(newdir) +    insert(stack,lfs.currentdir()) +end + +function dir.pop() +    local d = remove(stack) +    if d then +        lfs.chdir(d) +    end +    return d +end | 
