Advertisement
Guest User

Untitled

a guest
Nov 12th, 2018
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.37 KB | None | 0 0
  1. function terminal_code()
  2. local term = {}
  3. local cursorX, cursorY = 1, 1
  4. local cursorBlink = nil
  5. --- quick and dirty hacks that allow newer programs to run while not actually writing new code
  6. term.gpu = function() return component.gpu end
  7. term.getViewport = function() return 0, 0, component.gpu.getResolution() end
  8. term.getGlobalArea = function(ignored)
  9. local w,h,dx,dy = term.getViewport(window)
  10. return dx+1,dy+1,w,h
  11. end
  12. term.pull = event.pull
  13. term.keyboard = function() return component.keyboard end
  14. term.screen = function() return term.gpu().getScreen() end
  15.  
  16. local function toggleBlink()
  17. if term.isAvailable() then
  18. cursorBlink.state = not cursorBlink.state
  19. if cursorBlink.state then
  20. cursorBlink.alt = component.gpu.get(cursorX, cursorY)
  21. component.gpu.set(cursorX, cursorY, "_")
  22. else
  23. component.gpu.set(cursorX, cursorY, cursorBlink.alt)
  24. end
  25. end
  26. end
  27.  
  28. -------------------------------------------------------------------------------
  29.  
  30. function term.clear()
  31. if term.isAvailable() then
  32. local w, h = component.gpu.getResolution()
  33. component.gpu.fill(1, 1, w, h, " ")
  34. end
  35. cursorX, cursorY = 1, 1
  36. end
  37.  
  38. function term.clearLine()
  39. if term.isAvailable() then
  40. local w = component.gpu.getResolution()
  41. component.gpu.fill(1, cursorY, w, 1, " ")
  42. end
  43. cursorX = 1
  44. end
  45.  
  46. function term.getCursor()
  47. return cursorX, cursorY
  48. end
  49.  
  50. function term.setCursor(col, row)
  51. checkArg(1, col, "number")
  52. checkArg(2, row, "number")
  53. if cursorBlink and cursorBlink.state then
  54. toggleBlink()
  55. end
  56. cursorX = math.floor(col)
  57. cursorY = math.floor(row)
  58. end
  59.  
  60. function term.getCursorBlink()
  61. return cursorBlink ~= nil
  62. end
  63.  
  64. function term.setCursorBlink(enabled)
  65. checkArg(1, enabled, "boolean")
  66. if enabled then
  67. if not cursorBlink then
  68. cursorBlink = {}
  69. cursorBlink.id = event.timer(0.5, toggleBlink, math.huge)
  70. cursorBlink.state = false
  71. elseif not cursorBlink.state then
  72. toggleBlink()
  73. end
  74. elseif cursorBlink then
  75. event.cancel(cursorBlink.id)
  76. if cursorBlink.state then
  77. toggleBlink()
  78. end
  79. cursorBlink = nil
  80. end
  81. end
  82.  
  83. function term.isAvailable()
  84. return component.isAvailable("gpu") and component.isAvailable("screen")
  85. end
  86.  
  87. function term.readKey(echo)
  88. local blink = term.getCursorBlink()
  89. term.setCursorBlink(true)
  90. local ok, name, address, charOrValue, code = pcall(event.pull, "key_down")
  91. if not ok then
  92. term.setCursorBlink(blink)
  93. error("interrupted", 0)
  94. end
  95. if name == "key_down" then
  96. if echo then term.write(charOrValue) end
  97. term.setCursorBlink(blink)
  98. end
  99. end
  100.  
  101. function term.read(history, dobreak)
  102. checkArg(1, history, "table", "nil")
  103. history = history or {}
  104. table.insert(history, "")
  105. local offset = term.getCursor() - 1
  106. local scrollX, scrollY = 0, #history - 1
  107.  
  108. local function getCursor()
  109. local cx, cy = term.getCursor()
  110. return cx - offset + scrollX, 1 + scrollY
  111. end
  112.  
  113. local function line()
  114. local cbx, cby = getCursor()
  115. return history[cby]
  116. end
  117.  
  118. local function setCursor(nbx, nby)
  119. local w, h = component.gpu.getResolution()
  120. local cx, cy = term.getCursor()
  121.  
  122. scrollY = nby - 1
  123.  
  124. nbx = math.max(1, math.min(unicode.len(history[nby]) + 1, nbx))
  125. local ncx = nbx + offset - scrollX
  126. if ncx > w then
  127. local sx = nbx - (w - offset)
  128. local dx = math.abs(scrollX - sx)
  129. scrollX = sx
  130. component.gpu.copy(1 + offset + dx, cy, w - offset - dx, 1, -dx, 0)
  131. local str = unicode.sub(history[nby], nbx - (dx - 1), nbx)
  132. str = text.padRight(str, dx)
  133. component.gpu.set(1 + math.max(offset, w - dx), cy, unicode.sub(str, 1 + math.max(0, dx - (w - offset))))
  134. elseif ncx < 1 + offset then
  135. local sx = nbx - 1
  136. local dx = math.abs(scrollX - sx)
  137. scrollX = sx
  138. component.gpu.copy(1 + offset, cy, w - offset - dx, 1, dx, 0)
  139. local str = unicode.sub(history[nby], nbx, nbx + dx)
  140. --str = text.padRight(str, dx)
  141. component.gpu.set(1 + offset, cy, str)
  142. end
  143.  
  144. term.setCursor(nbx - scrollX + offset, cy)
  145. end
  146.  
  147. local function copyIfNecessary()
  148. local cbx, cby = getCursor()
  149. if cby ~= #history then
  150. history[#history] = line()
  151. setCursor(cbx, #history)
  152. end
  153. end
  154.  
  155. local function redraw()
  156. local cx, cy = term.getCursor()
  157. local bx, by = 1 + scrollX, 1 + scrollY
  158. local w, h = component.gpu.getResolution()
  159. local l = w - offset
  160. local str = unicode.sub(history[by], bx, bx + l)
  161. str = text.padRight(str, l)
  162. component.gpu.set(1 + offset, cy, str)
  163. end
  164.  
  165. local function home()
  166. local cbx, cby = getCursor()
  167. setCursor(1, cby)
  168. end
  169.  
  170. local function ende()
  171. local cbx, cby = getCursor()
  172. setCursor(unicode.len(line()) + 1, cby)
  173. end
  174.  
  175. local function left()
  176. local cbx, cby = getCursor()
  177. if cbx > 1 then
  178. setCursor(cbx - 1, cby)
  179. return true -- for backspace
  180. end
  181. end
  182.  
  183. local function right(n)
  184. n = n or 1
  185. local cbx, cby = getCursor()
  186. local be = unicode.len(line()) + 1
  187. if cbx < be then
  188. setCursor(math.min(be, cbx + n), cby)
  189. end
  190. end
  191.  
  192. local function up()
  193. local cbx, cby = getCursor()
  194. if cby > 1 then
  195. setCursor(1, cby - 1)
  196. redraw()
  197. ende()
  198. end
  199. end
  200.  
  201. local function down()
  202. local cbx, cby = getCursor()
  203. if cby < #history then
  204. setCursor(1, cby + 1)
  205. redraw()
  206. ende()
  207. end
  208. end
  209.  
  210. local function delete()
  211. copyIfNecessary()
  212. local cbx, cby = getCursor()
  213. if cbx <= unicode.len(line()) then
  214. history[cby] = unicode.sub(line(), 1, cbx - 1) ..
  215. unicode.sub(line(), cbx + 1)
  216. local cx, cy = term.getCursor()
  217. local w, h = component.gpu.getResolution()
  218. component.gpu.copy(cx + 1, cy, w - cx, 1, -1, 0)
  219. local br = cbx + (w - cx)
  220. local char = unicode.sub(line(), br, br)
  221. if not char or unicode.len(char) == 0 then
  222. char = " "
  223. end
  224. component.gpu.set(w, cy, char)
  225. end
  226. end
  227.  
  228. local function insert(value)
  229. copyIfNecessary()
  230. local cx, cy = term.getCursor()
  231. local cbx, cby = getCursor()
  232. local w, h = component.gpu.getResolution()
  233. history[cby] = unicode.sub(line(), 1, cbx - 1) ..
  234. value ..
  235. unicode.sub(line(), cbx)
  236. local len = unicode.len(value)
  237. local n = w - (cx - 1) - len
  238. if n > 0 then
  239. component.gpu.copy(cx, cy, n, 1, len, 0)
  240. end
  241. component.gpu.set(cx, cy, value)
  242. right(len)
  243. end
  244.  
  245. local function onKeyDown(char, code)
  246. term.setCursorBlink(false)
  247. if code == keyboard.keys.back then
  248. if left() then delete() end
  249. elseif code == keyboard.keys.delete then
  250. delete()
  251. elseif code == keyboard.keys.left then
  252. left()
  253. elseif code == keyboard.keys.right then
  254. right()
  255. elseif code == keyboard.keys.home then
  256. home()
  257. elseif code == keyboard.keys["end"] then
  258. ende()
  259. elseif code == keyboard.keys.up then
  260. up()
  261. elseif code == keyboard.keys.down then
  262. down()
  263. elseif code == keyboard.keys.enter then
  264. local cbx, cby = getCursor()
  265. if cby ~= #history then -- bring entry to front
  266. history[#history] = line()
  267. table.remove(history, cby)
  268. end
  269. return true, history[#history] .. "\n"
  270. elseif keyboard.isControlDown() and code == keyboard.keys.d then
  271. if line() == "" then
  272. history[#history] = ""
  273. return true, nil
  274. end
  275. elseif keyboard.isControlDown() and code == keyboard.keys.c then
  276. history[#history] = ""
  277. return true, nil
  278. elseif not keyboard.isControl(char) then
  279. insert(unicode.char(char))
  280. end
  281. term.setCursorBlink(true)
  282. term.setCursorBlink(true) -- force toggle to caret
  283. end
  284.  
  285. local function onClipboard(value)
  286. copyIfNecessary()
  287. term.setCursorBlink(false)
  288. local cbx, cby = getCursor()
  289. local l = value:find("\n", 1, true)
  290. if l then
  291. history[cby] = unicode.sub(line(), 1, cbx - 1)
  292. redraw()
  293. insert(unicode.sub(value, 1, l - 1))
  294. return true, line() .. "\n"
  295. else
  296. insert(value)
  297. term.setCursorBlink(true)
  298. term.setCursorBlink(true) -- force toggle to caret
  299. end
  300. end
  301.  
  302. local function cleanup()
  303. if history[#history] == "" then
  304. table.remove(history)
  305. end
  306. term.setCursorBlink(false)
  307. if term.getCursor() > 1 and dobreak ~= false then
  308. print()
  309. end
  310. end
  311.  
  312. term.setCursorBlink(true)
  313. while term.isAvailable() do
  314. local ocx, ocy = getCursor()
  315. local ok, name, address, charOrValue, code = pcall(event.pull)
  316. if not ok then
  317. cleanup()
  318. error("interrupted", 0)
  319. end
  320. local ncx, ncy = getCursor()
  321. if ocx ~= ncx or ocy ~= ncy then
  322. cleanup()
  323. return "" -- soft fail the read if someone messes with the term
  324. end
  325. if term.isAvailable() and -- may have changed since pull
  326. type(address) == "string" and
  327. component.isPrimary(address)
  328. then
  329. local done, result
  330. if name == "key_down" then
  331. done, result = onKeyDown(charOrValue, code)
  332. elseif name == "clipboard" then
  333. done, result = onClipboard(charOrValue)
  334. end
  335. if done then
  336. cleanup()
  337. return result
  338. end
  339. end
  340. end
  341. cleanup()
  342. return nil -- fail the read if term becomes unavailable
  343. end
  344.  
  345. function term.write(value, wrap)
  346. if not term.isAvailable() then
  347. return
  348. end
  349. value = tostring(value)
  350. if unicode.len(value) == 0 then
  351. return
  352. end
  353. do
  354. local noBell = value:gsub("\a", "")
  355. if #noBell ~= #value then
  356. value = noBell
  357. computer.beep()
  358. end
  359. end
  360. value = text.detab(value)
  361. local w, h = component.gpu.getResolution()
  362. if not w then
  363. return -- gpu lost its screen but the signal wasn't processed yet.
  364. end
  365. local blink = term.getCursorBlink()
  366. term.setCursorBlink(false)
  367. local line, nl
  368. repeat
  369. local wrapAfter, margin = math.huge, math.huge
  370. if wrap then
  371. wrapAfter, margin = w - (cursorX - 1), w
  372. end
  373. line, value, nl = text.wrap(value, wrapAfter, margin)
  374. component.gpu.set(cursorX, cursorY, line)
  375. cursorX = cursorX + unicode.len(line)
  376. if nl or (cursorX > w and wrap) then
  377. cursorX = 1
  378. cursorY = cursorY + 1
  379. end
  380. if cursorY > h then
  381. component.gpu.copy(1, 1, w, h, 0, -1)
  382. component.gpu.fill(1, h, w, 1, " ")
  383. cursorY = h
  384. end
  385. until not value
  386. term.setCursorBlink(blink)
  387. end
  388.  
  389. -------------------------------------------------------------------------------
  390.  
  391. return term
  392. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement