Advertisement
Guest User

Untitled

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