Advertisement
Alakazard12

Better Edit

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