kizz12

edit

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