Skip to content

Instantly share code, notes, and snippets.

@severak
Created October 21, 2012 13:44
Show Gist options
  • Save severak/3927004 to your computer and use it in GitHub Desktop.
Save severak/3927004 to your computer and use it in GitHub Desktop.
ONYX shell - unix-like shell simulator - version for Mobile Lua
-- VERSION FOR MOBILE LUA
----
-- Table FS
----
-- an unix-like filesystem simulation on lua tables
-- by Severak 2012
-- license: WTFPL
----
-- documentation will come later....
function tDir(t)
for k,v in pairs(t) do
if type(v)=="table" then
v[".."]=t
end
end
t["."]=t
return t
end
function TableFS(tree, startPath)
startPath = startPath or "/"
local state={}
local tfs={}
function walk(d, path)
local current=d
for name in path:gmatch("([^/]+)") do
if type(current[name])=="table" then
current=current[name]
elseif current[name] then
return current[name]
else
return nil
end
end
return current
end
state.root=tree
state.wd=walk(state.root,startPath)
tfs.load=function(path)
if string.sub(path,1,1)=="/" then
return walk(state.root, string.sub(path,2))
else
return walk(state.wd,path)
end
end
tfs.save=function(path,data)
local a,b=string.match(path,"(.+)/([^/]+)")
local dir=nil
local name=nil
if a and b then
dir=tfs.load(a)
name=b
else
dir=state.wd
name=path
end
dir[name]=data
end
tfs.dir=function(path)
path=path or "."
local cd=tfs.load(path)
if not (type(cd)=="table") then
error(string.format("%s is not dir"),path)
end
local listing={}
for k,v in pairs(cd) do
listing[#listing+1]=k
end
table.sort(listing)
local i=0
local n=#listing
return function()
i=i+1
if i <= n then return listing[i] end
end
end
tfs.chdir=function(path)
local newDir=tfs.load(path)
if newDir then
if type(newDir)=="table" then
state.wd=newDir
return true
end
return nil, "This isn't dir."
end
return nil, "Path goes to nowhere"
end
tfs.mkdir=function(name)
if state.wd[name] then
return nil, "Directory already exists."
else
state.wd[name]={}
state.wd[name][".."]=state.wd
state.wd[name]["."]=state.wd[name]
end
end
tfs.pwd=function()
curr=state.wd
local names={}
while curr[".."] do
prev=curr
curr=curr[".."]
for k,v in pairs(curr) do
if v==prev then
table.insert(names,1,k)
end
end
end
return "/" .. table.concat(names,"/")
end
return tfs
end
----
-- ONYX shell
----
-- unix-like shell simulator
-- by Severak 2012
-- license WTFPL
----
command={}
command["ver"]=function()
return "ONYX v 1.0"
end
--command["exit"]=function() os.exit() end
command["echo"]=function(argz)
return table.concat(argz," ")
end
command["ls"]=function(argz)
local out={}
local dir=argz[1] or "."
if not(type(tfs.load(dir))=="table") then
print(string.format("%s is not a dir.", dir))
return ""
end
for file in tfs.dir(dir) do
out[#out+1]=file
end
return table.concat(out,"\n")
end
command["cd"]=function(argz)
local ok,err=tfs.chdir(argz[1] or ".")
if not ok then
print("-onyx: ",err)
end
end
command["pwd"]=function(argz)
return tfs.pwd()
end
command["mkdir"]=function(argz)
local ok,err=tfs.mkdir(argz[1] or ".")
if ok then
return 0
else
print(err)
end
end
command["rmrf"]=function(argz)
if #argz>0 then
tfs.save(argz,nil)
end
end
function splitWords(sentence)
local ret={}
for word in sentence:gmatch("([^%s]+)") do
ret[#ret+1]=word
end
return ret
end
local tree=tDir{
home=tDir{
help="Work with it as you will work with unix.",
examples=tDir{
a="echo ok|reverse",
b="cat /doc/readme",
c="ls>dir.txt",
d="echo ok|reverse|tee reversed.txt|reverse>normal.txt"
}
},
doc=tDir{
readme="There is no readme today\n:-("
},
bin=tDir{},
dev=tDir{}
}
devMT={
__index=function(dir,file)
if file=="random" then
return math.random(255)
elseif file=="null" then
return ""
end
end,
__newindex=function(dir,file,data)
if file=="null" or file=="random" then
return nil
else
rawset(dir,file,data)
end
end
}
setmetatable(tree["dev"],devMT)
tfs=TableFS(tree,"home")
tfs.save("/bin/cat", function(argz,stdin)
local out={}
if #argz>0 then
for _,name in pairs(argz) do
local data,err=tfs.load(name)
if type(data)=="table" then
print(string.format("cat: %s: Is directory",name))
elseif data then
out[#out+1]=tostring(data)
else
print(string.format("cat: %s: %s",name,err or "File not found!"))
end
end
else
out[#out+1]=input.get()
end
return table.concat(out,"\n")
end)
tfs.save("/bin/reverse", function(argz,stdin)
return string.reverse(stdin or "")
end)
tfs.save("/bin/tee", function(argz,stdin)
for _,name in pairs(argz) do
tfs.save(name,stdin)
end
return stdin
end)
tfs.save("/bin/help", function()
print("Use it like unix.")
print("There is no other help...")
end)
function processPipe(cmds)
local out=""
for stdin in string.gmatch(cmds,"([^|]+)") do
local args=splitWords(stdin)
local cmd=table.remove(args,1)
if command[cmd] then
out=command[cmd](args)
else
local fun=tfs.load("/bin/"..cmd)
if type(fun)=="function" then
out=fun(args,out)
else
print(string.format("An attemp to call %s (not a function)",cmd))
break
end
end
end
return out or ""
end
function main()
while true do
local outfile=false
local stdin=input.get()
if stdin=="" then
freeze()
else
if stdin=="exit" then
break
end
if string.match(stdin,"(.+)>(.+)") then
stdin,outfile=string.match(stdin,"(.+)>(.+)")
end
local out=processPipe(stdin)
if not(out=="") then
if outfile then
tfs.save(outfile,out)
else
print(out)
end
end
end
end
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment