From ae4670bd8e0e45985e43402f246e4219cd29fcaa Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 21 Jul 2018 14:43:49 -0700 Subject: Improvements working towards better inline tests. Improved handling of file spoofing and adding -e command line flag for executing a string. --- files.lua | 146 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 83 insertions(+), 63 deletions(-) (limited to 'files.lua') diff --git a/files.lua b/files.lua index ef5c8c1..c6da8c8 100644 --- a/files.lua +++ b/files.lua @@ -1,11 +1,16 @@ local lpeg = require('lpeg') local re = require('re') -local files = { } -local _FILE_CACHE = { } -files.spoof = function(filename, contents) - _FILE_CACHE[filename] = contents +local Files = { } +local _SPOOFED_FILES = { } +local _FILE_CACHE = setmetatable({ }, { + __index = _SPOOFED_FILES +}) +local _BROWSE_CACHE = { } +Files.spoof = function(filename, contents) + _SPOOFED_FILES[filename] = contents + return contents end -files.read = function(filename) +Files.read = function(filename) do local file_contents = _FILE_CACHE[filename] if file_contents then @@ -13,9 +18,7 @@ files.read = function(filename) end end if filename == 'stdin' then - local contents = io.read('*a') - _FILE_CACHE['stdin'] = contents - return contents + return Files.spoof('stdin', io.read('*a')) end local file = io.open(filename) if package.nomsupath and not file then @@ -47,7 +50,10 @@ sanitize = function(path) path = gsub(path, "$", "") return path end -files.exists = function(path) +Files.exists = function(path) + if _SPOOFED_FILES[path] then + return true + end if not (io.popen("ls " .. tostring(sanitize(path))):close()) then return true end @@ -60,26 +66,28 @@ files.exists = function(path) end return false end -local _browse_cache = { } local browse browse = function(path) - if not (_browse_cache[path]) then - local f = io.popen('find -L "' .. package.nomsupath .. '/' .. path .. '" -not -path "*/\\.*" -type f -name "*.nom"') - local _files - do - local _tbl_0 = { } - for line in f:lines() do - local _key_0, _val_0 = line - _tbl_0[_key_0] = _val_0 + if not (_BROWSE_CACHE[path]) then + local files + if _SPOOFED_FILES[path] then + _BROWSE_CACHE[path] = { + path + } + else + local f = io.popen('find -L "' .. package.nomsupath .. '/' .. path .. '" -not -path "*/\\.*" -type f -name "*.nom"') + do + local _tbl_0 = { } + for line in f:lines() do + local _key_0, _val_0 = line + _tbl_0[_key_0] = _val_0 + end + files = _tbl_0 end - _files = _tbl_0 + _BROWSE_CACHE[path] = f:close() and files or false end - if not (f:close()) then - _files = false - end - _browse_cache[path] = _files end - return _browse_cache[path] + return _BROWSE_CACHE[path] end local ok, lfs = pcall(require, "lfs") if ok then @@ -92,7 +100,10 @@ if ok then return false end end - files.exists = function(path) + Files.exists = function(path) + if _SPOOFED_FILES[path] then + return true + end if path == 'stdin' or raw_file_exists(path) then return true end @@ -106,72 +117,81 @@ if ok then return false end browse = function(filename) - if not (_browse_cache[filename]) then - _browse_cache[filename] = false - local file_type, err = lfs.attributes(filename, 'mode') - if file_type == 'file' then - if match(filename, "%.nom$") or match(filename, "%.lua$") then - _browse_cache[filename] = { - filename - } - end - elseif file_type == 'char device' then - _browse_cache[filename] = { + if not (_BROWSE_CACHE[filename]) then + if _SPOOFED_FILES[filename] then + _BROWSE_CACHE[filename] = { filename } - elseif file_type == 'directory' or file_type == 'link' then - local _files = { } - for subfile in lfs.dir(filename) do - if not (subfile == "." or subfile == "..") then - local _list_0 = (browse(filename .. "/" .. subfile) or { }) - for _index_0 = 1, #_list_0 do - local f = _list_0[_index_0] - _files[#_files + 1] = f + else + local file_type, err = lfs.attributes(filename, 'mode') + if file_type == 'file' then + if match(filename, "%.nom$") or match(filename, "%.lua$") then + _BROWSE_CACHE[filename] = { + filename + } + else + _BROWSE_CACHE[filename] = false + end + elseif file_type == 'char device' then + _BROWSE_CACHE[filename] = { + filename + } + elseif file_type == 'directory' or file_type == 'link' then + local files = { } + for subfile in lfs.dir(filename) do + if not (subfile == "." or subfile == "..") then + local _list_0 = (browse(filename .. "/" .. subfile) or { }) + for _index_0 = 1, #_list_0 do + local f = _list_0[_index_0] + files[#files + 1] = f + end end end + _BROWSE_CACHE[filename] = files + else + _BROWSE_CACHE[filename] = false end - _browse_cache[filename] = _files end end - return _browse_cache[filename] + return _BROWSE_CACHE[filename] end else if io.popen('find . -maxdepth 0'):close() then error("Could not find 'luafilesystem' module and couldn't run system command `find` (this might happen on Windows). Please install `luafilesystem` (which can be found at: http://keplerproject.github.io/luafilesystem/ or `luarocks install luafilesystem`)", 0) end end -files.walk = function(path, flush_cache) +Files.walk = function(path, flush_cache) if flush_cache == nil then flush_cache = false end if flush_cache then - _browse_cache = { } + _BROWSE_CACHE = { } end - local _files = browse(path) - if package.nomsupath and not _files then + local files = browse(path) + if package.nomsupath and not files then for nomsupath in package.nomsupath:gmatch("[^;]+") do do - _files = browse(nomsupath .. "/" .. path) - if _files then + files = browse(nomsupath .. "/" .. path) + if files then break end end end end local iter - iter = function(_files, i) - if not (_files) then + iter = function(files, i) + if not (files) then return end i = i + 1 do - local f = _files[i] + local f = files[i] if f then return i, f end end end - return iter, _files, 0 + return iter, files, 0 end local line_counter = re.compile([[ lines <- {| line (%nl line)* |} line <- {} (!%nl .)* @@ -179,7 +199,7 @@ local line_counter = re.compile([[ lines <- {| line (%nl line)* |} nl = lpeg.P("\r") ^ -1 * lpeg.P("\n") }) local _LINE_STARTS = { } -files.get_line_starts = function(str) +Files.get_line_starts = function(str) if type(str) ~= 'string' then str = tostring(str) end @@ -194,8 +214,8 @@ files.get_line_starts = function(str) return line_starts end local log = { } -files.get_line_number = function(str, pos) - local line_starts = files.get_line_starts(str) +Files.get_line_number = function(str, pos) + local line_starts = Files.get_line_starts(str) local lo, hi = 1, #line_starts while lo <= hi do local mid = math.floor((lo + hi) / 2) @@ -207,8 +227,8 @@ files.get_line_number = function(str, pos) end return hi end -files.get_line = function(str, line_no) - local line_starts = files.get_line_starts(str) +Files.get_line = function(str, line_no) + local line_starts = Files.get_line_starts(str) return str:sub(line_starts[line_no] or 1, (line_starts[line_no + 1] or 1) - 2) end local get_lines = re.compile([[ lines <- {| line (%nl line)* |} @@ -216,7 +236,7 @@ local get_lines = re.compile([[ lines <- {| line (%nl line)* |} ]], { nl = lpeg.P("\r") ^ -1 * lpeg.P("\n") }) -files.get_lines = function(str) +Files.get_lines = function(str) return get_lines:match(str) end -return files +return Files -- cgit v1.2.3