Advertisement
Guest User

Untitled

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