1 local lpeg = require('lpeg')
2 local re = require('re')
5 run_cmd = function(cmd)
6 local f = io.popen(cmd .. ' 2>/dev/null')
11 for line in f:lines() do
12 _accum_0[_len_0] = line
17 if not (f:close()) then
22 local _SPOOFED_FILES = { }
23 local _BROWSE_CACHE = { }
24 local _anon_number = 0
25 Files.spoof = function(filename, contents)
27 filename, contents = "<anonymous file #" .. tostring(_anon_number) .. ">", filename
28 _anon_number = _anon_number + 1
30 _SPOOFED_FILES[filename] = contents
33 Files.read = function(filename)
35 local contents = _SPOOFED_FILES[filename]
40 if filename == 'stdin' or filename == '-' then
41 local contents = io.read('*a')
42 Files.spoof('stdin', contents)
43 Files.spoof('-', contents)
46 local file = io.open(filename)
50 local contents = file:read("*a")
52 return contents or nil
57 match, gsub = _obj_0.match, _obj_0.gsub
60 sanitize = function(path)
61 path = gsub(path, "\\", "\\\\")
62 path = gsub(path, "`", "")
63 path = gsub(path, '"', '\\"')
64 path = gsub(path, "$", "")
67 Files.exists = function(path)
68 if _SPOOFED_FILES[path] then
71 if path == 'stdin' or path == '-' then
74 if run_cmd("ls " .. tostring(sanitize(path))) then
79 Files.list = function(path)
80 if not (_BROWSE_CACHE[path]) then
82 if _SPOOFED_FILES[path] or path == 'stdin' or path == '-' then
83 _BROWSE_CACHE[path] = {
87 _BROWSE_CACHE[path] = run_cmd('find -L "' .. path .. '" -not -path "*/\\.*" -type f') or false
90 return _BROWSE_CACHE[path]
92 Files.make_directory = function(path)
93 return run_cmd('mkdir ' .. path)
95 local ok, lfs = pcall(require, "lfs")
98 raw_file_exists = function(filename)
99 local mode = lfs.attributes(filename, 'mode')
100 if mode == 'file' or mode == 'directory' or mode == 'link' then
106 Files.exists = function(path)
107 if _SPOOFED_FILES[path] then
110 if path == 'stdin' or path == '-' or raw_file_exists(path) then
115 Files.list = function(path)
116 if not (_BROWSE_CACHE[path]) then
117 if _SPOOFED_FILES[path] or path == 'stdin' or path == '-' then
118 _BROWSE_CACHE[path] = {
122 local file_type, err = lfs.attributes(path, 'mode')
123 local _exp_0 = file_type
124 if "file" == _exp_0 or "char device" == _exp_0 then
125 _BROWSE_CACHE[path] = {
128 elseif "directory" == _exp_0 or "link" == _exp_0 then
130 for subfile in lfs.dir(path) do
131 local _continue_0 = false
133 if subfile == "." or subfile == ".." then
137 local _list_0 = (Files.list(path .. "/" .. subfile) or { })
138 for _index_0 = 1, #_list_0 do
139 local f = _list_0[_index_0]
140 files[#files + 1] = f
144 if not _continue_0 then
148 _BROWSE_CACHE[path] = files
150 _BROWSE_CACHE[path] = false
153 if _BROWSE_CACHE[path] then
154 for i, f in ipairs(_BROWSE_CACHE[path]) do
155 if f:match("^%./") then
156 _BROWSE_CACHE[path][i] = f:sub(3)
161 return _BROWSE_CACHE[path]
163 Files.make_directory = lfs.mkdir
165 if not (run_cmd('find . -maxdepth 0')) then
168 url = 'https://github.com/spacewander/luafilesystem'
170 url = 'https://github.com/keplerproject/luafilesystem'
172 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: " .. tostring(url) .. " or `luarocks install luafilesystem`)\n" .. tostring(lfs) .. "\npackage.cpath: " .. tostring(package.cpath), 0)
175 local line_counter = re.compile([[ lines <- {| line (%nl line)* |}
178 nl = lpeg.P("\r") ^ -1 * lpeg.P("\n")
180 local _LINE_STARTS = { }
181 Files.get_line_starts = function(str)
182 if type(str) ~= 'string' then
186 local starts = _LINE_STARTS[str]
191 local line_starts = line_counter:match(str)
192 _LINE_STARTS[str] = line_starts
195 Files.get_line_number = function(str, pos)
196 local line_starts = Files.get_line_starts(str)
197 local lo, hi = 1, #line_starts
199 local mid = math.floor((lo + hi) / 2)
200 if line_starts[mid] > pos then
208 Files.get_line = function(str, line_no)
209 local line_starts = Files.get_line_starts(str)
210 local start = line_starts[line_no]
214 local stop = line_starts[line_no + 1]
218 return (str:sub(start, stop - 2))