-
Notifications
You must be signed in to change notification settings - Fork 7
/
util.lua
90 lines (81 loc) · 3.37 KB
/
util.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
-- PrimeUI by JackMacWindows
-- Public domain/CC0
local expect = require "cc.expect".expect
-- Initialization code
local PrimeUI = {}
do
local coros = {}
local restoreCursor
--- Adds a task to run in the main loop.
---@param func function The function to run, usually an `os.pullEvent` loop
function PrimeUI.addTask(func)
expect(1, func, "function")
local t = {coro = coroutine.create(func)}
coros[#coros+1] = t
_, t.filter = coroutine.resume(t.coro)
end
--- Sends the provided arguments to the run loop, where they will be returned.
---@param ... any The parameters to send
function PrimeUI.resolve(...)
coroutine.yield(coros, ...)
end
--- Clears the screen and resets all components. Do not use any previously
--- created components after calling this function.
function PrimeUI.clear()
-- Reset the screen.
term.setCursorPos(1, 1)
term.setCursorBlink(false)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
-- Reset the task list and cursor restore function.
coros = {}
restoreCursor = nil
end
--- Sets or clears the window that holds where the cursor should be.
---@param win window|nil The window to set as the active window
function PrimeUI.setCursorWindow(win)
expect(1, win, "table", "nil")
restoreCursor = win and win.restoreCursor
end
--- Gets the absolute position of a coordinate relative to a window.
---@param win window The window to check
---@param x number The relative X position of the point
---@param y number The relative Y position of the point
---@return number x The absolute X position of the window
---@return number y The absolute Y position of the window
function PrimeUI.getWindowPos(win, x, y)
if win == term then return x, y end
while win ~= term.native() and win ~= term.current() do
if not win.getPosition then return x, y end
local wx, wy = win.getPosition()
x, y = x + wx - 1, y + wy - 1
_, win = debug.getupvalue(select(2, debug.getupvalue(win.isColor, 1)), 1) -- gets the parent window through an upvalue
end
return x, y
end
--- Runs the main loop, returning information on an action.
---@return any ... The result of the coroutine that exited
function PrimeUI.run()
while true do
-- Restore the cursor and wait for the next event.
if restoreCursor then restoreCursor() end
local ev = table.pack(os.pullEvent())
-- Run all coroutines.
for _, v in ipairs(coros) do
if v.filter == nil or v.filter == ev[1] then
-- Resume the coroutine, passing the current event.
local res = table.pack(coroutine.resume(v.coro, table.unpack(ev, 1, ev.n)))
-- If the call failed, bail out. Coroutines should never exit.
if not res[1] then error(res[2], 2) end
-- If the coroutine resolved, return its values.
if res[2] == coros then return table.unpack(res, 3, res.n) end
-- Set the next event filter.
v.filter = res[2]
end
end
end
end
end
-- DO NOT COPY THIS LINE
return PrimeUI