Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local version="1.2.9"
- --THIS IS A TESTING VERSION, PLEASE REPORT ANY BUGS. IF YOU WISH TO REVERT TO THE LAST VERSION IT IS IN THE KAOSHELL.BAK FILE
- setfenv(nil,setmetatable(getfenv(),{__index=_G,__newindex=_G}))
- local tBanned={}
- myNet={}
- local function max(tPar) --find the highest numeric index
- local count=0
- for k,v in pairs(tPar) do
- if (tonumber(k) or 0)>(tonumber(count) or 0) then count=k end
- end
- return count
- end
- local function min(tPar) --find the lowest numeric index
- local count=1/0
- for k,v in pairs(tPar) do
- count=math.min(tonumber(k) or count,count)
- end
- return count
- end
- function count(t)
- if type(t)~="table" then
- error("table expected, got "..type(t),2)
- end
- local num=0
- for k,v in pairs(t) do
- num=num+1
- end
- return num
- end
- function safepairs(t)
- if type(t)~="table" then
- error("table expected, got "..type(t),2)
- end
- local tIndexes={}
- for k,v in pairs(t) do table.insert(tIndexes,k) end
- return coroutine.wrap(function() for i=1,#tIndexes do if t[tIndexes[i]] then coroutine.yield(tIndexes[i],t[tIndexes[i]]) end end end)
- end
- -- EXECUTION AND COROUTINE MANAGEMENT ----------------------------------------------------------------------------------
- local tCo={shell=coroutine.create(function() os.run({_G},"rom/programs/shell") end)}
- local function resume(ref,tEvts)
- local thread=type(tCo[ref])=="table" and tCo[ref][1] or tCo[ref]
- local ok,res=coroutine.resume(thread,unpack(tEvts))
- if not ok and res then
- os.queueEvent("message","coroutine "..ref.." threw the error: ",5)
- os.queueEvent("message",res,5)
- end
- if coroutine.status(thread)=="dead" then
- if not (type(tCo[ref])=="table" and tCo[ref][2]) then
- os.queueEvent("message","coroutine "..ref.." has died")
- end
- tCo[ref]=nil
- end
- end
- local customTerm=setmetatable({},{__index=term.native})
- local current
- begin=function()
- os.unloadAPI("rednet") os.loadAPI("rom/apis/rednet")
- table.insert(tCo,2,coroutine.create(rednet.run))
- local tEvts={}
- while count(tCo)~=0 do
- for k,v in safepairs(tCo) do
- current=k
- resume(k,tEvts)
- end
- current=nil
- while true do
- tEvts={coroutine.yield()}
- local tResult=textutils.unserialize(tEvts[1])
- if type(tResult)=="table" and tResult[1]=="KaoShell event" then
- if tCo[tResult[2]] then
- resume(tResult[2],tResult[4])
- elseif tResult[3] then
- os.queueEvent("message","coroutine "..tResult[3].." attempted to queue an event for nonexistant coroutine: "..tResult[2],4)
- end
- else
- break
- end
- end
- end
- print("all coroutines have been terminated, ending now")
- sleep(2)
- end
- local tBanned={pos="pos2",KaoS="fakeshit",[shell.getRunningProgram()]=(shell.getRunningProgram()).."2",["KaoShell.bak"]="aasdfa"}
- function loadUp()
- -- misc --------------------------------------------------------------------------
- KaoShell={}
- KaoShell.version=function()
- return "KaoShell "..version
- end
- os.version=KaoShell.version
- -- Coroutine management -----------------------------------------------------------
- KaoShell.queueEvent=function(ref,...)
- if not tCo[ref] then
- error("Invalid reference, coroutine "..ref.." does not exist",2)
- end
- os.queueEvent(textutils.serialize({"KaoShell event",ref,current,{...}}))
- end
- KaoShell.addCo=function(func,ref,bHide)
- ref=ref or max(tCo)+1
- local t=type(func)
- if t~="function" then
- print("incorrect param #1 function expected, got "..t)
- return nil, ("incorrect param #1 function expected, got "..t)
- end
- tCo[ref]={coroutine.create(func),bHide}
- return ref
- end
- KaoShell.remCo=function(num,b)
- num=num or 0
- if not tCo[num] then
- print("There is no coroutine under that reference")
- return nil
- elseif num==current then
- print("cannot remove the current coroutine")
- return nil
- end
- tCo[num]=nil
- if b then
- os.queueEvent("message","coroutine "..num.." has died")
- end
- return true
- end
- KaoShell.getCo=function(num)
- return tCo[num]
- end
- local update=function()
- local latestVer
- if http then
- local response = http.get("http://pastebin.com/raw.php?i=Yr3NQqQg")
- if type(response)=="table" then
- local KaoShell=response.readAll()
- response.close()
- latestVer=loadstring(KaoShell:sub(1,KaoShell:find("\n")-1).." return version")()
- if latestVer>version then
- if fs.old.exists("KaoShell.bak") then
- fs.old.delete("KaoShell.bak")
- end
- fs.old.move("startup","KaoShell.bak")
- local oFile=fs.old.open("startup","w")
- oFile.write(KaoShell)
- oFile.close()
- os.queueEvent("message","Update complete. You are now on KaoShell v"..latestVer,5)
- os.queueEvent("message","Terminal will auto-restart in 5 seconds",5)
- local restartTimer=os.startTimer(5)
- repeat
- local evts={os.pullEventRaw()}
- until evts[1]=="timer" and evts[2]==restartTimer and os.reboot() or evts[1]=="key"
- os.queueEvent("message","restart cancelled")
- end
- end
- end
- end
- KaoShell.addCo(update,"Updater",true)
- -- metatable addons --------------------------------------------------------------
- local nativeType=type
- type=function(input)
- local ok,mt=pcall(function() return getmetatable(input) end)
- return ok and nativeType(mt)=="table" and (nativeType(mt.__type)=="function" and mt.__type(input) or nativeType(mt.__type)~="function" and mt.__type) or nativeType(input)
- end
- local nativeTonumber=tonumber
- tonumber=function(...)
- local args={...}
- local ok,mt=pcall(function() return getmetatable(args[1]) end)
- return ok and nativeType(mt)=="table" and (nativeType(mt.__tonumber)=="function" and mt.__tonumber(...) or nativeType(mt.__tonumber)~="function" and mt.__tonumber) or nativeTonumber(...)
- end
- local nativeNext=next
- next=function(tInput,lastIndex)
- local ok,mt=pcall(function() return getmetatable(tInput) end)
- return ok and nativeType(mt)=="table" and (nativeType(mt.__next)=="function" and mt.__next(tInput,lastIndex) or nativeType(mt.__next)~="function" and mt.__next) or nativeNext(tInput,lastIndex)
- end
- -- myNet Daemon ----------------------------------------------------------------------
- function myNet.run() --myNet background coroutine
- while true do
- local input={os.pullEventRaw()}
- if input[1]=="rednet_message" then
- table.remove(input,1)
- local t=textutils.unserialize(input[2])
- if t and t[1]=="myNet" and not tBanned[t[3]] then
- tBanned[t[3]]=os.startTimer(2)
- rednet.broadcast(input[2])
- if not t[4] or t[4]==os.computerID() then
- os.queueEvent("myNet",t[2],t[3])
- end
- elseif input[2]=="PING" and pos.z and pos.y and pos.x then
- rednet.send(input[1],textutils.serialize({pos.x,pos.y,pos.z}))
- end
- elseif input[1]=="modem_message" and input[3]==gps.CHANNEL_GPS and input[5]=="PING" and pos.z and pos.y and pos.x then
- peripheral.call(tPeriphs("modem"),"transmit",input[4],gps.CHANNEL_GPS,textutils.serialize({pos.x,pos.y,pos.z}))
- elseif input[1]=="timer" then
- for k,v in pairs(tBanned) do
- if v==input[2] then
- tBanned[k]=nil
- break
- end
- end
- end
- end
- end
- KaoShell.addCo(myNet.run,"myNet Daemon")
- function myNet.send(message,id)
- rednet.broadcast(textutils.serialize({"myNet",os.computerID(),message,id}))
- end
- function myNet.receive(timeout)
- local timed=false
- if type(timeout)=="number" then timed=os.startTimer(timeout) end
- while true do
- local evts={os.pullEvent()}
- if evts[1]=="timer" and evts[2]==timed then
- return nil
- elseif evts[1]=="myNet" then
- return unpack(evts,2)
- end
- end
- end
- -- MESSAGING DEAMON ------------------------------------------------------------------------------
- local messages=function() --message display coroutine
- local timer
- local len
- local tMessages={}
- local msgLayer=term.newLayer(100)
- if term.isColor() then
- msgLayer.setTextColor(colors.red)
- msgLayer.setBackgroundColor(colors.white)
- end
- local function render()
- local size={term.getSize()}
- msgLayer.clear()
- local y=1
- for k,v in pairs(tMessages) do
- msgLayer.setCursorPos(1,y)
- msgLayer.setTextColor(v[3] or term.isColor() and colors.red or colors.black)
- msgLayer.setBackgroundColor(v[4] or colors.white)
- y=y+msgLayer.write(v[1],true)
- end
- layers.render()
- end
- while true do
- local evts={os.pullEvent()}
- if evts[1]=="message" and type(evts[2])=="string" then
- table.insert(tMessages,{evts[2],os.startTimer(tonumber(evts[3] or "") or 2),evts[4],evts[5]})
- render()
- elseif evts[1]=="timer" then
- for k,v in pairs(tMessages) do
- if evts[2]==v[2] then
- table.remove(tMessages,k)
- render()
- break
- end
- end
- end
- end
- end
- KaoShell.addCo(messages,"Messaging Daemon")
- -- PERIPHERAL MONITORING DAEMON --------------------------------------------------------------------
- local periphwatcher=function() --peripheral monitoring coroutine
- tPeriphs=setmetatable({},{__call=function(self,type)
- for k,v in pairs(self) do
- if v==type then
- return k
- end
- end
- end})
- for k,v in pairs(rs.getSides()) do
- if peripheral.getType(v)=="modem" then
- rednet.open(v)
- peripheral.call(v,"open",gps.CHANNEL_GPS)
- end
- if peripheral.isPresent(v) then
- tPeriphs[v]=peripheral.getType(v)
- end
- end
- while true do
- local evts={os.pullEventRaw()}
- if evts[1]=="peripheral" and peripheral.getType(evts[2]) then
- os.queueEvent("message",peripheral.getType(evts[2]).." detected on the "..evts[2].." side")
- tPeriphs[evts[2]]=peripheral.getType(evts[2])
- if tPeriphs[evts[2]]=="modem" then
- rednet.open(evts[2])
- peripheral.call(evts[2],"open",gps.CHANNEL_GPS)
- end
- elseif evts[1]=="peripheral_detach" and tPeriphs[evts[2]] then
- os.queueEvent("message",tPeriphs[evts[2]].." detached on the "..evts[2].." side")
- tPeriphs[evts[2]]=nil
- end
- end
- end
- KaoShell.addCo(periphwatcher,"Peripheral monitoring")
- -- TERM MOD -----------------------------------------------------------------------------------
- local bWritten=true
- local tsym={w=1,o=2,m=4,B=8,y=16,l=32,P=64,g=128,G=256,c=512,p=1024,b=2048,z=4096,q=8192,r=16384,a=32768}
- layers={render=function()
- term.native.setBackgroundColor(layers[min(layers)].getBackgroundColor())
- term.native.clear()
- local pos={term.native.getCursorPos()}
- for k,v in pairs(layers) do
- if type(v)=="layer" then
- v.render()
- end
- end
- term.native.setCursorPos(unpack(pos))
- end,scroll=function(nLines)
- for k,v in pairs(layers) do
- if type(v)=="layer" and v.linked then
- v.scroll(nLines,true)
- end
- end
- end}
- term.newLayer=function(index,tParams)
- local redirected=false
- tParams=tParams or {}
- local layer=setmetatable({},{__index=term.native,__type="layer"})
- table.insert(layers,index or #layers+1,layer)
- layer.linked=tParams.linked or false
- layer.showscroll=tParams.showscroll or false
- layer.scrolling=tParams.scrolling or true
- layer.scrolled=layer.linked and term.scrolled or 1
- local record=setmetatable({text={},tcol={},tback={}},{__call=function(self)
- for k,v in pairs(self) do
- local rem={}
- for row,tLine in pairs(v) do
- local cont=false
- for a,b in pairs(tLine) do
- cont=true
- end
- if not cont then
- table.insert(rem,row)
- end
- end
- for a,b in pairs(rem) do
- v[a]=nil
- end
- end
- end})
- for k,v in pairs(record) do setmetatable(v,{__index=function(self,index) if (tonumber(index) or 1)<=1 then return nil end self[index]={} return self[index] end,__newindex=function(self,index,value) if (tonumber(index) or 1)<=1 then return nil end rawset(self,index,value) end}) end
- layer.record=record
- layer.native={}
- layer.native.getSize=term.native.getSize
- layer.getSize=function()
- local size={term.native.getSize()}
- return size[1]-(layer.showscroll and 1 or 0),size[2]
- end
- local lX,lY=1,1
- layer.setCursorPos=function(x,y)
- if type(x)=="number" and type(y)=="number" then
- lX=math.floor(x)
- lY=math.floor(y)
- if redirected then
- if lX>0 and lY>0 then
- layer.setCursorBlink(nil,false)
- else
- layer.setCursorBlink(nil,true)
- end
- term.native.setCursorPos(lX,lY)
- end
- return true
- end
- return false
- end
- layer.getCursorPos=function()
- return lX,lY
- end
- local gcp=layer.getCursorPos
- local tCol=colors.white
- local tCols={}
- for k,v in pairs(colors) do if type(v)=="number" then tCols[v]=k end end
- colors.isColor=function(num)
- return tCols[num]~=nil
- end
- layer.setTextColor=function(col)
- if colors.isColor(col) then
- tCol=col
- return true
- end
- return false
- end
- layer.setTextColour=layer.setTextColor
- local tBack=colors.black
- layer.setBackgroundColor=function(col)
- if colors.isColor(col) then
- tBack=col
- return true
- end
- return false
- end
- layer.setBackgroundColour=layer.setBackgroundColor
- layer.getTextColor=function()
- return tCol
- end
- layer.getTextColour=layer.getTextColor
- layer.getBackgroundColor=function()
- return tBack
- end
- layer.getBackgroundColour=layer.getBackgroundColor
- layer.clear=function()
- for _,tRec in pairs(record) do
- local t={}
- for index,_ in pairs(tRec) do
- t[index]=true
- end
- for k,v in pairs(t) do
- tRec[k]=nil
- end
- end
- if not layer.linked then
- layer.scrolled=1
- end
- layer.render()
- end
- layer.clearLine=function()
- for _,tRec in pairs(record) do
- tRec[lY+layer.scrolled]=nil
- end
- end
- layer.write=function(sText,bScroll,bIndent)
- if lY<1 then return 0 end
- local size={layer.getSize()}
- local pos={gcp()}
- local fPos={layer.getCursorPos()}
- local nLinesPrinted=0
- sText=tostring(sText)
- local tS="w"
- local bS="a"
- for k,v in pairs(tsym) do
- if v==layer.getTextColor() then tS=k end
- if v==layer.getBackgroundColor() then bS=k end
- end
- local function isrt(t,tex,len)
- for x=lX,lX+len-1 do
- t[lY+layer.scrolled][x]=tex:sub(x-lX+1,x-lX+1)
- end
- end
- while #sText~=0 do
- local cPos={layer.getCursorPos()}
- if cPos[1]>size[1] then --goto next line if current cursor is past the end if the screen and refresh current pos
- layer.setCursorPos(bIndent and cPos[1] or 1,cPos[2]+1)
- cPos={layer.getCursorPos()}
- end
- if cPos[2]>size[2] then --if cursor is past the end of the screen then scroll down until that line is the bottom and set cursorpos to be the last line
- layer.scroll(cPos[2]-size[2])
- cPos={cPos[1],size[2]}
- layer.setCursorPos(cPos[1],size[2])
- elseif cPos[2]<1 then
- local offset=math.min(1-cPos[2],layer.scrolled-1)
- layer.scroll(-offset)
- layer.setCursorPos(cPos[1],cPos[2]+offset)
- cPos={cPos[1],cPos[2]+offset}
- end
- local len=math.min(bScroll and size[1]-cPos[1]+1 or #sText,sText:find("\n") or #sText) --get the length of the string to be printed, the length to the end of the line, the length to the next \n or the length of the entire string
- local str=sText:sub(1,len):gsub("\n","") --the actual string to be printed
- isrt(record.text,str,len)
- isrt(record.tcol,string.rep(tS,#str),len)
- isrt(record.tback,string.rep(bS,#str),len)
- sText=sText:sub(len+1)
- nLinesPrinted=nLinesPrinted+1
- if #sText~=0 then
- layer.setCursorPos(bIndent and fPos[1] or 1,cPos[2]+1)
- else
- layer.setCursorPos(((nLinesPrinted==1 or bIndent) and cPos[1] or 1)+len,cPos[2])
- end
- end
- bWritten=true
- --layers.render()
- return nLinesPrinted
- end
- layer.render=function(offsetX,offsetY,limX,limY)
- local pos={term.native.getCursorPos()}
- local col=term.getTextColor()
- local back=term.getBackgroundColor()
- for y,tLine in pairs(record.text) do
- local newy=y+(offsetY or 1)-1
- if newy<=(limY or y) then
- for x=1,math.min(max(tLine),({term.native.getSize()})[1]) do
- local newx=x+(offsetX or 1)-1
- if newx<=(limX or x) then
- if tsym[record.tback[y][x]] and newy-layer.scrolled>0 then
- term.native.setCursorPos(newx,newy-layer.scrolled)
- term.native.setTextColor(tsym[record.tcol[y][x]])
- term.native.setBackgroundColor(tsym[record.tback[y][x]])
- term.native.write(record.text[y][x])
- end
- end
- end
- end
- end
- if layer.showscroll then
- local size={layer.native.getSize()}
- local barSpace=size[2]-3
- local sizeY=math.max((max(layer.record.text)-1),layer.scrolled+size[2]-1)
- local nBarSize=math.floor(barSpace*size[2]/sizeY)
- local nBarPos=math.min(math.ceil((barSpace)*(layer.scrolled-1)/sizeY),barSpace)+2
- for y=1,size[2] do
- term.native.setCursorPos(size[1],y)
- term.native.setBackgroundColor(y>=nBarPos and y<=nBarPos+nBarSize and colors.white or colors.black)
- term.native.write(" ")
- end
- term.native.setTextColor(colors.white)
- term.native.setBackgroundColor(colors.black)
- term.native.setCursorPos(size[1],1)
- term.native.write("^")
- term.native.setCursorPos(size[1],size[2])
- term.native.write("v")
- end
- term.native.setCursorPos(unpack(pos))
- term.native.setTextColor(col)
- term.native.setBackgroundColor(back)
- end
- layer.scroll=function(nLines,bFromTop)
- if layer.scrolling then
- if layer.linked and not bFromTop then
- layers.scroll(nLines)
- else
- layer.scrolled=layer.scrolled+(tonumber(nLines) or 1)
- if layer.scrolled<1 then
- layer.scrolled=1
- end
- end
- bWritten=true
- end
- end
- layer.delete=function()
- for k,v in pairs(layers) do
- if layer==v then
- table.remove(layers,k)
- break
- end
- end
- local tIndexes={}
- for k,v in pairs(layer) do
- tIndexes[k]=true
- end
- for k,v in pairs(tIndexes) do
- layer[k]=nil
- end
- end
- layer.getTextAt=function(x,y,len)
- if rawget(record.text,y+layer.scrolled) then
- local str=""
- for cx=x,x+(len or 1)-1 do
- str=str..(record.text[y+layer.scrolled][cx] or " ")
- end
- return str,tsym[record.tcol[y+layer.scrolled][x]],tsym[record.tback[y+layer.scrolled][x]]
- end
- return string.rep(" ",x+(len or 1)-1)
- end
- local scb=term.native.setCursorBlink
- local cb=true
- local disableBlink=false
- layer.setCursorBlink=function(bOn,bDisable)
- if bDisable~=nil then
- disableBlink=bDisable
- if not bDisable then
- scb(cb)
- else
- scb(false)
- end
- else
- cb=bOn
- if not bOn or not disableBlink then
- scb(bOn)
- end
- end
- end
- layer.getCursorBlink=function(bOn,bDisable)
- return cb
- end
- layer.redirect=function()
- redirected=true
- end
- layer.restore=function()
- redirected=false
- end
- return layer
- end
- term.newWindow=function(x1,y1,x2,y2,index)
- local window=term.newLayer(index)
- local rd=window.render
- window.render=function()
- return rd(x1,y1,x2,y2)
- end
- local gs=window.getSize
- window.getSize=function()
- return x2-x1,y2-y1
- end
- return window
- end
- customTerm=term.newLayer(1,{linked=true,showscroll=true})
- local rd=term.redirect
- setfenv(rd,setmetatable({type=nativeType},{__index=getfenv(rd)}))
- setmetatable(term,{__index=term.native})
- local tRedirectStack={}
- term.redirect=function(tRedirectTarget)
- if type(tRedirectTarget)=="layer" then
- for k,v in pairs(term.native) do
- if not tRedirectTarget[k] then
- error("cannot redirect. missing function "..k,2)
- end
- end
- getmetatable(term).__index=tRedirectTarget
- if tRedirectTarget.redirect and type(tRedirectTarget.redirect)=="function" then
- tRedirectTarget.redirect()
- end
- rd(tRedirectTarget)
- if #tRedirectStack>=1 and type(tRedirectStack[1].restore)=="function" then
- tRedirectStack[1].restore()
- end
- table.insert(tRedirectStack,1,tRedirectTarget)
- end
- end
- local rstre=term.restore
- term.restore=function()
- if #tRedirectStack>1 then
- rstre()
- if tRedirectStack[1].restore then tRedirectStack[1].restore() end
- table.remove(tRedirectStack,1)
- getmetatable(term).__index=tRedirectStack[1]
- if tRedirectStack[1].redirect and type(tRedirectStack[1].redirect)=="function" then
- tRedirectStack[1].redirect()
- end
- end
- end
- term.redirect(customTerm)
- term.run=function()
- while true do
- local evts={os.pullEventRaw()}
- local size={term.getSize()}
- local pos={term.getCursorPos()}
- if evts[1]=="mouse_scroll" and (evts[2]==-1 and term.scrolled>1 or evts[2]==1) then
- term.scroll(evts[2])
- term.setCursorPos(pos[1],pos[2]-evts[2])
- --layers.render()
- elseif evts[1]=="mouse_click" and evts[3]==size[1]+1 then
- if evts[4]==1 then
- if term.scrolled>1 then
- term.scroll(-1)
- term.setCursorPos(pos[1],pos[2]+1)
- end
- elseif evts[4]==size[2] then
- term.scroll(1)
- term.setCursorPos(pos[1],pos[2]-1)
- else
- local barSpace=size[2]-3
- local sizeY=math.max((max(term.record.text)-1),term.scrolled+size[2]-1)
- local nBarSize=math.floor(barSpace*size[2]/sizeY)
- local nBarPos=math.min(math.ceil((barSpace)*(term.scrolled-1)/sizeY),barSpace)+2
- if evts[4]<nBarPos then
- local offset=math.min(size[2],term.scrolled-1)
- term.scroll(-offset)
- term.setCursorPos(pos[1],pos[2]+offset)
- elseif evts[4]>nBarPos+nBarSize-1 then
- term.scroll(size[2])
- term.setCursorPos(pos[1],pos[2]-size[2])
- end
- end
- --layers.render()
- end
- end
- end
- KaoShell.addCo(term.run,"Layer API")
- local yld=coroutine.yield
- coroutine.yield=function(...)
- if bWritten and setfenv(2,getfenv(2))==begin then
- layers.render()
- bWritten=false
- end
- return yld(...)
- end
- -- VARIABLE TAB COMPLETION ------------------------------------------------------------------------
- function string.split(str,chars,num,bIncl)
- num=tonumber(num)
- local tStrings={}
- local count=1
- local lastfound=1
- for at=1,str:len() do
- for i=1,#chars do
- if str:sub(at,at)==chars:sub(i,i) then
- if num~=nil and count<num then
- count=count+1
- elseif num~=nil then
- return str:sub(1,at-(bIncl and 0 or 1)),str:sub(at+1)
- else
- table.insert(tStrings,str:sub(lastfound,at-(bIncl and 0 or 1)))
- lastfound=at+1
- end
- break
- end
- end
- end
- if num==nil then
- table.insert(tStrings,str:sub(lastfound))
- return unpack(tStrings)
- end
- return false
- end
- function string.count(str,chars,num)
- local count=1
- local results=0
- for at=1,#str do
- for i=1,#chars do
- if str:sub(at,at)==chars:sub(i,i) then
- if num~=nil and count<num then
- count=count+1
- else
- results=results+1
- end
- end
- end
- end
- return results
- end
- function table.split(t,at)
- local t2={}
- if type(t)~="table" then
- error("incorrect param #1, table expected. got "..type(t),2)
- elseif type(at)~="number" then
- error("incorrect param #2, number expected. got "..type(at),2)
- elseif at>#t then
- return t2
- end
- for i=at,#t do
- t2[#t2+1]=t[i]
- t[i]=nil
- end
- return t2
- end
- local function complete(str,xPos)
- local tTerms={string.split(str," =",nil,true)}
- local totLen=0
- local selected
- for i=1,#tTerms do
- totLen=totLen+#tTerms[i]
- if totLen>xPos then
- selected=i
- totLen=totLen-#tTerms[i]
- break
- end
- totLen=totLen+1
- end
- selected=selected or #tTerms
- local result={string.split(table.remove(tTerms,selected),".")}
- local tRemainder=table.split(tTerms,selected)
- local at=_G
- local path=""
- for i=1,#result-1 do
- if not at[result[i]] or type(at[result[i]])~="table" then
- return false
- end
- at=at[result[i]]
- path=path..result[i]
- end
- local tOptions={}
- for k,v in pairs(at) do
- if type(k)=="string" and k:sub(1,result[#result]:len())==result[#result] then
- table.insert(tOptions,k)
- end
- end
- table.sort(tOptions)
- return coroutine.wrap(
- function()
- local prefix=table.concat(tTerms,"")
- local suffix=table.concat(tRemainder,"")
- local separators=string.count(prefix," =")+string.count(suffix," =")
- while true do
- for k,v in ipairs(tOptions) do
- local fP=path..(path~="" and "." or "")..v
- coroutine.yield(prefix..fP..suffix,#prefix+#fP)
- end
- local fP=path..(path~="" and "." or "")..result[#result]
- coroutine.yield(prefix..fP..suffix,#prefix+#fP)
- end
- end
- )
- end
- read=function(char,tHistory)
- tHistory=tHistory or {}
- if type(tHistory)~="table" then
- error("incorrect param #2, table expected. got "..type(tHistory),2)
- end
- local nSlot,xPos,newPos,scrolled,newScroll,output,prev=#tHistory+1,1,0,0,0,""," "
- local blink=term.getCursorBlink()
- term.setCursorBlink(true)
- local function render()
- local size={term.getSize()}
- term.scroll(math.max(0,({term.getCursorPos()})[2]-size[2]))
- local pos={term.getCursorPos()}
- pos[2]=math.min(pos[2],size[2])
- if newPos-newScroll>size[1]-pos[1]+xPos-scrolled then
- newScroll=newPos-size[1]+pos[1]-xPos+scrolled
- elseif newPos-1<newScroll then
- newScroll=math.max(newPos-1,0)
- end
- term.setCursorPos(pos[1]-xPos+scrolled,pos[2])
- term.write(string.rep(" ",#prev-scrolled))
- term.setCursorPos(pos[1]-xPos+scrolled,pos[2])
- term.write((char and char:sub(1,1):rep(#output-scrolled) or output:sub(newScroll+1)))
- term.setCursorPos(pos[1]-xPos+newPos-newScroll+scrolled,pos[2])
- prev=output
- xPos=newPos
- scrolled=newScroll
- end
- term.write(" ")
- render()
- repeat
- local bWritten=false
- local evts={os.pullEvent()}
- if evts[1]=="key" and evts[2]==200 and nSlot>1 then
- nSlot=nSlot-1
- output=tHistory[nSlot]
- newPos=#output
- bWritten=true
- elseif evts[1]=="key" and evts[2]==208 and nSlot<#tHistory+1 then
- nSlot=nSlot+1
- output=tHistory[nSlot] or ""
- newPos=#output
- bWritten=true
- elseif evts[1]=="char" then
- output=output:sub(1,xPos)..evts[2]..output:sub(xPos+1)
- newPos=newPos+1
- bWritten=true
- elseif evts[1]=="key" and evts[2]==14 then
- output=output:sub(1,math.max(xPos-1,0))..output:sub(xPos+1)
- newPos=math.max(newPos-1,0)
- bWritten=true
- elseif evts[1]=="key" and evts[2]==211 then
- output=output:sub(1,xPos)..output:sub(xPos+2)
- bWritten=true
- elseif evts[1]=="key" and evts[2]==203 then
- newPos=math.max(newPos-1,0)
- bWritten=true
- elseif evts[1]=="key" and evts[2]==205 then
- newPos=math.min(newPos+1,#output)
- bWritten=true
- elseif evts[1]=="key" and evts[2]==199 then
- newPos=0
- bWritten=true
- elseif evts[1]=="key" and evts[2]==207 then
- newPos=#output
- bWritten=true
- elseif evts[1]=="key" and evts[2]==15 then
- local comp=complete(output,xPos)
- if type(comp)=="function" then
- while true do
- if evts[1]=="char" or evts[1]=="key" and (evts[2]==14 or evts[2]==28 or evts[2]==200 or evts[2]==203 or evts[2]==205 or evts[2]==211 or evts[2]==199) then
- break
- elseif evts[1]=="key" and evts[2]==15 then
- output,newPos=comp()
- render()
- end
- evts={os.pullEvent()}
- end
- os.queueEvent(unpack(evts))
- end
- end
- if bWritten then
- render()
- end
- until evts[1]=="key" and evts[2]==28
- print()
- term.setCursorBlink(blink)
- return output
- end
- -- FS MOD ---------------------------------------------------------------------------------------
- local oldF={}
- for k,v in pairs(fs) do
- oldF[k]=v
- end
- fs.old=oldF
- local function checkstr(str)
- for k,v in pairs(tBanned) do
- if string.lower(str)==string.lower(k) then
- str=v
- end
- end
- return str
- end
- fs.open=function(sDir,sMode)
- return oldF.open(checkstr(shell.resolve(sDir)),sMode)
- end
- fs.makeDir=function(sDir)
- return oldF.makeDir(checkstr(shell.resolve(sDir)))
- end
- fs.rename=function(sDir1,sDir2)
- return oldF.rename(checkstr(shell.resolve(sDir1)),checkstr(shell.resolve(sDir2)))
- end
- fs.list=function(sDir)
- local tRes=oldF.list(sDir)
- local fList={}
- for i=1,#tRes do
- if not tBanned[tRes[i]] then
- local result=tRes[i]
- for k,v in pairs(tBanned) do
- if tRes[i]==v then
- result=k
- break
- end
- end
- table.insert(fList,result)
- end
- end
- return fList
- end
- fs.exists=function(sDir)
- return oldF.exists(checkstr(shell.resolve(sDir)))
- end
- fs.delete=function(sDir)
- return oldF.delete(checkstr(shell.resolve(sDir)))
- end
- fs.isDir=function(sDir)
- return oldF.isDir(checkstr(shell.resolve(sDir)))
- end
- -- POSITION TRACKING --------------------------------------------------------------------------------------
- local posrec={}
- pos=setmetatable({},{
- __index=function(self,index)
- return posrec[index]
- end,
- __newindex=function(self,index,value)
- posrec[index]=value
- local oFile=fs.old.open("pos","w")
- oFile.write(textutils.serialize(posrec))
- oFile.close()
- end
- })
- KaoShell.setPos=function(x,y,z,f)
- if type(x)=="number" and type(y)=="number" and type(z)=="number" and (type(f)=="number" or not f) then
- pos.x=x
- pos.y=y
- pos.z=z
- pos.face=f
- else
- error("Please specify numeric values for all 3 dimensions",2)
- end
- end
- KaoShell.getPos=function()
- return pos.x,pos.y,pos.z,pos.face
- end
- for k,v in pairs(rs.getSides()) do
- if peripheral.getType(v)=="modem" then
- rednet.open(v)
- end
- end
- if fs.old.exists("pos") then
- local oFile=fs.old.open("pos","r")
- posrec=textutils.unserialize(oFile.readAll())
- oFile.close()
- end
- if not (pos.z and pos.y and pos.x) then
- posrec.x,posrec.y,posrec.z=gps.locate(0.5)
- local bx,bz
- if turtle and posrec.z and posrec.x and not posrec.face and turtle.back() then
- sleep(0.5)
- bx,_,bz=gps.locate(0.5)
- while not turtle.forward() do end
- end
- if posrec.z and bz then
- posrec.face=((posrec.x<bx and 1) or (posrec.z<bz and 2) or (posrec.x>bx and 3) or (posrec.z>bz and 0))
- end
- end
- if turtle then
- local oFile=fs.old.open("pos","w")
- oFile.write(textutils.serialize(posrec))
- oFile.close()
- local oldT={}
- for k,v in pairs(turtle) do
- oldT[k]=v
- end
- turtle.old=oldT
- turtle.forward=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.forward() then
- if pos.face then
- local axis=pos.face%2==1 and "x" or "z"
- pos[axis]=pos[axis]+(pos.face>2 and 1 or -1)
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- turtle.back=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.back() then
- if pos.face then
- local axis=pos.face%2==1 and "x" or "z"
- pos[axis]=pos[axis]+(pos.face>2 and -1 or 1)
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- turtle.turnRight=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.turnRight() then
- if pos.face then
- pos.face=math.fmod(pos.face+1,4)
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- turtle.turnLeft=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.turnLeft() then
- if pos.face then
- pos.face=pos.face>0 and pos.face-1 or 3
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- turtle.up=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.up() then
- if pos.face then
- pos.y=pos.y+1
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- turtle.down=function(num)
- local res=true
- local count=0
- for i=1,tonumber(num) or 1 do
- if oldT.down() then
- if pos.face then
- pos.y=pos.y-1
- end
- else
- res=false
- count=count+1
- end
- end
- return res,count
- end
- if not turtle.getFuelLevel()=="unlimited" then
- KaoShell.addCo(function()
- while true do
- local evt=os.pullEventRaw()
- if evt=="turtle_response" and turtle.getFuelLevel()<10 then
- for i=1,16 do
- if turtle.refuel(1) then break end
- end
- end
- end
- end,"Refueler")
- end
- end
- -- GUI API --------------------------------------------------------------------------------------
- gui=term.newLayer(99)
- local tAreas={}
- local tButtons={}
- local tDropdowns={}
- local function render()
- gui.clear()
- local col=gui.getTextColor()
- local back=gui.getBackgroundColor()
- for k,v in pairs(tDropdowns) do
- if v.visible then
- gui.setCursorPos(v.x1,v.y)
- gui.setTextColor(v.col or col)
- gui.setBackgroundColor(v.back or back)
- gui.write(v.text)
- end
- end
- for k,v in pairs(tButtons) do
- if v.visible then
- gui.setCursorPos(v.x1,v.y)
- gui.setTextColor(v.col or col)
- gui.setBackgroundColor(v.back or back)
- gui.write(v.text)
- end
- end
- gui.setTextColor(col)
- gui.setBackgroundColor(back)
- end
- gui.run=function()
- while true do
- render()
- local evts={os.pullEventRaw()}
- local size={term.getSize()}
- if evts[1]=="mouse_click" then
- local clicked=false
- for k,v in pairs(tAreas) do
- if evts[2]==v.btn and evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]>=v.y1 and evts[4]<=v.y2 then
- pcall(function() v.func(evts[3],evts[4],evts[2]) end)
- end
- end
- for k,v in pairs(tButtons) do
- if evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]==v.y and v.visible then
- pcall(function() v.func(evts[3],evts[4],evts[2]) end)
- clicked=true
- end
- end
- for k,v in pairs(tDropdowns) do
- if v.isOpen then
- for num,btn in pairs(v.list) do
- btn.setVisibility(false)
- end
- v.isOpen=false
- elseif not clicked and evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]==v.y and v.visible then
- for num,btn in pairs(v.list) do
- btn.moveTo(v.x1,v.y+num-math.max(v.y+#v.list-size[2],0))
- btn.setVisibility(true)
- end
- v.isOpen=true
- end
- end
- end
- end
- end
- KaoShell.addCo(gui.run,"GUI API")
- gui.addArea=function(x1,y1,x2,y2,btn,func)
- if type(func)=="function" then
- local ref=#tAreas+1
- tAreas[ref]={x1=x1,y1=y1,x2=x2,y2=y2,btn=btn,func=func}
- return ref
- end
- end
- gui.remArea=function(ref)
- tAreas[ref]=nil
- end
- gui.button=function(x,y,text,func,col,back)
- local ref=#tButtons+1
- tButtons[ref]={x1=x,y=y,x2=x+#text-1,text=text,func=func,col=col,back=back,visible=true}
- render()
- return {toggleVisibility=function()
- tButtons[ref].visible=not tButtons[ref].visible
- render()
- return tButtons[ref].visible
- end,
- setVisibility=function(b)
- if type(b)~="boolean" then
- error("invalid argument, boolean expected. got "..type(b))
- end
- tButtons[ref].visible=b
- render()
- end,
- activate=func,
- moveTo=function(x,y)
- if type(x)==type(y) and type(y)=="number" then
- tButtons[ref].x1=x
- tButtons[ref].y=y
- tButtons[ref].x2=x+#tButtons[ref].text
- end
- end,
- setColors=function(text,background)
- tButtons[ref].col=colors.isColor(text) and text or tButtons[ref].col
- tButtons[ref].back=colors.isColor(background) and background or tButtons[ref].back
- end,
- delete=function()
- tButtons[ref]=nil
- end}
- end
- gui.dropDown=function(x,y,text,tList,col,back,bInherit)
- for k,v in pairs(tList) do
- tList[k]=gui.button(1,1,v.text or v[1],v.func or v[2],bInherit and col or v.col or v[3],bInherit and back or v.back or v[4])
- tList[k].setVisibility(false)
- end
- local ref=#tDropdowns+1
- tDropdowns[ref]={x1=x,y=y,x2=x+#text-1,text=text,list=tList,col=col,back=back,visible=true,isOpen=false}
- return {toggleVisibility=function()
- tDropdowns[ref].visible=not tDropdowns[ref].visible
- render()
- return tDropdowns[ref].visible
- end,
- setVisibility=function(b)
- if type(b)~="boolean" then
- error("invalid argument, boolean expected. got "..type(b))
- end
- tDropdowns[ref].visible=b
- render()
- end,
- activate=func,
- moveTo=function(x,y)
- if type(x)==type(y) and type(y)=="number" then
- tDropdowns[ref].x1=x
- tDropdowns[ref].y=y
- tDropdowns[ref].x2=x+#tDropdowns[ref].text
- end
- end,
- setColors=function(text,background)
- tDropdowns[ref].col=colors.isColor(text) and text or tDropdowns[ref].col
- tDropdowns[ref].back=colors.isColor(background) and background or tDropdowns[ref].back
- end,
- delete=function()
- tDropdowns[ref]=nil
- end}
- end
- end
- -- THE OVERRIDE ------------------------------------------------------------------------------------
- if not os.override then
- local rp=shell.resolveProgram
- shell.resolveProgram=function()
- shell.resolveProgram=rp
- return nil
- end
- local pe=os.pullEvent
- os.pullEvent=function()
- os.pullEvent=pe
- return "key"
- end
- local count=0
- local sd=os.shutdown
- os.shutdown=function()
- count=count+1
- if count==2 then
- os.shutdown=sd
- os.override=true
- term.clear()
- term.setCursorPos(term.getSize()/2-5,1)
- term.native.write("Loading...")
- loadUp()
- term.clear()
- term.setCursorPos(1,1)
- begin()
- end
- return false
- end
- shell.exit()
- end
Advertisement
Add Comment
Please, Sign In to add comment