Hiranus icon

multishell

Hiranus | PRO | 10/09/14 08:47:07 PM UTC | 0 ⭐ | 562 👁️ | Never ⏰ | []
Lua |

10.32 KB

|

None

|

0 👍

/

0 👎

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

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎