xXm0dzXx

Lunar

Oct 20th, 2012
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.22 KB | None | 0 0
  1. -- Get file to edit
  2. local tArgs = { ... }
  3. if #tArgs == 0 then
  4.     print( "Usage: " ..shell.getRunningProgram().. " <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,3
  17. local w,h = term.getSize()
  18. local scrollX, scrollY = 0,0
  19.  
  20. local tLines = {}
  21. local bRunning = true
  22.  
  23. -- Menus and other small animals.
  24. local bMenu = false
  25. local nMenuItem = 1
  26. local tMenuItems = {"Save", "Exit"}
  27. local tMenuOffsets = {1, 6}
  28. local sStatus = "Press Ctrl to access menu"
  29.  
  30. local classes = {
  31.     [1] = sPath,
  32. }
  33. local currentClass = sPath
  34.  
  35. local function load(_sPath)
  36.     tLines = {}
  37.     if fs.exists( _sPath ) then
  38.         local file = io.open( _sPath, "r" )
  39.         local sLine = file:read()
  40.         while sLine do
  41.             table.insert( tLines, sLine )
  42.             sLine = file:read()
  43.         end
  44.         file:close()
  45.     end
  46.    
  47.     if #tLines == 0 then
  48.         table.insert( tLines, "" )
  49.     end
  50. end
  51.  
  52. local function save( _sPath )
  53.     -- Create intervening folder
  54.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
  55.     if not fs.exists( sDir ) then
  56.         fs.makeDir( sDir )
  57.     end
  58.  
  59.     -- Save
  60.     local file = nil
  61.     local function innerSave()
  62.         file = fs.open( _sPath, "w" )
  63.         if file then
  64.             for n, sLine in ipairs( tLines ) do
  65.                 file.write( sLine .. "\n" )
  66.             end
  67.         else
  68.             error( "Failed to open ".._sPath )
  69.         end
  70.     end
  71.    
  72.     local ok = pcall( innerSave )
  73.     if file then
  74.         file.close()
  75.     end
  76.     return ok
  77. end
  78.  
  79. local function redrawText()
  80.     term.setCursorPos(1,2)
  81.     for i=1,w-1 do
  82.         write("~")
  83.     end
  84.     term.setCursorPos(1,1)
  85.     for i=1,#classes do
  86.         if classes[i] == currentPath then
  87.             local tX,tY = term.getCursorPos()
  88.             for i=tX-1,tX-1+#classes[i]+2 do
  89.                 term.setCursorPos(i, 2)
  90.                 write("-")
  91.             end
  92.             term.setCursorPos(tX-1, tY+1)
  93.             write("+")
  94.             term.setCursorPos(tX-1+#classes[i]+2, tY-1)
  95.             write("+")
  96.             term.setCursorPos(tX,tY)
  97.         end
  98.         write(classes[i])
  99.         write(" | ")
  100.     end
  101.    
  102.     for y=3,h-1 do
  103.         term.setCursorPos( 1 - scrollX, y )
  104.         term.clearLine()
  105.  
  106.         local sLine = tLines[ y + scrollY ]
  107.         if sLine ~= nil then
  108.             term.write( sLine )
  109.         end
  110.     end
  111.     term.setCursorPos( x - scrollX, y - scrollY )
  112. end
  113.  
  114. local function redrawLine(_nY)
  115.     local sLine = tLines[_nY]
  116.     term.setCursorPos( 1 - scrollX, _nY - scrollY )
  117.     term.clearLine()
  118.     term.write( sLine )
  119.     term.setCursorPos( x - scrollX, _nY - scrollY )
  120. end
  121.  
  122. local function setLeftStatus()
  123. end
  124.  
  125. local function redrawMenu()
  126.     term.setCursorPos( 1, h )
  127.     term.clearLine()
  128.  
  129.     local sLeft, sRight
  130.     if bMenu then
  131.         local sMenu = ""
  132.         for n,sItem in ipairs( tMenuItems ) do
  133.             if n == nMenuItem then
  134.                 sMenu = sMenu.."["..sItem.."]"
  135.             else
  136.                 sMenu = sMenu.." "..sItem.." "
  137.             end
  138.         end
  139.         sLeft = sMenu
  140.     else
  141.         sLeft = sStatus
  142.     end
  143.     sRight = "Ln "..y
  144.    
  145.     -- Left goes last so that it can overwrite the line numbers.
  146.     if sRight then
  147.         term.setCursorPos( w-sRight:len()+1, h )
  148.         term.write(sRight)
  149.     end
  150.     if sLeft then
  151.         term.setCursorPos( 1, h )
  152.         term.write(sLeft)
  153.     end
  154.    
  155.     -- Cursor highlights selection
  156.     if bMenu then
  157.         term.setCursorPos( tMenuOffsets[nMenuItem], h )
  158.     else
  159.         term.setCursorPos( x - scrollX, y - scrollY )
  160.     end
  161. end
  162.  
  163. local tMenuFuncs = {
  164.     Save=function()
  165.         if bReadOnly then
  166.             sStatus = "Access denied"
  167.         else
  168.             local ok, err = save( sPath )
  169.             if ok then
  170.                 sStatus="Saved to "..sPath
  171.             else
  172.                 sStatus="Error saving to "..sPath
  173.             end
  174.         end
  175.         redrawMenu()
  176.     end,
  177.     Exit=function()
  178.         bRunning = false
  179.     end
  180. }
  181.  
  182. local function doMenuItem( _n )
  183.     tMenuFuncs[tMenuItems[_n]]()
  184.     if bMenu then
  185.         bMenu = false
  186.         term.setCursorBlink( true )
  187.     end
  188.     redrawMenu()
  189. end
  190.  
  191. local function setCursor( x, y )
  192.     local screenX = x - scrollX
  193.     local screenY = y - scrollY
  194.    
  195.     local bRedraw = false
  196.     if screenX < 1 then
  197.         scrollX = x - 1
  198.         screenX = 1
  199.         bRedraw = true
  200.     elseif screenX > w then
  201.         scrollX = x - w
  202.         screenX = w
  203.         bRedraw = true
  204.     end
  205.    
  206.     if screenY < 1 then
  207.         scrollY = y - 1
  208.         screenY = 1
  209.         bRedraw = true
  210.     elseif screenY > h-1 then
  211.         scrollY = y - (h-1)
  212.         screenY = h-1
  213.         bRedraw = true
  214.     end
  215.    
  216.     if bRedraw then
  217.         redrawText()
  218.     end
  219.     term.setCursorPos( screenX, screenY )
  220.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
  221.     redrawMenu()
  222. end
  223.  
  224. -- Actual program functionality begins
  225. load(sPath)
  226.  
  227. term.clear()
  228. term.setCursorPos(x,3)
  229. term.setCursorBlink( true )
  230.  
  231. redrawText()
  232. redrawMenu()
  233.  
  234. -- Handle input
  235. while bRunning do
  236.     local sEvent, param = os.pullEvent()
  237.     if sEvent == "key" then
  238.         if param == keys.up then
  239.             -- Up
  240.             if not bMenu then
  241.                 if y > 3 then
  242.                     -- Move cursor up
  243.                     y = y - 1
  244.                     x = math.min( x, string.len( tLines[y] ) + 1 )
  245.                     setCursor( x, y )
  246.                 end
  247.             end
  248.         elseif param == keys.down then
  249.             -- Down
  250.             if not bMenu then
  251.                 -- Move cursor down
  252.                 if y < #tLines then
  253.                     y = y + 1
  254.                     x = math.min( x, string.len( tLines[y] ) + 1 )
  255.                     setCursor( x, y )
  256.                 end
  257.             end
  258.         elseif param == keys.tab then
  259.             -- Tab
  260.             if not bMenu then
  261.                 local sLine = tLines[y]
  262.  
  263.                 -- Indent line
  264.                 -- IN CASE OF INSERT TAB IN PLACE:
  265.                 -- tLines[y] = string.sub(sLine,1,x-1) .. "  " .. string.sub(sLine,x)
  266.                 tLines[y]='  '..tLines[y]
  267.                 x = x + 2
  268.                 setCursor( x, y )
  269.                 redrawLine(y)
  270.             end
  271.         elseif param == keys.pageUp then
  272.             -- Page Up
  273.             if not bMenu then
  274.                 -- Move up a page
  275.                 local sx,sy=term.getSize()
  276.                 y=y-sy-1
  277.                 if y<3 then y=3 end
  278.                 x = math.min( x, string.len( tLines[y] ) + 1 )
  279.                 setCursor( x, y )
  280.             end
  281.         elseif param == keys.pageDown then
  282.             -- Page Down
  283.             if not bMenu then
  284.                 -- Move down a page
  285.                 local sx,sy=term.getSize()
  286.                 if y<#tLines-sy-1 then
  287.                     y = y+sy-1
  288.                 else
  289.                     y = #tLines
  290.                 end
  291.                 x = math.min( x, string.len( tLines[y] ) + 1 )
  292.                 setCursor( x, y )
  293.             end
  294.         elseif param == keys.home then
  295.             -- Home
  296.             if not bMenu then
  297.                 -- [TODO] respect indentation here
  298.                 -- Move cursor to the beginning
  299.                 x=1
  300.                 setCursor(x,y)
  301.             end
  302.         elseif param == keys["end"] then
  303.             -- End
  304.             if not bMenu then
  305.                 -- Move cursor to the end
  306.                 x = string.len( tLines[y] ) + 1
  307.                 setCursor(x,y)
  308.             end
  309.         elseif param == keys.left then
  310.             -- Left
  311.             if not bMenu then
  312.                 if x > 1 then
  313.                     -- Move cursor left
  314.                     x = x - 1
  315.                 elseif x==1 and y>1 then
  316.                     x = string.len( tLines[y-1] ) + 1
  317.                     y = y - 1
  318.                 end
  319.                 setCursor( x, y )
  320.             else
  321.                 -- Move menu left
  322.                 nMenuItem = nMenuItem - 1
  323.                 if nMenuItem < 1 then
  324.                     nMenuItem = #tMenuItems
  325.                 end
  326.                 redrawMenu()
  327.             end
  328.         elseif param == keys.right then
  329.             -- Right
  330.             if not bMenu then
  331.                 if x < string.len( tLines[y] ) + 1 then
  332.                     -- Move cursor right
  333.                     x = x + 1
  334.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
  335.                     x = 1
  336.                     y = y + 1
  337.                 end
  338.                 setCursor( x, y )
  339.             else
  340.                 -- Move menu right
  341.                 nMenuItem = nMenuItem + 1
  342.                 if nMenuItem > #tMenuItems then
  343.                     nMenuItem = 1
  344.                 end
  345.                 redrawMenu()
  346.             end
  347.         elseif param == keys.delete then
  348.             -- Delete
  349.             if not bMenu then
  350.                 if  x < string.len( tLines[y] ) + 1 then
  351.                     local sLine = tLines[y]
  352.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  353.                     redrawLine(y)
  354.                 elseif y<#tLines then
  355.                     tLines[y] = tLines[y] .. tLines[y+1]
  356.                     table.remove( tLines, y+1 )
  357.                     redrawText()
  358.                     redrawMenu()
  359.                 end
  360.             end
  361.         elseif param == keys.backspace then
  362.             -- Backspace
  363.             if not bMenu then
  364.                 if x > 1 then
  365.                     -- Remove character
  366.                     local sLine = tLines[y]
  367.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  368.                     redrawLine(y)
  369.            
  370.                     x = x - 1
  371.                     setCursor( x, y )
  372.                 elseif y > 1 then
  373.                     -- Remove newline
  374.                     local sPrevLen = string.len( tLines[y-1] )
  375.                     tLines[y-1] = tLines[y-1] .. tLines[y]
  376.                     table.remove( tLines, y )
  377.                     redrawText()
  378.                
  379.                     x = sPrevLen + 1
  380.                     y = y - 1
  381.                     setCursor( x, y )
  382.                 end
  383.             end
  384.         elseif param == keys.enter then
  385.             -- Enter
  386.             if not bMenu then
  387.                 -- Newline
  388.                 local sLine = tLines[y]
  389.                 local _,spaces=string.find(sLine,"^[ ]+")
  390.                 if not spaces then
  391.                     spaces=0
  392.                 end
  393.                 tLines[y] = string.sub(sLine,1,x-1)
  394.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
  395.                 redrawText()
  396.            
  397.                 x = spaces+1
  398.                 y = y + 1
  399.                 setCursor( x, y )
  400.             else
  401.                 -- Menu selection
  402.                 doMenuItem( nMenuItem )
  403.             end
  404.         elseif param == keys.leftCtrl or param == keys.rightCtrl then
  405.             -- Menu toggle
  406.             bMenu = not bMenu
  407.             if bMenu then
  408.                 term.setCursorBlink( false )
  409.                 nMenuItem = 1
  410.             else
  411.                 term.setCursorBlink( true )
  412.             end
  413.             redrawMenu()
  414.         end
  415.     elseif sEvent == "char" then
  416.         if not bMenu then
  417.             -- Input text
  418.             local sLine = tLines[y]
  419.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  420.             redrawLine(y)
  421.        
  422.             x = x + string.len( param )
  423.             setCursor( x, y )
  424.         else
  425.             -- Select menu items
  426.             for n,sMenuItem in ipairs( tMenuItems ) do
  427.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
  428.                     doMenuItem( n )
  429.                     break
  430.                 end
  431.             end
  432.         end
  433.     end
  434. end
  435.  
  436. -- Cleanup
  437. term.clear()
  438. term.setCursorBlink( false )
  439. term.setCursorPos( 1, 1 )
Advertisement
Add Comment
Please, Sign In to add comment