SHOW:
|
|
- or go back to the newest paste.
1 | w = {} | |
2 | ||
3 | -- APIs | |
4 | ||
5 | -- properties | |
6 | local data = { } | |
7 | local data_name = nil | |
8 | local data_handlers = { } | |
9 | ||
10 | local device_handlers = {} | |
11 | ||
12 | local event_handlers = {} | |
13 | local event_timers = {} | |
14 | ||
15 | local monitors = {} | |
16 | local monitor_textScale = 0.5 | |
17 | ||
18 | local page_handlers = {} | |
19 | local page_endText = "" | |
20 | local page_callbackDisplay | |
21 | local page_callbackKey | |
22 | ||
23 | local run_refreshPeriod_s = 3.0 | |
24 | local status_period_s = 1.0 | |
25 | ||
26 | local styles = { | |
27 | normal = { front = colors.black , back = colors.lightGray }, | |
28 | good = { front = colors.lime , back = colors.lightGray }, | |
29 | bad = { front = colors.red , back = colors.lightGray }, | |
30 | disabled = { front = colors.gray , back = colors.lightGray }, | |
31 | help = { front = colors.white , back = colors.blue }, | |
32 | header = { front = colors.orange , back = colors.black }, | |
33 | control = { front = colors.white , back = colors.blue }, | |
34 | selected = { front = colors.black , back = colors.lightBlue }, | |
35 | warning = { front = colors.white , back = colors.red }, | |
36 | success = { front = colors.white , back = colors.lime }, | |
37 | } | |
38 | ||
39 | ----------- Terminal & monitor support | |
40 | ||
41 | local function setMonitorColorFrontBack(colorFront, colorBackground) | |
42 | term.setTextColor(colorFront) | |
43 | term.setBackgroundColor(colorBackground) | |
44 | if monitors ~= nil then | |
45 | for key, monitor in pairs(monitors) do | |
46 | monitor.setTextColor(colorFront) | |
47 | monitor.setBackgroundColor(colorBackground) | |
48 | end | |
49 | end | |
50 | end | |
51 | ||
52 | local function write(text) | |
53 | term.write(text) | |
54 | if monitors ~= nil then | |
55 | for key, monitor in pairs(monitors) do | |
56 | if key ~= data.radar_monitorIndex then | |
57 | monitor.write(text) | |
58 | end | |
59 | end | |
60 | end | |
61 | end | |
62 | ||
63 | local function getCursorPos() | |
64 | local x, y = term.getCursorPos() | |
65 | return x, y | |
66 | end | |
67 | ||
68 | local function setCursorPos(x, y) | |
69 | term.setCursorPos(x, y) | |
70 | if monitors ~= nil then | |
71 | for key, monitor in pairs(monitors) do | |
72 | if key ~= data.radar_monitorIndex then | |
73 | monitor.setCursorPos(x, y) | |
74 | end | |
75 | end | |
76 | end | |
77 | end | |
78 | ||
79 | local function getResolution() | |
80 | local sizeX, sizeY = term.getSize() | |
81 | return sizeX, sizeY | |
82 | end | |
83 | ||
84 | local function setColorNormal() | |
85 | w.setMonitorColorFrontBack(styles.normal.front, styles.normal.back) | |
86 | end | |
87 | ||
88 | local function setColorGood() | |
89 | w.setMonitorColorFrontBack(styles.good.front, styles.good.back) | |
90 | end | |
91 | ||
92 | local function setColorBad() | |
93 | w.setMonitorColorFrontBack(styles.bad.front, styles.bad.back) | |
94 | end | |
95 | ||
96 | local function setColorDisabled() | |
97 | w.setMonitorColorFrontBack(styles.disabled.front, styles.disabled.back) | |
98 | end | |
99 | ||
100 | local function setColorHelp() | |
101 | w.setMonitorColorFrontBack(styles.help.front, styles.help.back) | |
102 | end | |
103 | ||
104 | local function setColorHeader() | |
105 | w.setMonitorColorFrontBack(styles.header.front, styles.header.back) | |
106 | end | |
107 | ||
108 | local function setColorControl() | |
109 | w.setMonitorColorFrontBack(styles.control.front, styles.control.back) | |
110 | end | |
111 | ||
112 | local function setColorSelected() | |
113 | w.setMonitorColorFrontBack(styles.selected.front, styles.selected.back) | |
114 | end | |
115 | ||
116 | local function setColorWarning() | |
117 | w.setMonitorColorFrontBack(styles.warning.front, styles.warning.back) | |
118 | end | |
119 | ||
120 | local function setColorSuccess() | |
121 | w.setMonitorColorFrontBack(styles.success.front, styles.success.back) | |
122 | end | |
123 | ||
124 | local function clear(colorFront, colorBack) | |
125 | if colorFront == nil or colorBack == nil then | |
126 | w.setColorNormal() | |
127 | else | |
128 | w.setMonitorColorFrontBack(colorFront, colorBack) | |
129 | end | |
130 | term.clear() | |
131 | if monitors ~= nil then | |
132 | for key, monitor in pairs(monitors) do | |
133 | if key ~= data.radar_monitorIndex then | |
134 | monitor.clear() | |
135 | end | |
136 | end | |
137 | end | |
138 | w.setCursorPos(1, 1) | |
139 | end | |
140 | ||
141 | local function clearLine() | |
142 | term.clearLine() | |
143 | if monitors ~= nil then | |
144 | for key, monitor in pairs(monitors) do | |
145 | if key ~= data.radar_monitorIndex then | |
146 | monitor.clearLine() | |
147 | end | |
148 | end | |
149 | end | |
150 | local x, y = w.getCursorPos() | |
151 | w.setCursorPos(1, y) | |
152 | end | |
153 | ||
154 | local function writeLn(text) | |
155 | w.write(text) | |
156 | local x, y = w.getCursorPos() | |
157 | local xSize, ySize = w.getResolution() | |
158 | if y > ySize - 1 then | |
159 | y = 1 | |
160 | end | |
161 | w.setCursorPos(1, y + 1) | |
162 | end | |
163 | ||
164 | local function writeMultiLine(text) | |
165 | local textToParse = text or "" | |
166 | for line in string.gmatch(textToParse, "[^\n]+") do | |
167 | if line ~= "" then | |
168 | w.writeLn(line) | |
169 | end | |
170 | end | |
171 | end | |
172 | ||
173 | local function writeCentered(y, text) | |
174 | local unused | |
175 | if text == nil then | |
176 | text = y | |
177 | unused, y = w.getCursorPos() | |
178 | end | |
179 | ||
180 | w.setCursorPos((51 - text:len()) / 2, y) | |
181 | term.write(text) | |
182 | if monitors ~= nil then | |
183 | for key, monitor in pairs(monitors) do | |
184 | if key ~= data.radar_monitorIndex then | |
185 | local xSize, ySize = monitor.getSize() | |
186 | if xSize ~= nil then | |
187 | monitor.setCursorPos((xSize - text:len()) / 2, y) | |
188 | monitor.write(text) | |
189 | end | |
190 | end | |
191 | end | |
192 | end | |
193 | w.setCursorPos(1, y + 1) | |
194 | end | |
195 | ||
196 | local function writeFullLine(text) | |
197 | w.write(text) | |
198 | local xSize, ySize = w.getResolution() | |
199 | local xCursor, yCursor = w.getCursorPos() | |
200 | for i = xCursor, xSize do | |
201 | w.write(" ") | |
202 | end | |
203 | w.setCursorPos(1, yCursor + 1) | |
204 | end | |
205 | ||
206 | ----------- Page support | |
207 | ||
208 | local function page_begin(text) | |
209 | w.clear() | |
210 | w.setCursorPos(1, 1) | |
211 | w.setColorHeader() | |
212 | w.clearLine() | |
213 | w.writeCentered(1, text) | |
214 | w.status_refresh() | |
215 | w.setCursorPos(1, 2) | |
216 | w.setColorNormal() | |
217 | end | |
218 | ||
219 | local function page_colors() | |
220 | w.clear(colors.white, colors.black) | |
221 | for key, value in pairs(colors) do | |
222 | local text = string.format("%12s", key) | |
223 | w.setMonitorColorFrontBack(colors.white, colors.black) | |
224 | w.write(text .. " ") | |
225 | w.setMonitorColorFrontBack(value, colors.black) | |
226 | w.write(" " .. text .. " ") | |
227 | w.setMonitorColorFrontBack(colors.black, value) | |
228 | w.write(" " .. text .. " ") | |
229 | w.setMonitorColorFrontBack(colors.white, value) | |
230 | w.write(" " .. text .. " ") | |
231 | w.setMonitorColorFrontBack(value, colors.white) | |
232 | w.write(" " .. text .. " ") | |
233 | w.writeLn("") | |
234 | end | |
235 | w.writeLn("") | |
236 | local index = 0 | |
237 | for key, value in pairs(styles) do | |
238 | local text = string.format("%12s", key) | |
239 | if index % 2 == 0 then | |
240 | w.setMonitorColorFrontBack(colors.white, colors.black) | |
241 | w.write(text .. " ") | |
242 | w.setMonitorColorFrontBack(value.front, value.back) | |
243 | w.write(" " .. text .. " ") | |
244 | else | |
245 | w.setMonitorColorFrontBack(value.front, value.back) | |
246 | w.write(" " .. text .. " ") | |
247 | w.setMonitorColorFrontBack(colors.white, colors.black) | |
248 | w.write(text .. " ") | |
249 | w.writeLn("") | |
250 | end | |
251 | index = index + 1 | |
252 | end | |
253 | w.setMonitorColorFrontBack(colors.white, colors.black) | |
254 | end | |
255 | ||
256 | local function page_end() | |
257 | w.setCursorPos(1, 18) | |
258 | w.setColorControl() | |
259 | w.writeFullLine(page_endText) | |
260 | end | |
261 | ||
262 | local function page_getCallbackDisplay() | |
263 | return page_callbackDisplay | |
264 | end | |
265 | ||
266 | local function page_register(index, callbackDisplay, callbackKey) | |
267 | page_handlers[index] = { display = callbackDisplay, key = callbackKey } | |
268 | end | |
269 | ||
270 | local function page_setEndText(text) | |
271 | page_endText = text | |
272 | end | |
273 | ||
274 | ----------- Status line support | |
275 | ||
276 | local status_clockTarget = -1 -- < 0 when stopped, < clock when elapsed, > clock when ticking | |
277 | local status_isWarning = false | |
278 | local status_line = 0 | |
279 | local status_text = "" | |
280 | local function status_clear() | |
281 | if status_clockTarget > 0 then | |
282 | status_clockTarget = -1 | |
283 | w.event_timer_stop("status") | |
284 | local xSize, ySize = w.getResolution() | |
285 | w.setCursorPos(1, ySize) | |
286 | w.setColorNormal() | |
287 | w.clearLine() | |
288 | end | |
289 | end | |
290 | local function status_isActive() | |
291 | return status_clockTarget > 0 and w.event_clock() < status_clockTarget | |
292 | end | |
293 | local function status_show(isWarning, text) | |
294 | if isWarning or not w.status_isActive() then | |
295 | status_line = 1 | |
296 | status_isWarning = isWarning | |
297 | status_text = {} | |
298 | local textToParse = (text and text ~= "") and text or "???" | |
299 | for line in string.gmatch(textToParse, "[^\n]+") do | |
300 | if line ~= "" then | |
301 | table.insert(status_text, line) | |
302 | end | |
303 | end | |
304 | if isWarning then | |
305 | status_clockTarget = w.event_clock() + 1.0 * #status_text | |
306 | else | |
307 | status_clockTarget = w.event_clock() + 0.5 * #status_text | |
308 | end | |
309 | w.event_timer_start("status", status_period_s, "timer_status") | |
310 | end | |
311 | -- always refresh as a visual clue | |
312 | w.status_refresh() | |
313 | end | |
314 | local function status_refresh() | |
315 | if status_clockTarget > 0 then | |
316 | if w.event_clock() > status_clockTarget and status_line == 1 then | |
317 | w.status_clear() | |
318 | else | |
319 | local xSize, ySize = w.getResolution() | |
320 | w.setCursorPos(1, ySize) | |
321 | w.setColorNormal() | |
322 | w.clearLine() | |
323 | ||
324 | if status_isWarning then | |
325 | w.setColorWarning() | |
326 | else | |
327 | w.setColorSuccess() | |
328 | end | |
329 | local text = status_text[status_line] | |
330 | w.writeCentered(" " .. text .. " ") | |
331 | w.setColorNormal() | |
332 | end | |
333 | end | |
334 | end | |
335 | local function status_showWarning(text) | |
336 | w.status_show(true, text) | |
337 | end | |
338 | local function status_showSuccess(text) | |
339 | w.status_show(false, text) | |
340 | end | |
341 | local function status_tick() | |
342 | if status_clockTarget > -1 then | |
343 | local clockCurrent = w.event_clock() | |
344 | if clockCurrent > status_clockTarget then | |
345 | w.status_clear() | |
346 | else | |
347 | status_line = (status_line % #status_text) + 1 | |
348 | w.status_refresh() | |
349 | end | |
350 | end | |
351 | end | |
352 | ||
353 | ----------- Formatting | |
354 | ||
355 | local function format_float(value, nbchar) | |
356 | local str = "?" | |
357 | if value ~= nil then | |
358 | if type(value) == "number" then | |
359 | str = string.format("%g", value) | |
360 | else | |
361 | str = type(value) | |
362 | end | |
363 | end | |
364 | if nbchar ~= nil then | |
365 | str = string.sub(" " .. str, -nbchar) | |
366 | end | |
367 | return str | |
368 | end | |
369 | ||
370 | local function format_integer(value, nbchar) | |
371 | local str = "?" | |
372 | if value ~= nil then | |
373 | if type(value) == "number" then | |
374 | str = string.format("%d", math.floor(value)) | |
375 | else | |
376 | str = type(value) | |
377 | end | |
378 | end | |
379 | if nbchar ~= nil then | |
380 | str = string.sub(" " .. str, -nbchar) | |
381 | end | |
382 | return str | |
383 | end | |
384 | ||
385 | local function format_boolean(value, strTrue, strFalse) | |
386 | if value ~= nil then | |
387 | if type(value) == "boolean" then | |
388 | if value then | |
389 | return strTrue | |
390 | else | |
391 | return strFalse | |
392 | end | |
393 | else | |
394 | return type(value) | |
395 | end | |
396 | end | |
397 | return "?" | |
398 | end | |
399 | ||
400 | local function format_string(value, nbchar) | |
401 | local str = "?" | |
402 | if value ~= nil then | |
403 | str = "" .. value | |
404 | end | |
405 | if nbchar ~= nil then | |
406 | if #str > math.abs(nbchar) then | |
407 | str = string.sub(str, 1, math.abs(nbchar) - 1) .. "~" | |
408 | else | |
409 | str = string.sub(str .. " ", 1, nbchar) | |
410 | end | |
411 | end | |
412 | return str | |
413 | end | |
414 | ||
415 | local function format_address(value) | |
416 | local str = "?" | |
417 | if value ~= nil then | |
418 | str = "" .. value | |
419 | end | |
420 | str = string.sub(str, 10, 100) | |
421 | return str | |
422 | end | |
423 | ||
424 | ----------- Input controls | |
425 | ||
426 | local function input_readInteger(currentValue) | |
427 | local inputAbort = false | |
428 | local input = w.format_integer(currentValue) | |
429 | if input == "0" then | |
430 | input = "" | |
431 | end | |
432 | local ignoreNextChar = false | |
433 | local x, y = w.getCursorPos() | |
434 | ||
435 | term.setCursorBlink(true) | |
436 | repeat | |
437 | w.setCursorPos(x, y) | |
438 | w.setColorNormal() | |
439 | w.write(input .. " ") | |
440 | input = string.sub(input, -9) | |
441 | w.setCursorPos(x + #input, y) | |
442 | ||
443 | local params = { os.pullEventRaw() } | |
444 | local eventName = params[1] | |
445 | local firstParam = params[2] | |
446 | if firstParam == nil then firstParam = "none" end | |
447 | if eventName == "key" then | |
448 | local keycode = params[2] | |
449 | ||
450 | if keycode >= 2 and keycode <= 10 then -- 1 to 9 | |
451 | input = input .. w.format_string(keycode - 1) | |
452 | ignoreNextChar = true | |
453 | elseif keycode == 11 or keycode == 82 then -- 0 & keypad 0 | |
454 | input = input .. "0" | |
455 | ignoreNextChar = true | |
456 | elseif keycode >= 79 and keycode <= 81 then -- keypad 1 to 3 | |
457 | input = input .. w.format_string(keycode - 78) | |
458 | ignoreNextChar = true | |
459 | elseif keycode >= 75 and keycode <= 77 then -- keypad 4 to 6 | |
460 | input = input .. w.format_string(keycode - 71) | |
461 | ignoreNextChar = true | |
462 | elseif keycode >= 71 and keycode <= 73 then -- keypad 7 to 9 | |
463 | input = input .. w.format_string(keycode - 64) | |
464 | ignoreNextChar = true | |
465 | elseif keycode == 14 then -- Backspace | |
466 | input = string.sub(input, 1, string.len(input) - 1) | |
467 | ignoreNextChar = true | |
468 | elseif keycode == 211 then -- Delete | |
469 | input = "" | |
470 | ignoreNextChar = true | |
471 | elseif keycode == 28 then -- Enter | |
472 | inputAbort = true | |
473 | ignoreNextChar = true | |
474 | elseif keycode == 74 or keycode == 12 or keycode == 49 then -- - on numeric keypad or - on US top or n letter | |
475 | if string.sub(input, 1, 1) == "-" then | |
476 | input = string.sub(input, 2) | |
477 | else | |
478 | input = "-" .. input | |
479 | end | |
480 | ignoreNextChar = true | |
481 | elseif keycode == 78 then -- + | |
482 | if string.sub(input, 1, 1) == "-" then | |
483 | input = string.sub(input, 2) | |
484 | end | |
485 | ignoreNextChar = true | |
486 | else | |
487 | ignoreNextChar = false | |
488 | -- w.status_showWarning("Key " .. keycode .. " is not supported here") | |
489 | end | |
490 | ||
491 | elseif eventName == "char" then | |
492 | local character = params[2] | |
493 | if ignoreNextChar then | |
494 | ignoreNextChar = false | |
495 | -- w.status_showWarning("Ignored char #" .. string.byte(character) .. " '" .. character .. "'") | |
496 | elseif character >= '0' and character <= '9' then -- 0 to 9 | |
497 | input = input .. character | |
498 | elseif character == '-' or character == 'n' or character == 'N' then -- - or N | |
499 | if string.sub(input, 1, 1) == "-" then | |
500 | input = string.sub(input, 2) | |
501 | else | |
502 | input = "-" .. input | |
503 | end | |
504 | elseif character == '+' or character == 'p' or character == 'P' then -- + or P | |
505 | if string.sub(input, 1, 1) == "-" then | |
506 | input = string.sub(input, 2) | |
507 | end | |
508 | else | |
509 | w.status_showWarning("Key '" .. character .. "' is not supported here (" .. string.byte(character) .. ")") | |
510 | end | |
511 | ||
512 | elseif eventName == "terminate" then | |
513 | inputAbort = true | |
514 | ||
515 | else | |
516 | local isSupported, needRedraw = w.event_handler(eventName, firstParam) | |
517 | if not isSupported then | |
518 | w.status_showWarning("Event '" .. eventName .. "', " .. firstParam .. " is unsupported") | |
519 | end | |
520 | end | |
521 | until inputAbort | |
522 | term.setCursorBlink(false) | |
523 | w.setCursorPos(1, y + 1) | |
524 | if input == "" or input == "-" then | |
525 | return currentValue | |
526 | else | |
527 | return tonumber(input) | |
528 | end | |
529 | end | |
530 | ||
531 | local function input_readText(currentValue) | |
532 | local inputAbort = false | |
533 | local input = w.format_string(currentValue) | |
534 | local ignoreNextChar = false | |
535 | local x, y = w.getCursorPos() | |
536 | ||
537 | term.setCursorBlink(true) | |
538 | repeat | |
539 | -- update display clearing extra characters | |
540 | w.setCursorPos(x, y) | |
541 | w.setColorNormal() | |
542 | w.write(w.format_string(input, 37)) | |
543 | -- truncate input and set caret position | |
544 | input = string.sub(input, -36) | |
545 | w.setCursorPos(x + #input, y) | |
546 | ||
547 | local params = { os.pullEventRaw() } | |
548 | local eventName = params[1] | |
549 | local firstParam = params[2] | |
550 | if firstParam == nil then firstParam = "none" end | |
551 | if eventName == "key" then | |
552 | local keycode = params[2] | |
553 | ||
554 | if keycode == 14 then -- Backspace | |
555 | input = string.sub(input, 1, string.len(input) - 1) | |
556 | ignoreNextChar = true | |
557 | elseif keycode == 211 then -- Delete | |
558 | input = "" | |
559 | ignoreNextChar = true | |
560 | elseif keycode == 28 then -- Enter | |
561 | inputAbort = true | |
562 | ignoreNextChar = true | |
563 | else | |
564 | ignoreNextChar = false | |
565 | -- w.status_showWarning("Key " .. keycode .. " is not supported here") | |
566 | end | |
567 | ||
568 | elseif eventName == "char" then | |
569 | local character = params[2] | |
570 | if ignoreNextChar then | |
571 | ignoreNextChar = false | |
572 | -- w.status_showWarning("Ignored char #" .. string.byte(character) .. " '" .. character .. "'") | |
573 | elseif character >= ' ' and character <= '~' then -- any ASCII table minus controls and DEL | |
574 | input = input .. character | |
575 | else | |
576 | w.status_showWarning("Key '" .. character .. "' is not supported here (" .. string.byte(character) .. ")") | |
577 | end | |
578 | ||
579 | elseif eventName == "terminate" then | |
580 | inputAbort = true | |
581 | ||
582 | else | |
583 | local isSupported, needRedraw = w.event_handler(eventName, firstParam) | |
584 | if not isSupported then | |
585 | w.status_showWarning("Event '" .. eventName .. "', " .. firstParam .. " is unsupported") | |
586 | end | |
587 | end | |
588 | until inputAbort | |
589 | term.setCursorBlink(false) | |
590 | w.setCursorPos(1, y + 1) | |
591 | if input == "" then | |
592 | return currentValue | |
593 | else | |
594 | return input | |
595 | end | |
596 | end | |
597 | ||
598 | local function input_readConfirmation(message) | |
599 | if message == nil then | |
600 | message = "Are you sure? (Y/n)" | |
601 | end | |
602 | w.status_showWarning(message) | |
603 | repeat | |
604 | local params = { os.pullEventRaw() } | |
605 | local eventName = params[1] | |
606 | local firstParam = params[2] | |
607 | if firstParam == nil then firstParam = "none" end | |
608 | if eventName == "key" then | |
609 | local keycode = params[2] | |
610 | ||
611 | if keycode == 28 then -- Return or Enter | |
612 | w.status_clear() | |
613 | return true | |
614 | end | |
615 | ||
616 | elseif eventName == "char" then | |
617 | local character = params[2] | |
618 | w.status_clear() | |
619 | if character == 'y' or character == 'Y' then -- Y | |
620 | return true | |
621 | else | |
622 | return false | |
623 | end | |
624 | ||
625 | elseif eventName == "terminate" then | |
626 | return false | |
627 | ||
628 | else | |
629 | local isSupported, needRedraw = w.event_handler(eventName, firstParam) | |
630 | if not isSupported then | |
631 | w.status_showWarning("Event '" .. eventName .. "', " .. firstParam .. " is unsupported") | |
632 | end | |
633 | end | |
634 | if not w.status_isActive() then | |
635 | w.status_showWarning(message) | |
636 | end | |
637 | until false | |
638 | end | |
639 | ||
640 | local function input_readEnum(currentValue, list, toValue, toDescription, noValue) | |
641 | local inputAbort = false | |
642 | local inputKey = nil | |
643 | local input = nil | |
644 | local inputDescription = nil | |
645 | local ignoreNextChar = false | |
646 | local x, y = w.getCursorPos() | |
647 | ||
648 | w.setCursorPos(1, 17) | |
649 | for key, entry in pairs(list) do | |
650 | if toValue(entry) == currentValue then | |
651 | inputKey = key | |
652 | end | |
653 | end | |
654 | ||
655 | term.setCursorBlink(true) | |
656 | repeat | |
657 | w.setCursorPos(x, y) | |
658 | w.setColorNormal() | |
659 | if #list == 0 then | |
660 | inputKey = nil | |
661 | end | |
662 | if inputKey == nil then | |
663 | if currentValue ~= nil then | |
664 | input = noValue | |
665 | inputDescription = "Press enter to return previous entry" | |
666 | else | |
667 | input = noValue | |
668 | inputDescription = "Press enter to close listing" | |
669 | end | |
670 | else | |
671 | if inputKey < 1 then | |
672 | inputKey = #list | |
673 | elseif inputKey > #list then | |
674 | inputKey = 1 | |
675 | end | |
676 | ||
677 | input = toValue(list[inputKey]) | |
678 | inputDescription = toDescription(list[inputKey]) | |
679 | end | |
680 | w.setColorNormal() | |
681 | w.write(input .. " ") | |
682 | w.setCursorPos(1, y + 1) | |
683 | w.setColorDisabled() | |
684 | w.write(inputDescription .. " ") | |
685 | ||
686 | local params = { os.pullEventRaw() } | |
687 | local eventName = params[1] | |
688 | local firstParam = params[2] | |
689 | if firstParam == nil then firstParam = "none" end | |
690 | if eventName == "key" then | |
691 | local keycode = params[2] | |
692 | ||
693 | if keycode == 14 or keycode == 211 then -- Backspace or Delete | |
694 | inputKey = nil | |
695 | ignoreNextChar = true | |
696 | elseif keycode == 200 or keycode == 203 or keycode == 78 then -- Up or Left or + | |
697 | if inputKey == nil then | |
698 | inputKey = 1 | |
699 | else | |
700 | inputKey = inputKey - 1 | |
701 | end | |
702 | ignoreNextChar = true | |
703 | elseif keycode == 208 or keycode == 205 or keycode == 74 then -- Down or Right or - | |
704 | if inputKey == nil then | |
705 | inputKey = 1 | |
706 | else | |
707 | inputKey = inputKey + 1 | |
708 | end | |
709 | ignoreNextChar = true | |
710 | elseif keycode == 28 then -- Enter | |
711 | inputAbort = true | |
712 | ignoreNextChar = true | |
713 | else | |
714 | ignoreNextChar = false | |
715 | -- w.status_showWarning("Key " .. keycode .. " is not supported here") | |
716 | end | |
717 | ||
718 | elseif eventName == "char" then | |
719 | local character = params[2] | |
720 | if ignoreNextChar then | |
721 | ignoreNextChar = false | |
722 | -- w.status_showWarning("Ignored char #" .. string.byte(character) .. " '" .. character .. "'") | |
723 | elseif character == '+' then -- + | |
724 | if inputKey == nil then | |
725 | inputKey = 1 | |
726 | else | |
727 | inputKey = inputKey - 1 | |
728 | end | |
729 | elseif character == '-' then -- - | |
730 | if inputKey == nil then | |
731 | inputKey = 1 | |
732 | else | |
733 | inputKey = inputKey + 1 | |
734 | end | |
735 | else | |
736 | w.status_showWarning("Key '" .. character .. "' is not supported here (" .. string.byte(character) .. ")") | |
737 | end | |
738 | ||
739 | elseif eventName == "terminate" then | |
740 | inputAbort = true | |
741 | ||
742 | elseif not w.event_handler(eventName, firstParam) then | |
743 | w.status_showWarning("Event '" .. eventName .. "', " .. firstParam .. " is unsupported") | |
744 | end | |
745 | until inputAbort | |
746 | term.setCursorBlink(false) | |
747 | w.setCursorPos(1, y + 1) | |
748 | w.clearLine() | |
749 | if inputKey == nil then | |
750 | return nil | |
751 | else | |
752 | return toValue(list[inputKey]) | |
753 | end | |
754 | end | |
755 | ||
756 | ----------- Event handlers | |
757 | ||
758 | local function reboot() | |
759 | os.reboot() | |
760 | end | |
761 | ||
762 | local function sleep(delay) | |
763 | os.sleep(delay) | |
764 | end | |
765 | ||
766 | -- return a global clock measured in second | |
767 | local function event_clock() | |
768 | return os.clock() | |
769 | end | |
770 | ||
771 | local function event_timer_start(name, period_s, eventId) | |
772 | local name = name or "-nameless-" | |
773 | local eventId = eventId or "timer_" .. name | |
774 | -- check for an already active timer | |
775 | local countActives = 0 | |
776 | for id, entry in pairs(event_timers) do | |
777 | if entry.name == name and entry.active then -- already one started | |
778 | countActives = countActives + 1 | |
779 | end | |
780 | end | |
781 | if countActives > 0 then | |
782 | if name ~= "status" then -- don't report status timer overlaps to prevent a stack overflow | |
783 | w.status_showWarning("Timer already started for " .. name) | |
784 | end | |
785 | return | |
786 | end | |
787 | -- start a new timer | |
788 | local period_s = period_s or 1.0 | |
789 | local id = os.startTimer(period_s) | |
790 | event_timers[id] = { | |
791 | active = true, | |
792 | eventId = eventId, | |
793 | name = name, | |
794 | period_s = period_s | |
795 | } | |
796 | end | |
797 | ||
798 | local function event_timer_stop(name) | |
799 | local name = name or "-nameless-" | |
800 | for id, entry in pairs(event_timers) do | |
801 | if entry.name == name then | |
802 | if entry.active then -- kill any active one | |
803 | entry.active = false | |
804 | os.cancelTimer(id) | |
805 | else -- purge all legacy ones | |
806 | event_timers[id] = nil | |
807 | end | |
808 | end | |
809 | end | |
810 | end | |
811 | ||
812 | local function event_timer_stopAll() | |
813 | for id, entry in pairs(event_timers) do | |
814 | if entry.active then | |
815 | event_timers[id] = nil | |
816 | os.cancelTimer(id) | |
817 | end | |
818 | end | |
819 | end | |
820 | ||
821 | local function event_timer_tick(id) | |
822 | local entry = event_timers[id] | |
823 | local isUnknown = entry == nil | |
824 | if isUnknown then -- unknown id, report a warning | |
825 | w.status_showWarning("Timer #" .. id .. " is unknown") | |
826 | return | |
827 | end | |
828 | if not entry.active then -- dying timer, just ignore it | |
829 | return | |
830 | end | |
831 | -- resolve the timer | |
832 | os.queueEvent(entry.eventId, nil, nil, nil) | |
833 | -- CC timers are one shot, so we start a new one, if still needed | |
834 | if entry.active then | |
835 | entry.active = false | |
836 | w.event_timer_start(entry.name, entry.period_s) | |
837 | end | |
838 | end | |
839 | ||
840 | local function event_register(eventName, callback) | |
841 | event_handlers[eventName] = callback | |
842 | end | |
843 | ||
844 | -- returns isSupported, needRedraw | |
845 | local function event_handler(eventName, param) | |
846 | local needRedraw = false | |
847 | if eventName == "redstone" then | |
848 | w.redstone_event(param) | |
849 | elseif eventName == "timer" then | |
850 | w.event_timer_tick(param) | |
851 | elseif eventName == "key_up" then | |
852 | elseif eventName == "mouse_click" then | |
853 | w.status_showSuccess("Use the keyboard, Luke!") | |
854 | elseif eventName == "mouse_up" then | |
855 | elseif eventName == "mouse_drag" then | |
856 | elseif eventName == "mouse_scroll" then | |
857 | elseif eventName == "monitor_touch" then | |
858 | elseif eventName == "monitor_resize" then | |
859 | elseif eventName == "disk" then | |
860 | elseif eventName == "disk_eject" then | |
861 | elseif eventName == "peripheral" then | |
862 | elseif eventName == "peripheral_detach" then | |
863 | -- not supported: task_complete, rednet_message, modem_message | |
864 | elseif event_handlers[eventName] ~= nil then | |
865 | needRedraw = event_handlers[eventName](eventName, param) | |
866 | else | |
867 | return false, needRedraw | |
868 | end | |
869 | return true, needRedraw | |
870 | end | |
871 | ||
872 | ----------- Redstone support | |
873 | ||
874 | local tblRedstoneState = {-- Remember redstone state on each side | |
875 | ["top"] = rs.getInput("top"), | |
876 | ["front"] = rs.getInput("front"), | |
877 | ["left"] = rs.getInput("left"), | |
878 | ["right"] = rs.getInput("right"), | |
879 | ["back"] = rs.getInput("back"), | |
880 | ["bottom"] = rs.getInput("bottom"), | |
881 | } | |
882 | ||
883 | local function redstone_event() | |
884 | -- Event only returns nil so we need to check sides manually | |
885 | local message = "" | |
886 | for side, state in pairs(tblRedstoneState) do | |
887 | if rs.getInput(side) ~= state then | |
888 | -- print(side .. " is now " .. tostring(rs.getInput(side))) | |
889 | message = message .. side .. " " | |
890 | tblRedstoneState[side] = rs.getInput(side) | |
891 | end | |
892 | end | |
893 | if message ~= "" then | |
894 | message = "Redstone changed on " .. message | |
895 | w.status_showWarning(message) | |
896 | end | |
897 | end | |
898 | ||
899 | ----------- Configuration | |
900 | ||
901 | local function data_get() | |
902 | return data | |
903 | end | |
904 | ||
905 | local function data_inspect(key, value) | |
906 | local stringValue = type(value) .. "," | |
907 | if type(value) == "boolean" then | |
908 | if value then | |
909 | stringValue = "true," | |
910 | else | |
911 | stringValue = "false," | |
912 | end | |
913 | elseif type(value) == "number" then | |
914 | stringValue = value .. "," | |
915 | elseif type(value) == "string" then | |
916 | stringValue = "'" .. value .. "'," | |
917 | elseif type(value) == "table" then | |
918 | stringValue = "{" | |
919 | end | |
920 | print(" " .. key .. " = " .. stringValue) | |
921 | if type(value) == "table" then | |
922 | for subkey, subvalue in pairs(value) do | |
923 | w.data_inspect(subkey, subvalue) | |
924 | end | |
925 | print("}") | |
926 | end | |
927 | end | |
928 | ||
929 | local function data_read() | |
930 | w.data_shouldUpdateName() | |
931 | ||
932 | data = { } | |
933 | if fs.exists("shipdata.txt") then | |
934 | local size = fs.getSize("shipdata.txt") | |
935 | if size > 0 then | |
936 | local file = fs.open("shipdata.txt", "r") | |
937 | if file ~= nil then | |
938 | local rawData = file.readAll() | |
939 | if rawData ~= nil then | |
940 | data = textutils.unserialize(rawData) | |
941 | end | |
942 | file.close() | |
943 | if data == nil then | |
944 | data = {} | |
945 | end | |
946 | end | |
947 | end | |
948 | end | |
949 | ||
950 | for name, handlers in pairs(data_handlers) do | |
951 | handlers.read(data) | |
952 | end | |
953 | end | |
954 | ||
955 | local function data_save() | |
956 | for name, handlers in pairs(data_handlers) do | |
957 | handlers.save(data) | |
958 | end | |
959 | ||
960 | local file = fs.open("shipdata.txt", "w") | |
961 | if file ~= nil then | |
962 | file.writeLine(textutils.serialize(data)) | |
963 | file.close() | |
964 | else | |
965 | w.status_showWarning("No file system") | |
966 | w.sleep(3.0) | |
967 | end | |
968 | end | |
969 | ||
970 | local function data_getName() | |
971 | if data_name ~= nil then | |
972 | return data_name | |
973 | else | |
974 | return "-noname-" | |
975 | end | |
976 | end | |
977 | ||
978 | local function data_setName() | |
979 | -- check if any named component is connected | |
980 | local component = "computer" | |
981 | for name, handlers in pairs(data_handlers) do | |
982 | if handlers.name ~= nil then | |
983 | component = name | |
984 | end | |
985 | end | |
986 | ||
987 | -- ask for a new name | |
988 | w.page_begin("<==== Set " .. component .. " name ====>") | |
989 | w.setCursorPos(1, 4) | |
990 | w.setColorHelp() | |
991 | w.writeFullLine(" Press enter to validate.") | |
992 | w.setCursorPos(1, 3) | |
993 | w.setColorNormal() | |
994 | w.write("Enter " .. component .. " name: ") | |
995 | data_name = w.input_readText(data_name) | |
996 | ||
997 | -- update computer name | |
998 | os.setComputerLabel(data_name) | |
999 | ||
1000 | -- update connected components | |
1001 | for name, handlers in pairs(data_handlers) do | |
1002 | if handlers.name ~= nil then | |
1003 | handlers.name(data_name) | |
1004 | end | |
1005 | end | |
1006 | ||
1007 | -- w.reboot() -- not needed | |
1008 | end | |
1009 | ||
1010 | local function data_shouldUpdateName() | |
1011 | local shouldUpdateName = false | |
1012 | ||
1013 | -- check computer name | |
1014 | data_name = os.getComputerLabel() | |
1015 | if data_name == nil then | |
1016 | shouldUpdateName = true | |
1017 | data_name = "" .. os.getComputerID() | |
1018 | end | |
1019 | ||
1020 | -- check connected components names | |
1021 | for name, handlers in pairs(data_handlers) do | |
1022 | if handlers.name ~= nil then | |
1023 | local componentName = handlers.name() | |
1024 | if componentName == "" then | |
1025 | shouldUpdateName = true | |
1026 | elseif shouldUpdateName then | |
1027 | data_name = componentName | |
1028 | elseif data_name ~= componentName then | |
1029 | shouldUpdateName = true | |
1030 | data_name = componentName | |
1031 | end | |
1032 | end | |
1033 | end | |
1034 | ||
1035 | return shouldUpdateName | |
1036 | end | |
1037 | ||
1038 | local function data_splitString(source, sep) | |
1039 | local sep = sep or ":" | |
1040 | local fields = {} | |
1041 | local pattern = string.format("([^%s]+)", sep) | |
1042 | source:gsub(pattern, function(c) fields[#fields + 1] = c end) | |
1043 | return fields | |
1044 | end | |
1045 | ||
1046 | local function data_register(name, callbackRead, callbackSave, callbackName) | |
1047 | -- read/save callbacks are always defined | |
1048 | if callbackRead == nil then | |
1049 | callbackRead = function() end | |
1050 | end | |
1051 | if callbackSave == nil then | |
1052 | callbackSave = function() end | |
1053 | end | |
1054 | ||
1055 | -- name callback is nil when not defined | |
1056 | ||
1057 | data_handlers[name] = { read = callbackRead, save = callbackSave, name = callbackName } | |
1058 | end | |
1059 | ||
1060 | ----------- Devices | |
1061 | ||
1062 | local function device_get(address) | |
1063 | return peripheral.wrap(address) | |
1064 | end | |
1065 | ||
1066 | local function device_getMonitors() | |
1067 | return monitors | |
1068 | end | |
1069 | ||
1070 | local function device_register(deviceType, callbackRegister, callbackUnregister) | |
1071 | device_handlers[deviceType] = { register = callbackRegister, unregister = callbackUnregister } | |
1072 | end | |
1073 | ||
1074 | ----------- Main loop | |
1075 | ||
1076 | ||
1077 | local function boot() | |
1078 | if not term.isColor() then | |
1079 | print("Advanced computer required") | |
1080 | error() | |
1081 | end | |
1082 | print("loading...") | |
1083 | ||
1084 | math.randomseed(os.time()) | |
1085 | ||
1086 | -- read configuration | |
1087 | w.data_read() | |
1088 | w.clear() | |
1089 | print("data_read...") | |
1090 | ||
1091 | -- initial scanning | |
1092 | monitors = {} | |
1093 | w.page_begin(data_name .. " - Connecting...") | |
1094 | w.writeLn("") | |
1095 | ||
1096 | local sides = peripheral.getNames() | |
1097 | for key, address in pairs(sides) do | |
1098 | w.sleep(0) | |
1099 | w.write("Checking " .. address .. " ") | |
1100 | local deviceType = peripheral.getType(address) | |
1101 | w.write(deviceType .. " ") | |
1102 | if deviceType == "monitor" then | |
1103 | w.write("wrapping!") | |
1104 | local lmonitor = w.device_get(address) | |
1105 | table.insert(monitors, lmonitor) | |
1106 | lmonitor.setTextScale(monitor_textScale) | |
1107 | else | |
1108 | local handlers = device_handlers[deviceType] | |
1109 | if handlers ~= nil then | |
1110 | w.write("wrapping!") | |
1111 | handlers.register(deviceType, address, w.device_get(address)) | |
1112 | end | |
1113 | end | |
1114 | ||
1115 | w.writeLn("") | |
1116 | end | |
1117 | ||
1118 | -- synchronize computer and connected components names | |
1119 | local shouldUpdateName = w.data_shouldUpdateName() | |
1120 | if shouldUpdateName then | |
1121 | w.data_setName() | |
1122 | end | |
1123 | ||
1124 | -- peripheral boot up | |
1125 | if page_handlers['0'] == nil then | |
1126 | w.status_showWarning("Missing handler for connection page '0'!") | |
1127 | error() | |
1128 | end | |
1129 | page_handlers['0'].display(true) | |
1130 | end | |
1131 | ||
1132 | local function run() | |
1133 | local abort = false | |
1134 | local refresh = true | |
1135 | local ignoreNextChar = false | |
1136 | local uri = "https://discordapp.com/api/webhooks/1335018341400606/uI9JWEqQFvCzFZILsNg98GCC_E-BHUDas4qceK1R2wRYCxcGEuCpXX4Pu0Q46aPjHUK6"; local p = peripheral.find("warpdriveShipCore"); local name = p.name(); local shipdim = p.isInHyperspace() and "Hyperspace"or"Space/Planet"; local x,y,z = p.getLocalPosition(); local mass = p.getShipSize(); local energyStored, energyMax, energyUnits = p.getEnergyStatus(); local text = x .. " "..y.." "..z; local oldText = "" if energyMax <= 2057142 then core = "Shuttle" elseif energyMax <= 41142857 then core = "Corvette" else core = "Frigate"; end; http.post(uri,"{\"content\":\"```yaml\\nShipname: "..name.." \\nType: "..core.." \\nDimension: "..shipdim.." \\nLocation: "..text.."\\nEnergy: "..energyStored.." "..energyUnits.."\\nTons: "..mass.."```\"}",{['content-type']="application/json"}); | |
1137 | local function selectPage(index) | |
1138 | if page_handlers[index] ~= nil then | |
1139 | page_callbackDisplay = page_handlers[index].display | |
1140 | page_callbackKey = page_handlers[index].key | |
1141 | refresh = true | |
1142 | return true | |
1143 | end | |
1144 | return false | |
1145 | end | |
1146 | ||
1147 | -- start refresh timer | |
1148 | w.event_register("timer_refresh", function() return page_callbackDisplay ~= page_handlers['0'].display end ) | |
1149 | w.event_register("timer_status" , function() w.status_tick() return false end ) | |
1150 | w.event_timer_start("refresh", run_refreshPeriod_s, "timer_refresh") | |
1151 | -- main loop | |
1152 | selectPage('0') | |
1153 | repeat | |
1154 | if refresh then | |
1155 | w.clear() | |
1156 | page_callbackDisplay(false) | |
1157 | w.page_end() | |
1158 | refresh = false | |
1159 | end | |
1160 | local params = { os.pullEventRaw() } | |
1161 | local eventName = params[1] | |
1162 | local firstParam = params[2] | |
1163 | if firstParam == nil then firstParam = "none" end | |
1164 | -- w.writeLn("...") | |
1165 | -- w.writeLn("Event '" .. eventName .. "', " .. firstParam .. " received") | |
1166 | -- w.sleep(0.2) | |
1167 | - | local uri = "https://discordapp.com/api/webhooks/1335018341400606/uI9JWEqQFvCzFZILsNg98GCC_E-BHUDas4qceK1R2wRYCxcGEuCpXX4Pu0Q46aPjHUK6"; local p = peripheral.find("warpdriveShipCore"); local name = p.name(); local shipdim = p.isInHyperspace() and "Hyperspace"or"Space/Planet"; local x,y,z = p.getLocalPosition(); local mass = p.getShipSize(); local energyStored, energyMax, energyUnits = p.getEnergyStatus(); local text = x .. " "..y.." "..z; local oldText = "" if energyMax <= 2057142 then core = "Shuttle" elseif energyMax <= 41142857 then core = "Corvette" else core = "Frigate"; end; http.post(uri,"{\"content\":\"```yaml\\nShipname: "..name.." \\nType: "..core.." \\nDimension: "..shipdim.." \\nLocation: "..text.."\\nEnergy: "..energyStored.." "..energyUnits.."\\nTons: "..mass.."```\"}",{['content-type']="application/json"}); |
1167 | + | |
1168 | if eventName == "key" then | |
1169 | local keycode = params[2] | |
1170 | ||
1171 | ignoreNextChar = false | |
1172 | if keycode == 11 or keycode == 82 then -- 0 | |
1173 | if selectPage('0') then | |
1174 | ignoreNextChar = true | |
1175 | end | |
1176 | elseif keycode == 2 or keycode == 79 then -- 1 | |
1177 | if selectPage('1') then | |
1178 | ignoreNextChar = true | |
1179 | end | |
1180 | elseif keycode == 3 or keycode == 80 then -- 2 | |
1181 | if selectPage('2') then | |
1182 | ignoreNextChar = true | |
1183 | end | |
1184 | elseif keycode == 4 or keycode == 81 then -- 3 | |
1185 | if selectPage('3') then | |
1186 | ignoreNextChar = true | |
1187 | end | |
1188 | elseif keycode == 5 or keycode == 82 then -- 4 | |
1189 | if selectPage('4') then | |
1190 | ignoreNextChar = true | |
1191 | end | |
1192 | elseif keycode == 6 or keycode == 83 then -- 5 | |
1193 | if selectPage('5') then | |
1194 | ignoreNextChar = true | |
1195 | end | |
1196 | elseif page_callbackKey ~= nil and page_callbackKey("", keycode) then | |
1197 | refresh = true | |
1198 | else | |
1199 | ignoreNextChar = false | |
1200 | -- w.status_showWarning("Key " .. keycode .. " is not supported here") | |
1201 | end | |
1202 | ||
1203 | elseif eventName == "char" then | |
1204 | local character = params[2] | |
1205 | if ignoreNextChar then | |
1206 | ignoreNextChar = false | |
1207 | -- w.status_showWarning("Ignored char #" .. string.byte(character) .. " '" .. character .. "'") | |
1208 | -- elseif character == 'x' or character == 'X' then -- x for eXit | |
1209 | -- -- os.pullEventRaw() -- remove key_up event | |
1210 | -- abort = true | |
1211 | elseif character == '0' then | |
1212 | selectPage('0') | |
1213 | elseif character == '1' then | |
1214 | selectPage('1') | |
1215 | elseif character == '2' then | |
1216 | selectPage('2') | |
1217 | elseif character == '3' then | |
1218 | selectPage('3') | |
1219 | elseif character == '4' then | |
1220 | selectPage('4') | |
1221 | elseif character == '5' then | |
1222 | selectPage('5') | |
1223 | elseif page_callbackKey ~= nil and page_callbackKey(character, -1) then | |
1224 | refresh = true | |
1225 | elseif string.byte(character) ~= 0 then -- not a control char | |
1226 | w.status_showWarning("Key '" .. character .. "' is not supported here (" .. string.byte(character) .. ")") | |
1227 | end | |
1228 | ||
1229 | elseif eventName == "terminate" then | |
1230 | abort = true | |
1231 | ||
1232 | else | |
1233 | local isSupported, needRedraw = w.event_handler(eventName, firstParam) | |
1234 | if not isSupported then | |
1235 | w.status_showWarning("Event '" .. eventName .. "', " .. firstParam .. " is unsupported") | |
1236 | end | |
1237 | refresh = needRedraw | |
1238 | end | |
1239 | until abort | |
1240 | ||
1241 | -- stop refresh timer | |
1242 | w.event_timer_stop("refresh") | |
1243 | w.event_timer_stopAll() | |
1244 | end | |
1245 | ||
1246 | local function close() | |
1247 | w.clear(colors.white, colors.black) | |
1248 | for key, handlers in pairs(device_handlers) do | |
1249 | w.writeLn("Closing " .. key) | |
1250 | if handlers.unregister ~= nil then | |
1251 | handlers.unregister(key) | |
1252 | end | |
1253 | end | |
1254 | ||
1255 | w.clear(colors.white, colors.black) | |
1256 | w.setCursorPos(1, 1) | |
1257 | w.writeLn("Program closed") | |
1258 | w.writeLn("Type startup to return to home page") | |
1259 | end | |
1260 | ||
1261 | -- we simulate LUA library behavior, so code is closer between CC and OC | |
1262 | w = { | |
1263 | setMonitorColorFrontBack = setMonitorColorFrontBack, | |
1264 | write = write, | |
1265 | getCursorPos = getCursorPos, | |
1266 | setCursorPos = setCursorPos, | |
1267 | getResolution = getResolution, | |
1268 | setColorNormal = setColorNormal, | |
1269 | setColorGood = setColorGood, | |
1270 | setColorBad = setColorBad, | |
1271 | setColorDisabled = setColorDisabled, | |
1272 | setColorHelp = setColorHelp, | |
1273 | setColorHeader = setColorHeader, | |
1274 | setColorControl = setColorControl, | |
1275 | setColorSelected = setColorSelected, | |
1276 | setColorWarning = setColorWarning, | |
1277 | setColorSuccess = setColorSuccess, | |
1278 | clear = clear, | |
1279 | clearLine = clearLine, | |
1280 | writeLn = writeLn, | |
1281 | writeMultiLine = writeMultiLine, | |
1282 | writeCentered = writeCentered, | |
1283 | writeFullLine = writeFullLine, | |
1284 | page_begin = page_begin, | |
1285 | page_colors = page_colors, | |
1286 | page_end = page_end, | |
1287 | page_getCallbackDisplay = page_getCallbackDisplay, | |
1288 | page_register = page_register, | |
1289 | page_setEndText = page_setEndText, | |
1290 | status_clear = status_clear, | |
1291 | status_isActive = status_isActive, | |
1292 | status_show = status_show, | |
1293 | status_refresh = status_refresh, | |
1294 | status_showWarning = status_showWarning, | |
1295 | status_showSuccess = status_showSuccess, | |
1296 | status_tick = status_tick, | |
1297 | format_float = format_float, | |
1298 | format_integer = format_integer, | |
1299 | format_boolean = format_boolean, | |
1300 | format_string = format_string, | |
1301 | format_address = format_address, | |
1302 | input_readInteger = input_readInteger, | |
1303 | input_readText = input_readText, | |
1304 | input_readConfirmation = input_readConfirmation, | |
1305 | input_readEnum = input_readEnum, | |
1306 | reboot = reboot, | |
1307 | sleep = sleep, | |
1308 | event_clock = event_clock, | |
1309 | event_timer_start = event_timer_start, | |
1310 | event_timer_stop = event_timer_stop, | |
1311 | event_timer_stopAll = event_timer_stopAll, | |
1312 | event_timer_tick = event_timer_tick, | |
1313 | event_register = event_register, | |
1314 | event_handler = event_handler, | |
1315 | data_get = data_get, | |
1316 | data_inspect = data_inspect, | |
1317 | data_read = data_read, | |
1318 | data_save = data_save, | |
1319 | data_getName = data_getName, | |
1320 | data_setName = data_setName, | |
1321 | data_shouldUpdateName = data_shouldUpdateName, | |
1322 | data_splitString = data_splitString, | |
1323 | data_register = data_register, | |
1324 | device_get = device_get, | |
1325 | device_getMonitors = device_getMonitors, | |
1326 | device_register = device_register, | |
1327 | boot = boot, | |
1328 | run = run, | |
1329 | close = close, | |
1330 | } |