SHARE
TWEET

edit.lua

a guest Aug 19th, 2019 62 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 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)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top