QuickMuffin8782-Alt

Shedit (version 2)

Nov 23rd, 2020
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Credit to LoganDark2
  2.  
  3. --- EDITOR SETTINGS --
  4. local needAlias = false -- Whether you want the alias (on by default)
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41. local apiOK, apiERR
  42. if not fs.exists('.editor/api/lex') then
  43. apiOK, apiERR = shell.run('pastebin get edyuQ5xY .editor/api/lex')
  44. end
  45. if not fs.exists('.editor/api/ui.lua') then
  46. apiOK, apiERR = shell.run('pastebin get phmg6UN9 .editor/api/ui.lua')
  47. end
  48.  
  49. local lexSuccess = os.loadAPI('.editor/api/lex')
  50.  
  51. local uiSuccess = os.loadAPI('.editor/api/ui.lua')
  52.  
  53. local aliases = shell.aliases()
  54. local hasAlias = false
  55. local aliasLength = #aliases
  56. for a, b in pairs(aliases) do
  57. if b == shell.getRunningProgram() and a == "edit" then
  58. hasAlias = true
  59. end
  60. end
  61. if needAlias and not hasAlias then
  62. printError([[--==|| ALIAS ERROR ||==--
  63. Your alias setting isn't set. To fix the problem enter: alias edit ]] .. shell.getRunningProgram() .. [[ to fix.
  64. Edit ]] .. shell.getRunningProgram() .. [['s settings if you do not want it.]])
  65. end
  66.  
  67. -- Check for errors in the alias check
  68. if not needAlias then
  69. -- don't change. for errors.
  70. elseif needAlias and hasAlias then
  71. -- don't change. for errors.
  72. else
  73. printError( "A error has occurred during the code. Please run and try again." )
  74. return
  75. end
  76.  
  77. if not lexSuccess or not lex or not lex.lex then
  78. print('A valid lexer is required (file `lex` seems to be broken or not a lexer)')
  79. return
  80. end
  81.  
  82. -- Get file to edit
  83. local tArgs = { ... }
  84. if #tArgs == 0 then
  85. if not needAlias then
  86. print( "Usage: ".. fs.getName(shell.getRunningProgram()) .. " <path>" )
  87. elseif needAlias and hasAlias then
  88. print( "Usage: edit <path>" )
  89. else
  90. printError( "A error has occurred during the code. Please run and try again." )
  91. end
  92. return
  93. end
  94.  
  95. -- Error checking
  96. local sPath = "/" .. shell.dir() .. shell.resolve( tArgs[1] )
  97. local bReadOnly = fs.isReadOnly( sPath )
  98. if fs.exists( sPath ) and fs.isDir( sPath ) then
  99. print( "Cannot edit a directory." )
  100. return
  101. end
  102.  
  103. local x,y = 1,1
  104. local markX, markY = 1, 1
  105. local w,h = term.getSize()
  106. local scrollX, scrollY = 0,0
  107.  
  108. local tLines = {}
  109. local bRunning = true
  110.  
  111. -- Colors
  112. local highlightColor, keywordColor, commentColor, textColor, bgColor, stringColor
  113. if term.isColor() then
  114. bgColor = colors.black
  115. textColor = colors.white
  116. highlightColor = colors.yellow
  117. keywordColor = colors.yellow
  118. commentColor = colors.green
  119. stringColor = colors.red
  120. else
  121. bgColor = colors.black
  122. textColor = colors.white
  123. highlightColor = colors.white
  124. keywordColor = colors.white
  125. commentColor = colors.white
  126. stringColor = colors.white
  127. end
  128.  
  129. -- Menus
  130. local bMenu = false
  131. local nMenuItem = 1
  132. local tMenuItems = {}
  133. if not bReadOnly then
  134. table.insert( tMenuItems, "Save" )
  135. end
  136. if shell.openTab then
  137. table.insert( tMenuItems, "Run" )
  138. end
  139. if peripheral.find( "printer" ) then
  140. table.insert( tMenuItems, "Print" )
  141. end
  142. table.insert( tMenuItems, "Exit" )
  143. table.insert(tMenuItems, 'Tools')
  144. table.insert(tMenuItems, 'Find')
  145. table.insert(tMenuItems, 'Jump')
  146. table.insert(tMenuItems, 'Copy')
  147. table.insert(tMenuItems, 'VPaste')
  148.  
  149. local sStatus = "Press Ctrl to access menu"
  150. if string.len( sStatus ) > w - 5 then
  151. sStatus = "Press Ctrl for menu"
  152. end
  153.  
  154. local function load( _sPath )
  155. tLines = {}
  156. if fs.exists( _sPath ) then
  157. local file = io.open( _sPath, "r" )
  158. local sLine = file:read()
  159. while sLine do
  160. table.insert( tLines, sLine )
  161. sLine = file:read()
  162. end
  163. file:close()
  164. end
  165.  
  166. if #tLines == 0 then
  167. table.insert( tLines, "" )
  168. end
  169. end
  170.  
  171. local function save( _sPath )
  172. -- Create intervening folder
  173. local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len() )
  174. if not fs.exists( sDir ) then
  175. fs.makeDir( sDir )
  176. end
  177.  
  178. -- Save
  179. local file = nil
  180. local function innerSave()
  181. file = fs.open( _sPath, "w" )
  182. if file then
  183. for n, sLine in ipairs( tLines ) do
  184. file.write( sLine .. "\n" )
  185. end
  186. else
  187. error( "Failed to open ".._sPath )
  188. end
  189. end
  190.  
  191. local ok, err = pcall( innerSave )
  192. if file then
  193. file.close()
  194. end
  195. return ok, err
  196. end
  197.  
  198. local tKeywords = {
  199. ["and"] = true,
  200. ["break"] = true,
  201. ["do"] = true,
  202. ["else"] = true,
  203. ["elseif"] = true,
  204. ["end"] = true,
  205. ["false"] = true,
  206. ["for"] = true,
  207. ["function"] = true,
  208. ["if"] = true,
  209. ["in"] = true,
  210. ["local"] = true,
  211. ["nil"] = true,
  212. ["not"] = true,
  213. ["or"] = true,
  214. ["repeat"] = true,
  215. ["return"] = true,
  216. ["then"] = true,
  217. ["true"] = true,
  218. ["until"]= true,
  219. ["while"] = true,
  220. }
  221.  
  222. local function tryWrite( sLine, regex, color )
  223. local match = string.match( sLine, regex )
  224. if match then
  225. if type(color) == "number" then
  226. term.setTextColor( color )
  227. else
  228. term.setTextColor( color(match) )
  229. end
  230. term.write( match )
  231. term.setTextColor( textColor )
  232. return string.sub( sLine, string.len(match) + 1 )
  233. end
  234. return nil
  235. end
  236.  
  237. --[[local function writeHighlighted( sLine )
  238. while string.len(sLine) > 0 do
  239. sLine =
  240. tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColor ) or
  241. tryWrite( sLine, "^%-%-.*", commentColor ) or
  242. tryWrite( sLine, "^\"\"", stringColor ) or
  243. tryWrite( sLine, "^\".-[^\\]\"", stringColor ) or
  244. tryWrite( sLine, "^\'\'", stringColor ) or
  245. tryWrite( sLine, "^\'.-[^\\]\'", stringColor ) or
  246. tryWrite( sLine, "^%[%[.-%]%]", stringColor ) or
  247. tryWrite( sLine, "^[%w_]+", function( match )
  248. if tKeywords[ match ] then
  249. return keywordColor
  250. end
  251. return textColor
  252. end ) or
  253. tryWrite( sLine, "^[^%w_]", textColor )
  254. end
  255. end]]
  256.  
  257. local apis = {
  258. -- tables
  259. bit = true,
  260. bit32 = true,
  261. bitop = true,
  262. colors = true,
  263. colours = true,
  264. coroutine = true,
  265. disk = true,
  266. fs = true,
  267. gps = true,
  268. help = true,
  269. http = true,
  270. io = true,
  271. keys = true,
  272. math = true,
  273. os = true,
  274. paintutils = true,
  275. parallel = true,
  276. peripheral = true,
  277. rednet = true,
  278. redstone = true,
  279. rs = true,
  280. settings = true,
  281. shell = true,
  282. socket = true,
  283. string = true,
  284. table = true,
  285. term = true,
  286. textutils = true,
  287. vector = true,
  288. window = true,
  289.  
  290. -- functions
  291. assert = true,
  292. collectgarbage = true,
  293. dofile = true,
  294. error = true,
  295. getfenv = true,
  296. getmetatable = true,
  297. ipairs = true,
  298. loadfile = true,
  299. loadstring = true,
  300. module = true,
  301. next = true,
  302. pairs = true,
  303. pcall = true,
  304. print = true,
  305. rawequal = true,
  306. rawget = true,
  307. rawset = true,
  308. require = true,
  309. select = true,
  310. setfenv = true,
  311. setmetatable = true,
  312. tonumber = true,
  313. tostring = true,
  314. type = true,
  315. unpack = true,
  316. xpcall = true,
  317. printError = true,
  318. write = true
  319. }
  320.  
  321. local function onUpdate()
  322. tokenized = lex.lex(table.concat(tLines, '\n'))
  323. end
  324.  
  325. local function markExists()
  326. if markX ~= x or markY ~= y then
  327. return true
  328. else
  329. return false
  330. end
  331. end
  332.  
  333. local function isMarked(newX, newY)
  334. if (newY > markY and newY < y) or (newY > y and newY < markY) then
  335. return true
  336. end
  337.  
  338. if newY == markY and newY == y then
  339. if markX > x and newX >= x and newX < markX then
  340. return true
  341. elseif markX < x and newX >= markX and newX < x then
  342. return true
  343. end
  344. elseif newY == markY then
  345. if newX < markX and y < markY then
  346. return true
  347. elseif newX >= markX and y > markY then
  348. return true
  349. end
  350. elseif newY == y then
  351. if newX < x and y > markY then
  352. return true
  353. elseif newX >= x and y < markY then
  354. return true
  355. end
  356. end
  357.  
  358. return false
  359. end
  360.  
  361. local function getMarks()
  362. local msx, msy
  363. local mex, mey
  364.  
  365. if markY == y then
  366. if markX > x then
  367. msx = x
  368. msy = y
  369. mex = markX
  370. mey = markY
  371. else
  372. msx = markX
  373. msy = markY
  374. mex = x
  375. mey = y
  376. end
  377. else
  378. if markY > y then
  379. msx = x
  380. msy = y
  381. mex = markX
  382. mey = markY
  383. else
  384. msx = markX
  385. msy = markY
  386. mex = x
  387. mey = y
  388. end
  389. end
  390.  
  391. return msx, msy, mex, mey
  392. end
  393.  
  394. local function getCharDisplay(char)
  395. if char == '\t' then
  396. return ' '
  397. else
  398. return char
  399. end
  400. end
  401.  
  402. local function getCharWidth(char)
  403. return getCharDisplay(char):len()
  404. end
  405.  
  406. local function writeHighlighted(lineNr)
  407. local tokens = tokenized[lineNr] or {}
  408. local textColor = term.getTextColor()
  409. local bgColor = term.getBackgroundColor()
  410. local setX, setY = term.getCursorPos()
  411. local msx, msy, mex, mey = getMarks()
  412.  
  413. if lineNr < mey and lineNr >= msy then
  414. term.setBackgroundColor(colors.white)
  415. end
  416.  
  417. term.clearLine()
  418. term.setCursorPos(setX, setY)
  419.  
  420. for t = 1, #tokens do
  421. local token = tokens[t]
  422. local color = colors.white
  423.  
  424. if token.type == 'keyword' or token.type == 'operator' then
  425. color = colors.yellow
  426. elseif token.type == 'number' or token.type == 'value' then
  427. color = colors.purple
  428. elseif token.type == 'comment' then
  429. color = colors.green
  430. elseif token.type == 'ident' and apis[token.data] then
  431. color = colors.lightGray
  432. elseif token.type == 'string' then
  433. color = colors.cyan
  434. elseif token.type == 'escape' then
  435. color = colors.purple
  436. elseif token.type == 'unidentified' then
  437. color = colors.red
  438. end
  439.  
  440. for p = 1, #token.data do
  441. local sub = getCharDisplay(token.data:sub(p, p))
  442.  
  443. local cX, cY = p + token.posFirst - 1, lineNr
  444.  
  445. if (cY == msy and cY == mey and cX >= msx and cX < mex) or (cY == msy and cY ~= mey and cX >= msx) or (cY == mey and cY ~= msy and cX < mex) or (cY > msy and cY < mey) then
  446. term.setTextColor(colors.black)
  447. term.setBackgroundColor(color)
  448. else
  449. term.setBackgroundColor(colors.black)
  450. term.setTextColor(color)
  451. end
  452.  
  453. term.write(sub)
  454. end
  455. end
  456.  
  457. term.setTextColor(textColor)
  458. term.setBackgroundColor(bgColor)
  459. end
  460.  
  461. local tCompletions
  462. local nCompletion
  463.  
  464. local tCompleteEnv = _ENV
  465. local function complete( sLine )
  466. if settings.get( "edit.autocomplete" ) then
  467. local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.]+$" )
  468. if nStartPos then
  469. sLine = string.sub( sLine, nStartPos )
  470. end
  471. if #sLine > 0 then
  472. return textutils.complete( sLine, tCompleteEnv )
  473. end
  474. end
  475. return nil
  476. end
  477.  
  478. local function recomplete()
  479. local sLine = tLines[y]
  480. if not bMenu and not bReadOnly and x == string.len(sLine) + 1 then
  481. tCompletions = complete( sLine )
  482. if tCompletions and #tCompletions > 0 then
  483. nCompletion = 1
  484. else
  485. nCompletion = nil
  486. end
  487. else
  488. tCompletions = nil
  489. nCompletion = nil
  490. end
  491. end
  492.  
  493. local function writeCompletion( sLine )
  494. if nCompletion then
  495. local sCompletion = tCompletions[ nCompletion ]
  496. term.setTextColor( colors.white )
  497. term.setBackgroundColor( colors.gray )
  498. term.write( sCompletion )
  499. term.setTextColor( textColor )
  500. term.setBackgroundColor( bgColor )
  501. end
  502. end
  503.  
  504. local function getCursorX(lineNr)
  505. local line = tLines[lineNr]
  506. local cx = 1
  507.  
  508. for i = 1, x - 1 do
  509. cx = cx + getCharWidth(line:sub(i, i))
  510. end
  511.  
  512. return cx
  513. end
  514.  
  515. local function cxToPos(lineNr, cx)
  516. local line = tLines[lineNr]
  517. local num = 1
  518. local pos = 1
  519.  
  520. for i = 1, #line do
  521. amt = getCharWidth(line:sub(i, i))
  522.  
  523. if num + amt > cx then
  524. return pos
  525. else
  526. num = num + amt
  527. pos = pos + 1
  528. end
  529. end
  530.  
  531. return pos
  532. end
  533.  
  534. local function redrawText()
  535. local cursorX, cursorY = x, y
  536. for y=1,h-1 do
  537. term.setCursorPos( 1 - scrollX, y )
  538. term.clearLine()
  539.  
  540. local sLine = tLines[ y + scrollY ]
  541. if sLine ~= nil then
  542. --writeHighlighted( sLine )
  543. writeHighlighted(y + scrollY)
  544. if cursorY == y + scrollY and cursorX == #sLine + 1 then
  545. writeCompletion()
  546. end
  547. end
  548. end
  549.  
  550. local cx = getCursorX(y)
  551.  
  552. term.setCursorPos( cx - scrollX, y - scrollY )
  553. end
  554.  
  555. --[[local function redrawLine(_nY)
  556. local sLine = tLines[_nY]
  557. if sLine then
  558. term.setCursorPos( 1 - scrollX, _nY - scrollY )
  559. term.clearLine()
  560. --writeHighlighted( sLine )
  561. writeHighlighted(_nY)
  562. if _nY == y and x == #sLine + 1 then
  563. writeCompletion()
  564. end
  565. term.setCursorPos( x - scrollX, _nY - scrollY )
  566. end
  567. end]]
  568.  
  569. local redrawLine = redrawText
  570.  
  571. local function redrawMenu()
  572. -- Clear line
  573. term.setCursorPos( 1, h )
  574. term.clearLine()
  575.  
  576. -- Draw line numbers
  577. --[[term.setCursorPos( w - string.len( "Ln "..y ) + 1, h )
  578. term.setTextColor( highlightColor )
  579. term.write( "Ln " )
  580. term.setTextColor( textColor )
  581. term.write( y )]]
  582.  
  583. if not bMenu then
  584. -- Draw status
  585. term.setTextColor( colors.white )
  586. term.setBackgroundColor( colors.gray )
  587. term.write( sStatus )
  588. term.setTextColor( textColor )
  589. term.write((" "):rep(w))
  590. term.setCursorPos( 1, h )
  591. term.setCursorPos(w - ('[' .. x .. ':' .. y .. ']:[' .. markX .. ':' .. markY .. ']'):len() + 1, h)
  592. term.setTextColor( colors.lightGray )
  593. term.write('[')
  594. term.setTextColor( colors.white )
  595. term.write(x)
  596. term.setTextColor( colors.lightGray )
  597. term.write(':')
  598. term.setTextColor( colors.white )
  599. term.write(y)
  600. term.setTextColor( colors.lightGray )
  601. term.write(']:[')
  602. term.setTextColor( colors.white )
  603. term.write(markX)
  604. term.setTextColor( colors.lightGray )
  605. term.write(':')
  606. term.setTextColor( colors.white )
  607. term.write(markY)
  608. term.setTextColor( colors.lightGray )
  609. term.write(']')
  610. term.setTextColor(textColor)
  611. term.setBackgroundColor(bgColor)
  612. else
  613. -- Draw menu
  614. term.setBackgroundColor( colors.gray )
  615. term.setTextColor( textColor )
  616. term.write((" "):rep(w))
  617. term.setCursorPos( 1, h )
  618. for nItem,sItem in pairs( tMenuItems ) do
  619. if nItem == nMenuItem then
  620. term.setBackgroundColor( colors.lightGray )
  621. term.setTextColor( colors.white )
  622. term.write( " " )
  623. term.write( sItem )
  624. term.write( " " )
  625. term.setBackgroundColor( colors.gray )
  626. term.setTextColor( colors.lightGray )
  627. term.write( " " )
  628. else
  629. term.setBackgroundColor( colors.gray )
  630. term.setTextColor( colors.lightGray )
  631. term.write( " " )
  632. term.write( sItem )
  633. term.write( " " )
  634. term.write( " " )
  635. end
  636. term.setBackgroundColor( bgColor )
  637. term.setTextColor( textColor )
  638. end
  639. end
  640.  
  641. -- Reset cursor
  642. term.setCursorPos( getCursorX(y) - scrollX, y - scrollY )
  643. end
  644.  
  645. local function setCursor( newX, newY )
  646. local oldX, oldY = x, y
  647. x, y = newX, newY
  648. local screenX = getCursorX(y) - scrollX
  649. local screenY = y - scrollY
  650.  
  651. local bRedraw = false
  652. if screenX < 1 then
  653. scrollX = getCursorX(y) - 1
  654. screenX = 1
  655. bRedraw = true
  656. elseif screenX > w then
  657. scrollX = scrollX + (screenX - w)
  658. screenX = w
  659. bRedraw = true
  660. end
  661.  
  662. if screenY < 1 then
  663. scrollY = y - 1
  664. screenY = 1
  665. bRedraw = true
  666. elseif screenY > h-1 then
  667. scrollY = y - (h-1)
  668. screenY = h-1
  669. bRedraw = true
  670. end
  671.  
  672. recomplete()
  673. if bRedraw then
  674. redrawText()
  675. elseif y ~= oldY then
  676. redrawLine( oldY )
  677. redrawLine( y )
  678. else
  679. redrawLine( y )
  680. end
  681. term.setCursorPos( screenX, screenY )
  682.  
  683. redrawMenu()
  684. end
  685.  
  686. local function setCursorMark(newX, newY)
  687. markX, markY = newX, newY
  688. setCursor(newX, newY)
  689. end
  690.  
  691. local function deleteMarked()
  692. if markExists() then
  693. local msx, msy, mex, mey = getMarks()
  694.  
  695. if msy == mey then
  696. local line = tLines[mey]
  697.  
  698. tLines[mey] = line:sub(1, msx - 1) .. line:sub(mex)
  699. else
  700. if mey - msy > 1 then
  701. for i = 1, mey - msy - 1 do
  702. table.remove(tLines, msy + 1)
  703. end
  704. end
  705.  
  706. local line = tLines[msy]
  707. local line2 = tLines[msy + 1]
  708.  
  709. tLines[msy] = line:sub(1, msx - 1) .. line2:sub(mex)
  710. table.remove(tLines, msy + 1)
  711. end
  712.  
  713. setCursorMark(msx, msy)
  714. end
  715. end
  716.  
  717. local function getMarked()
  718. if markExists() then
  719. local msx, msy, mex, mey = getMarks()
  720.  
  721. if msy == mey then
  722. return tLines[msy]:sub(msx, mex - 1)
  723. else
  724. local marked = tLines[msy]:sub(msx)
  725.  
  726. if mey - msy > 1 then
  727. for i = msy + 1, mey - 1 do
  728. marked = marked .. '\n' .. tLines[i]
  729. end
  730. end
  731.  
  732. marked = marked .. '\n' .. tLines[mey]:sub(1, mex - 1)
  733.  
  734. return marked
  735. end
  736. end
  737. end
  738.  
  739. local toolsFuncs = {
  740. {
  741. 'Convert 2 spaces to tabs',
  742. function()
  743. for i = 1, #tLines do
  744. local line = tLines[i]
  745. local count = 0
  746.  
  747. while true do
  748. if line:sub(count * 2 + 1, count * 2 + 2) == ' ' then
  749. count = count + 1
  750. else
  751. break
  752. end
  753. end
  754.  
  755. tLines[i] = ('\t'):rep(count) .. line:sub(count * 2 + 1)
  756. end
  757. end
  758. }, {
  759. 'Convert tabs to 2 spaces',
  760. function()
  761. for i = 1, #tLines do
  762. local line = tLines[i]
  763. local count = 0
  764.  
  765. while true do
  766. if line:sub(count + 1, count + 1) == '\t' then
  767. count = count + 1
  768. else
  769. break
  770. end
  771. end
  772.  
  773. tLines[i] = (' '):rep(count) .. line:sub(count + 1)
  774. end
  775. end
  776. }, {
  777. 'Filter out profanity', function()
  778. if true then
  779. sStatus = "This is not finished"
  780. return
  781. end
  782. --[[> This feature is coming soon. <]]--
  783. end
  784. }
  785. }
  786.  
  787. -- for testing scrolling, etc in the tools menu
  788. --[[for i = 1, 50 do
  789. table.insert(toolsFuncs, {'Do nothing ' .. tostring(i), function() end})
  790. end]]
  791.  
  792. if cloud_catcher then
  793. table.insert(toolsFuncs, {
  794. 'Connect file remotely (CloudCatcher)',
  795. function()
  796. cloud_catcher.edit(sPath)
  797. end
  798. })
  799. end
  800.  
  801.  
  802. local findHistory = {}
  803. local jumpHistory = {}
  804. local vClipboard = ''
  805.  
  806. local tMenuFuncs = {
  807. Save = function()
  808. if bReadOnly then
  809. sStatus = "Access denied"
  810. else
  811. local ok, err = save( sPath )
  812. if ok then
  813. sStatus="Saved to "..sPath
  814. else
  815. sStatus="Error saving to "..sPath
  816. end
  817. end
  818. redrawMenu()
  819. end,
  820. Print = function()
  821. local printer = peripheral.find( "printer" )
  822. if not printer then
  823. sStatus = "No printer attached"
  824. return
  825. end
  826.  
  827. local nPage = 0
  828. local sName = fs.getName( sPath )
  829. if printer.getInkLevel() < 1 then
  830. sStatus = "Printer out of ink"
  831. return
  832. elseif printer.getPaperLevel() < 1 then
  833. sStatus = "Printer out of paper"
  834. return
  835. end
  836.  
  837. local screenTerminal = term.current()
  838. local printerTerminal = {
  839. getCursorPos = printer.getCursorPos,
  840. setCursorPos = printer.setCursorPos,
  841. getSize = printer.getPageSize,
  842. write = printer.write,
  843. }
  844. printerTerminal.scroll = function()
  845. if nPage == 1 then
  846. printer.setPageTitle( sName.." (page "..nPage..")" )
  847. end
  848.  
  849. while not printer.newPage() do
  850. if printer.getInkLevel() < 1 then
  851. sStatus = "Printer out of ink, please refill"
  852. elseif printer.getPaperLevel() < 1 then
  853. sStatus = "Printer out of paper, please refill"
  854. else
  855. sStatus = "Printer output tray full, please empty"
  856. end
  857.  
  858. term.redirect( screenTerminal )
  859. redrawMenu()
  860. term.redirect( printerTerminal )
  861.  
  862. local timer = os.startTimer(0.5)
  863. sleep(0.5)
  864. end
  865.  
  866. nPage = nPage + 1
  867. if nPage == 1 then
  868. printer.setPageTitle( sName )
  869. else
  870. printer.setPageTitle( sName.." (page "..nPage..")" )
  871. end
  872. end
  873.  
  874. bMenu = false
  875. term.redirect( printerTerminal )
  876. local ok, error = pcall( function()
  877. term.scroll()
  878. for n, sLine in ipairs( tLines ) do
  879. print( sLine )
  880. end
  881. end )
  882. term.redirect( screenTerminal )
  883. if not ok then
  884. print( error )
  885. end
  886.  
  887. while not printer.endPage() do
  888. sStatus = "Printer output tray full, please empty"
  889. redrawMenu()
  890. sleep( 0.5 )
  891. end
  892. bMenu = true
  893.  
  894. if nPage > 1 then
  895. sStatus = "Printed "..nPage.." Pages"
  896. else
  897. sStatus = "Printed 1 Page"
  898. end
  899. redrawMenu()
  900. end,
  901. Exit = function()
  902. bRunning = false
  903. end,
  904. Run = function()
  905. local sTempPath = "/.temp"
  906. local ok, err = save( sTempPath )
  907. if ok then
  908. local nTask = shell.openTab( sTempPath )
  909. if nTask then
  910. shell.switchTab( nTask )
  911. else
  912. sStatus="Error starting Task"
  913. end
  914. fs.delete( sTempPath )
  915. else
  916. sStatus="Error saving to "..sTempPath
  917. end
  918. redrawMenu()
  919. end,
  920. Tools = function()
  921. bMenu = false
  922. redrawText()
  923. redrawMenu()
  924.  
  925. local bgColor = term.getBackgroundColor()
  926. local smoothAA = 2
  927. local smoothAB = h - 1
  928. local scrollY = 0
  929. local height = h - 8
  930. local offset = 5
  931. local selected = 1
  932. local run = false
  933.  
  934. while smoothAB > 2.1 do
  935. paintutils.drawFilledBox(2, smoothAB, w - 1, (smoothAB - 2) + h - 1, colors.gray)
  936. smoothAB = smoothAB + ui.smoothAdd(smoothAB, smoothAA, 3)
  937. term.setCursorPos(3, (smoothAB - 2) + 3)
  938. term.write('Tools')
  939. term.setTextColor(colors.lightGray)
  940. term.setCursorPos(3, (smoothAB - 2) + offset + height + 1)
  941. term.write('Arrows to select. Enter to run. Ctrl to cancel.')
  942. term.setBackgroundColor(colors.gray)
  943. term.setTextColor(colors.lightGray)
  944. local toWrite = '(1/' .. tostring(#toolsFuncs) .. ')'
  945. term.setCursorPos(w - toWrite:len() - 1, (smoothAB - 2) + 3)
  946. term.write(toWrite)
  947. term.setTextColor(colors.white)
  948.  
  949. for i = 1, height do
  950. term.setBackgroundColor(colors.gray)
  951. local index = i + scrollY
  952. term.setTextColor(colors.white)
  953.  
  954. if selected == index then
  955. term.setTextColor(keywordColor)
  956. end
  957.  
  958. if index <= #toolsFuncs then
  959. paintutils.drawLine(3, (smoothAB - 2) + offset + i - 1 , w - 1, offset + i - 1, color)
  960. term.setCursorPos(3, (smoothAB - 2) + offset + index - scrollY - 1)
  961.  
  962. if 1 == index then
  963. term.write('> ')
  964. else
  965. term.write(' ')
  966. end
  967.  
  968. term.write(toolsFuncs[index][1])
  969. end
  970. term.setBackgroundColor(bgColor)
  971. end
  972. redrawMenu()
  973. sleep(0.01)
  974. end
  975. term.setTextColour(colors.white)
  976. term.setBackgroundColor(colors.gray)
  977. term.setCursorPos(3, 3)
  978. term.write('Tools')
  979.  
  980. term.setTextColor(colors.lightGray)
  981. term.setCursorPos(3, offset + height + 1)
  982. term.write('Arrows to select. Enter to run. Ctrl to cancel.')
  983.  
  984. while true do
  985. term.setBackgroundColor(colors.gray)
  986. term.setTextColor(colors.lightGray)
  987. local toWrite = '(' .. tostring(selected) .. '/' .. tostring(#toolsFuncs) .. ')'
  988. term.setCursorPos(w - toWrite:len() - 1, 3)
  989. term.write(toWrite)
  990. term.setTextColor(colors.white)
  991.  
  992. for i = 1, height do
  993. local index = i + scrollY
  994. term.setTextColor(colors.white)
  995.  
  996. if selected == index then
  997. term.setTextColor(keywordColor)
  998. end
  999.  
  1000. if index <= #toolsFuncs then
  1001. paintutils.drawLine(3, offset + i - 1, w - 1, offset + i - 1, color)
  1002. term.setCursorPos(3, offset + index - scrollY - 1)
  1003.  
  1004. if selected == index then
  1005. term.write('> ')
  1006. else
  1007. term.write(' ')
  1008. end
  1009.  
  1010. term.write(toolsFuncs[index][1])
  1011. end
  1012. end
  1013.  
  1014. local evt, arg1, arg2, arg3 = os.pullEvent()
  1015. local clampScroll = false
  1016.  
  1017. if evt == 'key' then
  1018. clampScroll = true
  1019.  
  1020. if arg1 == keys.up then
  1021. if selected == 1 then
  1022. selected = #toolsFuncs
  1023. else
  1024. selected = selected - 1
  1025. end
  1026. elseif arg1 == keys.down then
  1027. if selected == #toolsFuncs then
  1028. selected = 1
  1029. else
  1030. selected = selected + 1
  1031. end
  1032. elseif arg1 == keys.pageUp then
  1033. selected = math.max(1, math.min(#toolsFuncs, selected - height))
  1034. elseif arg1 == keys.pageDown then
  1035. selected = math.max(1, math.min(#toolsFuncs, selected + height))
  1036. elseif arg1 == keys.enter then
  1037. run = true
  1038.  
  1039. break
  1040. elseif arg1 == keys.leftCtrl then
  1041. break
  1042. else
  1043. clampScroll = false
  1044. end
  1045. elseif evt == 'mouse_click' then
  1046. if arg1 == 1 then
  1047. if arg2 > 1 and arg2 < w then
  1048. if arg3 >= offset and arg3 < offset + height then
  1049. local index = arg3 - offset + scrollY + 1
  1050.  
  1051. if index <= #toolsFuncs then
  1052. selected = index
  1053. run = true
  1054.  
  1055. break
  1056. end
  1057. end
  1058. end
  1059. end
  1060. elseif evt == 'mouse_scroll' then
  1061. if arg2 > 1 and arg2 < w then
  1062. if arg3 >= offset and arg3 < offset + height then
  1063. scrollY = math.max(0, math.min(#toolsFuncs - height, scrollY + arg1))
  1064. end
  1065. end
  1066. end
  1067.  
  1068. if clampScroll == true then
  1069. if selected > height + scrollY then
  1070. scrollY = selected - height
  1071. elseif selected <= scrollY then
  1072. scrollY = selected - 1
  1073. end
  1074. end
  1075. end
  1076.  
  1077. term.setBackgroundColor(bgColor)
  1078. redrawText()
  1079. redrawMenu()
  1080. bMenu = true
  1081.  
  1082. if run then
  1083. if not bReadOnly then
  1084. bMenu = false
  1085. redrawMenu()
  1086. toolsFuncs[selected][2]()
  1087. onUpdate()
  1088. redrawText()
  1089. bMenu = true
  1090. else
  1091. sStatus = 'File is read-only'
  1092. end
  1093. end
  1094. end,
  1095. Find = function()
  1096. term.setCursorPos(1, h)
  1097. term.clearLine()
  1098. term.setBackgroundColor(colors.gray)
  1099. term.setTextColor(colors.white)
  1100. term.write((" "):rep(w))
  1101. term.setCursorPos( 1, h )
  1102. term.write('Find: ')
  1103. term.setTextColor(colors.lightGray)
  1104.  
  1105. local text = read(nil, findHistory)
  1106. table.insert(findHistory, text)
  1107.  
  1108. local fLine, fPos
  1109. local found = false
  1110.  
  1111. for i = y, #tLines do
  1112. local searchText = tLines[i]
  1113.  
  1114. if i == y then
  1115. searchText = searchText:sub(x + 1)
  1116. end
  1117.  
  1118. local searchPat = ''
  1119.  
  1120. local escapedChars = {
  1121. ['%'] = true, ['.'] = true, ['('] = true, [')'] = true,
  1122. ['%'] = true, ['+'] = true, ['-'] = true, ['*'] = true,
  1123. ['?'] = true, ['['] = true, ['^'] = true, ['$'] = true
  1124. }
  1125.  
  1126. for i = 1, #text do
  1127. local char = text:sub(i, i)
  1128.  
  1129. if escapedChars[char] == true then
  1130. searchPat = searchPat .. '%'
  1131. end
  1132.  
  1133. searchPat = searchPat .. char
  1134. end
  1135.  
  1136. local pos = searchText:find(searchPat)
  1137.  
  1138. if pos then
  1139. fLine = i
  1140. fPos = pos
  1141.  
  1142. if i == y then
  1143. fPos = fPos + x
  1144. end
  1145.  
  1146. found = true
  1147.  
  1148. break
  1149. end
  1150. end
  1151.  
  1152. if not found then
  1153. sStatus = 'Found no matches'
  1154. else
  1155. setCursorMark(fPos, fLine)
  1156. setCursor(fPos + text:len(), fLine)
  1157. sStatus = 'Found a match on line ' .. tostring(fLine)
  1158. end
  1159.  
  1160. redrawText()
  1161. term.setBackgroundColor(bgColor)
  1162. term.setTextColour(highlightColor)
  1163. end,
  1164. Jump = function()
  1165. term.setCursorPos(1, h)
  1166. term.clearLine()
  1167. term.setBackgroundColor(colors.gray)
  1168. term.setTextColor(colors.white)
  1169. term.write((" "):rep(w))
  1170. term.setCursorPos( 1, h )
  1171. term.write('Jump: ')
  1172. term.setTextColor(colors.lightGray)
  1173.  
  1174. local toJump = read(nil, jumpHistory)
  1175. table.insert(jumpHistory, toJump)
  1176.  
  1177. local num = tonumber(toJump)
  1178.  
  1179. if not num then
  1180. sStatus = 'Invalid line'
  1181. else
  1182. if num % 1 == 0 then
  1183. if num >= 1 and num <= #tLines then
  1184. setCursorMark(1, num)
  1185. sStatus = 'Successfully jumped to line ' .. toJump
  1186. else
  1187. sStatus = 'Line is not in the range 1 - ' .. tostring(#tLines)
  1188. end
  1189. else
  1190. sStatus = 'Line must be an integer'
  1191. end
  1192. end
  1193.  
  1194. term.setBackgroundColor(bgColor)
  1195. term.setTextColor(highlightColor)
  1196. redrawText()
  1197. end,
  1198. Copy = function()
  1199. vClipboard = getMarked()
  1200. if vClipboard == nil then return end
  1201.  
  1202. local lines = 1
  1203.  
  1204. for i = 1, #vClipboard do
  1205. if vClipboard:sub(i, i) == '\n' then
  1206. lines = lines + 1
  1207. end
  1208. end
  1209.  
  1210. sStatus = 'Copied ' .. tostring(lines) .. ' lines'
  1211. end,
  1212. VPaste = function()
  1213. if not bReadOnly then
  1214. deleteMarked()
  1215. local lines = 1
  1216.  
  1217. if vClipboard == nil then return end
  1218.  
  1219. for i = 1, #vClipboard do
  1220. local char = vClipboard:sub(i, i)
  1221.  
  1222. if char == '\n' then
  1223. lines = lines + 1
  1224. local sLine = tLines[y]
  1225. tLines[y] = string.sub(sLine,1,x-1)
  1226. table.insert( tLines, y+1, string.sub(sLine,x) )
  1227. x = 1
  1228. y = y + 1
  1229. else
  1230. tLines[y] = tLines[y]:sub(1, x - 1) .. char .. tLines[y]:sub(x)
  1231. x = x + 1
  1232. end
  1233. end
  1234.  
  1235. setCursorMark(x, y)
  1236. onUpdate()
  1237. redrawText()
  1238.  
  1239. sStatus = 'Pasted ' .. tostring(lines) .. ' lines'
  1240. else
  1241. sStatus = 'File is read-only'
  1242. end
  1243. end
  1244. }
  1245.  
  1246. local function doMenuItem( _n )
  1247. tMenuFuncs[tMenuItems[_n]]()
  1248. if bMenu then
  1249. bMenu = false
  1250. term.setCursorBlink( true )
  1251. end
  1252. redrawMenu()
  1253. end
  1254.  
  1255. -- Actual program functionality begins
  1256. load(sPath)
  1257.  
  1258. term.setBackgroundColor( bgColor )
  1259. term.clear()
  1260. term.setCursorPos(getCursorX(y), y)
  1261. term.setCursorBlink( true )
  1262.  
  1263. recomplete()
  1264. onUpdate()
  1265. redrawText()
  1266. redrawMenu()
  1267.  
  1268. local function acceptCompletion()
  1269. if nCompletion then
  1270. -- Append the completion
  1271. local sCompletion = tCompletions[ nCompletion ]
  1272. tLines[y] = tLines[y] .. sCompletion
  1273. onUpdate()
  1274. setCursorMark( x + string.len( sCompletion ), y )
  1275. end
  1276. end
  1277.  
  1278. local holdingShift = false
  1279.  
  1280. -- Handle input
  1281. while bRunning do
  1282. local sEvent, param, param2, param3 = os.pullEvent()
  1283. if sEvent == "key" then
  1284. local oldX, oldY = x, y
  1285. if param == keys.up then
  1286. local cursorSet = setCursorMark
  1287.  
  1288. if holdingShift then
  1289. cursorSet = setCursor
  1290. end
  1291.  
  1292. -- Up
  1293. if not bMenu then
  1294. if nCompletion then
  1295. -- Cycle completions
  1296. nCompletion = nCompletion - 1
  1297. if nCompletion < 1 then
  1298. nCompletion = #tCompletions
  1299. end
  1300. redrawLine(y)
  1301.  
  1302. elseif y > 1 then
  1303. -- Move cursor up
  1304. --[[cursorSet(
  1305. math.min( x, string.len( tLines[y - 1] ) + 1 ),
  1306. y - 1
  1307. )]]
  1308.  
  1309. local cx = getCursorX(y)
  1310. local pos = cxToPos(y - 1, cx)
  1311.  
  1312. cursorSet(pos, y - 1)
  1313. else
  1314. cursorSet(1, y)
  1315. end
  1316. end
  1317.  
  1318. elseif param == keys.down then
  1319. local cursorSet = setCursorMark
  1320.  
  1321. if holdingShift then
  1322. cursorSet = setCursor
  1323. end
  1324.  
  1325. -- Down
  1326. if not bMenu then
  1327. -- Move cursor down
  1328. if nCompletion then
  1329. -- Cycle completions
  1330. nCompletion = nCompletion + 1
  1331. if nCompletion > #tCompletions then
  1332. nCompletion = 1
  1333. end
  1334. redrawLine(y)
  1335.  
  1336. elseif y < #tLines then
  1337. -- Move cursor down
  1338. --[[cursorSet(
  1339. math.min( x, string.len( tLines[y + 1] ) + 1 ),
  1340. y + 1
  1341. )]]
  1342.  
  1343. local cx = getCursorX(y)
  1344. local pos = cxToPos(y + 1, cx)
  1345.  
  1346. cursorSet(pos, y + 1)
  1347. else
  1348. cursorSet(#tLines[y] + 1, y)
  1349. end
  1350. end
  1351.  
  1352. elseif param == keys.tab then
  1353. -- Tab
  1354. if not bMenu and not bReadOnly then
  1355. if nCompletion and x == string.len(tLines[y]) + 1 then
  1356. -- Accept autocomplete
  1357. acceptCompletion()
  1358. else
  1359. local msx, msy, mex, mey = getMarks()
  1360.  
  1361. for i = msy, mey do
  1362. local line = tLines[i]
  1363.  
  1364. if holdingShift then
  1365. -- Unindent line
  1366. if line:sub(1, 1) == '\t' then
  1367. line = line:sub(2)
  1368. end
  1369. else
  1370. -- Indent line
  1371. if markExists() then
  1372. line = '\t' .. line
  1373. else
  1374. line = line:sub(1, x - 1) .. '\t' .. line:sub(x)
  1375. end
  1376. end
  1377.  
  1378. tLines[i] = line
  1379. end
  1380.  
  1381. if holdingShift then
  1382. markX = math.max(1, markX - 1)
  1383. setCursor(math.max(1, x - 1), y)
  1384. else
  1385. markX = markX + 1
  1386. setCursor(x + 1, y)
  1387. end
  1388.  
  1389. onUpdate()
  1390. redrawText()
  1391. end
  1392. end
  1393.  
  1394. elseif param == keys.pageUp then
  1395. local cursorSet = setCursorMark
  1396.  
  1397. if holdingShift then
  1398. cursorSet = setCursor
  1399. end
  1400.  
  1401. -- Page Up
  1402. if not bMenu then
  1403. -- Move up a page
  1404. local newY
  1405. if y - (h - 1) >= 1 then
  1406. newY = y - (h - 1)
  1407. else
  1408. newY = 1
  1409. end
  1410. cursorSet(
  1411. math.min( x, string.len( tLines[newY] ) + 1 ),
  1412. newY
  1413. )
  1414. end
  1415.  
  1416. elseif param == keys.pageDown then
  1417. local cursorSet = setCursorMark
  1418.  
  1419. if holdingShift then
  1420. cursorSet = setCursor
  1421. end
  1422.  
  1423. -- Page Down
  1424. if not bMenu then
  1425. -- Move down a page
  1426. local newY
  1427. if y + (h - 1) <= #tLines then
  1428. newY = y + (h - 1)
  1429. else
  1430. newY = #tLines
  1431. end
  1432. local newX = math.min( x, string.len( tLines[newY] ) + 1 )
  1433. cursorSet( newX, newY )
  1434. end
  1435.  
  1436. elseif param == keys.home then
  1437. local cursorSet = setCursorMark
  1438.  
  1439. if holdingShift then
  1440. cursorSet = setCursor
  1441. end
  1442.  
  1443. -- Home
  1444. if not bMenu then
  1445. -- Move cursor to the beginning
  1446. if x > 1 then
  1447. cursorSet(1,y)
  1448. end
  1449. end
  1450.  
  1451. elseif param == keys["end"] then
  1452. local cursorSet = setCursorMark
  1453.  
  1454. if holdingShift then
  1455. cursorSet = setCursor
  1456. end
  1457.  
  1458. -- End
  1459. if not bMenu then
  1460. -- Move cursor to the end
  1461. local nLimit = string.len( tLines[y] ) + 1
  1462. if x < nLimit then
  1463. cursorSet( nLimit, y )
  1464. end
  1465. end
  1466.  
  1467. elseif param == keys.left then
  1468. local cursorSet = setCursorMark
  1469.  
  1470. if holdingShift then
  1471. cursorSet = setCursor
  1472. end
  1473.  
  1474. -- Left
  1475. if not bMenu then
  1476. if x > 1 then
  1477. -- Move cursor left
  1478. cursorSet( x - 1, y )
  1479. elseif x==1 and y>1 then
  1480. cursorSet( string.len( tLines[y-1] ) + 1, y - 1 )
  1481. end
  1482. else
  1483. -- Move menu left
  1484. nMenuItem = nMenuItem - 1
  1485. if nMenuItem < 1 then
  1486. nMenuItem = #tMenuItems
  1487. end
  1488. redrawMenu()
  1489. end
  1490.  
  1491. elseif param == keys.right then
  1492. local cursorSet = setCursorMark
  1493.  
  1494. if holdingShift then
  1495. cursorSet = setCursor
  1496. end
  1497.  
  1498. -- Right
  1499. if not bMenu then
  1500. local nLimit = string.len( tLines[y] ) + 1
  1501. if x < nLimit then
  1502. -- Move cursor right
  1503. cursorSet( x + 1, y )
  1504. elseif nCompletion and x == string.len(tLines[y]) + 1 then
  1505. -- Accept autocomplete
  1506. acceptCompletion()
  1507. elseif x==nLimit and y<#tLines then
  1508. -- Go to next line
  1509. cursorSet( 1, y + 1 )
  1510. end
  1511. else
  1512. -- Move menu right
  1513. nMenuItem = nMenuItem + 1
  1514. if nMenuItem > #tMenuItems then
  1515. nMenuItem = 1
  1516. end
  1517. redrawMenu()
  1518. end
  1519.  
  1520. elseif param == keys.delete then
  1521. -- Delete
  1522. if not bMenu and not bReadOnly then
  1523. if markExists() then
  1524. deleteMarked()
  1525. else
  1526. local nLimit = string.len( tLines[y] ) + 1
  1527. if x < nLimit then
  1528. local sLine = tLines[y]
  1529. tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  1530. elseif y<#tLines then
  1531. tLines[y] = tLines[y] .. tLines[y+1]
  1532. table.remove( tLines, y+1 )
  1533. end
  1534. end
  1535.  
  1536. onUpdate()
  1537. recomplete()
  1538. redrawText()
  1539. end
  1540.  
  1541. elseif param == keys.backspace then
  1542. -- Backspace
  1543. if not bMenu and not bReadOnly then
  1544. if markExists() then
  1545. deleteMarked()
  1546. else
  1547. if x > 1 then
  1548. -- Remove character
  1549. local sLine = tLines[y]
  1550. tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  1551. setCursorMark( x - 1, y )
  1552. elseif y > 1 then
  1553. -- Remove newline
  1554. local sPrevLen = string.len( tLines[y-1] )
  1555. tLines[y-1] = tLines[y-1] .. tLines[y]
  1556. table.remove( tLines, y )
  1557. setCursorMark( sPrevLen + 1, y - 1 )
  1558. end
  1559. end
  1560.  
  1561. onUpdate()
  1562. recomplete()
  1563. redrawText()
  1564. end
  1565.  
  1566. elseif param == keys.enter then
  1567. -- Enter
  1568. if not bMenu and not bReadOnly then
  1569. deleteMarked()
  1570.  
  1571. -- Newline
  1572. local sLine = tLines[y]
  1573. local _,tabs=string.find(sLine,"^[\t]+")
  1574. if not tabs then
  1575. tabs=0
  1576. end
  1577. tLines[y] = string.sub(sLine,1,x-1)
  1578. table.insert( tLines, y+1, string.rep('\t',tabs)..string.sub(sLine,x) )
  1579. onUpdate()
  1580. setCursorMark( tabs + 1, y + 1 )
  1581. redrawText()
  1582.  
  1583. elseif bMenu then
  1584. -- Menu selection
  1585. doMenuItem( nMenuItem )
  1586.  
  1587. end
  1588.  
  1589. elseif (param == keys.leftCtrl or param == keys.rightCtrl or param == keys.rightAlt) and not param2 then
  1590. -- Menu toggle
  1591. bMenu = not bMenu
  1592. if bMenu then
  1593. term.setCursorBlink( false )
  1594. else
  1595. term.setCursorBlink( true )
  1596. end
  1597. redrawMenu()
  1598.  
  1599. elseif param == 42 then
  1600. holdingShift = true
  1601. end
  1602.  
  1603. elseif sEvent == 'key_up' then
  1604. if param == 42 then
  1605. holdingShift = false
  1606. end
  1607.  
  1608. elseif sEvent == "char" then
  1609. if not bMenu and not bReadOnly then
  1610. deleteMarked()
  1611.  
  1612. -- Input text
  1613. local sLine = tLines[y]
  1614. tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  1615. onUpdate()
  1616. setCursorMark( x + 1, y )
  1617.  
  1618. elseif bMenu then
  1619. -- Select menu items
  1620. for n,sMenuItem in ipairs( tMenuItems ) do
  1621. if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
  1622. doMenuItem( n )
  1623. break
  1624. end
  1625. end
  1626. end
  1627.  
  1628. elseif sEvent == "paste" then
  1629. if not bMenu and not bReadOnly then
  1630. -- Input text
  1631. --[[local sLine = tLines[y]
  1632. tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  1633. onUpdate()
  1634. setCursorMark( x + string.len( param ), y )]]
  1635.  
  1636. --[[deleteMarked()
  1637.  
  1638. local newX, newY = x, y
  1639.  
  1640. for i = 1, #param do
  1641. local char = param:sub(i, i)
  1642.  
  1643. if char == '\n' then
  1644. local rest = tLines[newY]:sub(newX)
  1645. tLines[newY] = tLines[newY]:sub(1, newX - 1)
  1646.  
  1647. table.insert(tLines, rest, newY + 1)
  1648.  
  1649. newY = newY + 1
  1650. newX = 1
  1651. else
  1652. local line = tLines[newY]
  1653.  
  1654. line = line:sub(1, newX - 1) .. char .. line:sub(newX)
  1655.  
  1656. tLines[newY] = line
  1657. newX = newX + 1
  1658. end
  1659. end
  1660.  
  1661. onUpdate()
  1662. setCursorMark(newX, newY)]]
  1663.  
  1664. local oldvClipboard = vClipboard
  1665. vClipboard = param
  1666. tMenuFuncs.VPaste()
  1667. redrawMenu()
  1668. vClipboard = oldvClipboard
  1669. end
  1670.  
  1671. elseif sEvent == "mouse_click" then
  1672. local cursorSet = setCursorMark
  1673.  
  1674. if holdingShift then
  1675. cursorSet = setCursor
  1676. end
  1677.  
  1678. if not bMenu then
  1679. if param == 1 then
  1680. -- Left click
  1681. local cx,cy = param2, param3
  1682. if cy < h then
  1683. local tx, ty = cx + scrollX, cy + scrollY
  1684. local newX, newY
  1685.  
  1686. if ty <= #tLines then
  1687. newY = math.min(#tLines, math.max(ty, 1))
  1688. tx = cxToPos(ty, tx)
  1689. newX = math.min(tLines[newY]:len() + 1, math.max(1, tx))
  1690. else
  1691. newY = #tLines
  1692. newX = #tLines[newY] + 1
  1693. end
  1694.  
  1695. cursorSet(newX, newY)
  1696. end
  1697. end
  1698. end
  1699.  
  1700. elseif sEvent == "mouse_drag" then
  1701. if not bMenu then
  1702. if param == 1 then
  1703. -- Left click
  1704. local cx,cy = param2, param3
  1705. if cy < h then
  1706. local tx, ty = cx + scrollX, cy + scrollY
  1707. local newX, newY
  1708.  
  1709. if ty <= #tLines then
  1710. newY = math.min(#tLines, math.max(ty, 1))
  1711. tx = cxToPos(ty, tx)
  1712. newX = math.min(tLines[newY]:len() + 1, math.max(1, tx))
  1713. else
  1714. newY = #tLines
  1715. newX = #tLines[newY] + 1
  1716. end
  1717.  
  1718. setCursor(newX, newY)
  1719. end
  1720. end
  1721. end
  1722.  
  1723. elseif sEvent == "mouse_scroll" then
  1724. if not bMenu then
  1725. if param == -1 then
  1726. -- Scroll up
  1727. if scrollY > 0 then
  1728. -- Move cursor up
  1729. scrollY = scrollY - 1
  1730. redrawText()
  1731. end
  1732.  
  1733. elseif param == 1 then
  1734. -- Scroll down
  1735. local nMaxScroll = #tLines - (h-1)
  1736. if scrollY < nMaxScroll then
  1737. -- Move cursor down
  1738. scrollY = scrollY + 1
  1739. redrawText()
  1740. end
  1741.  
  1742. end
  1743. end
  1744.  
  1745. elseif sEvent == "term_resize" then
  1746. w,h = term.getSize()
  1747. setCursor( x, y )
  1748. redrawMenu()
  1749. redrawText()
  1750.  
  1751. end
  1752. end
  1753.  
  1754. -- Cleanup
  1755. term.clear()
  1756. term.setCursorBlink( false )
  1757. term.setCursorPos( 1, 1 )
  1758.  
Add Comment
Please, Sign In to add comment