lua-users home
lua-l archive

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


Here's another little example of how metamethods can do interesting
things, so that what appears to be a function actually translates into
a shell command.

The idea is to write the shell commands in a natural Lua way:

print(shell.which 'lua')
print(shell.chmod('+x','test3.lua'))
print(shell.gcc ({'-shared','-fpic'},'test 3.lua'))

and then use __index on the shell table to do the translation. This
could be called the 'shell pattern' for lack of a better term.

-- shell.lua
shell = {}
local mt = {}
setmetatable(shell,mt)

function shell.command(cmd,no_lf)
    print(cmd)
   local f = io.popen(cmd..' 2>&1; echo "-retcode:$?"' ,'r')
   local l = f:read '*a'
   f:close()
   local i1,i2,ret = l:find('%-retcode:(%d+)\n$')
   if no_lf and i1 > 1 then i1 = i1 - 1 end
   l = l:sub(1,i1-1)
   return tonumber(ret),l
end

local concat

concat = function (args)
    for i,s in ipairs(args) do
        if type(s) == 'table' then
            args[i] = concat(s)
        else
            args[i] = s:find '%s' and '"'..s..'"' or s
        end
    end
    return table.concat(args,' ')
end

function mt.__index(t,k)
    return function(...)
        return shell.command(k..' '..concat{...},true)
    end
end

print(shell.which 'lua')
print(shell.chmod('+x','test3.lua'))
print(shell.gcc ({'-shared','-fpic'},'test 3.lua'))
------

And the output is:

which lua
0	/usr/local/bin/lua
chmod +x test3.lua
0	
gcc -shared -fpic "test 3.lua"
1	gcc: test 3.lua: No such file or directory
gcc: no input files

Ignore the particular implementation of shell.command, which can be
more elegantly done with luaex.

A subpattern here is a generalization of concat to handle nested
tables, which makes it easy to compose command lines.

For example, to compile simple Lua extensions:

local liboptions = {'-shared','-fpic'}
local includes = {'-I','/home/sdonovan/lua/include'}

function lcompile(name)
   local status = shell.gcc(liboptions,includes,name..'.c','-o',name..'.so')
   return status == 0
end

steve d.