Guest User

edil

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