Advertisement
lewislovesgames

Custom Edit For ComputerCraft

Jan 7th, 2015
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.84 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.  
  16. local x,y = 1,1
  17. local w,h = term.getSize()
  18. local scrollX, scrollY = 0,0
  19.  
  20. local tLines = {}
  21. 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.green
  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
  45. if bReadOnly then
  46.         tMenuItems = { "Exit", "Print" }
  47. else
  48.         tMenuItems = { "Save", "Exit", "Print" }
  49. end
  50.        
  51. local sStatus = "Press Ctrl to access menu"
  52.  
  53. local function load( _sPath )
  54.         tLines = {}
  55.         if fs.exists( _sPath ) then
  56.                 local file = io.open( _sPath, "r" )
  57.                 local sLine = file:read()
  58.                 while sLine do
  59.                         table.insert( tLines, sLine )
  60.                         sLine = file:read()
  61.                 end
  62.                 file:close()
  63.         end
  64.        
  65.         if #tLines == 0 then
  66.                 table.insert( tLines, "" )
  67.         end
  68. end
  69.  
  70. local function save( _sPath )
  71.         -- Create intervening folder
  72.         local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
  73.         if not fs.exists( sDir ) then
  74.                 fs.makeDir( sDir )
  75.         end
  76.  
  77.         -- Save
  78.         local file = nil
  79.         local function innerSave()
  80.                 file = fs.open( _sPath, "w" )
  81.                 if file then
  82.                         for n, sLine in ipairs( tLines ) do
  83.                                 file.write( sLine .. "\n" )
  84.                         end
  85.                 else
  86.                         error( "Failed to open ".._sPath )
  87.                 end
  88.         end
  89.        
  90.         local ok = pcall( innerSave )
  91.         if file then
  92.                 file.close()
  93.         end
  94.         return ok
  95. end
  96.  
  97. local tKeywords = {
  98.         ["and"] = true,
  99.         ["break"] = true,
  100.         ["do"] = true,
  101.         ["else"] = true,
  102.         ["elseif"] = true,
  103.         ["end"] = true,
  104.         ["false"] = true,
  105.         ["for"] = true,
  106.         ["function"] = true,
  107.         ["if"] = true,
  108.         ["in"] = true,
  109.         ["local"] = true,
  110.         ["nil"] = true,
  111.         ["not"] = true,
  112.         ["or"] = true,
  113.         ["repeat"] = true,
  114.         ["return"] = true,
  115.         ["then"] = true,
  116.         ["true"] = true,
  117.         ["until"]= true,
  118.         ["while"] = true,
  119.         ["os"] = true,
  120.         ["fs"] = true,
  121.         ["io"] = true,
  122.         ["colors"] = true,
  123.         ["colours"] = true,
  124.         ["parallel"] = true,
  125.         ["term"] = true,
  126.         ["shell"] = true,
  127.         ["redstone"] = true,
  128.         ["rs"] = true,
  129.         ["http"] = true,
  130.         ["rednet"] = true,
  131.         ["textutils"] = true,
  132.         ["math"] = true,
  133.         ["disk"] = true,
  134.         ["table"] = true,
  135.         ["coroutine"] = true,
  136.         ["bit"] = true,
  137.         ["help"] = true,
  138.         ["string"] = true,
  139. }
  140.  
  141. local function tryWrite( sLine, regex, colour )
  142.         local match = string.match( sLine, regex )
  143.         if match then
  144.                 if type(colour) == "number" then
  145.                         term.setTextColour( colour )
  146.                 else
  147.                         term.setTextColour( colour(match) )
  148.                 end
  149.                 term.write( match )
  150.                 term.setTextColour( textColour )
  151.                 return string.sub( sLine, string.len(match) + 1 )
  152.         end
  153.         return nil
  154. end
  155.  
  156. local function writeHighlighted( sLine )
  157.         while string.len(sLine) > 0 do
  158.                 sLine =
  159.                         tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
  160.                         tryWrite( sLine, "^%-%-.*", commentColour ) or
  161.                         tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
  162.                         tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
  163.                         tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
  164.                         tryWrite( sLine, "^[%w_]+", function( match )
  165.                                 if tKeywords[ match ] then
  166.                                         return keywordColour
  167.                                 end
  168.                                 return textColour
  169.                         end ) or
  170.                         tryWrite( sLine, "^[^%w_]", textColour )
  171.         end
  172. end
  173.  
  174. local function redrawText()
  175.         for y=1,h-1 do
  176.                 term.setCursorPos( 1 - scrollX, y )
  177.                 term.clearLine()
  178.  
  179.                 local sLine = tLines[ y + scrollY ]
  180.                 if sLine ~= nil then
  181.                         writeHighlighted( sLine )
  182.                 end
  183.         end
  184.         term.setCursorPos( x - scrollX, y - scrollY )
  185. end
  186.  
  187. local function redrawLine(_nY)
  188.         local sLine = tLines[_nY]
  189.         term.setCursorPos( 1 - scrollX, _nY - scrollY )
  190.         term.clearLine()
  191.         writeHighlighted( sLine )
  192.         term.setCursorPos( x - scrollX, _nY - scrollY )
  193. end
  194.  
  195. local function redrawMenu()
  196.     -- Clear line
  197.     term.setCursorPos( 1, h )
  198.         term.clearLine()
  199.  
  200.     -- Draw line numbers
  201.     term.setCursorPos( w - string.len( "Ln "..y ) + 1, h )
  202.     term.setTextColour( highlightColour )
  203.     term.write( "Ln " )
  204.     term.setTextColour( textColour )
  205.     term.write( y )
  206.  
  207.     term.setCursorPos( 1, h )
  208.         if bMenu then
  209.         -- Draw menu
  210.                 term.setTextColour( textColour )
  211.                 for nItem,sItem in pairs( tMenuItems ) do
  212.                         if nItem == nMenuItem then
  213.                                 term.setTextColour( highlightColour )
  214.                                 term.write( "[" )
  215.                                 term.setTextColour( textColour )
  216.                                 term.write( sItem )
  217.                                 term.setTextColour( highlightColour )
  218.                                 term.write( "]" )
  219.                         term.setTextColour( textColour )
  220.                         else
  221.                                 term.write( " "..sItem.." " )
  222.                         end
  223.                 end
  224.     else
  225.         -- Draw status
  226.         term.setTextColour( highlightColour )
  227.         term.write( sStatus )
  228.         term.setTextColour( textColour )
  229.     end
  230.  
  231.         -- Reset cursor
  232.         term.setCursorPos( x - scrollX, y - scrollY )
  233. end
  234.  
  235. local tMenuFuncs = {
  236.         Save=function()
  237.                 if bReadOnly then
  238.                         sStatus = "Access denied"
  239.                 else
  240.                         local ok, err = save( sPath )
  241.                         if ok then
  242.                                 sStatus="Saved to "..sPath
  243.                         else
  244.                                 sStatus="Error saving to "..sPath
  245.                         end
  246.                 end
  247.                 redrawMenu()
  248.         end,
  249.         Print=function()
  250.                 local printer = peripheral.find( "printer" )
  251.                 if not printer then
  252.                         sStatus = "No printer attached"
  253.                         return
  254.                 end
  255.  
  256.                 local nPage = 0
  257.                 local sName = fs.getName( sPath )
  258.                 if printer.getInkLevel() < 1 then
  259.                         sStatus = "Printer out of ink"
  260.                         return
  261.                 elseif printer.getPaperLevel() < 1 then
  262.                         sStatus = "Printer out of paper"
  263.                         return
  264.                 end
  265.  
  266.                 local screenTerminal = term.current()
  267.                 local printerTerminal = {
  268.                         getCursorPos = printer.getCursorPos,
  269.                         setCursorPos = printer.setCursorPos,
  270.                         getSize = printer.getPageSize,
  271.                         write = printer.write,
  272.                 }
  273.                 printerTerminal.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.redirect( screenTerminal )
  288.                                 redrawMenu()
  289.                                 term.redirect( printerTerminal )
  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( printerTerminal )
  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.redirect( screenTerminal )
  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 and not bReadOnly then
  416.                                 -- Indent line
  417.                                 tLines[y]="  "..tLines[y]
  418.                                 x = x + 2
  419.                                 setCursor( x, y )
  420.                                 redrawLine(y)
  421.                         end
  422.                 elseif param == keys.pageUp then
  423.                         -- Page Up
  424.                         if not bMenu then
  425.                                 -- Move up a page
  426.                                 if y - (h - 1) >= 1 then
  427.                                         y = y - (h - 1)
  428.                                 else
  429.                                         y = 1
  430.                                 end
  431.                                 x = math.min( x, string.len( tLines[y] ) + 1 )
  432.                                 setCursor( x, y )
  433.                         end
  434.                 elseif param == keys.pageDown then
  435.                         -- Page Down
  436.                         if not bMenu then
  437.                                 -- Move down a page
  438.                                 if y + (h - 1) <= #tLines then
  439.                                         y = y + (h - 1)
  440.                                 else
  441.                                         y = #tLines
  442.                                 end
  443.                                 x = math.min( x, string.len( tLines[y] ) + 1 )
  444.                                 setCursor( x, y )
  445.                         end
  446.                 elseif param == keys.home then
  447.                         -- Home
  448.                         if not bMenu then
  449.                                 -- Move cursor to the beginning
  450.                                 x=1
  451.                                 setCursor(x,y)
  452.                         end
  453.                 elseif param == keys["end"] then
  454.                         -- End
  455.                         if not bMenu then
  456.                                 -- Move cursor to the end
  457.                                 x = string.len( tLines[y] ) + 1
  458.                                 setCursor(x,y)
  459.                         end
  460.                 elseif param == keys.left then
  461.                         -- Left
  462.                         if not bMenu then
  463.                                 if x > 1 then
  464.                                         -- Move cursor left
  465.                                         x = x - 1
  466.                                 elseif x==1 and y>1 then
  467.                                         x = string.len( tLines[y-1] ) + 1
  468.                                         y = y - 1
  469.                                 end
  470.                                 setCursor( x, y )
  471.                         else
  472.                                 -- Move menu left
  473.                                 nMenuItem = nMenuItem - 1
  474.                                 if nMenuItem < 1 then
  475.                                         nMenuItem = #tMenuItems
  476.                                 end
  477.                                 redrawMenu()
  478.                         end
  479.                 elseif param == keys.right then
  480.                         -- Right
  481.                         if not bMenu then
  482.                                 if x < string.len( tLines[y] ) + 1 then
  483.                                         -- Move cursor right
  484.                                         x = x + 1
  485.                                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
  486.                                         x = 1
  487.                                         y = y + 1
  488.                                 end
  489.                                 setCursor( x, y )
  490.                         else
  491.                                 -- Move menu right
  492.                                 nMenuItem = nMenuItem + 1
  493.                                 if nMenuItem > #tMenuItems then
  494.                                         nMenuItem = 1
  495.                                 end
  496.                                 redrawMenu()
  497.                         end
  498.                 elseif param == keys.delete then
  499.                         -- Delete
  500.                         if not bMenu and not bReadOnly then
  501.                                 if  x < string.len( tLines[y] ) + 1 then
  502.                                         local sLine = tLines[y]
  503.                                         tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  504.                                         redrawLine(y)
  505.                                 elseif y<#tLines then
  506.                                         tLines[y] = tLines[y] .. tLines[y+1]
  507.                                         table.remove( tLines, y+1 )
  508.                                         redrawText()
  509.                                         redrawMenu()
  510.                                 end
  511.                         end
  512.                 elseif param == keys.backspace then
  513.                         -- Backspace
  514.                         if not bMenu and not bReadOnly then
  515.                                 if x > 1 then
  516.                                         -- Remove character
  517.                                         local sLine = tLines[y]
  518.                                         tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  519.                                         redrawLine(y)
  520.                        
  521.                                         x = x - 1
  522.                                         setCursor( x, y )
  523.                                 elseif y > 1 then
  524.                                         -- Remove newline
  525.                                         local sPrevLen = string.len( tLines[y-1] )
  526.                                         tLines[y-1] = tLines[y-1] .. tLines[y]
  527.                                         table.remove( tLines, y )
  528.                                         redrawText()
  529.                                
  530.                                         x = sPrevLen + 1
  531.                                         y = y - 1
  532.                                         setCursor( x, y )
  533.                                 end
  534.                         end
  535.                 elseif param == keys.enter then
  536.                         -- Enter
  537.                         if not bMenu and not bReadOnly then
  538.                                 -- Newline
  539.                                 local sLine = tLines[y]
  540.                                 local _,spaces=string.find(sLine,"^[ ]+")
  541.                                 if not spaces then
  542.                                         spaces=0
  543.                                 end
  544.                                 tLines[y] = string.sub(sLine,1,x-1)
  545.                                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
  546.                                 redrawText()
  547.                        
  548.                                 x = spaces+1
  549.                                 y = y + 1
  550.                                 setCursor( x, y )
  551.                         elseif bMenu then
  552.                                 -- Menu selection
  553.                                 doMenuItem( nMenuItem )
  554.                         end
  555.                 elseif param == keys.leftCtrl or param == keys.rightCtrl then
  556.                         -- Menu toggle
  557.                         bMenu = not bMenu
  558.                         if bMenu then
  559.                                 term.setCursorBlink( false )
  560.                         else
  561.                                 term.setCursorBlink( true )
  562.                         end
  563.                         redrawMenu()
  564.                 end
  565.                
  566.         elseif sEvent == "char" then
  567.                 if not bMenu and not bReadOnly then
  568.                         -- Input text
  569.                         local sLine = tLines[y]
  570.                         tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  571.                         redrawLine(y)
  572.                
  573.                         x = x + 1
  574.                         setCursor( x, y )
  575.                 elseif bMenu then
  576.                         -- Select menu items
  577.                         for n,sMenuItem in ipairs( tMenuItems ) do
  578.                                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
  579.                                         doMenuItem( n )
  580.                                         break
  581.                                 end
  582.                         end
  583.                 end
  584.  
  585.         elseif sEvent == "paste" then
  586.                 if not bMenu and not bReadOnly then
  587.                         -- Input text
  588.                         local sLine = tLines[y]
  589.                         tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  590.                         redrawLine(y)
  591.  
  592.                         x = x + string.len( param )
  593.                         setCursor( x, y )
  594.                 end
  595.                
  596.         elseif sEvent == "mouse_click" then
  597.                 if not bMenu then
  598.                         if param == 1 then
  599.                                 -- Left click
  600.                                 local cx,cy = param2, param3
  601.                                 if cy < h then
  602.                                         y = math.min( math.max( scrollY + cy, 1 ), #tLines )
  603.                                         x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
  604.                                         setCursor( x, y )
  605.                                 end
  606.                         end
  607.                 end
  608.                
  609.         elseif sEvent == "mouse_scroll" then
  610.                 if not bMenu then
  611.                         if param == -1 then
  612.                                 -- Scroll up
  613.                                 if scrollY > 0 then
  614.                                         -- Move cursor up
  615.                                         scrollY = scrollY - 1
  616.                                         redrawText()
  617.                                 end
  618.                        
  619.                         elseif param == 1 then
  620.                                 -- Scroll down
  621.                                 local nMaxScroll = #tLines - (h-1)
  622.                                 if scrollY < nMaxScroll then
  623.                                         -- Move cursor down
  624.                                         scrollY = scrollY + 1
  625.                                         redrawText()
  626.                                 end
  627.                                
  628.                         end
  629.                 end
  630.  
  631.         elseif sEvent == "term_resize" then
  632.             w,h = term.getSize()
  633.         setCursor( x, y )
  634.         redrawMenu()
  635.         redrawText()
  636.  
  637.         end
  638. end
  639.  
  640. -- Cleanup
  641. term.clear()
  642. term.setCursorBlink( false )
  643. term.setCursorPos( 1, 1 )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement