SHARE
TWEET

Edit

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