-- Setup process switching
local parentTerm = term.current()
local w,h = parentTerm.getSize()
local tProcesses = {}
local nCurrentProcess = nil
local nRunningProcess = nil
local multishell = {}
function freeSpace (space)
for i=1,space,1 do
write(" ")
end
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 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
local function setProcessTitle( n, sTitle )
tProcesses[ n ].sTitle = sTitle
end
function resumeProcess( nProcess, sEvent, ... )
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
end
function multishell.killProcess (ID)
if ID~=1 then
resumeProcess( ID, "terminate")
end
end
local nLastProcess = 0
local function launchProcess( tProgramEnv, sProgramPath, ... )
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
end )
tProcess.sFilter = nil
tProcess.terminal = tProcess.window
tProcess.bInteracted = false
tProcesses[ nProcess ] = tProcess
resumeProcess( nProcess )
return nProcess
end
local function cullProcess( nProcess )
local tProcess = tProcesses[ nProcess ]
--printTable(tProcess)
--local cor = tProcess.co
--print (cor)
--print (coroutine.status(cor))
if coroutine.status( tProcess.co ) == "dead" then
multishell.printTable(tProcess,1,"window","terminal")
if nCurrentProcess~=1 then
if nCurrentProcess == nProcess then
selectProcess( 1 )
end
if nCurrentProcess~= 1 then
tProcesses[ nProcess ] = nil
end
end
end
end
local function cullProcesses()
local culled = false
for n=multishell.getCount(),1,-1 do
culled = culled or cullProcess( n )
end
return culled
end
function multishell.getFocus()
return nCurrentProcess
end
function multishell.setFocus( n )
if n >= 1 and n <= multishell.getCount() then
selectProcess( n )
return true
end
return false
end
function multishell.getTitle( n )
if n >= 1 and n <= multishell.getCount() then
return tProcesses[n].sTitle
end
return nil
end
function multishell.setTitle( n, sTitle )
if n >= 1 and n <= multishell.getCount() 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
-- Begin
--parentTerm.clear()
selectProcess( launchProcess( {
["shell"] = shell,
["multishell"] = multishell,
}, "/rom/programs/shell" ) )
-- Run processes
while multishell.getCount() > 0 do
-- Get the event
local tEventData = { os.pullEventRaw() }
local sEvent = tEventData[1]
if sEvent == "char" or sEvent == "key" or sEvent == "paste" or sEvent == "terminate" then
-- Keyboard event
-- Passthrough to current process
resumeProcess( nCurrentProcess, unpack( tEventData ) )
cullProcess( nCurrentProcess )
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 )
-- cullProcess( nCurrentProcess )
elseif sEvent == "process_kill" then
resumeProcess( tEventData[2], unpack( tEventData ) )
else
-- Other event
-- Passthrough to all processes
print (sEvent)
local nLimit = multishell.getCount() -- Storing this ensures any new things spawned don't get the event
for n=2,nLimit do
resumeProcess( n, unpack( tEventData ) )
end
-- cullProcesses()
end
end
-- Shutdown
term.redirect( parentTerm )
Comments
0 B
|👍
/👎