-- 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 )