Advertisement
Redxone

batedit

Jul 22nd, 2015
633
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 20.06 KB | None | 0 0
  1. -- Get file to edit
  2. local tArgs = { ... }
  3. if #tArgs == 0 then
  4.         print( "Usage: bat <path>" )
  5.         return
  6. end
  7.  
  8. -- Error checking
  9. local sPath = shell.resolve( tArgs[1] )
  10. local bReadOnly = fs.isReadOnly( sPath )
  11. if fs.exists( sPath ) and fs.isDir( sPath ) then
  12.         print( "Cannot edit a directory." )
  13.         return
  14. end
  15.  
  16. local x,y = 1,1
  17. local w,h = term.getSize()
  18. local scrollX, scrollY = 0,0
  19.  
  20. local tLines = {}
  21. local bRunning = true
  22.  
  23. -- Colours
  24. local highlightColour, keywordColour, commentColour, textColour, bgColour
  25. if term.isColour() then
  26.         bgColour = colours.black
  27.         textColour = colours.blue
  28.         highlightColour = colours.white
  29.         keywordColour = colours.orange
  30.         commentColour = colours.green
  31.         stringColour = colours.blue
  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", "Compile"}
  49. end
  50.        
  51. local sStatus = "Press Ctrl to access menu"
  52. if string.len( sStatus ) > w - 5 then
  53.     sStatus = "Press Ctrl for menu"
  54. end
  55.  
  56. local function load( _sPath )
  57.         tLines = {}
  58.         if fs.exists( _sPath ) then
  59.                 local file = io.open( _sPath, "r" )
  60.                 local sLine = file:read()
  61.                 while sLine do
  62.                         table.insert( tLines, sLine )
  63.                         sLine = file:read()
  64.                 end
  65.                 file:close()
  66.         end
  67.        
  68.         if #tLines == 0 then
  69.                 table.insert( tLines, "" )
  70.         end
  71. end
  72.  
  73. local function save( _sPath )
  74.         -- Create intervening folder
  75.         local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
  76.         if not fs.exists( sDir ) then
  77.                 fs.makeDir( sDir )
  78.         end
  79.  
  80.         -- Save
  81.         local file = nil
  82.         local function innerSave()
  83.                 file = fs.open( _sPath, "w" )
  84.                 if file then
  85.                         for n, sLine in ipairs( tLines ) do
  86.                                 file.write( sLine .. "\n" )
  87.                         end
  88.                 else
  89.                         error( "Failed to open ".._sPath )
  90.                 end
  91.         end
  92.        
  93.         local ok = pcall( innerSave )
  94.         if file then
  95.                 file.close()
  96.         end
  97.         return ok
  98. end
  99.  
  100. local tKeywords = {
  101.         ["echo"] = true,
  102.  ["cls"] = true,
  103.  ["copy"] = true,
  104.  ["move"] = true,
  105.  ["start"] = true,
  106.  ["time"] = true,
  107.  ["exit"] = true,
  108.  ["color"] = true,
  109.  ["del"] = true,
  110.  ["bat"] = true,
  111.  ["on"] = true,
  112.  ["off"] = true,
  113.  ["dir"] = true,
  114.  ["edit"] = true,
  115.  ["@echo"] = true,
  116. }
  117.  
  118. local function tryWrite( sLine, regex, colour )
  119.         local match = string.match( sLine, regex )
  120.         if match then
  121.                 if type(colour) == "number" then
  122.                         term.setTextColour( colour )
  123.                 else
  124.                         term.setTextColour( colour(match) )
  125.                 end
  126.                 term.write( match )
  127.                 term.setTextColour( textColour )
  128.                 return string.sub( sLine, string.len(match) + 1 )
  129.         end
  130.         return nil
  131. end
  132.  
  133. local function writeHighlighted( sLine )
  134.         while string.len(sLine) > 0 do
  135.                 sLine =
  136.                         tryWrite( sLine, "^%:%:%[%[::%]%]", commentColour ) or
  137.                         tryWrite( sLine, "^%:%:.*", commentColour ) or
  138.                         tryWrite( sLine, "^\".:[^\\]\"", stringColour ) or
  139.                         tryWrite( sLine, "^\'.:[^\\]\'", stringColour ) or
  140.                         tryWrite( sLine, "^%[%[.::%]%]", stringColour ) or
  141.                         tryWrite( sLine, "^[%w_]+", function( match )
  142.                                 if tKeywords[ match ] then
  143.                                         return keywordColour
  144.                                 end
  145.                                 return textColour
  146.                         end ) or
  147.                         tryWrite( sLine, "^[^%w_]", textColour )
  148.         end
  149. end
  150.  
  151. local function redrawText()
  152.         for y=1,h-1 do
  153.                 term.setCursorPos( 1 - scrollX, y )
  154.                 term.clearLine()
  155.  
  156.                 local sLine = tLines[ y + scrollY ]
  157.                 if sLine ~= nil then
  158.                         writeHighlighted( sLine )
  159.                 end
  160.         end
  161.         term.setCursorPos( x - scrollX, y - scrollY )
  162. end
  163.  
  164. local function redrawLine(_nY)
  165.         local sLine = tLines[_nY]
  166.         term.setCursorPos( 1 - scrollX, _nY - scrollY )
  167.         term.clearLine()
  168.         writeHighlighted( sLine )
  169.         term.setCursorPos( x - scrollX, _nY - scrollY )
  170. end
  171.  
  172. local function redrawMenu()
  173.     -- Clear line
  174.     term.setCursorPos( 1, h )
  175.         term.clearLine()
  176.  
  177.     -- Draw line numbers
  178.     term.setCursorPos( w - string.len( "LN "..y ) + 1, h )
  179.     term.setTextColour( highlightColour )
  180.     term.write( "LN " )
  181.     term.setTextColour( textColour )
  182.     term.write( y )
  183.  
  184.     term.setCursorPos( 1, h )
  185.         if bMenu then
  186.         -- Draw menu
  187.                 term.setTextColour( textColour )
  188.                 for nItem,sItem in pairs( tMenuItems ) do
  189.                         if nItem == nMenuItem then
  190.                                 term.setTextColour( highlightColour )
  191.                                 term.write( "[" )
  192.                                 term.setTextColour( textColour )
  193.                                 term.write( sItem )
  194.                                 term.setTextColour( highlightColour )
  195.                                 term.write( "]" )
  196.                         term.setTextColour( textColour )
  197.                         else
  198.                                 term.write( " "..sItem.." " )
  199.                         end
  200.                 end
  201.     else
  202.         -- Draw status
  203.         term.setTextColour( highlightColour )
  204.         term.write( sStatus )
  205.         term.setTextColour( textColour )
  206.     end
  207.  
  208.         -- Reset cursor
  209.         term.setCursorPos( x - scrollX, y - scrollY )
  210. end
  211.  
  212. local tMenuFuncs = {
  213.         Save=function()
  214.                 if bReadOnly then
  215.                         sStatus = "Access denied"
  216.                 else
  217.                         local ok, err = save( sPath )
  218.                         if ok then
  219.                                 sStatus="Saved to "..sPath
  220.                         else
  221.                                 sStatus="Error saving to "..sPath
  222.                         end
  223.                 end
  224.                 redrawMenu()
  225.         end,
  226.         Compile=function()
  227.           if(_DOS == nil)then
  228.          sStatus = "Please Run Inside CS-DOS!"
  229.       else
  230.         _DOS.runQue = sPath
  231.         sStatus = "File queued to compile when exited"
  232.      end
  233.      
  234.   end,
  235.   Exit=function()
  236.       bRunning=false
  237.   end,
  238. }
  239.  
  240. local function doMenuItem( _n )
  241.         tMenuFuncs[tMenuItems[_n]]()
  242.         if bMenu then
  243.                 bMenu = false
  244.                 term.setCursorBlink( true )
  245.         end
  246.         redrawMenu()
  247. end
  248.  
  249. local function setCursor( x, y )
  250.         local screenX = x - scrollX
  251.         local screenY = y - scrollY
  252.        
  253.         local bRedraw = false
  254.         if screenX < 1 then
  255.                 scrollX = x - 1
  256.                 screenX = 1
  257.                 bRedraw = true
  258.         elseif screenX > w then
  259.                 scrollX = x - w
  260.                 screenX = w
  261.                 bRedraw = true
  262.         end
  263.        
  264.         if screenY < 1 then
  265.                 scrollY = y - 1
  266.                 screenY = 1
  267.                 bRedraw = true
  268.         elseif screenY > h-1 then
  269.                 scrollY = y - (h-1)
  270.                 screenY = h-1
  271.                 bRedraw = true
  272.         end
  273.        
  274.         if bRedraw then
  275.                 redrawText()
  276.         end
  277.         term.setCursorPos( screenX, screenY )
  278.        
  279.         -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
  280.         redrawMenu()
  281. end
  282.  
  283. -- Actual program functionality begins
  284. load(sPath)
  285.  
  286. term.setBackgroundColour( bgColour )
  287. term.clear()
  288. term.setCursorPos(x,y)
  289. term.setCursorBlink( true )
  290.  
  291. redrawText()
  292. redrawMenu()
  293.  
  294. -- Handle input
  295. while bRunning do
  296.         local sEvent, param, param2, param3 = os.pullEvent()
  297.         if sEvent == "key" then
  298.                 if param == keys.up then
  299.                         -- Up
  300.                         if not bMenu then
  301.                                 if y > 1 then
  302.                                         -- Move cursor up
  303.                                         y = y - 1
  304.                                         x = math.min( x, string.len( tLines[y] ) + 1 )
  305.                                         setCursor( x, y )
  306.                                 end
  307.                         end
  308.                 elseif param == keys.down then
  309.                         -- Down
  310.                         if not bMenu then
  311.                                 -- Move cursor down
  312.                                 if y < #tLines then
  313.                                         y = y + 1
  314.                                         x = math.min( x, string.len( tLines[y] ) + 1 )
  315.                                         setCursor( x, y )
  316.                                 end
  317.                         end
  318.                 elseif param == keys.tab then
  319.                         -- Tab
  320.                         if not bMenu and not bReadOnly then
  321.                                 -- Indent line
  322.                                 tLines[y]="  "..tLines[y]
  323.                                 x = x + 2
  324.                                 setCursor( x, y )
  325.                                 redrawLine(y)
  326.                         end
  327.                 elseif param == keys.pageUp then
  328.                         -- Page Up
  329.                         if not bMenu then
  330.                                 -- Move up a page
  331.                                 if y - (h - 1) >= 1 then
  332.                                         y = y - (h - 1)
  333.                                 else
  334.                                         y = 1
  335.                                 end
  336.                                 x = math.min( x, string.len( tLines[y] ) + 1 )
  337.                                 setCursor( x, y )
  338.                         end
  339.                 elseif param == keys.pageDown then
  340.                         -- Page Down
  341.                         if not bMenu then
  342.                                 -- Move down a page
  343.                                 if y + (h - 1) <= #tLines then
  344.                                         y = y + (h - 1)
  345.                                 else
  346.                                         y = #tLines
  347.                                 end
  348.                                 x = math.min( x, string.len( tLines[y] ) + 1 )
  349.                                 setCursor( x, y )
  350.                         end
  351.                 elseif param == keys.home then
  352.                         -- Home
  353.                         if not bMenu then
  354.                                 -- Move cursor to the beginning
  355.                                 x=1
  356.                                 setCursor(x,y)
  357.                         end
  358.                 elseif param == keys["end"] then
  359.                         -- End
  360.                         if not bMenu then
  361.                                 -- Move cursor to the end
  362.                                 x = string.len( tLines[y] ) + 1
  363.                                 setCursor(x,y)
  364.                         end
  365.                 elseif param == keys.left then
  366.                         -- Left
  367.                         if not bMenu then
  368.                                 if x > 1 then
  369.                                         -- Move cursor left
  370.                                         x = x - 1
  371.                                 elseif x==1 and y>1 then
  372.                                         x = string.len( tLines[y-1] ) + 1
  373.                                         y = y - 1
  374.                                 end
  375.                                 setCursor( x, y )
  376.                         else
  377.                                 -- Move menu left
  378.                                 nMenuItem = nMenuItem - 1
  379.                                 if nMenuItem < 1 then
  380.                                         nMenuItem = #tMenuItems
  381.                                 end
  382.                                 redrawMenu()
  383.                         end
  384.                 elseif param == keys.right then
  385.                         -- Right
  386.                         if not bMenu then
  387.                                 if x < string.len( tLines[y] ) + 1 then
  388.                                         -- Move cursor right
  389.                                         x = x + 1
  390.                                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
  391.                                         x = 1
  392.                                         y = y + 1
  393.                                 end
  394.                                 setCursor( x, y )
  395.                         else
  396.                                 -- Move menu right
  397.                                 nMenuItem = nMenuItem + 1
  398.                                 if nMenuItem > #tMenuItems then
  399.                                         nMenuItem = 1
  400.                                 end
  401.                                 redrawMenu()
  402.                         end
  403.                 elseif param == keys.delete then
  404.                         -- Delete
  405.                         if not bMenu and not bReadOnly then
  406.                                 if  x < string.len( tLines[y] ) + 1 then
  407.                                         local sLine = tLines[y]
  408.                                         tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  409.                                         redrawLine(y)
  410.                                 elseif y<#tLines then
  411.                                         tLines[y] = tLines[y] .. tLines[y+1]
  412.                                         table.remove( tLines, y+1 )
  413.                                         redrawText()
  414.                                         redrawMenu()
  415.                                 end
  416.                         end
  417.                 elseif param == keys.backspace then
  418.                         -- Backspace
  419.                         if not bMenu and not bReadOnly then
  420.                                 if x > 1 then
  421.                                         -- Remove character
  422.                                         local sLine = tLines[y]
  423.                                         tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  424.                                         redrawLine(y)
  425.                        
  426.                                         x = x - 1
  427.                                         setCursor( x, y )
  428.                                 elseif y > 1 then
  429.                                         -- Remove newline
  430.                                         local sPrevLen = string.len( tLines[y-1] )
  431.                                         tLines[y-1] = tLines[y-1] .. tLines[y]
  432.                                         table.remove( tLines, y )
  433.                                         redrawText()
  434.                                
  435.                                         x = sPrevLen + 1
  436.                                         y = y - 1
  437.                                         setCursor( x, y )
  438.                                 end
  439.                         end
  440.                 elseif param == keys.enter then
  441.                         -- Enter
  442.                         if not bMenu and not bReadOnly then
  443.                                 -- Newline
  444.                                 local sLine = tLines[y]
  445.                                 local _,spaces=string.find(sLine,"^[ ]+")
  446.                                 if not spaces then
  447.                                         spaces=0
  448.                                 end
  449.                                 tLines[y] = string.sub(sLine,1,x-1)
  450.                                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
  451.                                 redrawText()
  452.                        
  453.                                 x = spaces+1
  454.                                 y = y + 1
  455.                                 setCursor( x, y )
  456.                         elseif bMenu then
  457.                                 -- Menu selection
  458.                                 doMenuItem( nMenuItem )
  459.                         end
  460.                 elseif param == keys.leftCtrl or param == keys.rightCtrl then
  461.                         -- Menu toggle
  462.                         bMenu = not bMenu
  463.                         if bMenu then
  464.                                 term.setCursorBlink( false )
  465.                         else
  466.                                 term.setCursorBlink( true )
  467.                         end
  468.                         redrawMenu()
  469.                 end
  470.                
  471.         elseif sEvent == "char" then
  472.                 if not bMenu and not bReadOnly then
  473.                         -- Input text
  474.                         local sLine = tLines[y]
  475.                         tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  476.                         redrawLine(y)
  477.                
  478.                         x = x + 1
  479.                         setCursor( x, y )
  480.                 elseif bMenu then
  481.                         -- Select menu items
  482.                         for n,sMenuItem in ipairs( tMenuItems ) do
  483.                                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
  484.                                         doMenuItem( n )
  485.                                         break
  486.                                 end
  487.                         end
  488.                 end
  489.  
  490.         elseif sEvent == "paste" then
  491.                 if not bMenu and not bReadOnly then
  492.                         -- Input text
  493.                         local sLine = tLines[y]
  494.                         tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  495.                         redrawLine(y)
  496.  
  497.                         x = x + string.len( param )
  498.                         setCursor( x, y )
  499.                 end
  500.                
  501.         elseif sEvent == "mouse_click" then
  502.                 if not bMenu then
  503.                         if param == 1 then
  504.                                 -- Left click
  505.                                 local cx,cy = param2, param3
  506.                                 if cy < h then
  507.                                         y = math.min( math.max( scrollY + cy, 1 ), #tLines )
  508.                                         x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
  509.                                         setCursor( x, y )
  510.                                 end
  511.                         end
  512.                 end
  513.                
  514.         elseif sEvent == "mouse_scroll" then
  515.                 if not bMenu then
  516.                         if param == -1 then
  517.                                 -- Scroll up
  518.                                 if scrollY > 0 then
  519.                                         -- Move cursor up
  520.                                         scrollY = scrollY - 1
  521.                                         redrawText()
  522.                                 end
  523.                        
  524.                         elseif param == 1 then
  525.                                 -- Scroll down
  526.                                 local nMaxScroll = #tLines - (h-1)
  527.                                 if scrollY < nMaxScroll then
  528.                                         -- Move cursor down
  529.                                         scrollY = scrollY + 1
  530.                                         redrawText()
  531.                                 end
  532.                                
  533.                         end
  534.                 end
  535.  
  536.         elseif sEvent == "term_resize" then
  537.             w,h = term.getSize()
  538.         setCursor( x, y )
  539.         redrawMenu()
  540.         redrawText()
  541.  
  542.         end
  543. end
  544.  
  545. -- Cleanup
  546. term.clear()
  547. term.setCursorBlink( false )
  548. term.setCursorPos( 1, 1 )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement