aboutsummaryrefslogtreecommitdiff
path: root/files.moon
blob: e873c1de826b54ec3002b29c58857f3ff6041ecb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
-- Some file utilities for searching for files recursively and using package.nomsupath
files = {}

_FILE_CACHE = {}

-- Create a fake file and put it in the cache
files.spoof = (filename, contents)->
    _FILE_CACHE[filename] = contents

-- Read a file's contents (searching first locally, then in the nomsupath)
files.read = (filename)->
    if file_contents = _FILE_CACHE[filename]
        return file_contents
    file = io.open(filename)
    if package.nomsupath and not file
        for nomsupath in package.nomsupath\gmatch("[^;]+")
            file = io.open(nomsupath.."/"..filename)
            break if file
    return nil unless file
    contents = file\read("*a")
    file\close!
    _FILE_CACHE[filename] = contents
    return contents

iterate_single = (item, prev) -> if item == prev then nil else item

-- `walk` returns an iterator over all files matching a path.
{:match, :gsub} = string
iterate_single = (item, prev) -> if item == prev then nil else item
ok, lfs = pcall(require, "lfs")
if ok
    files.walk = (path)->
        -- Return 'true' if any files or directories are found, otherwise 'false'
        browse = (filename)->
            file_type = lfs.attributes(filename, 'mode')
            if file_type == 'file'
                if match(filename, "%.nom$") or match(filename, "%.lua$")
                    coroutine.yield filename
                    return true
            elseif file_type == 'directory'
                for subfile in lfs.dir(filename)
                    -- Only include .nom files unless directly specified
                    unless subfile == "." or subfile == ".." or not subfile\match("%.nom$")
                        browse(filename.."/"..subfile)
                return true
            elseif file_type == 'char device'
                coroutine.yield(filename)
                return true
            return false
        return coroutine.wrap ->
            if not browse(path) and package.nomsupath
                for nomsupath in package.nomsupath\gmatch("[^;]+")
                    break if browse(nomsupath.."/"..path)
            return nil
else
    ret = os.execute('find . -maxdepth 0')
    unless ret == true or ret == 0
        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

    files.walk = (path)->
        -- Sanitize path
        if match(path, "%.nom$") or match(path, "%.lua$") or match(path, "^/dev/fd/[012]$")
            return iterate_single, path
        -- TODO: improve sanitization
        path = gsub(path,"\\","\\\\")
        path = gsub(path,"`","")
        path = gsub(path,'"','\\"')
        path = gsub(path,"$","")
        return coroutine.wrap ->
            f = io.popen('find -L "'..path..'" -not -path "*/\\.*" -type f -name "*.nom"')
            found = false
            for line in f\lines!
                found = true
                coroutine.yield(line)
            if not found and package.nomsupath
                f\close!
                for nomsupath in package.nomsupath\gmatch("[^;]+")
                    f = io.popen('find -L "'..package.nomsupath..'/'..path..'" -not -path "*/\\.*" -type f -name "*.nom"')
                    for line in f\lines!
                        found = true
                        coroutine.yield(line)
                    f\close!
                    break if found
            unless found
                error("Invalid file path: "..tostring(path))

return files