Leo_Verto

cedit

May 7th, 2013
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.74 KB | None | 0 0
  1. -- Get file to edit
  2. local tArgs = { ... }
  3. if #tArgs == 0 then
  4.     print( "Usage: edit <path>" )
  5.     return
  6. end
  7.  
  8. local tfHighlighting = {false}
  9.  
  10. -- Error checking
  11. local sPath = shell.resolve( tArgs[1] )
  12. local bReadOnly = fs.isReadOnly( sPath )
  13. if fs.exists( sPath ) and fs.isDir( sPath ) then
  14.     print( "Cannot edit a directory." )
  15.     return
  16. end
  17.  
  18. local workstring = tArgs[2]
  19. if workstring ~= nil then
  20.   if string.find(workstring, "s") then
  21.     tfHighlighting[1] = true
  22.   end
  23. else
  24.  
  25. end
  26.  
  27. -- Import API list
  28. local tApis = {}
  29. for k,v in pairs( _G ) do
  30.     if type(k) == "string" and type(v) == "table" and k ~= "_G" then
  31.         table.insert( tApis, k )
  32.     end
  33. end
  34.  
  35. local x,y = 1,1
  36. local w,h = term.getSize()
  37. local scrollX, scrollY = 0,0
  38.  
  39. local tLines = {}
  40. local bRunning = true
  41.  
  42. -- Colours
  43. local topicColour, easterEgg, specialLight, highlightColour, keywordColour, commentColour, textColour, bgColour
  44. if term.isColour() then
  45.     bgColour = colours.black
  46.     textColour = colours.white
  47.     highlightColour = colours.yellow
  48.     keywordColour = colours.yellow
  49.     commentColour = colours.lime
  50.     stringColour = colours.red
  51.  specialLight = colours.cyan
  52.  easterEgg = colours.orange
  53.  topicColour = colours.grey
  54. else
  55.     bgColour = colours.black
  56.     textColour = colours.white
  57.     highlightColour = colours.white
  58.     keywordColour = colours.white
  59.     commentColour = colours.white
  60.     stringColour = colours.white
  61.  specialLight = colours.white
  62.  easterEgg = colours.white
  63.  topicColour = colours.black
  64. end
  65.  
  66. -- Menus
  67. local bMenu = false
  68. local nMenuItem = 1
  69. local tMenuItems = {"Save", "Exit", "Print", "Cancel"}
  70. local sStatus = "Press f1 to access menu"
  71.  
  72. local function load(_sPath)
  73.     tLines = {}
  74.     if fs.exists( _sPath ) then
  75.         local file = io.open( _sPath, "r" )
  76.         local sLine = file:read()
  77.         while sLine do
  78.             table.insert( tLines, sLine )
  79.             sLine = file:read()
  80.         end
  81.         file:close()
  82.     end
  83.    
  84.     if #tLines == 0 then
  85.         table.insert( tLines, "" )
  86.     end
  87. end
  88.  
  89. local function save( _sPath )
  90.     -- Create intervening folder
  91.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
  92.     if not fs.exists( sDir ) then
  93.         fs.makeDir( sDir )
  94.     end
  95.  
  96.     -- Save
  97.     local file = nil
  98.     local function innerSave()
  99.         file = fs.open( _sPath, "w" )
  100.         if file then
  101.             for n, sLine in ipairs( tLines ) do
  102.                 file.write( sLine .. "\n" )
  103.             end
  104.         else
  105.             error( "Failed to open ".._sPath )
  106.         end
  107.     end
  108.    
  109.     local ok = pcall( innerSave )
  110.     if file then
  111.         file.close()
  112.     end
  113.     return ok
  114. end
  115.  
  116. local tKeywords = {
  117.     ["and"] = true,
  118.     ["break"] = true,
  119.     ["do"] = true,
  120.     ["else"] = true,
  121.     ["elseif"] = true,
  122.     ["end"] = true,
  123.     ["false"] = true,
  124.     ["for"] = true,
  125.     ["function"] = true,
  126.     ["if"] = true,
  127.     ["in"] = true,
  128.     ["local"] = true,
  129.     ["nil"] = true,
  130.     ["not"] = true,
  131.     ["or"] = true,
  132.     ["repeat"] = true,
  133.     ["return"] = true,
  134.     ["then"] = true,
  135.     ["true"] = true,
  136.     ["until"]= true,
  137.     ["while"] = true,
  138. }
  139.  
  140. local tspecial = {}
  141.  
  142. for k, v in next, tApis, nil do
  143. tspecial[v] = true
  144. end
  145.  
  146. local tEasterEgg = {
  147.  ["potato"] = true,
  148.  ["potatoes"] = true,
  149.  ["reinei"] = true,
  150.  ["hackingroelz"] = true,
  151.  ["cruor"] = true,
  152.  ["leo"] = true,
  153.  ["verto"] = true,
  154.  ["leo_verto"] = true
  155. }
  156.  
  157. local function tryWrite( sLine, regex, colour )
  158.     local match = string.match( sLine, regex )
  159.     if match then
  160.         if type(colour) == "number" then
  161.             term.setTextColour( colour )
  162.         else
  163.             term.setTextColour( colour(match) )
  164.         end
  165.         term.write( match )
  166.         term.setTextColour( textColour )
  167.         return string.sub( sLine, string.len(match) + 1 )
  168.     end
  169.     return nil
  170. end
  171.  
  172. local function writeHighlighted( sLine )
  173.     while string.len(sLine) > 0 do
  174.   if tfHighlighting[1] == false then   
  175.          sLine =
  176.              tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
  177.              tryWrite( sLine, "^%-%-.*", commentColour ) or
  178.              tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
  179.              tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
  180.              tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
  181.              tryWrite( sLine, "^[%w_]+", function( match )
  182.                  if tKeywords[ match ] then
  183.                      return keywordColour
  184.                 end
  185.      if tspecial[match] then
  186.       return specialLight
  187.      end
  188.      if tEasterEgg[match] then
  189.       return easterEgg
  190.      end
  191.                  return textColour
  192.             end ) or
  193.              tryWrite( sLine, "^[^%w_]", textColour )
  194.   else
  195.    sLine=
  196.     tryWrite( sLine, "^%$.-%$", topicColour) or
  197.     tryWrite( sLine, "^[%w_]", textColour) or
  198.     tryWrite( sLine, "^[^%w_]", textColour)
  199.   end
  200.     end
  201. end
  202.  
  203. local function redrawText()
  204.     for y=1,h-1 do
  205.         term.setCursorPos( 1 - scrollX, y )
  206.         term.clearLine()
  207.  
  208.         local sLine = tLines[ y + scrollY ]
  209.         if sLine ~= nil then
  210.             writeHighlighted( sLine )
  211.         end
  212.     end
  213.     term.setCursorPos( x - scrollX, y - scrollY )
  214. end
  215.  
  216. local function redrawLine(_nY)
  217.     local sLine = tLines[_nY]
  218.     term.setCursorPos( 1 - scrollX, _nY - scrollY )
  219.     term.clearLine()
  220.     writeHighlighted( sLine )
  221.     term.setCursorPos( x - scrollX, _nY - scrollY )
  222. end
  223.  
  224. local function setLeftStatus()
  225. end
  226.  
  227. local function redrawMenu()
  228.   term.setCursorPos( 1, h )
  229.     term.clearLine()
  230.  
  231.     local sLeft, sRight
  232.     local nLeftColour, nLeftHighlight1, nLeftHighlight2
  233.     if bMenu then
  234.         local sMenu = ""
  235.         for n,sItem in ipairs( tMenuItems ) do
  236.             if n == nMenuItem then
  237.                 nLeftHighlight1 = sMenu:len() + 1
  238.                 nLeftHighlight2 = sMenu:len() + sItem:len() + 2
  239.             end
  240.             sMenu = sMenu.." "..sItem.." "
  241.         end
  242.         sLeft = sMenu
  243.         nLeftColour = textColour
  244.     else
  245.         sLeft = sStatus
  246.         nLeftColour = highlightColour
  247.     end
  248.    
  249.     -- Left goes last so that it can overwrite the line numbers.
  250.     sRight = "Ln "..y
  251.     term.setTextColour( highlightColour )
  252.     term.setCursorPos( w-sRight:len() + 1, h )
  253.     term.write(sRight)
  254.  
  255.     sRight = tostring(y)
  256.     term.setTextColour( textColour )
  257.     term.setCursorPos( w-sRight:len() + 1, h )
  258.     term.write(sRight)
  259.  
  260.     if sLeft then
  261.         term.setCursorPos( 1, h )
  262.         term.setTextColour( nLeftColour )
  263.         term.write(sLeft)      
  264.         if nLeftHighlight1 then
  265.             term.setTextColour( highlightColour )
  266.             term.setCursorPos( nLeftHighlight1, h )
  267.             term.write( "[" )
  268.             term.setCursorPos( nLeftHighlight2, h )
  269.             term.write( "]" )
  270.         end
  271.         term.setTextColour( textColour )
  272.     end
  273.    
  274.     -- Cursor highlights selection
  275.     term.setCursorPos( x - scrollX, y - scrollY )
  276. end
  277.  
  278. local tMenuFuncs = {
  279.     Save=function()
  280.         if bReadOnly then
  281.             sStatus = "Access denied"
  282.         else
  283.             local ok, err = save( sPath )
  284.             if ok then
  285.                 sStatus="Saved to "..sPath
  286.             else
  287.                 sStatus="Error saving to "..sPath
  288.             end
  289.         end
  290.         redrawMenu()
  291.     end,
  292.     Print=function()
  293.         local sPrinterSide = nil
  294.         for n,sSide in ipairs(rs.getSides()) do
  295.             if peripheral.isPresent(sSide) and peripheral.getType(sSide) == "printer" then
  296.                 sPrinterSide = sSide
  297.                 break
  298.             end
  299.         end
  300.        
  301.         if not sPrinterSide then
  302.             sStatus = "No printer attached"
  303.             return
  304.         end
  305.  
  306.         local nPage = 0
  307.         local sName = fs.getName( sPath )
  308.         local printer = peripheral.wrap(sPrinterSide)
  309.         if printer.getInkLevel() < 1 then
  310.             sStatus = "Printer out of ink"
  311.             return
  312.         elseif printer.getPaperLevel() < 1 then
  313.             sStatus = "Printer out of paper"
  314.             return
  315.         end
  316.        
  317.         local terminal = {
  318.             getCursorPos = printer.getCursorPos,
  319.             setCursorPos = printer.setCursorPos,
  320.             getSize = printer.getPageSize,
  321.             write = printer.write,
  322.         }
  323.         terminal.scroll = function()
  324.             if nPage == 1 then
  325.                 printer.setPageTitle( sName.." (page "..nPage..")" )           
  326.             end
  327.            
  328.             while not printer.newPage() do
  329.                 if printer.getInkLevel() < 1 then
  330.                     sStatus = "Printer out of ink, please refill"
  331.                 elseif printer.getPaperLevel() < 1 then
  332.                     sStatus = "Printer out of paper, please refill"
  333.                 else
  334.                     sStatus = "Printer output tray full, please empty"
  335.                 end
  336.    
  337.                 term.restore()
  338.                 redrawMenu()
  339.                 term.redirect( terminal )
  340.                
  341.                 local timer = os.startTimer(0.5)
  342.                 sleep(0.5)
  343.             end
  344.  
  345.             nPage = nPage + 1
  346.             if nPage == 1 then
  347.                 printer.setPageTitle( sName )
  348.             else
  349.                 printer.setPageTitle( sName.." (page "..nPage..")" )
  350.             end
  351.         end
  352.        
  353.         bMenu = false
  354.         term.redirect( terminal )
  355.         local ok, error = pcall( function()
  356.             term.scroll()
  357.             for n, sLine in ipairs( tLines ) do
  358.                 print( sLine )
  359.             end
  360.         end )
  361.         term.restore()
  362.         if not ok then
  363.             print( error )
  364.         end
  365.        
  366.         while not printer.endPage() do
  367.             sStatus = "Printer output tray full, please empty"
  368.             redrawMenu()
  369.             sleep( 0.5 )
  370.         end
  371.         bMenu = true
  372.            
  373.         if nPage > 1 then
  374.             sStatus = "Printed "..nPage.." Pages"
  375.         else
  376.             sStatus = "Printed 1 Page"
  377.         end
  378.         redrawMenu()
  379.     end,
  380.     Exit=function()
  381.         bRunning = false
  382.     end,
  383.  Cancel=function()
  384.   sStatus = "Press f1 to access menu"
  385.  end
  386. }
  387.  
  388. local function doMenuItem( _n )
  389.     tMenuFuncs[tMenuItems[_n]]()
  390.     if bMenu then
  391.         bMenu = false
  392.         term.setCursorBlink( true )
  393.     end
  394.     redrawMenu()
  395. end
  396.  
  397. local function setCursor( x, y )
  398.     local screenX = x - scrollX
  399.     local screenY = y - scrollY
  400.    
  401.     local bRedraw = false
  402.     if screenX < 1 then
  403.         scrollX = x - 1
  404.         screenX = 1
  405.         bRedraw = true
  406.     elseif screenX > w then
  407.         scrollX = x - w
  408.         screenX = w
  409.         bRedraw = true
  410.     end
  411.    
  412.     if screenY < 1 then
  413.         scrollY = y - 1
  414.         screenY = 1
  415.         bRedraw = true
  416.     elseif screenY > h-1 then
  417.         scrollY = y - (h-1)
  418.         screenY = h-1
  419.         bRedraw = true
  420.     end
  421.    
  422.     if bRedraw then
  423.         redrawText()
  424.     end
  425.     term.setCursorPos( screenX, screenY )
  426.    
  427.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
  428.     redrawMenu()
  429. end
  430.  
  431. -- Actual program functionality begins
  432. load(sPath)
  433.  
  434. term.setBackgroundColour( bgColour )
  435. term.clear()
  436. term.setCursorPos(x,y)
  437. term.setCursorBlink( true )
  438.  
  439. redrawText()
  440. redrawMenu()
  441.  
  442. -- Handle input
  443. while bRunning do
  444.     local sEvent, param, param2, param3 = os.pullEvent()
  445.     if sEvent == "key" then
  446.         if param == keys.up then
  447.             -- Up
  448.             if not bMenu then
  449.                 if y > 1 then
  450.                     -- Move cursor up
  451.                     y = y - 1
  452.                     x = math.min( x, string.len( tLines[y] ) + 1 )
  453.                     setCursor( x, y )
  454.                 end
  455.             end
  456.         elseif param == keys.down then
  457.             -- Down
  458.             if not bMenu then
  459.                 -- Move cursor down
  460.                 if y < #tLines then
  461.                     y = y + 1
  462.                     x = math.min( x, string.len( tLines[y] ) + 1 )
  463.                     setCursor( x, y )
  464.                 end
  465.             end
  466.         elseif param == keys.tab then
  467.             -- Tab
  468.             if not bMenu then
  469.                 local sLine = tLines[y]
  470.  
  471.                 -- Indent line
  472.                 -- IN CASE OF INSERT TAB IN PLACE:
  473.                 -- tLines[y] = string.sub(sLine,1,x-1) .. "  " .. string.sub(sLine,x)
  474.                 tLines[y]="  "..tLines[y]
  475.                 x = x + 2
  476.                 setCursor( x, y )
  477.                 redrawLine(y)
  478.             end
  479.         elseif param == keys.pageUp then
  480.             -- Page Up
  481.             if not bMenu then
  482.                 -- Move up a page
  483.                 local sx,sy=term.getSize()
  484.                 y=y-sy-1
  485.                 if y<1 then y=1 end
  486.                 x = math.min( x, string.len( tLines[y] ) + 1 )
  487.                 setCursor( x, y )
  488.             end
  489.         elseif param == keys.pageDown then
  490.             -- Page Down
  491.             if not bMenu then
  492.                 -- Move down a page
  493.                 local sx,sy=term.getSize()
  494.                 if y<#tLines-sy-1 then
  495.                     y = y+sy-1
  496.                 else
  497.                     y = #tLines
  498.                 end
  499.                 x = math.min( x, string.len( tLines[y] ) + 1 )
  500.                 setCursor( x, y )
  501.             end
  502.         elseif param == keys.home then
  503.             -- Home
  504.             if not bMenu then
  505.                 -- Move cursor to the beginning
  506.                 x=1
  507.                 setCursor(x,y)
  508.             end
  509.         elseif param == keys["end"] then
  510.             -- End
  511.             if not bMenu then
  512.                 -- Move cursor to the end
  513.                 x = string.len( tLines[y] ) + 1
  514.                 setCursor(x,y)
  515.             end
  516.         elseif param == keys.left then
  517.             -- Left
  518.             if not bMenu then
  519.                 if x > 1 then
  520.                     -- Move cursor left
  521.                     x = x - 1
  522.                 elseif x==1 and y>1 then
  523.                     x = string.len( tLines[y-1] ) + 1
  524.                     y = y - 1
  525.                 end
  526.                 setCursor( x, y )
  527.             else
  528.                 -- Move menu left
  529.                 nMenuItem = nMenuItem - 1
  530.                 if nMenuItem < 1 then
  531.                     nMenuItem = #tMenuItems
  532.                 end
  533.                 redrawMenu()
  534.             end
  535.         elseif param == keys.right then
  536.             -- Right
  537.             if not bMenu then
  538.                 if x < string.len( tLines[y] ) + 1 then
  539.                     -- Move cursor right
  540.                     x = x + 1
  541.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
  542.                     x = 1
  543.                     y = y + 1
  544.                 end
  545.                 setCursor( x, y )
  546.             else
  547.                 -- Move menu right
  548.                 nMenuItem = nMenuItem + 1
  549.                 if nMenuItem > #tMenuItems then
  550.                     nMenuItem = 1
  551.                 end
  552.                 redrawMenu()
  553.             end
  554.         elseif param == keys.delete then
  555.             -- Delete
  556.             if not bMenu then
  557.                 if  x < string.len( tLines[y] ) + 1 then
  558.                     local sLine = tLines[y]
  559.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  560.                     redrawLine(y)
  561.                 elseif y<#tLines then
  562.                     tLines[y] = tLines[y] .. tLines[y+1]
  563.                     table.remove( tLines, y+1 )
  564.                     redrawText()
  565.                     redrawMenu()
  566.                 end
  567.             end
  568.         elseif param == keys.backspace then
  569.             -- Backspace
  570.             if not bMenu then
  571.                 if x > 1 then
  572.                     -- Remove character
  573.                     local sLine = tLines[y]
  574.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  575.                     redrawLine(y)
  576.            
  577.                     x = x - 1
  578.                     setCursor( x, y )
  579.                 elseif y > 1 then
  580.                     -- Remove newline
  581.                     local sPrevLen = string.len( tLines[y-1] )
  582.                     tLines[y-1] = tLines[y-1] .. tLines[y]
  583.                     table.remove( tLines, y )
  584.                     redrawText()
  585.                
  586.                     x = sPrevLen + 1
  587.                     y = y - 1
  588.                     setCursor( x, y )
  589.                 end
  590.             end
  591.         elseif param == keys.enter then
  592.             -- Enter
  593.             if not bMenu then
  594.                 -- Newline
  595.                 local sLine = tLines[y]
  596.                 local _,spaces=string.find(sLine,"^[ ]+")
  597.                 if not spaces then
  598.                     spaces=0
  599.                 end
  600.                 tLines[y] = string.sub(sLine,1,x-1)
  601.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
  602.                 redrawText()
  603.            
  604.                 x = spaces+1
  605.                 y = y + 1
  606.                 setCursor( x, y )
  607.             else
  608.                 -- Menu selection
  609.                 doMenuItem( nMenuItem )
  610.             end
  611.         elseif param == 59 then
  612.             -- Menu toggle
  613.             bMenu = not bMenu
  614.             if bMenu then
  615.                 term.setCursorBlink( false )
  616.                 nMenuItem = 1
  617.             else
  618.                 term.setCursorBlink( true )
  619.             end
  620.             redrawMenu()
  621.         end
  622.        
  623.     elseif sEvent == "char" then
  624.         if not bMenu then
  625.             -- Input text
  626.             local sLine = tLines[y]
  627.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  628.             redrawLine(y)
  629.        
  630.             x = x + string.len( param )
  631.             setCursor( x, y )
  632.         else
  633.             -- Select menu items
  634.             for n,sMenuItem in ipairs( tMenuItems ) do
  635.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
  636.                     doMenuItem( n )
  637.                     break
  638.                 end
  639.             end
  640.         end
  641.        
  642.     elseif sEvent == "mouse_click" then
  643.     if param == 1 then
  644.       -- Left click
  645.             local cx,cy = param2, param3
  646.       if bMenu then
  647.         local nMenuLength = 0
  648.         for i=1, #tMenuItems do
  649.           nMenuLength = nMenuLength + tMenuItems[i]:len() + 3
  650.         end
  651.           if cy == h and cx <= nMenuLength then
  652.             local checkx = 2
  653.             for i=1, #tMenuItems do
  654.               if cx >= (checkx - 1) and cx <= (checkx + tMenuItems[i]:len() + 1) then
  655.                 if nMenuItem == i then
  656.                   doMenuItem(nMenuItem)
  657.                 else
  658.                   nMenuItem = i
  659.                 end
  660.                 redrawMenu()
  661.                 break
  662.               end
  663.               checkx = checkx + tMenuItems[i]:len() + 3
  664.             end
  665.           else
  666.             bMenu = false
  667.             nMenuItem = 1
  668.           end
  669.       elseif cy == h and cx < sStatus:len() then
  670.         bMenu = true
  671.         redrawMenu()
  672.       else
  673.         y = math.min( math.max( scrollY + cy, 1 ), #tLines )
  674.                 x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
  675.                 setCursor( x, y )
  676.             end
  677.     end
  678.        
  679.     elseif sEvent == "mouse_scroll" then
  680.         if not bMenu then
  681.             if param == -1 then
  682.                 -- Scroll up
  683.                 if scrollY > 0 then
  684.                     -- Move cursor up
  685.                     scrollY = scrollY - 1
  686.                     redrawText()
  687.                 end
  688.            
  689.             elseif param == 1 then
  690.                 -- Scroll down
  691.                 local nMaxScroll = #tLines - (h-1)
  692.                 if scrollY < nMaxScroll then
  693.                     -- Move cursor down
  694.                     scrollY = scrollY + 1
  695.                     redrawText()
  696.                 end
  697.                
  698.             end
  699.         end
  700.     end
  701. end
  702.  
  703. -- Cleanup
  704. term.clear()
  705. term.setCursorBlink( false )
  706. term.setCursorPos( 1, 1 )
Advertisement
Add Comment
Please, Sign In to add comment