Guest User

Редактор openOS(1.7.5) с интеграцией бибы подсветки синтакси

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