function preReq ()
local col=term.isColour()
local requiresPocket=false
if requiresPocket then
if col and pocket then
return true
end
else
if col then
return true
end
end
return false
end
-------------------------------------------------------------------------
--diagnostic stuff
oldOsVersion=os.version
os.version = function()
return oldOsVersion().." & X project"
end
------------------------------------------------------------------------
function multishells()
-- Setup process switching
local parentTerm = term.current()
local w,h = parentTerm.getSize()
local tProcesses = {}
local nCurrentProcess = nil
local nRunningProcess = nil
local multishell = {}
local nLastProcess = 0
---------------------------------------------------------------------
---Diagnostic stuff
function freeSpace (space)
for i=1,space,1 do
write(" ")
end
end
function multishell.printProcesses()
multishell.printTable(tProcesses,1,"window","terminal")
end
function multishell.printStatus(ID)
print (coroutine.status(tProcesses[ID].co))
end
function multishell.printTable (tab,dep,...)
local filter={...}
if dep==nil then
dep=1
end
print ("")
freeSpace(dep-1)
print ("{")
for i,v in pairs (tab) do
local filMatch=false
for j,w in pairs (filter) do
if w==i then
filMatch=true
end
end
if not filMatch then
freeSpace(dep)
write (i.." ")
if type(v) =="table" then
dep=dep+1
multishell.printTable(v,dep,unpack(filter))
dep=dep-1
else
print (v)
end
local curX,curY = term.getCursorPos()
local sizeX,sizeY = term.getSize()
if curY == sizeY then
os.pullEvent("key")
end
end
end
freeSpace(dep-1)
print ("}")
end
----------------------------------------------------------------------
local function selectProcess( n )
if nCurrentProcess ~= n then
if tProcesses[n] ~= nil then
if nCurrentProcess then
local tOldProcess = tProcesses[ nCurrentProcess ]
tOldProcess.window.setVisible( false )
end
nCurrentProcess = n
if nCurrentProcess then
local tNewProcess = tProcesses[ nCurrentProcess ]
tNewProcess.window.setVisible( true )
tNewProcess.bInteracted = true
end
end
end
end
local function setProcessTitle( n, sTitle )
tProcesses[ n ].sTitle = sTitle
end
function resumeProcess( nProcess, sEvent, ... )
if multishell.isValid(nProcess) then
local tProcess = tProcesses[ nProcess ]
--local sFilter = tProcess.sFilter
-- if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
local nPreviousProcess = nRunningProcess
nRunningProcess = nProcess
term.redirect( tProcess.terminal )
local ok, result = coroutine.resume( tProcess.co, sEvent, ... )
tProcess.terminal = term.current()
if ok then
tProcess.sFilter = result
else
printError( result )
end
nRunningProcess = nPreviousProcess
--end
-- else
-- print ("you failed")
-- end
else
print ("you failed")
end
end
function multishell.killProcess (ID)
if ID~=1 and multishell.isValid(ID) then
resumeProcess( ID, "terminate")
end
end
local function launchProcess( tProgramEnv, sProgramPath, ... )
if not tProgramEnv.multishell then
tProgramEnv.multishell=multishell
end
if not tProgramEnv.shell then
tProgramEnv.shell=shell
end
local tProgramArgs = { ... }
nLastProcess = nLastProcess + 1
local nProcess = nLastProcess
local tProcess = {}
tProcess.sTitle = fs.getName( sProgramPath )
tProcess.window = window.create( parentTerm, 1, 1, w, h, false )
tProcess.co = coroutine.create( function()
--if nLastProcess~=1 then
-- parallel.waitForAny(
-- function() os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) ) end,
-- function() endProcess(nProcess) end
-- )
--else
os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )
--end
if not tProcess.bInteracted then
term.setCursorBlink( false )
print( "Press any key to continue" )
os.pullEvent( "char" )
end
if nCurrentProcess==nProcess then
selectProcess (1)
end
os.queueEvent("check_Processes")
end )
-- tProcess.sFilter = nil
tProcess.terminal = tProcess.window
tProcess.bInteracted = false
tProcesses[ nProcess ] = tProcess
resumeProcess( nProcess )
return nProcess
end
local function cullProcess( nProcess )
--if nProcess==nil then
-- return
--end
local tProcess = tProcesses[ nProcess ]
if tProcess==nil then
return
end
--printTable(tProcess)
--local cor = tProcess.co
--print (cor)
--print (coroutine.status(cor))
--
--multishell.printTable(tProcess,1,"window","terminal")
--print (coroutine.status(tProcess.co))
--if tProcesses[nProcess].active==false then
if coroutine.status( tProcess.co ) == "dead" then
if nCurrentProcess==nProcess then
selectProcess (1)
end
tProcesses[nProcess] = nil
end
end
local function cullProcesses()
--local culled = false
--for n=multishell.getCount(),1,-1 do
--culled = culled or cullProcess( n )
--end
--return culled
for i=1, nLastProcess do
if multishell.isValid(i) then
cullProcess( i )
end
end
end
function multishell.checkProcesses()
cullProcesses()
end
function multishell.isValid(id)
if tProcesses[id]~=nil then
return true
end
return false
end
function multishell.getProcesses()
local procArray = {}
local index=1
for id,proc in pairs(tProcesses) do
procArray[index]={}
procArray[index].id=id
procArray[index].title=proc.sTitle
index=index+1
end
return procArray
end
function multishell.getFocus()
return nCurrentProcess
end
function multishell.setFocus( n )
if multishell.isValid(n) then
selectProcess( n )
return true
end
return false
end
function multishell.getLastID()
return nLastProcess
end
function multishell.getTitle( n )
if multishell.isValid(n) then
return tProcesses[n].sTitle
end
return nil
end
function multishell.setTitle( n, sTitle )
if multishell.isValid(n) then
setProcessTitle( n, sTitle )
end
end
function multishell.getCurrent()
return nRunningProcess
end
function multishell.launch( tProgramEnv, sProgramPath, ... )
local previousTerm = term.current()
local nResult = launchProcess( tProgramEnv, sProgramPath, ... )
term.redirect( previousTerm )
return nResult
end
function multishell.getCount()
local count = 0
for id, proc in pairs(tProcesses) do
count = count + 1
end
return count
end
local jump={false,false}
-- Begin
parentTerm.clear()
selectProcess( launchProcess( {
["shell"] = shell,
["multishell"] = multishell
}, "/rom/programs/shell" ) )
-- Run processes
while multishell.isValid(1) do
-- Get the event
if jump[1] and jump[2] then
selectProcess(1)
--print ("jumped")
end
local tEventData = { os.pullEventRaw() }
local sEvent = tEventData[1]
if sEvent == "check_Processes" then
cullProcesses()
elseif sEvent == "terminate" then
if nCurrentProcess ~= 1 then
resumeProcess( nCurrentProcess, unpack( tEventData ) )
cullProcesses()
end
elseif sEvent == "tabChangeDisable" then
jump[1]=false
jump[2]=false
elseif sEvent == "key" then
if jump[1]==false and tEventData[2]==29 then
jump[1]=true
os.queueEvent("tabChangeDisable")
elseif jump[2]==false and tEventData[2]==56 then
jump[2]=true
os.queueEvent("tabChangeDisable")
end
resumeProcess( nCurrentProcess, unpack( tEventData ) )
elseif sEvent == "char" or sEvent == "paste" then
-- Keyboard event
-- Passthrough to current process
resumeProcess( nCurrentProcess, unpack( tEventData ) )
elseif sEvent == "mouse_click" or sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
-- Click event
local button, x, y = tEventData[2], tEventData[3], tEventData[4]
-- Passthrough to current process
resumeProcess( nCurrentProcess, sEvent, button, x, y )
elseif sEvent=="send_event" then
if multishell.isValid(tEventData[2]) then
local target = tEventData[2]
tEventData[2] = nRunningProcess
resumeProcess( target, unpack( tEventData ) )
end
else
-- Other event
-- Passthrough to all processes
local nLimit = nLastProcess -- Storing this ensures any new things spawned don't get the event
for n=1,nLimit do
if multishell.isValid(n) then
resumeProcess( n, unpack( tEventData ) )
end
end
end
end
-- Shutdown
term.redirect( parentTerm )
end
-----------------------------------------------------------------------------------
local function run(mainFunc, errFunc)
local oldOsShutdown, oldCoroutineStatus = os.shutdown, coroutine.status
if type(mainFunc) ~= "function" then
error("Nothing to run", 2)
end
local function clearScreen()
term.redirect(type(term.native) == "function" and term.native() or term.native)
term.setBackgroundColour(colours.black)
term.setTextColour(colours.white)
term.setCursorPos(1, 1)
term.setCursorBlink(false)
term.clear()
end
local function coroutineStatusOverride(...)
return "dead"
end
local function osShutdownOverride()
clearScreen()
rednet.close()
os.unloadAPI("rednet")
os.loadAPI("/rom/apis/rednet")
rawset(os, "shutdown", oldOsShutdown)
rawset(coroutine, "status", oldCoroutineStatus)
local ok, err = pcall(mainFunc)
if not ok then
clearScreen()
pcall( function()
if type(errFunc) == "function" then
errFunc(err)
else
printError(err)
print("Press any key to continue")
os.pullEvent("key")
end
end )
end
os.sleep(2)
os.shutdown()
end
rawset(os, "shutdown", osShutdownOverride)
rawset(coroutine, "status", coroutineStatusOverride)
end
if preReq() then
run(multishells)
else
print("You need advanced pocket computer to run X project")
end
Comments
0 B
|👍
/👎