Advertisement
Guest User

edit.lua

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