supreamcallum45

Untitled

Jan 3rd, 2021
813
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --# Monitor Mirror v2.1 - Program to mirror terminal contents onto monitor.
  2. --# Made By Wojbie
  3. --# http://pastebin.com/DW3LCC3L
  4.  
  5. function printUsage()
  6.     print( "Usage: mirror <name> <program> <arguments>" )
  7.     return
  8. end
  9.  
  10. local tArgs = { ... }
  11. if #tArgs < 2 then
  12.     printUsage()
  13.     return
  14. end
  15.  
  16. local sName = tArgs[1]
  17. if peripheral.getType( sName ) ~= "monitor" then
  18.     print( "No monitor named ".. sName )
  19.     return
  20. end
  21.  
  22. local sProgram = tArgs[2]
  23. local sPath = shell.resolveProgram( sProgram )
  24. if sPath == nil then
  25.     print( "No such program: "..sProgram )
  26.     return
  27. end
  28.  
  29. local fMain = function()
  30.     shell.run( sPath, table.unpack( tArgs, 3 ) )
  31. end
  32.  
  33.  
  34. --Spacial table that will transferr all functions call to each and every sub table. Static tables version
  35. function createMultitable(...)
  36.  
  37.     local tab = {...}
  38.     if #tab==1 and tab[1] and type(tab[1])=="table" then tab = tab[1] end
  39.     if #tab==0 then error("Expected table of tables or any tables to table. I know it makes no sense.", 2) end
  40.  
  41.     local manymeta={ --Anytime index is requested fist table is used as refference.
  42.     ["__index"]=function (parent , key)
  43.         if tab and tab[1] and tab[1][key] then --If it has value it tested then
  44.             if type(tab[1][key]) =="function" then --If its function then a function that calls all tables in row is made
  45.                 return function(...)
  46.                     local ret={}
  47.                     local tArgs={...}
  48.                     for i,k in ipairs(tab) do
  49.                         if k[key] then
  50.                             if #ret==0 then ret={k[key](unpack(tArgs))} --ret contains returns from first table that returned anything.
  51.                             else k[key](unpack(tArgs)) end
  52.                         end
  53.                     end
  54.                     return unpack(ret)
  55.                 end
  56.             else
  57.                 return tab[1][key]  --If its not a function then its just given out.
  58.             end
  59.         else
  60.             return nil --Of it not exist in first table give nothing
  61.         end
  62.     end,
  63.     ["__newindex"]=function (parent, key, value) --If someone wants to add anything to the table
  64.         --do nothing.
  65.     end,
  66.     ["__call"]=function (parent, key) --If someone calls table like function give him direct acces to table list.
  67.         --if key then tab = key end changing of content disalowed in static mode
  68.         return tab
  69.     end,
  70.     ["__len"]=function (parent, key) --Not sure if it works but this is giving the leanght of first table or 0 if there is no first table.
  71.         return (tab[1] and #tab[1]) or 0
  72.     end,
  73.     ["__metatable"]=false,--No touching the metatable.
  74.     --["__type"]="WojbieManyMeta",--Custom type? Not in current version and not sure if wise. Commented out for now.
  75.     }
  76.  
  77.     local out = {}
  78.     for key,fun in pairs(tab[1]) do --create static table of multitable functions using first one as template
  79.         out[key] = function(...)
  80.             local ret={}
  81.             local tArgs={...}
  82.             for i,k in ipairs(tab) do
  83.                 if k[key] then
  84.                     if #ret==0 then ret={k[key](unpack(tArgs))} --ret contains returns from first table that returned anything.
  85.                     else k[key](unpack(tArgs)) end
  86.                 end
  87.             end
  88.             return unpack(ret)
  89.         end
  90.     end
  91.     return setmetatable(out,manymeta) --create acctual manymeta table and return it
  92.    
  93. end
  94.  
  95.  --Create Window that is inside other terminal object of selected size. If setTextScale is defined it attempts to finds largest possible size for terminal. Its auto centered and not needed part of screen is painter gray and frame is added. If sName is defined its added onto frame if possible.
  96. local tBor={"+","-","|"}--{"#","=","H"}
  97. local function createFramedWindow(sSide,nX,nY,sName)
  98.    
  99.     if (type( sSide ) ~= "table" and type( sSide ) ~= "string") or
  100.        type( nX ) ~= "number" or
  101.        type( nY ) ~= "number" or
  102.        (sName ~= nil and type( sName ) ~= "string")then
  103.         error( "Expected string/object, number, number, [string]", 2 )
  104.     end
  105.    
  106.     local monitor
  107.     if type( sSide ) == "table" then monitor = sSide
  108.     else monitor = peripheral.wrap(sSide) end
  109.    
  110.     if not monitor then error( "No monitor detected on side "..sSide, 2 ) end
  111.    
  112.     local nOffTop,nOffBot,nOffLeft,nOffRight
  113.     local nOffTopBot, nOffLeftnXRight
  114.     local nMonX,nMonY
  115.     local tLines
  116.     local win = window.create( monitor, 1, 1, nX, nY, false )
  117.     local reposition = win.reposition
  118.    
  119.     local function redraw()
  120.         for i=1,nMonY,1 do
  121.             monitor.setCursorPos(1,i)
  122.             if i<nOffTop then monitor.blit(tLines.e,tLines.f,tLines.b) --print(i,tLines.e)
  123.             elseif i==nOffTop then monitor.blit(tLines.n or tLines.t,tLines.f,tLines.b) --print(i,tLines.n)
  124.             elseif i<nOffTopBot then monitor.blit(tLines.m,tLines.f,tLines.b) --print(i,tLines.m)
  125.             elseif i==nOffTopBot then monitor.blit(tLines.t,tLines.f,tLines.b) --print(i,tLines.t)
  126.             else monitor.blit(tLines.e,tLines.f,tLines.b) end --print(i,tLines.m)
  127.         end
  128.     end
  129.    
  130.     local function build()
  131.         if monitor.setTextScale then
  132.             local nCX,nCY
  133.             for i=5,0.5,-0.5 do
  134.                 monitor.setTextScale(i)
  135.                 nCX,nCY = monitor.getSize()
  136.                 if nCX > nX and nCY > nY then break end
  137.             end
  138.         end
  139.         nMonX,nMonY = monitor.getSize()
  140.        
  141.         nOffLeft=math.max((nMonX-nX)/2,0)
  142.         nOffRight=math.ceil(nOffLeft)
  143.         nOffLeft=math.floor(nOffLeft)
  144.         nOffTop=math.max((nMonY-nY)/2,0)
  145.         nOffBot=math.ceil(nOffTop)
  146.         nOffTop=math.floor(nOffTop)
  147.         nOffTopBot=nOffTop+nY+1
  148.         nOffLeftnXRight = nOffLeft + nX + nOffRight
  149.                
  150.         tLines = {}
  151.         tLines.e = string.rep(" ",nOffLeftnXRight)
  152.         tLines.t = string.rep(" ",math.max(0,nOffLeft-1))..(nOffLeft>0 and tBor[1] or "")..string.rep(tBor[2],nX)..(nOffRight>0 and tBor[1] or "")..string.rep(" ",math.max(0,nOffRight-1))
  153.         tLines.m = string.rep(" ",math.max(0,nOffLeft-1))..(nOffLeft>0 and tBor[3] or "")..string.rep(" ",nX)..(nOffRight>0 and tBor[3] or "")..string.rep(" ",math.max(0,nOffRight-1))
  154.         if sName and type(sName)=="string" and #sName<= nX then
  155.             local sName2=string.sub(sName, 1, nX)
  156.             local a=(nX-string.len(sName2))/2
  157.             local b=math.ceil(a)
  158.             a=math.floor(a)
  159.             tLines.n = string.rep(" ",math.max(0,nOffLeft-1))..(nOffLeft>0 and tBor[1] or "")..string.rep(tBor[2],a)..sName2..string.rep(tBor[2],b)..(nOffRight>0 and tBor[1] or "")..string.rep(" ",math.max(0,nOffRight-1))
  160.         end
  161.         tLines.f = string.rep("7",nOffLeftnXRight) --0
  162.         tLines.b = string.rep("8",nOffLeftnXRight) --f
  163.        
  164.         redraw()
  165.         reposition( nOffLeft+1, nOffTop+1, nX, nY ) --window.reposition localized
  166.         win.setVisible( true )
  167.        
  168.     end
  169.  
  170.     build()
  171.     win.redrawBorder = function() return redraw() end
  172.     win.synch = function() return build() end
  173.     win.setName = function(A) sName=(A ~= nil and type( A ) == "string") and A or nil return build() end
  174.     win.resize = function(A,B)
  175.         if  type( A ) ~= "number" or
  176.             type( B ) ~= "number" then
  177.             error( "Expected number, number", 2 )
  178.         end
  179.         nX,nY = A,B
  180.         return build()
  181.     end
  182.     win.localize = function(A,B)
  183.         local x,y = A-nOffLeft,B-nOffTop
  184.         if x>0 and y>0 and x<=nX and y<=nY then
  185.             return x,y
  186.         end
  187.     end  --localizes coordinates for inside of the window.
  188.    
  189.     return win
  190.    
  191.     --if sSide is a monitor object (like multiMon! http://www.computercraft.info/forums2/index.php?/topic/18229-multimon-multiple-monitors-in-computercraft/) use it instead of side.
  192.     --create window on monitor
  193.     --sized nX nY
  194.     --centered on monitor
  195.     --monitor scalled to max text size possible.
  196.     --remove reposition call and store it in local wariable.
  197.     --add synch function that rescales monitor and redraws window. if provided with new nX,nY it will resize too.
  198.  
  199. end
  200.  
  201. local function  mirrorToMonitors(fMain,tSides,sName) --tSides is table with monitor sides to write on. If empty or not defined it will take all possible sides.
  202.     if type( fMain ) ~= "function" or
  203.         (tSides ~= nil and type( tSides ) ~= "table") or
  204.         (sName ~= nil and type( sName ) ~= "string") then
  205.         error( "Expected function, table, [string]", 2 )
  206.     end
  207.    
  208.    
  209.     local parent = term.current()
  210.     local x,y = parent.getSize()
  211.     local tMirrorsSides = {}
  212.     local tMirrors = {}
  213.    
  214.     if not tSides or #tSides == 0 then
  215.         peripheral.find("monitor",function(name,wrap) tMirrorsSides[name] = createFramedWindow(name,x,y,sName) table.insert(tMirrors,tMirrorsSides[name]) end)
  216.     else
  217.         for i,k in pairs(tSides) do
  218.             if peripheral.isPresent(k) and peripheral.getType(k) == "monitor" then
  219.                 tMirrorsSides[k] = createFramedWindow(k,x,y,sName)
  220.                 table.insert(tMirrors,tMirrorsSides[k])
  221.             end
  222.         end
  223.     end
  224.    
  225.     local mirr = createMultitable(tMirrors)
  226.     local mix = createMultitable(parent,mirr)
  227.     term.redirect(mix)
  228.  
  229.     local co = coroutine.create(fMain)
  230.  
  231.     local function resume( ... )
  232.         local ok, param = coroutine.resume( co, ... )
  233.         if not ok then
  234.             printError( param )
  235.         end
  236.         return param
  237.     end
  238.  
  239.     local ok, param = pcall( function()
  240.         local sFilter = resume()
  241.         local TResizeLoop = {}
  242.         while coroutine.status( co ) ~= "dead" do
  243.             local tEvent = { os.pullEventRaw() }
  244.             if tEvent[1] == "term_resize" then
  245.                 mirr.resize(parent.getSize())
  246.             elseif tEvent[1] == "monitor_resize" and tMirrorsSides[tEvent[2]] then
  247.                 if TResizeLoop[tEvent[2]] then
  248.                     TResizeLoop[tEvent[2]] = false
  249.                 else
  250.                     tMirrorsSides[tEvent[2]].synch()
  251.                     TResizeLoop[tEvent[2]] = true
  252.                 end
  253.             end
  254.             if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == "terminate" then
  255.                 sFilter = resume( table.unpack( tEvent ) )
  256.             end
  257.             if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "mouse_click") then
  258.                 if tEvent[1] == "monitor_touch" and tMirrorsSides[tEvent[2]] then
  259.                     tEvent[3],tEvent[4] = tMirrorsSides[tEvent[2]].localize(tEvent[3],tEvent[4])
  260.                     if tEvent[3] then
  261.                         sFilter = resume( "mouse_click", 1, table.unpack( tEvent, 3 ) )
  262.                         if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "mouse_up") then
  263.                             sFilter = resume( "mouse_up", 1, table.unpack( tEvent, 3 ) )
  264.                         end
  265.                     end
  266.                 end
  267.             end
  268.         end
  269.     end )  
  270.    
  271.     term.redirect(parent)
  272.     if not ok then
  273.         printError( param )
  274.     end
  275. end
  276.  
  277. mirrorToMonitors(fMain,{sName},sProgram)
Advertisement
Add Comment
Please, Sign In to add comment