Advertisement
fatboychummy

Simple coroutine handler implementation

Nov 24th, 2023 (edited)
1,068
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.66 KB | None | 0 0
  1. -- Simple coroutine handler implementation, by Fatboychummy.
  2.  
  3. local function coro_handler(win, func, ...)
  4.   local coro = coroutine.create(func) -- the coroutine we will be responsible for
  5.  
  6.   -- redirect to the window to ensure we are on the correct window.
  7.   local old_win = term.redirect(win)
  8.  
  9.   -- initialize the coroutine.
  10.   local ok, event_filter = coroutine.resume(coro, ...)
  11.   -- `event_filter` is the event the coroutine is currently listening for. If `nil`, any event is fine.
  12.   -- `ok` is whether or not the coroutine errored when ran.
  13.  
  14.   -- and redirect back to the original window once we're done, so other
  15.   -- programs don't start suddenly drawing to our program's window.
  16.   term.redirect(old_win)
  17.  
  18.   while true do
  19.     -- Check the status of the coroutine. If it is dead, we exit.
  20.     if coroutine.status(coro) == "dead" then
  21.       return
  22.     end
  23.  
  24.     -- Here we grab the next event from the parent.
  25.     local event_data = table.pack(coroutine.yield(event_filter))
  26.  
  27.     -- HERE IS WHERE YOU WOULD ALTER THE EVENT DATA.
  28.     -- For example, to decrement all y positions of mouse events by 1, do the following:
  29.     local ev = event_data[1]
  30.     if ev == "mouse_click" or ev == "mouse_drag" or ev == "mouse_up" then
  31.       event_data[4] = event_data[4] - 1
  32.     end
  33.  
  34.     -- Now, we run the coroutine once. However, we only want to resume the event if:
  35.     -- 1. The coroutine is listening for the event.
  36.     -- 2. The coroutine is listening for any event.
  37.     -- 3. The event is "terminate", which is always propagated.
  38.     -- or 4. The mouse event is NOT at position 1 (position 0 now, since we decremented it).
  39.     --    This is because the mouse event is now at the top bar, which we don't want to propagate.
  40.     if event_filter == nil or event_filter == event_data[1] or event_data[1] == "terminate" or event_data[4] ~= 0 then
  41.       -- redirect to the window to ensure we are on the correct window.
  42.       old_win = term.redirect(win)
  43.  
  44.       ok, event_filter = coroutine.resume(coro, table.unpack(event_data, 1, event_data.n))
  45.  
  46.       -- and redirect back to the original window once we're done, so other
  47.       -- programs don't start suddenly drawing to our program's window.
  48.       term.redirect(old_win)
  49.     end
  50.  
  51.     -- If the coroutine errored, we propagate the error.
  52.     if not ok then
  53.       -- The error message is stored in `event_filter` when the coroutine errors.
  54.       error(event_filter, 0)
  55.     end
  56.   end
  57. end
  58.  
  59. -- Get the size of the terminal.
  60. local w, h = term.getSize()
  61.  
  62. -- Create a window that is 1 height less than the terminal size (for the program).
  63. -- We also position it at y=2, since the top bar is at y=1.
  64. local program_window = window.create(term.current(), 1, 2, w, h - 1)
  65.  
  66. -- Create a window that is 1 height and the width of the terminal (for the top bar).
  67. local top_bar_window = window.create(term.current(), 1, 1, w, 1)
  68.  
  69. -- Our sample "program" that will be run in a coroutine.
  70. local function program()
  71.   while true do
  72.     print("We got an event!")
  73.     print("Event data:", os.pullEvent())
  74.   end
  75. end
  76.  
  77. -- Our sample top bar that just flashes random colours once per second.
  78. local function top_bar()
  79.   while true do
  80.     top_bar_window.setBackgroundColor(2^(math.random(0, 15)))
  81.     top_bar_window.clear()
  82.     sleep(1)
  83.   end
  84. end
  85.  
  86. -- And now we tie it together with the parallel library.
  87.  
  88. parallel.waitForAny(
  89.   function()
  90.     -- Run the program in a coroutine.
  91.     -- We need this wrap-around function because `coro_handler` requires arguments.
  92.     coro_handler(program_window, program)
  93.   end,
  94.   top_bar -- Run the top bar.
  95. )
  96.  
  97. -- 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