Advertisement
nagoL2015

edit

Aug 15th, 2017
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 31.56 KB | None | 0 0
  1. -- Get file to edit
  2. local tArgs = {...}
  3.  
  4. if #tArgs == 0 then
  5.     print("Usage: edit <path>")
  6.     return
  7. end
  8.  
  9. -- Error checking
  10. local sPath = shell.resolve(tArgs[1])
  11. local bReadOnly = fs.isReadOnly(sPath)
  12.  
  13. if fs.exists(sPath) and fs.isDir(sPath) then
  14.     print("Cannot edit a directory.")
  15.     return
  16. end
  17.  
  18. local x, y = 1, 1
  19. local w, h = term.getSize()
  20. local scrollX, scrollY = 0, 0
  21.  
  22. local tLines = {}
  23. local bRunning = true
  24.  
  25. -- Colors
  26. local highlightColor, keywordColor, commentColor, textColor, bgColor, stringColor, functionColor, numberColor, operatorColor
  27.  
  28. if term.isColor() then
  29.     bgColor = colors.black
  30.     textColor = colors.white
  31.     highlightColor = colors.cyan
  32.     keywordColor = colors.cyan
  33.     commentColor = colors.green
  34.     stringColor = colors.red
  35.     functionColor = colors.purple
  36.     numberColor = colors.orange
  37.     operatorColor = colors.blue
  38. else
  39.     bgColor = colors.black
  40.     textColor = colors.white
  41.     highlightColor = colors.white
  42.     keywordColor = colors.white
  43.     commentColor = colors.white
  44.     stringColor = colors.white
  45.     functionColor = colors.white
  46.     numberColor = colors.white
  47.     operatorColor = colors.white
  48. end
  49.  
  50. -- Menus
  51. local bMenu = false
  52. local nMenuItem = 1
  53. local tMenuItems
  54.  
  55. if bReadOnly then
  56.     tMenuItems = {"Exit"}
  57. else
  58.     tMenuItems = {"Save", "Exit"}
  59. end
  60.    
  61. local sStatus = "Press Ctrl to access menu"
  62.  
  63. local function load(_sPath)
  64.     tLines = {}
  65.    
  66.     if fs.exists(_sPath) then
  67.         local file = io.open(_sPath, "r")
  68.         local sLine = file:read()
  69.        
  70.         while sLine do
  71.             table.insert(tLines, sLine)
  72.             sLine = file:read()
  73.         end
  74.        
  75.         file:close()
  76.     end
  77.    
  78.     if #tLines == 0 then
  79.         table.insert(tLines, "")
  80.     end
  81. end
  82.  
  83. local function save(_sPath)
  84.     -- Create intervening folder
  85.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len())
  86.  
  87.     -- Save
  88.     local file = nil
  89.    
  90.     local function innerSave()
  91.         file = fs.open(_sPath, "w")
  92.        
  93.         if file then
  94.             for n, sLine in ipairs(tLines) do
  95.                 file.write(sLine .. "\n")
  96.             end
  97.         else
  98.             error("Failed to open " .. _sPath)
  99.         end
  100.     end
  101.    
  102.     local ok = pcall(innerSave)
  103.    
  104.     if file then
  105.         file:close()
  106.     end
  107.    
  108.     return ok
  109. end
  110.  
  111. local tKeywords = {
  112.     --Keywords
  113.     ["and"] = keywordColor,
  114.     ["break"] = keywordColor,
  115.     ["do"] = keywordColor,
  116.     ["else"] = keywordColor,
  117.     ["elseif"] = keywordColor,
  118.     ["end"] = keywordColor,
  119.     ["false"] = keywordColor,
  120.     ["for"] = keywordColor,
  121.     ["function"] = keywordColor,
  122.     ["if"] = keywordColor,
  123.     ["in"] = keywordColor,
  124.     ["local"] = keywordColor,
  125.     ["nil"] = keywordColor,
  126.     ["not"] = keywordColor,
  127.     ["or"] = keywordColor,
  128.     ["repeat"] = keywordColor,
  129.     ["return"] = keywordColor,
  130.     ["then"] = keywordColor,
  131.     ["true"] = keywordColor,
  132.     ["until"]= keywordColor,
  133.     ["while"] = keywordColor,
  134.    
  135.     --Bit
  136.     ["bit"] = functionColor,
  137.     ["bit.blshift"] = functionColor,
  138.     ["bit.brshift"] = functionColor,
  139.     ["bit.blogic_rshift"] = functionColor,
  140.     ["bit.bxor"] = functionColor,
  141.     ["bit.bor"] = functionColor,
  142.     ["bit.band"] = functionColor,
  143.     ["bit.bnot"] = functionColor,
  144.    
  145.     --Colors
  146.     ["colors.white"] = colors.white,
  147.     ["colors.orange"] = colors.orange,
  148.     ["colors.magenta"] = colors.magenta,
  149.     ["colors.lightBlue"] = colors.lightBlue,
  150.     ["colors.yellow"] = colors.yellow,
  151.     ["colors.lime"] = colors.lime,
  152.     ["colors.pink"] = colors.pink,
  153.     ["colors.gray"] = colors.gray,
  154.     ["colors.lightGray"] = colors.lightGray,
  155.     ["colors.cyan"] = colors.cyan,
  156.     ["colors.purple"] = colors.purple,
  157.     ["colors.blue"] = colors.blue,
  158.     ["colors.brown"] = colors.brown,
  159.     ["colors.green"] = colors.green,
  160.     ["colors.red"] = colors.red,
  161.     ["colors.black"] = colors.black,
  162.     ["colors"] = functionColor,
  163.     ["colors.combine"] = functionColor,
  164.     ["colors.subtract"] = functionColor,
  165.     ["colors.test"] = functionColor,
  166.    
  167.     --Commands
  168.     ["commands"] = functionColor,
  169.     ["commands.exec"] = functionColor,
  170.     ["commands.execAsync"] = functionColor,
  171.     ["commands.list"] = functionColor,
  172.     ["commands.getBlockPosition"] = functionColor,
  173.     ["commands.getBlockInfo"] = functionColor,
  174.     ["commands.getBlockInfos"] = functionColor,
  175.    
  176.     --Coroutine
  177.     ["coroutine"] = functionColor,
  178.     ["coroutine.create"] = functionColor,
  179.     ["coroutine.resume"] = functionColor,
  180.     ["coroutine.running"] = functionColor,
  181.     ["coroutine.status"] = functionColor,
  182.     ["coroutine.wrap"] = functionColor,
  183.     ["coroutine.yield"] = functionColor,
  184.    
  185.     --disk
  186.     ["disk"] = functionColor,
  187.     ["disk.isPresent"] = functionColor,
  188.     ["disk.hasData"] = functionColor,
  189.     ["disk.getMountPath"] = functionColor,
  190.     ["disk.setLabel"] = functionColor,
  191.     ["disk.getLabel"] = functionColor,
  192.     ["disk.getId"] = functionColor,
  193.     ["disk.hasAudio"] = functionColor,
  194.     ["disk.getAudioTitle"] = functionColor,
  195.     ["disk.playAudio"] = functionColor,
  196.     ["disk.stopAudio"] = functionColor,
  197.     ["disk.eject"] = functionColor,
  198.    
  199.     --fs
  200.     ["fs"] = functionColor,
  201.     ["fs.list"] = functionColor,
  202.     ["fs.exists"] = functionColor,
  203.     ["fs.isDir"] = functionColor,
  204.     ["fs.isReadOnly"] = functionColor,
  205.     ["fs.getName"] = functionColor,
  206.     ["fs.getDrive"] = functionColor,
  207.     ["fs.getSize"] = functionColor,
  208.     ["fs.getFreeSpace"] = functionColor,
  209.     ["fs.makeDir"] = functionColor,
  210.     ["fs.move"] = functionColor,
  211.     ["fs.copy"] = functionColor,
  212.     ["fs.delete"] = functionColor,
  213.     ["fs.combine"] = functionColor,
  214.     ["fs.open"] = functionColor,
  215.     ["fs.find"] = functionColor,
  216.     ["fs.getDir"] = functionColor,
  217.     ["fs.complete"] = functionColor,
  218.    
  219.     --gps
  220.     ["gps"] = functionColor,
  221.     ["gps.locate"] = functionColor,
  222.    
  223.     --help
  224.     ["help"] = functionColor,
  225.     ["help.path"] = functionColor,
  226.     ["help.setPath"] = functionColor,
  227.     ["help.lookup"] = functionColor,
  228.     ["help.topics"] = functionColor,
  229.     ["help.completeTopic"] = functionColor,
  230.    
  231.     --HTTP
  232.     ["http"] = functionColor,
  233.     ["http.request"] = functionColor,
  234.     ["http.get"] = functionColor,
  235.     ["http.post"] = functionColor,
  236.     ["http.checkURL"] = functionColor,
  237.    
  238.     --io
  239.     ["io"] = functionColor,
  240.     ["io.open"] = functionColor,
  241.     ["io.write"] = functionColor,
  242.     ["io.read"] = functionColor,
  243.    
  244.     --Keys
  245.     ["keys"] = functionColor,
  246.     ["keys.getName"] = functionColor,
  247.    
  248.     --Math
  249.     ["math"] = functionColor,
  250.     ["math.abs"] = functionColor,
  251.     ["math.acos"] = functionColor,
  252.     ["math.asin"] = functionColor,
  253.     ["math.atan"] = functionColor,
  254.     ["math.atan2"] = functionColor,
  255.     ["math.ceil"] = functionColor,
  256.     ["math.cos"] = functionColor,
  257.     ["math.cosh"] = functionColor,
  258.     ["math.deg"] = functionColor,
  259.     ["math.exp"] = functionColor,
  260.     ["math.floor"] = functionColor,
  261.     ["math.fmod"] = functionColor,
  262.     ["math.frexp"] = functionColor,
  263.     ["math.huge"] = functionColor,
  264.     ["math.ldexp"] = functionColor,
  265.     ["math.log"] = functionColor,
  266.     ["math.log10"] = functionColor,
  267.     ["math.max"] = functionColor,
  268.     ["math.min"] = functionColor,
  269.     ["math.modf"] = functionColor,
  270.     ["math.pi"] = functionColor,
  271.     ["math.pow"] = functionColor,
  272.     ["math.rad"] = functionColor,
  273.     ["math.random"] = functionColor,
  274.     ["math.randomseed"] = functionColor,
  275.     ["math.sin"] = functionColor,
  276.     ["math.sinh"] = functionColor,
  277.     ["math.sqrt"] = functionColor,
  278.     ["math.tan"] = functionColor,
  279.     ["math.tanh"] = functionColor,
  280.    
  281.     --multishell
  282.     ["multishell"] = functionColor,
  283.     ["multishell.getCurrent"] = functionColor,
  284.     ["multishell.getCount"] = functionColor,
  285.     ["multishell.launch"] = functionColor,
  286.     ["multishell.setFocus"] = functionColor,
  287.     ["multishell.setTitle"] = functionColor,
  288.     ["multishell.getTitle"] = functionColor,
  289.     ["multishell.getFocus"] = functionColor,
  290.    
  291.     --os
  292.     ["os"] = functionColor,
  293.     ["os.version"] = functionColor,
  294.     ["os.getComputerID"] = functionColor,
  295.     ["os.getComputerLabel"] = functionColor,
  296.     ["os.run"] = functionColor,
  297.     ["os.loadAPI"] = functionColor,
  298.     ["os.unloadAPI"] = functionColor,
  299.     ["os.pullEvent"] = functionColor,
  300.     ["os.pullEventRaw"] = functionColor,
  301.     ["os.queueEvent"] = functionColor,
  302.     ["os.clock"] = functionColor,
  303.     ["os.startTimer"] = functionColor,
  304.     ["os.cancelTimer"] = functionColor,
  305.     ["os.time"] = functionColor,
  306.     ["os.sleep"] = functionColor,
  307.     ["sleep"] = functionColor,
  308.     ["os.day"] = functionColor,
  309.     ["os.setAlarm"] = functionColor,
  310.     ["os.cancelAlarm"] = functionColor,
  311.     ["os.shutdown"] = functionColor,
  312.     ["os.reboot"] = functionColor,
  313.    
  314.     --paintutils
  315.     ["paintutils"] = functionColor,
  316.     ["paintutils.loadImage"] = functionColor,
  317.     ["paintutils.drawImage"] = functionColor,
  318.     ["paintutils.drawPixel"] = functionColor,
  319.     ["paintutils.drawLine"] = functionColor,
  320.     ["paintutils.drawBox"] = functionColor,
  321.     ["paintutils.drawFilledBox"] = functionColor,
  322.    
  323.     --parallel
  324.     ["parallel"] = functionColor,
  325.     ["parallel.waitForAny"] = functionColor,
  326.     ["parallel.waitForAll"] = functionColor,
  327.    
  328.     --peripheral
  329.     ["peripheral"] = functionColor,
  330.     ["peripheral.isPresent"] = functionColor,
  331.     ["peripheral.getType"] = functionColor,
  332.     ["peripheral.getMethods"] = functionColor,
  333.     ["peripheral.call"] = functionColor,
  334.     ["peripheral.wrap"] = functionColor,
  335.     ["peripheral.find"] = functionColor,
  336.     ["peripheral.getNames"] = functionColor,
  337.    
  338.     --rednet
  339.     ["rednet"] = functionColor,
  340.     ["rednet.open"] = functionColor,
  341.     ["rednet.close"] = functionColor,
  342.     ["rednet.send"] = functionColor,
  343.     ["rednet.broadcast"] = functionColor,
  344.     ["rednet.receive"] = functionColor,
  345.     ["rednet.isOpen"] = functionColor,
  346.     ["rednet.host"] = functionColor,
  347.     ["rednet.unhost"] = functionColor,
  348.     ["rednet.lookup"] = functionColor,
  349.     ["rednet.run"] = functionColor,
  350.    
  351.     --redstone
  352.     ["redstone"] = functionColor,
  353.     ["redstone.getSides"] = functionColor,
  354.     ["redstone.getInput"] = functionColor,
  355.     ["redstone.setOutput"] = functionColor,
  356.     ["redstone.getOutput"] = functionColor,
  357.     ["redstone.getAnalogIutput"] = functionColor,
  358.     ["redstone.setAnalogOutput"] = functionColor,
  359.     ["redstone.getAnalogOutput"] = functionColor,
  360.     ["redstone.getBundledOutput"] = functionColor,
  361.     ["redstone.setBundledOutput"] = functionColor,
  362.     ["redstone.getBundledIutput"] = functionColor,
  363.     ["redstone.testBundledIutput"] = functionColor,
  364.    
  365.     --settings
  366.     ["settings"] = functionColor,
  367.     ["settings.set"] = functionColor,
  368.     ["settings.get"] = functionColor,
  369.     ["settings.unset"] = functionColor,
  370.     ["settings.clear"] = functionColor,
  371.     ["settings.getNames"] = functionColor,
  372.     ["settings.load"] = functionColor,
  373.     ["settings.save"] = functionColor,
  374.    
  375.     --shell
  376.     ["shell"] = functionColor,
  377.     ["shell.exit"] = functionColor,
  378.     ["shell.run"] = functionColor,
  379.     ["shell.dir"] = functionColor,
  380.     ["shell.setDir"] = functionColor,
  381.     ["shell.path"] = functionColor,
  382.     ["shell.setPath"] = functionColor,
  383.     ["shell.resolve"] = functionColor,
  384.     ["shell.resolveProgram"] = functionColor,
  385.     ["shell.aliases"] = functionColor,
  386.     ["shell.setAlias"] = functionColor,
  387.     ["shell.clearAlias"] = functionColor,
  388.     ["shell.programs"] = functionColor,
  389.     ["shell.getRunningProgram"] = functionColor,
  390.     ["shell.openTab"] = functionColor,
  391.     ["shell.switchTab"] = functionColor,
  392.     ["shell.complete"] = functionColor,
  393.     ["shell.completeProgram"] = functionColor,
  394.     ["shell.setCompletionFunction"] = functionColor,
  395.     ["shell.getCompletionInfo"] = functionColor,
  396.    
  397.     --string
  398.     ["string"] = functionColor,
  399.     ["string.byte"] = functionColor,
  400.     ["string.char"] = functionColor,
  401.     ["string.dump"] = functionColor,
  402.     ["string.find"] = functionColor,
  403.     ["string.format"] = functionColor,
  404.     ["string.gmatch"] = functionColor,
  405.     ["string.gsub"] = functionColor,
  406.     ["string.len"] = functionColor,
  407.     ["string.lower"] = functionColor,
  408.     ["string.upper"] = functionColor,
  409.     ["string.match"] = functionColor,
  410.     ["string.rep"] = functionColor,
  411.     ["string.reverse"] = functionColor,
  412.     ["string.sub"] = functionColor,
  413.    
  414.     --table
  415.     ["table"] = functionColor,
  416.     ["table.concat"] = functionColor,
  417.     ["table.insert"] = functionColor,
  418.     ["table.maxn"] = functionColor,
  419.     ["table.remove"] = functionColor,
  420.     ["table.sort"] = functionColor,
  421.    
  422.     --term
  423.     ["term"] = functionColor,
  424.     ["term.write"] = functionColor,
  425.     ["term.blit"] = functionColor,
  426.     ["term.clear"] = functionColor,
  427.     ["term.clearLine"] = functionColor,
  428.     ["term.getCursorPos"] = functionColor,
  429.     ["term.setCursorPos"] = functionColor,
  430.     ["term.setCursorBlink"] = functionColor,
  431.     ["term.isColor"] = functionColor,
  432.     ["term.getSize"] = functionColor,
  433.     ["term.scroll"] = functionColor,
  434.     ["term.redirect"] = functionColor,
  435.     ["term.current"] = functionColor,
  436.     ["term.native"] = functionColor,
  437.     ["term.setTextColor"] = functionColor,
  438.     ["term.getTextColor"] = functionColor,
  439.     ["term.setBackgroundColor"] = functionColor,
  440.     ["term.getBackgroundColor"] = functionColor,
  441.    
  442.     --textutils
  443.     ["textutils"] = functionColor,
  444.     ["textutils.slowWrite"] = functionColor,
  445.     ["textutils.slowPrint"] = functionColor,
  446.     ["textutils.formatTime"] = functionColor,
  447.     ["textutils.tabulate"] = functionColor,
  448.     ["textutils.pagedTabulate"] = functionColor,
  449.     ["textutils.pagedPrint"] = functionColor,
  450.     ["textutils.serialize"] = functionColor,
  451.     ["textutils.unserialize"] = functionColor,
  452.     ["textutils.serializeJSON"] = functionColor,
  453.     ["textutils.urlEncode"] = functionColor,
  454.     ["textutils.complete"] = functionColor,
  455.  
  456.     --turtle
  457.     ["turtle"] = functionColor,
  458.     ["turtle.craft"] = functionColor,
  459.     ["turtle.forward"] = functionColor,
  460.     ["turtle.back"] = functionColor,
  461.     ["turtle.up"] = functionColor,
  462.     ["turtle.down"] = functionColor,
  463.     ["turtle.turnLeft"] = functionColor,
  464.     ["turtle.turnRight"] = functionColor,
  465.     ["turtle.select"] = functionColor,
  466.     ["turtle.getSelectedSlot"] = functionColor,
  467.     ["turtle.getItemCount"] = functionColor,
  468.     ["turtle.getItemSpace"] = functionColor,
  469.     ["turtle.getItemDetail"] = functionColor,
  470.     ["turtle.equipLeft"] = functionColor,
  471.     ["turtle.equipRight"] = functionColor,
  472.     ["turtle.attack"] = functionColor,
  473.     ["turtle.attackUp"] = functionColor,
  474.     ["turtle.attackDown"] = functionColor,
  475.     ["turtle.dig"] = functionColor,
  476.     ["turtle.digUp"] = functionColor,
  477.     ["turtle.digDown"] = functionColor,
  478.     ["turtle.place"] = functionColor,
  479.     ["turtle.placeUp"] = functionColor,
  480.     ["turtle.placeDown"] = functionColor,
  481.     ["turtle.detect"] = functionColor,
  482.     ["turtle.detectUp"] = functionColor,
  483.     ["turtle.detectDown"] = functionColor,
  484.     ["turtle.inspect"] = functionColor,
  485.     ["turtle.inspectUp"] = functionColor,
  486.     ["turtle.inspectDown"] = functionColor,
  487.     ["turtle.compare"] = functionColor,
  488.     ["turtle.compareUp"] = functionColor,
  489.     ["turtle.compareDown"] = functionColor,
  490.     ["turtle.compareTo"] = functionColor,
  491.     ["turtle.drop"] = functionColor,
  492.     ["turtle.dropUp"] = functionColor,
  493.     ["turtle.dropDown"] = functionColor,
  494.     ["turtle.suck"] = functionColor,
  495.     ["turtle.suckUp"] = functionColor,
  496.     ["turtle.suckDown"] = functionColor,
  497.     ["turtle.refuel"] = functionColor,
  498.     ["turtle.getFuelLevel"] = functionColor,
  499.     ["turtle.getFuelLimit"] = functionColor,
  500.     ["turtle.transferTo"] = functionColor,
  501.    
  502.     --vector
  503.     ["vector"] = functionColor,
  504.     ["vector.new"] = functionColor,
  505.    
  506.     --lua
  507.     ["tonumber"] = functionColor,
  508.     ["tostring"] = functionColor,
  509.     ["print"] = functionColor,
  510.     ["pairs"] = functionColor,
  511.     ["ipairs"] = functionColor,
  512.     ["pcall"] = functionColor,
  513.     ["error"] = functionColor,
  514. }
  515.  
  516. local function tryWrite(sLine, regex, color)
  517.     local match = string.match(sLine, regex)
  518.    
  519.     if match then
  520.         if type(color) == "number" then
  521.             term.setTextColor(color)
  522.         else
  523.             term.setTextColor(color(match))
  524.         end
  525.        
  526.         term.write(match)
  527.         term.setTextColor(textColor)
  528.         return string.sub(sLine, string.len(match) + 1)
  529.     end
  530.    
  531.     return nil
  532. end
  533.  
  534. local function writeHighlighted(sLine)
  535.     function match(m)
  536.         if tKeywords[m] then
  537.             return tKeywords[m]
  538.         end
  539.         return textColor
  540.     end
  541.  
  542.     while string.len(sLine) > 0 do
  543.         sLine =
  544.             tryWrite(sLine, "^%-%-%[%[.-%]%]", commentColor) or
  545.             tryWrite(sLine, "^%-%-.*", commentColor) or
  546.             tryWrite(sLine, "^\".-[^\\]\"", stringColor) or
  547.             tryWrite(sLine, "^\'.-[^\\]\'", stringColor) or
  548.             tryWrite(sLine, "^\"\"", stringColor) or
  549.             tryWrite(sLine, "^''", stringColor) or
  550.             tryWrite(sLine, "^%[%[.-%]%]", stringColor) or
  551.             tryWrite(sLine, "^[.]+", operatorColor) or
  552.             tryWrite(sLine, "^[%d%.]+", numberColor) or
  553.             tryWrite(sLine, "^[%d%a%._]+", match) or
  554.             tryWrite(sLine, "^[^%w_.]", operatorColor)
  555.     end
  556. end
  557.  
  558. local function redrawText()
  559.     for y = 1,h - 1 do
  560.         term.setCursorPos(1 - scrollX, y)
  561.         term.clearLine()
  562.  
  563.         local sLine = tLines[y + scrollY]
  564.        
  565.         if sLine ~= nil then
  566.             writeHighlighted(sLine)
  567.         end
  568.     end
  569.    
  570.     term.setCursorPos(x - scrollX, y - scrollY)
  571. end
  572.  
  573. local function redrawLine(_nY)
  574.     local sLine = tLines[_nY]
  575.     term.setCursorPos(1 - scrollX, _nY - scrollY)
  576.     term.clearLine()
  577.     writeHighlighted(sLine)
  578.     term.setCursorPos(x - scrollX, _nY - scrollY)
  579. end
  580.  
  581. local function redrawMenu()
  582.     -- Clear line
  583.     term.setCursorPos(1, h)
  584.     term.clearLine()
  585.  
  586.     -- Draw line numbers
  587.     term.setCursorPos(w - string.len("Ln " .. y) + 1, h)
  588.     term.setTextColor(highlightColor)
  589.     term.write("Ln ")
  590.     term.setTextColor(textColor)
  591.     term.write(y)
  592.  
  593.     term.setCursorPos(1, h)
  594.    
  595.     if bMenu then
  596.         -- Draw menu
  597.         term.setTextColor(textColor)
  598.        
  599.         for nItem, sItem in pairs(tMenuItems) do
  600.             if nItem == nMenuItem then
  601.                 term.setTextColor(highlightColor)
  602.                 term.write("[")
  603.                 term.setTextColor(textColor)
  604.                 term.write(sItem)
  605.                 term.setTextColor(highlightColor)
  606.                 term.write("]")
  607.                 term.setTextColor(textColor)
  608.             else
  609.                 term.write(" " .. sItem .. " ")
  610.             end
  611.         end
  612.     else
  613.         -- Draw status
  614.         term.setTextColor(highlightColor)
  615.         term.write(sStatus)
  616.         term.setTextColor(textColor)
  617.     end
  618.  
  619.     -- Reset cursor
  620.     term.setCursorPos(x - scrollX, y - scrollY)
  621. end
  622.  
  623. local tMenuFuncs = {
  624.     Save = function ()
  625.         if bReadOnly then
  626.             sStatus = "Access denied"
  627.         else
  628.             local ok, err = save(sPath)
  629.            
  630.             if ok then
  631.                 sStatus="Press Ctrl to access menu"
  632.             else
  633.                 sStatus="Press Ctrl to access menu"
  634.             end
  635.         end
  636.        
  637.         redrawMenu()
  638.     end,
  639.     Print = function ()
  640.         local printer = peripheral.find("printer")
  641.        
  642.         if not printer then
  643.             sStatus = "No printer attached"
  644.             return
  645.         end
  646.  
  647.         local nPage = 0
  648.         local sName = fs.getName(sPath)
  649.        
  650.         if printer.getInkLevel() < 1 then
  651.             sStatus = "Printer out of ink"
  652.             return
  653.         elseif printer.getPaperLevel() < 1 then
  654.             sStatus = "Printer out of paper"
  655.             return
  656.         end
  657.  
  658.         local screenTerminal = term.current()
  659.         local printerTerminal = {
  660.             getCursorPos = printer.getCursorPos,
  661.             setCursorPos = printer.setCursorPos,
  662.             getSize = printer.getPageSize,
  663.             write = printer.write,
  664.         }
  665.         printerTerminal.scroll = function ()
  666.             if nPage == 1 then
  667.                 printer.setPageTitle(sName .. " (page " .. nPage .. ")")          
  668.             end
  669.            
  670.             while not printer.newPage() do
  671.                 if printer.getInkLevel() < 1 then
  672.                     sStatus = "Printer out of ink, please refill"
  673.                 elseif printer.getPaperLevel() < 1 then
  674.                     sStatus = "Printer out of paper, please refill"
  675.                 else
  676.                     sStatus = "Printer output tray full, please empty"
  677.                 end
  678.    
  679.                 term.redirect(screenTerminal)
  680.                 redrawMenu()
  681.                 term.redirect(printerTerminal)
  682.                
  683.                 local timer = os.startTimer(0.5)
  684.                 sleep(0.5)
  685.             end
  686.  
  687.             nPage = nPage + 1
  688.             if nPage == 1 then
  689.                 printer.setPageTitle(sName)
  690.             else
  691.                 printer.setPageTitle(sName .. " (page " .. nPage .. ")")
  692.             end
  693.         end
  694.        
  695.         bMenu = false
  696.         term.redirect(printerTerminal)
  697.        
  698.         local ok, error = pcall(function ()
  699.             term.scroll()
  700.             for n, sLine in ipairs(tLines) do
  701.                 print(sLine)
  702.             end
  703.         end)
  704.        
  705.         term.redirect(screenTerminal)
  706.        
  707.         if not ok then
  708.             print(error)
  709.         end
  710.        
  711.         while not printer.endPage() do
  712.             sStatus = "Printer output tray full, please empty"
  713.             redrawMenu()
  714.             sleep(0.5)
  715.         end
  716.        
  717.         bMenu = true
  718.            
  719.         if nPage > 1 then
  720.             sStatus = "Printed " .. nPage .. " Pages"
  721.         else
  722.             sStatus = "Printed 1 Page"
  723.         end
  724.        
  725.         redrawMenu()
  726.     end,
  727.     Exit = function ()
  728.         bRunning = false
  729.     end
  730. }
  731.  
  732. local function doMenuItem(_n)
  733.     tMenuFuncs[tMenuItems[_n]]()
  734.    
  735.     if bMenu then
  736.         bMenu = false
  737.         term.setCursorBlink(true)
  738.     end
  739.    
  740.     redrawMenu()
  741. end
  742.  
  743. local function setCursor(x, y)
  744.     local screenX = x - scrollX
  745.     local screenY = y - scrollY
  746.    
  747.     local bRedraw = false
  748.    
  749.     if screenX < 1 then
  750.         scrollX = x - 1
  751.         screenX = 1
  752.         bRedraw = true
  753.     elseif screenX > w then
  754.         scrollX = x - w
  755.         screenX = w
  756.         bRedraw = true
  757.     end
  758.    
  759.     if screenY < 1 then
  760.         scrollY = y - 1
  761.         screenY = 1
  762.         bRedraw = true
  763.     elseif screenY > h - 1 then
  764.         scrollY = y - (h - 1)
  765.         screenY = h - 1
  766.         bRedraw = true
  767.     end
  768.    
  769.     if bRedraw then
  770.         redrawText()
  771.     end
  772.     term.setCursorPos(screenX, screenY)
  773.    
  774.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
  775.     redrawMenu()
  776. end
  777.  
  778. -- Actual program functionality begins
  779. load(sPath)
  780.  
  781. term.setBackgroundColor(bgColor)
  782. term.clear()
  783. term.setCursorPos(x, y)
  784. term.setCursorBlink(true)
  785.  
  786. redrawText()
  787. redrawMenu()
  788.  
  789. -- Handle input
  790. while bRunning do
  791.     local sEvent, param, param2, param3 = os.pullEvent()
  792.    
  793.     if sEvent == "key" then
  794.         if param == keys.up then
  795.             -- Up
  796.             if not bMenu then
  797.                 if y > 1 then
  798.                     -- Move cursor up
  799.                     y = y - 1
  800.                     x = math.min(x, string.len(tLines[y]) + 1)
  801.                     setCursor(x, y)
  802.                 end
  803.             end
  804.         elseif param == keys.down then
  805.             -- Down
  806.             if not bMenu then
  807.                 -- Move cursor down
  808.                 if y < #tLines then
  809.                     y = y + 1
  810.                     x = math.min(x, string.len(tLines[y]) + 1)
  811.                     setCursor(x, y)
  812.                 end
  813.             end
  814.         elseif param == keys.tab then
  815.             -- Tab
  816.             if not bMenu and not bReadOnly then
  817.                 -- Indent line
  818.                 tLines[y] = "  " .. tLines[y]
  819.                 x = x + 2
  820.                 setCursor(x, y)
  821.                 redrawLine(y)
  822.             end
  823.         elseif param == keys.pageUp then
  824.             -- Page Up
  825.             if not bMenu then
  826.                 -- Move up a page
  827.                 if y - (h - 1) >= 1 then
  828.                     y = y - (h - 1)
  829.                 else
  830.                     y = 1
  831.                 end
  832.                 x = math.min(x, string.len(tLines[y]) + 1)
  833.                 setCursor(x, y)
  834.             end
  835.         elseif param == keys.pageDown then
  836.             -- Page Down
  837.             if not bMenu then
  838.                 -- Move down a page
  839.                 if y + (h - 1) <= #tLines then
  840.                     y = y + (h - 1)
  841.                 else
  842.                     y = #tLines
  843.                 end
  844.                 x = math.min(x, string.len(tLines[y]) + 1)
  845.                 setCursor(x, y)
  846.             end
  847.         elseif param == keys.home then
  848.             -- Home
  849.             if not bMenu then
  850.                 -- Move cursor to the beginning
  851.                 x = 1
  852.                 setCursor(x, y)
  853.             end
  854.         elseif param == keys["end"] then
  855.             -- End
  856.             if not bMenu then
  857.                 -- Move cursor to the end
  858.                 x = string.len(tLines[y]) + 1
  859.                 setCursor(x, y)
  860.             end
  861.         elseif param == keys.left then
  862.             -- Left
  863.             if not bMenu then
  864.                 if x > 1 then
  865.                     -- Move cursor left
  866.                     x = x - 1
  867.                 elseif x == 1 and y > 1 then
  868.                     x = string.len(tLines[y - 1]) + 1
  869.                     y = y - 1
  870.                 end
  871.                 setCursor(x, y)
  872.             else
  873.                 -- Move menu left
  874.                 nMenuItem = nMenuItem - 1
  875.                 if nMenuItem < 1 then
  876.                     nMenuItem = #tMenuItems
  877.                 end
  878.                 redrawMenu()
  879.             end
  880.         elseif param == keys.right then
  881.             -- Right
  882.             if not bMenu then
  883.                 if x < string.len(tLines[y]) + 1 then
  884.                     -- Move cursor right
  885.                     x = x + 1
  886.                 elseif x == string.len(tLines[y]) + 1 and y < #tLines then
  887.                     x = 1
  888.                     y = y + 1
  889.                 end
  890.                 setCursor(x, y)
  891.             else
  892.                 -- Move menu right
  893.                 nMenuItem = nMenuItem + 1
  894.                 if nMenuItem > #tMenuItems then
  895.                     nMenuItem = 1
  896.                 end
  897.                 redrawMenu()
  898.             end
  899.         elseif param == keys.delete then
  900.             -- Delete
  901.             if not bMenu and not bReadOnly then
  902.                 if  x < string.len(tLines[y]) + 1 then
  903.                     local sLine = tLines[y]
  904.                     tLines[y] = string.sub(sLine, 1, x - 1) .. string.sub(sLine, x + 1)
  905.                     redrawLine(y)
  906.                 elseif y < #tLines then
  907.                     tLines[y] = tLines[y] .. tLines[y + 1]
  908.                     table.remove(tLines, y + 1)
  909.                     redrawText()
  910.                     redrawMenu()
  911.                 end
  912.             end
  913.         elseif param == keys.backspace then
  914.             -- Backspace
  915.             if not bMenu and not bReadOnly then
  916.                 if x > 1 then
  917.                     -- Remove character
  918.                     local sLine = tLines[y]
  919.                     tLines[y] = string.sub(sLine, 1, x - 2) .. string.sub(sLine, x)
  920.                     redrawLine(y)
  921.            
  922.                     x = x - 1
  923.                     setCursor(x, y)
  924.                 elseif y > 1 then
  925.                     -- Remove newline
  926.                     local sPrevLen = string.len(tLines[y - 1])
  927.                     tLines[y - 1] = tLines[y - 1] .. tLines[y]
  928.                     table.remove(tLines, y)
  929.                     redrawText()
  930.                
  931.                     x = sPrevLen + 1
  932.                     y = y - 1
  933.                     setCursor(x, y)
  934.                 end
  935.             end
  936.         elseif param == keys.enter then
  937.             -- Enter
  938.             if not bMenu and not bReadOnly then
  939.                 -- Newline
  940.                 local sLine = tLines[y]
  941.                 local _, spaces = string.find(sLine, "^[ ]+")
  942.                
  943.                 if not spaces then
  944.                     spaces = 0
  945.                 end
  946.                
  947.                 tLines[y] = string.sub(sLine, 1, x - 1)
  948.                 table.insert(tLines, y + 1, string.rep(' ', spaces) .. string.sub(sLine, x))
  949.                 redrawText()
  950.            
  951.                 x = spaces + 1
  952.                 y = y + 1
  953.                 setCursor(x, y)
  954.             elseif bMenu then
  955.                 -- Menu selection
  956.                 doMenuItem(nMenuItem)
  957.             end
  958.         elseif param == keys.leftCtrl then
  959.             -- Menu toggle
  960.             bMenu = not bMenu
  961.            
  962.             if bMenu then
  963.                 term.setCursorBlink(false)
  964.             else
  965.                 term.setCursorBlink(true)
  966.             end
  967.            
  968.             redrawMenu()
  969.         end
  970.        
  971.     elseif sEvent == "char" then
  972.         if not bMenu and not bReadOnly then
  973.             -- Input text
  974.             local sLine = tLines[y]
  975.             tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x)
  976.             redrawLine(y)
  977.        
  978.             x = x + 1
  979.             setCursor(x, y)
  980.         elseif bMenu then
  981.             -- Select menu items
  982.             for n, sMenuItem in ipairs(tMenuItems) do
  983.                 if string.lower(string.sub(sMenuItem, 1, 1)) == string.lower(param) then
  984.                     doMenuItem(n)
  985.                     break
  986.                 end
  987.             end
  988.         end
  989.     elseif sEvent == "paste" then
  990.         if not bMenu and not bReadOnly then
  991.             -- Input text
  992.             local sLine = tLines[y]
  993.             tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x)
  994.             redrawLine(y)
  995.  
  996.             x = x + string.len(param)
  997.             setCursor(x, y)
  998.         end
  999.     elseif sEvent == "mouse_click" then
  1000.         if not bMenu then
  1001.             if param == 1 then
  1002.                 -- Left click
  1003.                 local cx, cy = param2, param3
  1004.                 if cy < h then
  1005.                     y = math.min(math.max(scrollY + cy, 1), #tLines)
  1006.                     x = math.min(math.max(scrollX + cx, 1), string.len(tLines[y]) + 1)
  1007.                     setCursor(x, y)
  1008.                 end
  1009.             end
  1010.         end
  1011.     elseif sEvent == "mouse_scroll" then
  1012.         if not bMenu then
  1013.             if param == -1 then
  1014.                 -- Scroll up
  1015.                 if scrollY > 0 then
  1016.                     -- Move cursor up
  1017.                     scrollY = scrollY - 1
  1018.                     redrawText()
  1019.                 end
  1020.             elseif param == 1 then
  1021.                 -- Scroll down
  1022.                 local nMaxScroll = #tLines - (h - 1)
  1023.                
  1024.                 if scrollY < nMaxScroll then
  1025.                     -- Move cursor down
  1026.                     scrollY = scrollY + 1
  1027.                     redrawText()
  1028.                 end
  1029.             end
  1030.         end
  1031.  
  1032.     elseif sEvent == "window_resize" then
  1033.         w, h = term.getSize()
  1034.         setCursor(x, y)
  1035.         redrawMenu()
  1036.         redrawText()
  1037.     end
  1038. end
  1039.  
  1040. -- Cleanup
  1041. term.clear()
  1042. term.setCursorBlink(false)
  1043. term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement