lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Mildred <ml.mildred593 <at> online.fr> writes:

> I just created a module for lua 5.1.
> It is an interactive shell that can be used with debug.debug() or when
> lua is in interactive mode. Its purpose is to easily know the structure
> of tables.

Oh man, that is hilarious.

I figured that we needed to complete the circle, so I made a little module
that represents the actual filesystem as Lua tables.  Now we can use your
shell to cd into actual directories and cat actual files!

--------------------------------------------------------------------------
--
-- "Mounts" the filesystem root in the "files" global.  Directories
-- are represented as tables, and files are strings.
-- 
-- for filename in pairs(files) do print(filename) end
-- local secrets = files.Users.bret["secrets.txt"]
--
--------------------------------------------------------------------------

local lfs = require "lfs"
local yield = coroutine.yield

local dirpaths = {}  -- Maps dir proxy table to pathname, and vice-versa.
local dir_mt = {}    -- Metatable for dir proxy tables.

local function dirProxy (pathname) -- Make new proxy if one doesn't exist.
    local dir = dirpaths[pathname] or setmetatable({}, dir_mt)
    dirpaths[dir] = pathname
    dirpaths[pathname] = dir
    return dir
end

dir_mt.__index = function (t,k)  -- Read file or directory.
    local pathname = dirpaths[t] .. "/" .. k
    local mode = lfs.attributes(pathname,"mode")
    if mode == "directory" then return dirProxy(pathname)
    elseif mode == "file" then
        local file = io.open(pathname)
        if not file then return end
        local contents = file:read("*a")
        file:close()
        return contents
    end
end

local function dirNext (t) -- Iterate over directory (but don't read files)
    local dirpath = dirpaths[t] .. "/"
    for filename in lfs.dir(dirpath) do
        local pathname = dirpath .. filename
        local mode = lfs.attributes(pathname,"mode")
        if mode == "file" then yield(filename, "Your data here.")
        elseif mode == "directory" then yield(filename, dirProxy(pathname))
        end
    end
end

-- Let us say a prayer for the __pairs metamethod.
local oldpairs = pairs
local function newpairs (t)  -- Override pairs so we can iterate over dirs.
    if dirpaths[t] then return coroutine.wrap(dirNext), t, nil end
    return oldpairs(t)
end

-- Exports.
files = dirProxy("")  -- filesystem root
pairs = newpairs