Advertisement
xeritt

OpenComputers text editor

Sep 3rd, 2018
333
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local fs = require("filesystem")
  2. local keyboard = require("keyboard")
  3. local shell = require("shell")
  4. local term = require("term") -- TODO use tty and cursor position instead of global area and gpu
  5. local text = require("text")
  6. local hl = require("highlighter") --https://pastebin.com/KNmLY5vX /lib/highlighter.lua
  7.  
  8. local unicode = require("unicode")
  9.  
  10. local copybuffer = ""
  11. local xcopy = 0
  12. local ycopy = 0
  13.  
  14. if not term.isAvailable() then
  15.   return
  16. end
  17. local gpu = term.gpu()
  18. local args, options = shell.parse(...)
  19. if #args == 0 then
  20.   io.write("Usage: edit <filename>")
  21.   return
  22. end
  23.  
  24. local filename = shell.resolve(args[1])
  25. local file_parentpath = fs.path(filename)
  26.  
  27. if fs.exists(file_parentpath) and not fs.isDirectory(file_parentpath) then
  28.   io.stderr:write(string.format("Not a directory: %s\n", file_parentpath))
  29.   return 1
  30. end
  31.  
  32. local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly()
  33.  
  34. if fs.isDirectory(filename) then
  35.   io.stderr:write("file is a directory\n")
  36.   return 1
  37. elseif not fs.exists(filename) and readonly then
  38.   io.stderr:write("file system is read only\n")
  39.   return 1
  40. end
  41.  
  42. local function loadConfig()
  43.   -- Try to load user settings.
  44.   local env = {}
  45.   local config = loadfile("/home/etc/edit.cfg", nil, env)
  46.   if config then
  47.     pcall(config)
  48.   end
  49.   -- Fill in defaults.
  50.   env.keybinds = env.keybinds or {
  51.     left = {{"left"}},
  52.     right = {{"right"}},
  53.     up = {{"up"}},
  54.     down = {{"down"}},
  55.     home = {{"home"}},
  56.     eol = {{"end"}},
  57.     pageUp = {{"pageUp"}},
  58.     pageDown = {{"pageDown"}},
  59.  
  60.     backspace = {{"back"}},
  61.     delete = {{"delete"}},
  62.     deleteLine = {{"control", "delete"}, {"shift", "delete"}},
  63.     copyLine = {{"control", "c"}},
  64.     pasteLine = {{"control", "v"}},
  65.     newline = {{"enter"}},
  66.  
  67.     save = {{"control", "s"}},
  68.     close = {{"control", "w"}},
  69.     find = {{"control", "f"}},
  70.     findnext = {{"control", "g"}, {"control", "n"}, {"f3"}}
  71.   }
  72.   -- Generate config file if it didn't exist.
  73.   if not config then
  74.     local root = fs.get("/home")
  75.     if root and not root.isReadOnly() then
  76.       fs.makeDirectory("/etc")
  77.       local f = io.open("/home/etc/edit.cfg", "w")
  78.       if f then
  79.         local serialization = require("serialization")
  80.         for k, v in pairs(env) do
  81.           f:write(k.."="..tostring(serialization.serialize(v, math.huge)).."\n")
  82.         end
  83.         f:close()
  84.       end
  85.     end
  86.   end
  87.   return env
  88. end
  89.  
  90. term.clear()
  91. term.setCursorBlink(true)
  92.  
  93. local running = true
  94. local buffer = {}
  95. local scrollX, scrollY = 0, 0
  96. local config = loadConfig()
  97.  
  98. local getKeyBindHandler -- forward declaration for refind()
  99.  
  100. local function helpStatusText()
  101.   local function prettifyKeybind(label, command)
  102.     local keybind = type(config.keybinds) == "table" and config.keybinds[command]
  103.     if type(keybind) ~= "table" or type(keybind[1]) ~= "table" then return "" end
  104.     local alt, control, shift, key
  105.     for _, value in ipairs(keybind[1]) do
  106.       if value == "alt" then alt = true
  107.       elseif value == "control" then control = true
  108.       elseif value == "shift" then shift = true
  109.       else key = value end
  110.     end
  111.     if not key then return "" end
  112.     return label .. ": [" ..
  113.            (control and "Ctrl+" or "") ..
  114.            (alt and "Alt+" or "") ..
  115.            (shift and "Shift+" or "") ..
  116.            unicode.upper(key) ..
  117.            "] "
  118.   end
  119.   return prettifyKeybind("Save", "save") ..
  120.          prettifyKeybind("Close", "close") ..
  121.          prettifyKeybind("Copy Line", "copyLine") ..
  122.          prettifyKeybind("Paste Line", "pasteLine") ..
  123.          prettifyKeybind("Find", "find")
  124. end
  125.  
  126. -------------------------------------------------------------------------------
  127.  
  128. local function setStatus(value)
  129.   local x, y, w, h = term.getGlobalArea()
  130.   value = unicode.wlen(value) > w - 10 and unicode.wtrunc(value, w - 9) or value
  131.   value = text.padRight(value, w - 10)
  132.   gpu.set(x, y + h - 1, value)
  133. end
  134.  
  135. local function getArea()
  136.   local x, y, w, h = term.getGlobalArea()
  137.   return x, y, w, h - 1
  138. end
  139.  
  140. local function removePrefix(line, length)
  141.   if length >= unicode.wlen(line) then
  142.     return ""
  143.   else
  144.     local prefix = unicode.wtrunc(line, length + 1)
  145.     local suffix = unicode.sub(line, unicode.len(prefix) + 1)
  146.     length = length - unicode.wlen(prefix)
  147.     if length > 0 then
  148.       suffix = (" "):rep(unicode.charWidth(suffix) - length) .. unicode.sub(suffix, 2)
  149.     end
  150.     return suffix
  151.   end
  152. end
  153.  
  154. local function lengthToChars(line, length)
  155.   if length > unicode.wlen(line) then
  156.     return unicode.len(line) + 1
  157.   else
  158.     local prefix = unicode.wtrunc(line, length)
  159.     return unicode.len(prefix) + 1
  160.   end
  161. end
  162.  
  163.  
  164. local function isWideAtPosition(line, x)
  165.   local index = lengthToChars(line, x)
  166.   if index > unicode.len(line) then
  167.     return false, false
  168.   end
  169.   local prefix = unicode.sub(line, 1, index)
  170.   local char = unicode.sub(line, index, index)
  171.   --isWide, isRight
  172.   return unicode.isWide(char), unicode.wlen(prefix) == x
  173. end
  174.  
  175. local function drawLine(x, y, w, h, lineNr)
  176.   local yLocal = lineNr - scrollY
  177.   if yLocal > 0 and yLocal <= h then
  178.     local str = removePrefix(buffer[lineNr] or "", scrollX)
  179.     str = unicode.wlen(str) > w and unicode.wtrunc(str, w + 1) or str
  180.     str = text.padRight(str, w)
  181.     --gpu.set(x, y - 1 + lineNr - scrollY, str)
  182.     hl.put(x, y - 1 + lineNr - scrollY, str)
  183.   end
  184. end
  185.  
  186. local function getCursor()
  187.   local cx, cy = term.getCursor()
  188.   return cx + scrollX, cy + scrollY
  189. end
  190.  
  191. local function line()
  192.   local cbx, cby = getCursor()
  193.   return buffer[cby]
  194. end
  195.  
  196. local function getNormalizedCursor()
  197.   local cbx, cby = getCursor()
  198.   local wide, right = isWideAtPosition(buffer[cby], cbx)
  199.   if wide and right then
  200.     cbx = cbx - 1
  201.   end
  202.   return cbx, cby
  203. end
  204.  
  205. local function setCursor(nbx, nby)
  206.   local x, y, w, h = getArea()
  207.   nby = math.max(1, math.min(#buffer, nby))
  208.  
  209.   local ncy = nby - scrollY
  210.   if ncy > h then
  211.     term.setCursorBlink(false)
  212.     local sy = nby - h
  213.     local dy = math.abs(scrollY - sy)
  214.     scrollY = sy
  215.     if h > dy then
  216.       gpu.copy(x, y + dy, w, h - dy, 0, -dy)
  217.     end
  218.     for lineNr = nby - (math.min(dy, h) - 1), nby do
  219.       drawLine(x, y, w, h, lineNr)
  220.     end
  221.   elseif ncy < 1 then
  222.     term.setCursorBlink(false)
  223.     local sy = nby - 1
  224.     local dy = math.abs(scrollY - sy)
  225.     scrollY = sy
  226.     if h > dy then
  227.       gpu.copy(x, y, w, h - dy, 0, dy)
  228.     end
  229.     for lineNr = nby, nby + (math.min(dy, h) - 1) do
  230.       drawLine(x, y, w, h, lineNr)
  231.     end
  232.   end
  233.   term.setCursor(term.getCursor(), nby - scrollY)
  234.  
  235.   nbx = math.max(1, math.min(unicode.wlen(line()) + 1, nbx))
  236.   local wide, right = isWideAtPosition(line(), nbx)
  237.   local ncx = nbx - scrollX
  238.   if ncx > w or (ncx + 1 > w and wide and not right) then
  239.     term.setCursorBlink(false)
  240.     scrollX = nbx - w + ((wide and not right) and 1 or 0)
  241.     for lineNr = 1 + scrollY, math.min(h + scrollY, #buffer) do
  242.       drawLine(x, y, w, h, lineNr)
  243.     end
  244.   elseif ncx < 1 or (ncx - 1 < 1 and wide and right) then
  245.     term.setCursorBlink(false)
  246.     scrollX = nbx - 1 - ((wide and right) and 1 or 0)
  247.     for lineNr = 1 + scrollY, math.min(h + scrollY, #buffer) do
  248.       drawLine(x, y, w, h, lineNr)
  249.     end
  250.   end
  251.   term.setCursor(nbx - scrollX, nby - scrollY)
  252.   --update with term lib
  253.   nbx, nby = getCursor()
  254.   gpu.set(x + w - 10, y + h, text.padLeft(string.format("%d,%d", nby, nbx), 10))
  255. end
  256.  
  257. local function highlight(bx, by, length, enabled)
  258.   local x, y, w, h = getArea()
  259.   local cx, cy = bx - scrollX, by - scrollY
  260.   cx = math.max(1, math.min(w, cx))
  261.   cy = math.max(1, math.min(h, cy))
  262.   length = math.max(1, math.min(w - cx, length))
  263.  
  264.   local fg, fgp = gpu.getForeground()
  265.   local bg, bgp = gpu.getBackground()
  266.   if enabled then
  267.     gpu.setForeground(bg, bgp)
  268.     gpu.setBackground(fg, fgp)
  269.   end
  270.   local indexFrom = lengthToChars(buffer[by], bx)
  271.   local value = unicode.sub(buffer[by], indexFrom)
  272.   if unicode.wlen(value) > length then
  273.     value = unicode.wtrunc(value, length + 1)
  274.   end
  275.  -- gpu.set(x - 1 + cx, y - 1 + cy, value)
  276.   hl.put(x - 1 + cx, y - 1 + cy, value)
  277.   if enabled then
  278.     gpu.setForeground(fg, fgp)
  279.     gpu.setBackground(bg, bgp)
  280.   end
  281. end
  282.  
  283. local function home()
  284.   local cbx, cby = getCursor()
  285.   setCursor(1, cby)
  286. end
  287.  
  288. local function ende()
  289.   local cbx, cby = getCursor()
  290.   setCursor(unicode.wlen(line()) + 1, cby)
  291. end
  292.  
  293. local function left()
  294.   local cbx, cby = getNormalizedCursor()
  295.   if cbx > 1 then
  296.     local wideTarget, rightTarget = isWideAtPosition(line(), cbx - 1)
  297.     if wideTarget and rightTarget then
  298.       setCursor(cbx - 2, cby)
  299.     else
  300.       setCursor(cbx - 1, cby)
  301.     end
  302.     return true -- for backspace
  303.   elseif cby > 1 then
  304.     setCursor(cbx, cby - 1)
  305.     ende()
  306.     return true -- again, for backspace
  307.   end
  308. end
  309.  
  310. local function right(n)
  311.   n = n or 1
  312.   local cbx, cby = getNormalizedCursor()
  313.   local be = unicode.wlen(line()) + 1
  314.   local wide, right = isWideAtPosition(line(), cbx + n)
  315.   if wide and right then
  316.     n = n + 1
  317.   end
  318.   if cbx + n <= be then
  319.     setCursor(cbx + n, cby)
  320.   elseif cby < #buffer then
  321.     setCursor(1, cby + 1)
  322.   end
  323. end
  324.  
  325. local function up(n)
  326.   n = n or 1
  327.   local cbx, cby = getCursor()
  328.   if cby > 1 then
  329.     setCursor(cbx, cby - n)
  330.   end
  331. end
  332.  
  333. local function down(n)
  334.   n = n or 1
  335.   local cbx, cby = getCursor()
  336.   if cby < #buffer then
  337.     setCursor(cbx, cby + n)
  338.   end
  339. end
  340.  
  341. local function delete(fullRow)
  342.   local cx, cy = term.getCursor()
  343.   local cbx, cby = getCursor()
  344.   local x, y, w, h = getArea()
  345.   local function deleteRow(row)
  346.     local content = table.remove(buffer, row)
  347.     local rcy = cy + (row - cby)
  348.     if rcy <= h then
  349.       gpu.copy(x, y + rcy, w, h - rcy, 0, -1)
  350.       drawLine(x, y, w, h, row + (h - rcy))
  351.     end
  352.     return content
  353.   end
  354.   if fullRow then
  355.     term.setCursorBlink(false)
  356.     if #buffer > 1 then
  357.       deleteRow(cby)
  358.     else
  359.       buffer[cby] = ""
  360.       gpu.fill(x, y - 1 + cy, w, 1, " ")
  361.     end
  362.     setCursor(1, cby)
  363.   elseif cbx <= unicode.wlen(line()) then
  364.     term.setCursorBlink(false)
  365.     local index = lengthToChars(line(), cbx)
  366.     buffer[cby] = unicode.sub(line(), 1, index - 1) ..
  367.                   unicode.sub(line(), index + 1)
  368.     drawLine(x, y, w, h, cby)
  369.   elseif cby < #buffer then
  370.     term.setCursorBlink(false)
  371.     local append = deleteRow(cby + 1)
  372.     buffer[cby] = buffer[cby] .. append
  373.     drawLine(x, y, w, h, cby)
  374.   else
  375.     return
  376.   end
  377.   setStatus(helpStatusText())
  378. end
  379.  
  380. local function insert(value)
  381.   if not value or unicode.len(value) < 1 then
  382.     return
  383.   end
  384.   term.setCursorBlink(false)
  385.   local cx, cy = term.getCursor()
  386.   local cbx, cby = getCursor()
  387.   local x, y, w, h = getArea()
  388.   local index = lengthToChars(line(), cbx)
  389.   buffer[cby] = unicode.sub(line(), 1, index - 1) ..
  390.                 value ..
  391.                 unicode.sub(line(), index)
  392.   drawLine(x, y, w, h, cby)
  393.   right(unicode.wlen(value))
  394.   setStatus(helpStatusText())
  395. end
  396.  
  397. local function enter()
  398.   term.setCursorBlink(false)
  399.   local cx, cy = term.getCursor()
  400.   local cbx, cby = getCursor()
  401.   local x, y, w, h = getArea()
  402.   local index = lengthToChars(line(), cbx)
  403.   table.insert(buffer, cby + 1, unicode.sub(buffer[cby], index))
  404.   buffer[cby] = unicode.sub(buffer[cby], 1, index - 1)
  405.   drawLine(x, y, w, h, cby)
  406.   if cy < h then
  407.     if cy < h - 1 then
  408.       gpu.copy(x, y + cy, w, h - (cy + 1), 0, 1)
  409.     end
  410.     drawLine(x, y, w, h, cby + 1)
  411.   end
  412.   setCursor(1, cby + 1)
  413.   setStatus(helpStatusText())
  414. end
  415.  
  416. local findText = ""
  417.  
  418. local function find()
  419.   local x, y, w, h = getArea()
  420.   local cx, cy = term.getCursor()
  421.   local cbx, cby = getCursor()
  422.   local ibx, iby = cbx, cby
  423.   while running do
  424.     if unicode.len(findText) > 0 then
  425.       local sx, sy
  426.       for syo = 1, #buffer do -- iterate lines with wraparound
  427.         sy = (iby + syo - 1 + #buffer - 1) % #buffer + 1
  428.         sx = string.find(buffer[sy], findText, syo == 1 and ibx or 1, true)
  429.         if sx and (sx >= ibx or syo > 1) then
  430.           break
  431.         end
  432.       end
  433.       if not sx then -- special case for single matches
  434.         sy = iby
  435.         sx = string.find(buffer[sy], findText, nil, true)
  436.       end
  437.       if sx then
  438.         sx = unicode.wlen(string.sub(buffer[sy], 1, sx - 1)) + 1
  439.         cbx, cby = sx, sy
  440.         setCursor(cbx, cby)
  441.         highlight(cbx, cby, unicode.wlen(findText), true)
  442.       end
  443.     end
  444.     term.setCursor(7 + unicode.wlen(findText), h + 1)
  445.     setStatus("Find: " .. findText)
  446.  
  447.     local _, address, char, code = term.pull("key_down")
  448.     if address == term.keyboard() then
  449.       local handler, name = getKeyBindHandler(code)
  450.       highlight(cbx, cby, unicode.wlen(findText), false)
  451.       if name == "newline" then
  452.         break
  453.       elseif name == "close" then
  454.         handler()
  455.       elseif name == "backspace" then
  456.         findText = unicode.sub(findText, 1, -2)
  457.       elseif name == "find" or name == "findnext" then
  458.         ibx = cbx + 1
  459.         iby = cby
  460.       elseif not keyboard.isControl(char) then
  461.         findText = findText .. unicode.char(char)
  462.       end
  463.     end
  464.   end
  465.   setCursor(cbx, cby)
  466.   setStatus(helpStatusText())
  467. end
  468.  
  469. -------------------------------------------------------------------------------
  470.  
  471. local keyBindHandlers = {
  472.   left = left,
  473.   right = right,
  474.   up = up,
  475.   down = down,
  476.   home = home,
  477.   eol = ende,
  478.   pageUp = function()
  479.     local x, y, w, h = getArea()
  480.     up(h - 1)
  481.   end,
  482.   pageDown = function()
  483.     local x, y, w, h = getArea()
  484.     down(h - 1)
  485.   end,
  486.  
  487.   backspace = function()
  488.     if not readonly and left() then
  489.       delete()
  490.     end
  491.   end,
  492.   delete = function()
  493.     if not readonly then
  494.       delete()
  495.     end
  496.   end,
  497.   deleteLine = function()
  498.     if not readonly then
  499.       delete(true)
  500.     end
  501.   end,
  502.   newline = function()
  503.     if not readonly then
  504.       enter()
  505.     end
  506.   end,
  507.   copyLine = function()
  508.     setStatus("Copy line")
  509.     xcopy, ycopy = getCursor()
  510.     copybuffer=line()
  511.     highlight(0, ycopy, unicode.len(copybuffer), true)
  512.   end,
  513.   pasteLine = function()
  514.     if (unicode.len(copybuffer)>0) then
  515.       insert(copybuffer)
  516.       highlight(0, ycopy, unicode.len(copybuffer), false)
  517.     end
  518.   end,
  519.   save = function()
  520.     if readonly then return end
  521.     local new = not fs.exists(filename)
  522.     local backup
  523.     if not new then
  524.       backup = filename .. "~"
  525.       for i = 1, math.huge do
  526.         if not fs.exists(backup) then
  527.           break
  528.         end
  529.         backup = filename .. "~" .. i
  530.       end
  531.       fs.copy(filename, backup)
  532.     end
  533.     if not fs.exists(file_parentpath) then
  534.       fs.makeDirectory(file_parentpath)
  535.     end
  536.     local f, reason = io.open(filename, "w")
  537.     if f then
  538.       local chars, firstLine = 0, true
  539.       for _, line in ipairs(buffer) do
  540.         if not firstLine then
  541.           line = "\n" .. line
  542.         end
  543.         firstLine = false
  544.         f:write(line)
  545.         chars = chars + unicode.len(line)
  546.       end
  547.       f:close()
  548.       local format
  549.       if new then
  550.         format = [["%s" [New] %dL,%dC written]]
  551.       else
  552.         format = [["%s" %dL,%dC written]]
  553.       end
  554.       setStatus(string.format(format, fs.name(filename), #buffer, chars))
  555.     else
  556.       setStatus(reason)
  557.     end
  558.     if not new then
  559.       fs.remove(backup)
  560.     end
  561.   end,
  562.   close = function()
  563.     -- TODO ask to save if changed
  564.     running = false
  565.   end,
  566.   find = function()
  567.     findText = ""
  568.     find()
  569.   end,
  570.   findnext = find
  571. }
  572.  
  573. getKeyBindHandler = function(code)
  574.   if type(config.keybinds) ~= "table" then return end
  575.   -- Look for matches, prefer more 'precise' keybinds, e.g. prefer
  576.   -- ctrl+del over del.
  577.   local result, resultName, resultWeight = nil, nil, 0
  578.   for command, keybinds in pairs(config.keybinds) do
  579.     if type(keybinds) == "table" and keyBindHandlers[command] then
  580.       for _, keybind in ipairs(keybinds) do
  581.         if type(keybind) == "table" then
  582.           local alt, control, shift, key = false, false, false
  583.           for _, value in ipairs(keybind) do
  584.             if value == "alt" then alt = true
  585.             elseif value == "control" then control = true
  586.             elseif value == "shift" then shift = true
  587.             else key = value end
  588.           end
  589.           local keyboardAddress = term.keyboard()
  590.           if (alt     == not not keyboard.isAltDown(keyboardAddress)) and
  591.              (control == not not keyboard.isControlDown(keyboardAddress)) and
  592.              (shift   == not not keyboard.isShiftDown(keyboardAddress)) and
  593.              code == keyboard.keys[key] and
  594.              #keybind > resultWeight
  595.           then
  596.             resultWeight = #keybind
  597.             resultName = command
  598.             result = keyBindHandlers[command]
  599.           end
  600.         end
  601.       end
  602.     end
  603.   end
  604.   return result, resultName
  605. end
  606.  
  607. -------------------------------------------------------------------------------
  608.  
  609. local function onKeyDown(char, code)
  610.   local handler = getKeyBindHandler(code)
  611.   if handler then
  612.     handler()
  613.   elseif readonly and code == keyboard.keys.q then
  614.     running = false
  615.   elseif not readonly then
  616.     if not keyboard.isControl(char) then
  617.       insert(unicode.char(char))
  618.     elseif unicode.char(char) == "\t" then
  619.       insert("  ")
  620.     end
  621.   end
  622. end
  623.  
  624. local function onClipboard(value)
  625.   value = value:gsub("\r\n", "\n")
  626.   local cbx, cby = getCursor()
  627.   local start = 1
  628.   local l = value:find("\n", 1, true)
  629.   if l then
  630.     repeat
  631.       local line = string.sub(value, start, l - 1)
  632.       line = text.detab(line, 2)
  633.       insert(line)
  634.       enter()
  635.       start = l + 1
  636.       l = value:find("\n", start, true)
  637.     until not l
  638.   end
  639.   insert(string.sub(value, start))
  640. end
  641.  
  642. local function onClick(x, y)
  643.   setCursor(x + scrollX, y + scrollY)
  644. end
  645.  
  646. local function onScroll(direction)
  647.   local cbx, cby = getCursor()
  648.   setCursor(cbx, cby - direction * 12)
  649. end
  650.  
  651. -------------------------------------------------------------------------------
  652.  
  653. do
  654.   local f = io.open(filename)
  655.   if f then
  656.     local x, y, w, h = getArea()
  657.     local chars = 0
  658.     for line in f:lines() do
  659.       table.insert(buffer, line)
  660.       chars = chars + unicode.len(line)
  661.       if #buffer <= h then
  662.         drawLine(x, y, w, h, #buffer)
  663.       end
  664.     end
  665.     f:close()
  666.     if #buffer == 0 then
  667.       table.insert(buffer, "")
  668.     end
  669.     local format
  670.     if readonly then
  671.       format = [["%s" [readonly] %dL,%dC]]
  672.     else
  673.       format = [["%s" %dL,%dC]]
  674.     end
  675.     setStatus(string.format(format, fs.name(filename), #buffer, chars))
  676.   else
  677.     table.insert(buffer, "")
  678.     setStatus(string.format([["%s" [New File] ]], fs.name(filename)))
  679.   end
  680.   setCursor(1, 1)
  681. end
  682.  
  683. while running do
  684.   local event, address, arg1, arg2, arg3 = term.pull()
  685.   if address == term.keyboard() or address == term.screen() then
  686.     local blink = true
  687.     if event == "key_down" then
  688.       onKeyDown(arg1, arg2)
  689.     elseif event == "clipboard" and not readonly then
  690.       onClipboard(arg1)
  691.     elseif event == "touch" or event == "drag" then
  692.       local x, y, w, h = getArea()
  693.       arg1 = arg1 - x + 1
  694.       arg2 = arg2 - y + 1
  695.       if arg1 >= 1 and arg2 >= 1 and arg1 <= w and arg2 <= h then
  696.         onClick(arg1, arg2)
  697.       end
  698.     elseif event == "scroll" then
  699.       onScroll(arg3)
  700.     else
  701.       blink = false
  702.     end
  703.     if blink then
  704.       term.setCursorBlink(true)
  705.     end
  706.   end
  707. end
  708.  
  709. term.clear()
  710. term.setCursorBlink(true)
Advertisement
RAW Paste Data Copied
Advertisement