aboutsummaryrefslogtreecommitdiff

– Some file utilities for searching for files recursively and using package.nomsupath lpeg = require ‘lpeg’ re = require ‘re’ Files = {}

run_cmd = (cmd)-> f = io.popen(cmd..’ 2>/dev/null’) lines = [line for line in f\lines!] return nil unless f\close! return lines

SPOOFEDFILES = {} BROWSECACHE = {}

– Create a fake file and put it in the cache anonnumber = 0 Files.spoof = (filename, contents)-> if not contents filename, contents = “”, filename anonnumber += 1 SPOOFEDFILES[filename] = contents return filename

– Read a file’s contents Files.read = (filename)-> if contents = SPOOFEDFILES[filename] return contents if filename == ‘stdin’ or filename == ‘-’ contents = io.read(‘a’) Files.spoof(‘stdin’, contents) Files.spoof(‘-’, contents) return contents file = io.open(filename) return nil unless file contents = file\read(“a”) file\close! return contents or nil

{:match, :gsub} = string

– TODO: improve sanitization sanitize = (path)-> path = gsub(path,”\”,”\\”) path = gsub(path,”`”,””) path = gsub(path,’”’,’\”’) path = gsub(path,”$”,””) return path

Files.exists = (path)-> return true if SPOOFEDFILES[path] return true if path == ‘stdin’ or path == ‘-’ return true if run_cmd(“ls #{sanitize(path)}”) return false

Files.list = (path)-> unless BROWSECACHE[path] local files BROWSECACHE[path] = if SPOOFEDFILES[path] or path == ‘stdin’ or path == ‘-’ {path} else run_cmd(‘find -L “‘..path..’” -not -path “/\.” -type f’) or false return BROWSECACHE[path]

Files.makedirectory = (path)-> runcmd(‘mkdir ‘..path)

ok, lfs = pcall(require, “lfs”) if ok rawfileexists = (filename)-> mode = lfs.attributes(filename, ‘mode’) return if mode == ‘file’ or mode == ‘directory’ or mode == ‘link’ then true else false Files.exists = (path)-> return true if SPOOFEDFILES[path] return true if path == ‘stdin’ or path == ‘-’ or rawfileexists(path) return false

Files.list = (path)->
    unless _BROWSE_CACHE[path]
        _BROWSE_CACHE[path] = if _SPOOFED_FILES[path] or path == 'stdin' or path == '-'
            {path}
        else
            file_type, err = lfs.attributes(path, 'mode')
            switch file_type
                when "file", "char device"
                    {path}
                when "directory", "link"
                    files = {}
                    for subfile in lfs.dir(path)
                        continue if subfile == "." or subfile == ".."
                        for f in *(Files.list(path.."/"..subfile) or {})
                            files[#files+1] = f
                    files
                else false
        -- Filter out any "./" prefix to standardize
        if _BROWSE_CACHE[path]
            for i,f in ipairs(_BROWSE_CACHE[path])
                if f\match("^%./") then _BROWSE_CACHE[path][i] = f\sub(3)
    return _BROWSE_CACHE[path]

Files.make_directory = lfs.mkdir

else unless run_cmd(‘find . -maxdepth 0’) url = if jit ‘https://github.com/spacewander/luafilesystem’ else ‘https://github.com/keplerproject/luafilesystem’ 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: #{url} or luarocks install luafilesystem)\n#{lfs}\npackage.cpath: #{package.cpath}”, 0

line_counter = re.compile([[ lines <- {| line (%nl line)* |} line <- {} (!%nl .)* ]], nl:lpeg.P(“\r”)^-1 * lpeg.P(“\n”))

– LINE_STARTS is a mapping from strings to a table that maps line number to character positions LINESTARTS = {} Files.getlinestarts = (str)-> if type(str) != ‘string’ str = tostring(str) if starts = LINESTARTS[str] return starts linestarts = linecounter\match(str) LINESTARTS[str] = linestarts return linestarts

Files.getlinenumber = (str, pos)-> linestarts = Files.getlinestarts(str) – Binary search for line number of position lo, hi = 1, #linestarts while lo <= hi mid = math.floor((lo+hi)/2) if line_starts[mid] > pos hi = mid-1 else lo = mid+1 return hi

Files.getline = (str, lineno)-> linestarts = Files.getlinestarts(str) start = linestarts[lineno] return unless start stop = linestarts[line_no+1] return unless stop return (str\sub(start, stop - 2))

return Files