This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
MarcoPolo0306's profile picture

How do I run a program inside a window?

Started by MarcoPolo0306, 27 August 2017 - 12:07 PM
MarcoPolo0306 #1
Posted 27 August 2017 - 02:07 PM
I am making a new OS that is mostly focused on multi-tasking. I am trying to figure out how I can run programs inside the window.
Please help! (;
Bomb Bloke #2
Posted 27 August 2017 - 02:15 PM
A good start is to read through multishell's source. Note that you'll need a fairly solid understanding as to how ComputerCraft's event system makes use of coroutines.
Edited on 27 August 2017 - 12:15 PM
Dave-ee Jones #3
Posted 28 August 2017 - 05:29 AM
Basically what you do is you create a window (or 2, or 3 or however many) and have each of them running a different coroutine.

Coroutines are based on functions, so you can run a program in a function. Then you can create a window and redirect to the window, then resume the coroutine. See below:

local function run1()
  shell.run("/rom/programs/shell")
end
local function run2()
  shell.run("/rom/programs/shell")
end
local cor1 = coroutine.create(run1)
local cor2 = coroutine.create(run2)
local selectedWindow = nil -- You need to create 2 windows, then select which one you want here
local selectedCoroutine = cor1
local e = {}
while true do
  term.redirect(selectedWindow)
  coroutine.resume(selectedCoroutine, unpack(e))
  e = { os.pullEvent() }
end

That should get you started (I didn't test it, but it should be on the right track). You do need to create the windows.

There are multiple ways you could swap between the windows. Either a key press, mouse click (click inside a window to select it which is what my djOS has) or even a timer if you really wanted to.
Edited on 28 August 2017 - 03:32 AM
Bomb Bloke #4
Posted 28 August 2017 - 06:33 AM
That should get you started (I didn't test it, but it should be on the right track).

Checking event filters is fairly important. You can't just resume any coroutine with any event.
Dave-ee Jones #5
Posted 28 August 2017 - 07:19 AM
That should get you started (I didn't test it, but it should be on the right track).

Checking event filters is fairly important. You can't just resume any coroutine with any event.

Correct, but he will quickly realise that when his shells start picking up all this random event catching. HOWEVER, the shells will only pick up the events they put down. You might notice that that program doesn't have any code running except for themselves (the 2 shells, and they only pass their own events, for now). Once there are timers and things that are meant to run inside their own windows that's when it will be an issue, however my djOS didn't have that issue very bad at all.
Exerro #6
Posted 30 August 2017 - 08:57 PM
I think Bomb Bloke is referring to how os.pullEvent("key") calls coroutine.yield("key") and expects the resumer to only resume it with a "key" event. You should have an event filter variable associated with each coroutine, that's checked before resuming the coroutine.
Like this…

local co1, filter1 = coroutine.create( func )
local ev = { opening_params, ... }
local ok
while true do
    if not filter1 or filter1 == ev[1] then
        -- redirection stuff
        ok, data = coroutine.resume( co1, unpack( ev ) )
        -- end redirection stuff
        if not ok then
            error( data, 0 )
        else
            filter1 = data
        end
    end
    ev = { coroutine.yield() }
end