AndreSoYeah

edit

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