Advertisement
thegreatstudio

text

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