Hiranus icon

multishell under construction

Hiranus | PRO | 10/06/14 07:38:52 PM UTC | 0 ⭐ | 582 👁️ | Never ⏰ | []
Lua |

6.31 KB

|

None

|

0 👍

/

0 👎

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

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

    0 B

    |

    👍

    /

    👎