Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Simple coroutine handler implementation, by Fatboychummy.
- local function coro_handler(win, func, ...)
- local coro = coroutine.create(func) -- the coroutine we will be responsible for
- -- redirect to the window to ensure we are on the correct window.
- local old_win = term.redirect(win)
- -- initialize the coroutine.
- local ok, event_filter = coroutine.resume(coro, ...)
- -- `event_filter` is the event the coroutine is currently listening for. If `nil`, any event is fine.
- -- `ok` is whether or not the coroutine errored when ran.
- -- and redirect back to the original window once we're done, so other
- -- programs don't start suddenly drawing to our program's window.
- term.redirect(old_win)
- while true do
- -- Check the status of the coroutine. If it is dead, we exit.
- if coroutine.status(coro) == "dead" then
- return
- end
- -- Here we grab the next event from the parent.
- local event_data = table.pack(coroutine.yield(event_filter))
- -- HERE IS WHERE YOU WOULD ALTER THE EVENT DATA.
- -- For example, to decrement all y positions of mouse events by 1, do the following:
- local ev = event_data[1]
- if ev == "mouse_click" or ev == "mouse_drag" or ev == "mouse_up" then
- event_data[4] = event_data[4] - 1
- end
- -- Now, we run the coroutine once. However, we only want to resume the event if:
- -- 1. The coroutine is listening for the event.
- -- 2. The coroutine is listening for any event.
- -- 3. The event is "terminate", which is always propagated.
- -- or 4. The mouse event is NOT at position 1 (position 0 now, since we decremented it).
- -- This is because the mouse event is now at the top bar, which we don't want to propagate.
- if event_filter == nil or event_filter == event_data[1] or event_data[1] == "terminate" or event_data[4] ~= 0 then
- -- redirect to the window to ensure we are on the correct window.
- old_win = term.redirect(win)
- ok, event_filter = coroutine.resume(coro, table.unpack(event_data, 1, event_data.n))
- -- and redirect back to the original window once we're done, so other
- -- programs don't start suddenly drawing to our program's window.
- term.redirect(old_win)
- end
- -- If the coroutine errored, we propagate the error.
- if not ok then
- -- The error message is stored in `event_filter` when the coroutine errors.
- error(event_filter, 0)
- end
- end
- end
- -- Get the size of the terminal.
- local w, h = term.getSize()
- -- Create a window that is 1 height less than the terminal size (for the program).
- -- We also position it at y=2, since the top bar is at y=1.
- local program_window = window.create(term.current(), 1, 2, w, h - 1)
- -- Create a window that is 1 height and the width of the terminal (for the top bar).
- local top_bar_window = window.create(term.current(), 1, 1, w, 1)
- -- Our sample "program" that will be run in a coroutine.
- local function program()
- while true do
- print("We got an event!")
- print("Event data:", os.pullEvent())
- end
- end
- -- Our sample top bar that just flashes random colours once per second.
- local function top_bar()
- while true do
- top_bar_window.setBackgroundColor(2^(math.random(0, 15)))
- top_bar_window.clear()
- sleep(1)
- end
- end
- -- And now we tie it together with the parallel library.
- parallel.waitForAny(
- function()
- -- Run the program in a coroutine.
- -- We need this wrap-around function because `coro_handler` requires arguments.
- coro_handler(program_window, program)
- end,
- top_bar -- Run the top bar.
- )
- -- We use `parallel.waitForAny` above because we want the top bar to stop when the program stops.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement