local utils = {} function utils.promptChoices(choices, default) local c = default or 1 local ox, oy = term.getCursorPos() while true do term.setCursorPos(ox, oy) for i, choice in ipairs(choices) do if i == c then term.setTextColor(colors.white) else term.setTextColor(colors.lightGray) end local label = choice if type(choice) == "table" then label = choice[1] or choice["label"] end print(label) end local event, key, is_held = os.pullEvent("key") if key == keys.up then c = math.max(1, c - 1) elseif key == keys.down then c = math.min(#choices, c + 1) elseif key == keys.enter then break end end term.setTextColor(colors.white) local choice = choices[c] if type(choice) == "table" then choice = choice[2] or choice["value"] end return choice end function utils.readFile(path) if not fs.exists(path) then printError("File " .. path .. " not found") return nil end local file = fs.open(path, "r") if not file then printError("Could not open file") return nil end local data = file.readAll() file.close() return data end function utils.writeFile(path, content, overwrite) overwrite = overwrite or false if not overwrite and fs.exists(path) then return true end local f = fs.open(path, "w") if not f then printError("Could not open file " .. path) return false end f.write(content) f.close() return true end function utils.waitForKey(targetKey) if targetKey then print("Press " .. keys.getName(targetKey):upper() .. " to continue") else print("Press any key to continue") end while true do local event, key, is_held = os.pullEvent("key") if not targetKey or key == targetKey then break end end end function utils.split(data, sep) local t = {} for str in string.gmatch(data, "([^" .. sep .. "]+)") do table.insert(t, str) end return t end function utils.splitLines(data) return utils.split(data, "\n") end function utils.round(x) return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5) end return utils