Hiranus

multishell

Oct 9th, 2014
395
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.32 KB | None | 0 0
  1. function preReq ()
  2.     local col=term.isColour()
  3.     local requiresPocket=false
  4.     if requiresPocket then
  5.         if col and pocket then
  6.             return true
  7.         end
  8.     else
  9.         if col then
  10.             return true
  11.         end
  12.     end
  13.     return false
  14. end
  15. -------------------------------------------------------------------------
  16. --diagnostic stuff
  17. oldOsVersion=os.version
  18. os.version = function()
  19.     return oldOsVersion().." & X project"
  20. end
  21. ------------------------------------------------------------------------
  22. function multishells()
  23.     -- Setup process switching
  24.     local parentTerm = term.current()
  25.     local w,h = parentTerm.getSize()
  26.  
  27.     local tProcesses = {}
  28.     local nCurrentProcess = nil
  29.     local nRunningProcess = nil
  30.     local multishell = {}
  31.     local nLastProcess = 0
  32.  
  33.     ---------------------------------------------------------------------
  34.     ---Diagnostic stuff
  35.    
  36.     function freeSpace (space)
  37.         for i=1,space,1 do
  38.             write(" ")
  39.         end
  40.     end
  41.  
  42.     function multishell.printProcesses()
  43.         multishell.printTable(tProcesses,1,"window","terminal")
  44.     end
  45.     function multishell.printStatus(ID)
  46.         print (coroutine.status(tProcesses[ID].co))
  47.     end
  48.  
  49.  
  50.  
  51.     function multishell.printTable (tab,dep,...)
  52.         local filter={...}
  53.  
  54.         if dep==nil then
  55.         dep=1
  56.         end
  57.         print ("")
  58.         freeSpace(dep-1)
  59.         print ("{")
  60.         for i,v in pairs (tab) do
  61.             local filMatch=false
  62.             for j,w in pairs (filter) do
  63.                 if w==i then
  64.                     filMatch=true
  65.                 end
  66.             end
  67.             if not filMatch then
  68.                 freeSpace(dep)
  69.                 write (i.."    ")
  70.                 if type(v) =="table" then
  71.                     dep=dep+1
  72.                     multishell.printTable(v,dep,unpack(filter))
  73.                     dep=dep-1
  74.                 else
  75.                     print (v)
  76.                 end
  77.                 local curX,curY = term.getCursorPos()
  78.                 local sizeX,sizeY = term.getSize()
  79.                 if curY == sizeY then
  80.                     os.pullEvent("key")
  81.                 end
  82.             end
  83.         end
  84.         freeSpace(dep-1)
  85.         print ("}")
  86.     end
  87.    
  88.     ----------------------------------------------------------------------
  89.  
  90.     local function selectProcess( n )
  91.  
  92.         if nCurrentProcess ~= n then
  93.             if tProcesses[n] ~= nil then
  94.                 if nCurrentProcess then
  95.                     local tOldProcess = tProcesses[ nCurrentProcess ]
  96.                     tOldProcess.window.setVisible( false )
  97.                 end
  98.                 nCurrentProcess = n
  99.                 if nCurrentProcess then
  100.                     local tNewProcess = tProcesses[ nCurrentProcess ]
  101.                     tNewProcess.window.setVisible( true )
  102.                     tNewProcess.bInteracted = true
  103.                 end
  104.             end
  105.         end
  106.     end
  107.  
  108.     local function setProcessTitle( n, sTitle )
  109.         tProcesses[ n ].sTitle = sTitle
  110.     end
  111.  
  112.     function resumeProcess( nProcess, sEvent, ... )
  113.         if multishell.isValid(nProcess) then
  114.             local tProcess = tProcesses[ nProcess ]
  115.             --local sFilter = tProcess.sFilter
  116.    
  117.         --  if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
  118.                 local nPreviousProcess = nRunningProcess
  119.                 nRunningProcess = nProcess
  120.  
  121.                 term.redirect( tProcess.terminal )
  122.    
  123.                 local ok, result = coroutine.resume( tProcess.co, sEvent, ... )
  124.        
  125.                 tProcess.terminal = term.current()
  126.        
  127.                 if ok then
  128.                     tProcess.sFilter = result
  129.                 else
  130.                     printError( result )
  131.                 end
  132.                 nRunningProcess = nPreviousProcess
  133.             --end
  134.         --  else
  135.         --  print ("you failed")
  136.         --  end
  137.         else
  138.             print ("you failed")
  139.         end
  140.     end
  141.  
  142.     function multishell.killProcess (ID)
  143.         if ID~=1 and multishell.isValid(ID) then
  144.             resumeProcess( ID, "terminate")
  145.         end
  146.     end
  147.  
  148.     local function launchProcess( tProgramEnv, sProgramPath, ... )
  149.    
  150.         if  not tProgramEnv.multishell then
  151.             tProgramEnv.multishell=multishell
  152.         end
  153.         if  not tProgramEnv.shell then
  154.             tProgramEnv.shell=shell
  155.         end
  156.         local tProgramArgs = { ... }
  157.         nLastProcess = nLastProcess + 1
  158.         local nProcess = nLastProcess
  159.         local tProcess = {}
  160.         tProcess.sTitle = fs.getName( sProgramPath )
  161.         tProcess.window = window.create( parentTerm, 1, 1, w, h, false )
  162.         tProcess.co = coroutine.create( function()
  163.             --if nLastProcess~=1 then
  164.             --      parallel.waitForAny(
  165.             --      function() os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) ) end,
  166.             --      function() endProcess(nProcess) end
  167.             --      )
  168.             --else
  169.             os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )
  170.             --end
  171.             if not tProcess.bInteracted then
  172.                 term.setCursorBlink( false )
  173.                 print( "Press any key to continue" )
  174.                 os.pullEvent( "char" )
  175.             end
  176.             if nCurrentProcess==nProcess then
  177.                 selectProcess (1)
  178.             end
  179.             os.queueEvent("check_Processes")
  180.         end )
  181.        
  182.     --  tProcess.sFilter = nil
  183.         tProcess.terminal = tProcess.window
  184.         tProcess.bInteracted = false
  185.         tProcesses[ nProcess ] = tProcess
  186.         resumeProcess( nProcess )
  187.         return nProcess
  188.     end
  189.  
  190.     local function cullProcess( nProcess )
  191.         --if nProcess==nil then
  192.         --  return
  193.         --end      
  194.         local tProcess = tProcesses[ nProcess ]
  195.         if tProcess==nil then
  196.             return
  197.         end
  198.         --printTable(tProcess)
  199.         --local cor = tProcess.co
  200.         --print (cor)
  201.         --print (coroutine.status(cor))
  202.         --
  203.         --multishell.printTable(tProcess,1,"window","terminal")
  204.         --print (coroutine.status(tProcess.co))
  205.         --if tProcesses[nProcess].active==false then
  206.         if coroutine.status( tProcess.co ) == "dead" then
  207.             if nCurrentProcess==nProcess then
  208.                 selectProcess (1)
  209.             end
  210.             tProcesses[nProcess] = nil
  211.         end
  212.     end
  213.  
  214.     local function cullProcesses()
  215.         --local culled = false
  216.         --for n=multishell.getCount(),1,-1 do
  217.         --culled = culled or cullProcess( n )
  218.         --end
  219.         --return culled
  220.          for i=1, nLastProcess do
  221.             if multishell.isValid(i) then
  222.                 cullProcess( i )
  223.             end
  224.         end
  225.     end
  226.  
  227.     function multishell.checkProcesses()
  228.         cullProcesses()
  229.     end
  230.  
  231.     function multishell.isValid(id)
  232.         if tProcesses[id]~=nil then
  233.             return true
  234.         end
  235.         return false
  236.     end
  237.    
  238.     function multishell.getProcesses()
  239.         local procArray = {}
  240.         local index=1
  241.         for id,proc in pairs(tProcesses) do
  242.             procArray[index]={}
  243.             procArray[index].id=id
  244.             procArray[index].title=proc.sTitle
  245.             index=index+1
  246.         end
  247.         return procArray
  248.     end
  249.    
  250.    
  251.  
  252.     function multishell.getFocus()
  253.         return nCurrentProcess
  254.     end
  255.  
  256.     function multishell.setFocus( n )
  257.         if multishell.isValid(n) then
  258.             selectProcess( n )
  259.             return true
  260.         end
  261.         return false
  262.     end
  263.     function multishell.getLastID()
  264.         return nLastProcess
  265.     end
  266.     function multishell.getTitle( n )
  267.         if multishell.isValid(n) then
  268.             return tProcesses[n].sTitle
  269.         end
  270.         return nil
  271.     end
  272.  
  273.     function multishell.setTitle( n, sTitle )
  274.         if multishell.isValid(n) then
  275.             setProcessTitle( n, sTitle )
  276.         end
  277.     end
  278.  
  279.     function multishell.getCurrent()
  280.         return nRunningProcess
  281.     end
  282.  
  283.     function multishell.launch( tProgramEnv, sProgramPath, ... )
  284.         local previousTerm = term.current()
  285.         local nResult = launchProcess( tProgramEnv, sProgramPath, ... )
  286.         term.redirect( previousTerm )
  287.         return nResult
  288.     end
  289.  
  290.     function multishell.getCount()
  291.         local count = 0
  292.  
  293.         for id, proc in pairs(tProcesses) do
  294.             count = count + 1
  295.         end
  296.         return count
  297.     end
  298.    
  299.     local jump={false,false}
  300.    
  301.    
  302.     -- Begin
  303.     parentTerm.clear()
  304.     selectProcess( launchProcess( {
  305.         ["shell"] = shell,
  306.         ["multishell"] = multishell
  307.     }, "/rom/programs/shell" ) )
  308.    
  309.     -- Run processes
  310.     while multishell.isValid(1) do
  311.         -- Get the event
  312.         if jump[1] and jump[2] then
  313.             selectProcess(1)
  314.             --print ("jumped")
  315.         end
  316.         local tEventData = { os.pullEventRaw() }
  317.         local sEvent = tEventData[1]
  318.         if sEvent == "check_Processes" then
  319.             cullProcesses()
  320.         elseif sEvent == "terminate" then
  321.             if nCurrentProcess ~= 1 then
  322.                 resumeProcess( nCurrentProcess, unpack( tEventData ) )
  323.                 cullProcesses()
  324.             end
  325.        
  326.         elseif sEvent == "tabChangeDisable" then
  327.             jump[1]=false
  328.             jump[2]=false
  329.        
  330.         elseif sEvent == "key" then
  331.             if jump[1]==false and tEventData[2]==29 then
  332.                 jump[1]=true
  333.                 os.queueEvent("tabChangeDisable")
  334.             elseif jump[2]==false and tEventData[2]==56 then
  335.                 jump[2]=true
  336.                 os.queueEvent("tabChangeDisable")
  337.             end
  338.        
  339.             resumeProcess( nCurrentProcess, unpack( tEventData ) )
  340.        
  341.        
  342.         elseif sEvent == "char" or sEvent == "paste" then
  343.  
  344.             -- Keyboard event
  345.             -- Passthrough to current process
  346.            
  347.             resumeProcess( nCurrentProcess, unpack( tEventData ) )
  348.            
  349.         elseif sEvent == "mouse_click" or sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
  350.             -- Click event
  351.             local button, x, y = tEventData[2], tEventData[3], tEventData[4]
  352.             -- Passthrough to current process
  353.             resumeProcess( nCurrentProcess, sEvent, button, x, y )
  354.  
  355.         elseif sEvent=="send_event" then
  356.             if multishell.isValid(tEventData[2]) then
  357.                 local target = tEventData[2]
  358.                 tEventData[2] = nRunningProcess
  359.                 resumeProcess( target, unpack( tEventData ) )
  360.             end
  361.         else
  362.             -- Other event
  363.             -- Passthrough to all processes
  364.             local nLimit = nLastProcess -- Storing this ensures any new things spawned don't get the event
  365.             for n=1,nLimit do
  366.                 if multishell.isValid(n) then
  367.                     resumeProcess( n, unpack( tEventData ) )
  368.                 end
  369.             end
  370.         end
  371.     end
  372.  
  373.     -- Shutdown
  374.     term.redirect( parentTerm )
  375. end
  376. -----------------------------------------------------------------------------------
  377. local function run(mainFunc, errFunc)
  378.     local oldOsShutdown, oldCoroutineStatus = os.shutdown, coroutine.status
  379.     if type(mainFunc) ~= "function" then
  380.             error("Nothing to run", 2)
  381.     end
  382.  
  383.  
  384.   local function clearScreen()
  385.         term.redirect(type(term.native) == "function" and term.native() or term.native)
  386.         term.setBackgroundColour(colours.black)
  387.         term.setTextColour(colours.white)
  388.         term.setCursorPos(1, 1)
  389.         term.setCursorBlink(false)
  390.         term.clear()
  391.   end
  392.   local function coroutineStatusOverride(...)
  393.         return "dead"
  394.   end
  395.  
  396.   local function osShutdownOverride()
  397.  
  398.         clearScreen()
  399.  
  400.         rednet.close()
  401.         os.unloadAPI("rednet")
  402.         os.loadAPI("/rom/apis/rednet")
  403.  
  404.         rawset(os, "shutdown", oldOsShutdown)
  405.         rawset(coroutine, "status", oldCoroutineStatus)
  406.        
  407.        
  408.         local ok, err = pcall(mainFunc)
  409.  
  410.         if not ok then
  411.             clearScreen()
  412.             pcall( function()
  413.                 if type(errFunc) == "function" then
  414.                   errFunc(err)
  415.                 else
  416.                   printError(err)
  417.                   print("Press any key to continue")
  418.                   os.pullEvent("key")
  419.                 end
  420.           end )
  421.         end
  422.    
  423.         os.sleep(2)
  424.         os.shutdown()
  425.  
  426.   end
  427.  
  428.   rawset(os, "shutdown", osShutdownOverride)
  429.   rawset(coroutine, "status", coroutineStatusOverride)
  430. end
  431.  
  432. if preReq() then
  433.     run(multishells)
  434. else
  435.     print("You need advanced pocket computer to run X project")
  436. end
Advertisement
Add Comment
Please, Sign In to add comment