This commit is contained in:
2025-12-12 14:29:57 -05:00
parent 06f5605e3d
commit f6dd0bd669
7 changed files with 215 additions and 97 deletions

146
task-manager.lua Normal file
View File

@@ -0,0 +1,146 @@
local monitor = peripheral.find("monitor")
local programs = {}
local isRunning = false
local function addProgram(name, program)
table.insert(programs, {name = name, program = program})
end
local function runProgram(programOrPath)
local programModule
if type(programOrPath) == "string" then
if fs.exists(programOrPath) then
-- Load the file as a chunk. In Lua 5.2+ use the env parameter instead of setfenv.
local env = _ENV or _G
local programChunk, err = loadfile(programOrPath, "t", env)
if not programChunk then
print("Error loading program: " .. err)
return false
end
-- Run the chunk to get the module table
local success, result = pcall(programChunk)
if not success then
print("Error executing program file: " .. tostring(result))
return false
end
programModule = result
else
print("Program not found: " .. programOrPath)
return false
end
elseif type(programOrPath) == "table" then
programModule = programOrPath
else
print("Invalid program type")
return false
end
if type(programModule) ~= "table" or not programModule.main then
print("Error: Program must return a table with at least a 'main' function.")
return false
end
-- Setup Monitor
local w, h = monitor.getSize()
monitor.setBackgroundColor(colors.black)
monitor.clear()
-- Draw X button
monitor.setCursorPos(w, 1)
monitor.setBackgroundColor(colors.red)
monitor.setTextColor(colors.white)
monitor.write("X")
monitor.setBackgroundColor(colors.black)
-- Create window for program
local win = window.create(monitor, 1, 2, w, h - 1)
local oldTerm = term.redirect(win)
-- Lifecycle: START
if programModule.start then
local ok, err = pcall(programModule.start)
if not ok then
print("Error in start(): " .. tostring(err))
term.redirect(oldTerm)
return false
end
end
-- Lifecycle: MAIN (Run in parallel with exit watcher)
local function runMain()
-- We wrap main in pcall to catch errors without crashing the driver
local ok, err = pcall(programModule.main)
if not ok then
win.setTextColor(colors.red)
win.write("Runtime Error: " .. tostring(err))
sleep(2) -- Let user see error
end
end
local function watchExit()
while true do
local _, _, x, y = os.pullEvent("monitor_touch")
if x == w and y == 1 then
return
end
end
end
parallel.waitForAny(runMain, watchExit)
-- Lifecycle: STOP
if programModule.stop then
pcall(programModule.stop)
end
term.redirect(oldTerm)
return true
end
local function exitProgram()
isRunning = false
end
local function drawList()
monitor.clear()
monitor.setCursorPos(1, 1)
monitor.write("Available Programs:")
for i, program in ipairs(programs) do
monitor.setCursorPos(1, i + 2) -- Start from line 3
monitor.write(i .. ". " .. program.name)
end
monitor.setCursorPos(1, #programs + 4)
monitor.write("Click to run")
end
local function listPrograms()
isRunning = true
while isRunning do
drawList()
local event, side, x, y = os.pullEvent("monitor_touch")
local programIndex = y - 2
if programIndex > 0 and programIndex <= #programs then
local program = programs[programIndex]
monitor.clear()
monitor.setCursorPos(1,1)
monitor.write("Running " .. program.name .. "...")
sleep(0.5)
runProgram(program.program)
end
end
end
return {
addProgram = addProgram,
runProgram = runProgram,
exitProgram = exitProgram,
listPrograms = listPrograms
}