Sharidan

methods

Jan 16th, 2016 (edited)
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.65 KB | None | 0 0
  1. --
  2. -- Methods browser
  3. --
  4. -- by: Sharidan - www.sharidan.dk
  5. --
  6.  
  7. local function wrapTerm(obj)
  8.   -- Wraps the specified terminal/monitor object with additional methods
  9.   obj.width, obj.height = obj.getSize()
  10.   function obj._fixMono(c)
  11.     if (c == colors.black or c == colors.blue or c == colors.green or c == colors.cyan or c == colors.red or c == colors.purple or c == colors.brown or c == colors.gray) then
  12.       return colors.black
  13.     else
  14.       return colors.white
  15.     end
  16.   end
  17.   function obj.color(fore, back)
  18.     local f, b = fore, back
  19.     if (not obj.isColor()) then
  20.       f = obj._fixMono(fore)
  21.       if (back) then
  22.         b = obj._fixMono(back)
  23.       end
  24.     end
  25.     obj.setTextColor(f)
  26.     if (b) then
  27.       obj.setBackgroundColor(b)
  28.     end
  29.   end
  30.   function obj.cls(fore, back)
  31.     if (fore) then
  32.       obj.color(fore, back)
  33.     end
  34.     obj.clear()
  35.     obj.setCursorPos(1, 1)
  36.   end
  37.   function obj.clearln(y, fore, back)
  38.     if (fore) then
  39.       obj.color(fore, back)
  40.     end
  41.     obj.setCursorPos(1, y)
  42.     obj.clearLine()
  43.   end
  44.   function obj.gotoXY(x, y)
  45.     obj.setCursorPos(x, y)
  46.   end
  47.   function obj.writeXY(x, y, text)
  48.     local txt = ""..text..""
  49.     obj.setCursorPos(x, y)
  50.     obj.write(txt)
  51.   end
  52.   function obj.rightXY(x, y, text)
  53.     local txt = ""..text..""
  54.     obj.setCursorPos((x - #txt) + 1, y)
  55.     obj.write(txt)
  56.   end
  57.   function obj.centerY(y, text)
  58.     local txt = ""..text..""
  59.     obj.setCursorPos(math.floor((obj.width - #txt) / 2) + 1, y)
  60.     obj.write(txt)
  61.   end
  62.   function obj.progressBar(x, y, w, v, m)
  63.     local tw, th = term.getSize()
  64.     term.setTextColor(colors.white)
  65.     term.setBackgroundColor(colors.black)
  66.     term.setCursorPos(x, y)
  67.     term.write(string.rep(" ", w))
  68.     term.clearLine()
  69.     local b = math.ceil((tw / 100) * (v / (m / 100)))
  70.     if (b > tw) then
  71.       b = tw
  72.     end
  73.     term.setCursorPos(x, y)
  74.     local l = tw - b
  75.     if (b > 0) then
  76.       term.setTextColor(colors.white)
  77.       term.setBackgroundColor(colors.white)
  78.       term.write(string.rep("#", b))
  79.     end
  80.     term.setTextColor(colors.white)
  81.     term.setBackgroundColor(colors.black)
  82.     term.write(string.rep("#", l))
  83.   end
  84. end
  85. wrapTerm(term)
  86. local function wrapText(text, width)
  87.   local function split(str, pat)
  88.     local r = {}
  89.     if (string.find(str, pat)) then
  90.       for s in str:gmatch("[^"..pat.."]+") do
  91.         table.insert(r, s)
  92.       end
  93.     else
  94.       table.insert(r, str)
  95.     end
  96.     return r
  97.   end
  98.   local txt = split(text, "\n")
  99.   local l = {}
  100.   for t = 1, #txt do
  101.     local cl = ""
  102.     local msg = ""..txt[t]..""
  103.     for w in msg:gmatch("%S+%s*") do
  104.       if (#cl + #w >= width) then
  105.         table.insert(l, cl)
  106.         cl = w
  107.       else
  108.         cl = cl..w
  109.       end
  110.     end -- for
  111.     if (cl ~= "") then
  112.       table.insert(l, cl)
  113.     end
  114.   end
  115.   return l
  116. end
  117.  
  118. local function newList()
  119.   -- Self contained list object
  120.   local self = {}
  121.  
  122.   self._e = {}
  123.   self._s = 0
  124.   self._x = 1
  125.   self._y = 1
  126.   self._w = 0
  127.   self._h = 0
  128.   self._mw = 0
  129.   self._mh = 0
  130.  
  131.   function self._calcSize()
  132.     self._mw = 0
  133.     for i = 1, #self._e do
  134.       if (#self._e[i] > self._mw) then
  135.         self._mw = tonumber(#self._e[i])
  136.       end
  137.     end
  138.     self._mh = tonumber(#self._e)
  139.   end
  140.  
  141.   function self.clear()
  142.     self._e = {}
  143.     self._s = 0
  144.     self._o = 0
  145.     self._x = 1
  146.     self._y = 1
  147.     self._w = 0
  148.     self._h = 0
  149.     self._a = 1 -- 0: left, 1: center, 2: right
  150.     self._mw = 0
  151.     self._mh = 0
  152.   end
  153.   function self.add(caption)
  154.     table.insert(self._e, caption)
  155.     self._s = 1
  156.     self._o = 0
  157.     self._calcSize()
  158.   end
  159.   function self.getWidth()
  160.     if (self._w == 0) then
  161.       return self._mw + 2
  162.     else
  163.       return self._w
  164.     end
  165.   end
  166.   function self.setHeight(h)
  167.     self._h = tonumber(h)
  168.   end
  169.   function self.getHeight()
  170.     if (self._h == 0) then
  171.       return self._mh
  172.     else
  173.       return self._h
  174.     end
  175.   end
  176.   function self.setPos(x, y)
  177.     self._x = tonumber(x)
  178.     self._y = tonumber(y)
  179.   end
  180.   function self.setAlign(a)
  181.     if (a == "left") then
  182.       self._a = 0
  183.     elseif (a == "center") then
  184.       self._a = 1
  185.     elseif (a == "right") then
  186.       self._a = 2
  187.     end
  188.   end
  189.   function self.setList(lst)
  190.     self._e = {}
  191.     for i = 1, #lst do
  192.       self.add(lst[i])
  193.     end
  194.     if (self._h > term.height) then
  195.       self._h = term.height
  196.     end
  197.   end
  198.   function self.render()
  199.     local py = 1
  200.     local w = 0
  201.     if (self._w > 0) then
  202.       w = self._w
  203.     else
  204.       w = self._mw + 2
  205.     end
  206.     for i = 1, self._h do
  207.       local idx = i + self._o
  208.       if (idx <= #self._e) then
  209.         local prefix, caption, suffix = "", self._e[idx], ""
  210.         if (self._a == 0) then
  211.           -- Left align
  212.           prefix = " "
  213.           suffix = string.rep(" ", (w - 1) - #caption)
  214.         elseif (self._a == 1) then
  215.           -- Centered
  216.           local half = math.floor((w - #caption) / 2)
  217.           prefix = string.rep(" ", half)
  218.           if (half * 2 < (w - #caption)) then
  219.             half = half + 1
  220.           end
  221.           suffix = string.rep(" ", half)
  222.         elseif (self._a == 2) then
  223.           -- Right align
  224.           prefix = string.rep(" ", (w - 1) - #caption)
  225.           suffix = " "
  226.         end
  227.         if (self._s == idx) then
  228.           term.setTextColor(colors.black)
  229.           term.setBackgroundColor(colors.white)
  230.         else  
  231.           term.setTextColor(colors.white)
  232.           term.setBackgroundColor(colors.black)
  233.         end
  234.         term.setCursorPos(self._x, (self._y + py) - 1)
  235.         term.write(prefix..caption..suffix)
  236.         py = py + 1
  237.       end
  238.     end
  239.   end
  240.   function self.checkEvent(event, p1, p2, p3, p4)
  241.     local r = nil
  242.     if (event == "key") then
  243.       if (p1 == keys.home) then -- home
  244.         self._s = 1
  245.         self._o = 0
  246.         self.render()
  247.       elseif (p1 == keys.up) then -- up
  248.         if (self._s > 1) then
  249.           self._s = self._s - 1
  250.           if (self._s < self._o + 1) then
  251.             self._o = self._o - 1
  252.           end
  253.           self.render()
  254.         end
  255.       elseif (p1 == keys.down) then -- down
  256.         if (self._s + 1 <= #self._e) then
  257.           self._s = self._s + 1
  258.           if (self._s - self._o > self._h) then
  259.             self._o = self._o + 1
  260.           end
  261.           self.render()
  262.         end
  263.       elseif (p1 == keys["end"]) then -- end
  264.         self._s = #self._e
  265.         self._o = #self._e - self._h
  266.         if (self._o < 0) then
  267.           self._o = 0
  268.         end
  269.         self.render()
  270.       elseif (p1 == keys.enter) then -- enter
  271.         r = tostring(self._e[self._s])
  272.       end
  273.     end
  274.     return r
  275.   end
  276.   self.clear()
  277.  
  278.   return self
  279. end
  280.  
  281. local devs = {}
  282. local function getDevices()
  283.   local r = {}
  284.   r.t = {}
  285.   local lst = peripheral.getNames()
  286.   for i = 1, #lst do
  287.     local typ = peripheral.getType(lst[i])
  288.     if (typ) then
  289.       local fnd = nil
  290.       for t = 1, #r.t do
  291.         if (r.t[t] == typ) then
  292.           fnd = true
  293.           break
  294.         end
  295.       end
  296.       if (not fnd) then
  297.         table.insert(r.t, typ)
  298.         table.sort(r.t)
  299.         r[typ] = {}
  300.       end
  301.       table.insert(r[typ], lst[i])
  302.       table.sort(r[typ])
  303.     end
  304.   end
  305.   return r
  306. end
  307.  
  308. local noDesc = "No description available."
  309. local function splitValue(value)
  310.   local vName, vType, vDesc, vOpt = "", "", noDesc, false
  311.  
  312.   if (type(value) == "string") then
  313.     vType = tostring(value)
  314.     if (vType == "BOOLEAN") then
  315.       vDesc = "true if success."
  316.     elseif (vType == "VOID") then
  317.       vName = nil
  318.     end
  319.   elseif (type(value) == "table") then
  320.     vName = tostring(value.name)
  321.     vType = tostring(value.type)
  322.     vDesc = tostring(value.description)
  323.     if (value.optional == true) then
  324.       vOpt = true
  325.     end
  326.   else
  327.     vType = tostring(value)
  328.   end
  329.   if (vName) then
  330.     return { vName, vType, vDesc, vOpt }
  331.   end
  332. end
  333. local function getVarInfo(var)
  334.   local r = ""
  335.  
  336.   if (var[4] == true) then
  337.     r = "<"..var[1]..">"
  338.   else
  339.     r = var[1]
  340.   end
  341.   if (var[1] ~= "") then
  342.     r = r.." :: "
  343.   end
  344.   r = r..var[2]
  345.   if (var[4] == true) then
  346.     r = r.." (optional)"
  347.   end
  348.   r = r.."\n"
  349.   r = r..var[3]
  350.  
  351.   return r
  352. end
  353.  
  354. local function usageMenu(dev, meth)
  355.   term.cls(colors.white, colors.black)
  356.   local p = peripheral.wrap(dev)
  357.   local m = p.getAdvancedMethodsData()
  358.   local name, desc, args, ret = nil, nil, {}, {}
  359.   for a, b in pairs(m) do
  360.     if (a == meth) then
  361.       for property, value in pairs(b) do
  362.         if (property == "name") then
  363.           if (value) then
  364.             name = value
  365.           end
  366.         elseif (property == "returnType") then
  367.           if (type(value) == "table") then
  368.             for i = 1, #value do
  369.               local v = splitValue(value[i])
  370.               if (v) then
  371.                 table.insert(ret, v)
  372.               end
  373.             end
  374.           elseif (type(value) == "string") then
  375.             if (string.lower(value) ~= "void" and string.lower(value) ~= "nil") then
  376.               local v = splitValue(value[i])
  377.               if (v) then
  378.                 table.insert(ret, v)
  379.               end
  380.             end
  381.           end
  382.         elseif (property == "returnTypes") then
  383.           if (type(value) == "table") then
  384.             for i = 1, #value do
  385.               local v = splitValue(value[i])
  386.               if (v) then
  387.                 table.insert(ret, v)
  388.               end
  389.             end
  390.           elseif (type(value) == "string") then
  391.             if (string.lower(value) ~= "void" and string.lower(value) ~= "nil") then
  392.               local v = splitValue(value[i])
  393.               if (v) then
  394.                 table.insert(ret, v)
  395.               end
  396.             end
  397.           end
  398.         elseif (property == "description") then
  399.           if (value) then
  400.             desc = value
  401.           end
  402.         elseif (property == "args") then
  403.           if (type(value) == "table") then
  404.             for i = 1, #value do
  405.               local v = splitValue(value[i])
  406.               if (v) then
  407.                 table.insert(args, v)
  408.               end
  409.             end
  410.           elseif (type(value) == "string") then
  411.             local v = splitValue(value[i])
  412.             if (v) then
  413.               table.insert(args, v)
  414.             end
  415.           end
  416.         end
  417.       end
  418.       break
  419.     end
  420.   end
  421.   if (name == nil) then
  422.     name = meth
  423.   end
  424.   if (desc == nil) then
  425.     desc = noDesc
  426.   end
  427.  
  428.   local g, s = "method", 1
  429.   local done = nil
  430.   local drawUI = true
  431.   while not done do
  432.     if (drawUI) then
  433.       term.cls(colors.white, colors.black)
  434.       term.clearln(1, colors.black, colors.white)
  435.       term.writeXY(2, 1, "Hardware Method Browser")
  436.      
  437.       if (#ret == 0 and #args == 0) then
  438.         term.color(colors.white, colors.black)
  439.         term.writeXY(2, 4, name.."()")
  440.       else
  441.         if (#ret > 0) then
  442.           term.color(colors.white, colors.black)
  443.           local sr = s
  444.           if (g ~= "return") then
  445.             sr = 0
  446.           end
  447.           local x = 4
  448.           for i = 1, #ret do
  449.             if (i == sr) then
  450.               term.color(colors.black, colors.white)
  451.             else
  452.               term.color(colors.white, colors.black)
  453.             end
  454.             local txt = " "..ret[i][2]..""
  455.             term.writeXY(x, 3, txt)
  456.             x = x + (#txt) + 1
  457.             if (i < #ret) then
  458.               term.color(colors.white, colors.black)
  459.               term.writeXY(x, 3, ",")
  460.               x = x + 1
  461.             end
  462.           end
  463.         end
  464.         term.color(colors.white, colors.black)
  465.         local x = 4
  466.         if (#ret > 0) then
  467.           term.writeXY(4, 4, "=")
  468.           x = x + 2
  469.         end
  470.         if (g == "method") then
  471.           term.color(colors.black, colors.white)
  472.         end
  473.         term.writeXY(x, 4, " "..name.." ")
  474.         term.color(colors.white, colors.black)
  475.         x = x + #name + 3
  476.         if (#args == 0) then
  477.           term.writeXY(x, 4, "()")
  478.         else
  479.           term.writeXY(x, 4, "(")
  480.         end
  481.         if (#args > 0) then
  482.           term.color(colors.white, colors.black)
  483.           local sa = s
  484.           if (g ~= "args") then
  485.             sa = 0
  486.           end
  487.           local x = 4
  488.           for i = 1, #args do
  489.             if (i == sa) then
  490.               term.color(colors.black, colors.white)
  491.             else
  492.               term.color(colors.white, colors.black)
  493.             end
  494.             local txt = " "..args[i][1]..""
  495.             term.writeXY(x, 5, txt)
  496.             x = x + (#txt) + 1
  497.             if (i < #args) then
  498.               term.color(colors.white, colors.black)
  499.               term.writeXY(x, 5, ",")
  500.               x = x + 1
  501.             end
  502.           end
  503.           term.color(colors.white, colors.black)
  504.           term.writeXY(4, 6, ")")
  505.         end
  506.       end
  507.      
  508.       local txt = {}
  509.       if (g == "return") then
  510.         txt = wrapText(getVarInfo(ret[s]), term.width - 2)
  511.       elseif (g == "method") then
  512.         txt = wrapText(desc, term.width - 2)
  513.       elseif (g == "args") then
  514.         txt = wrapText(getVarInfo(args[s]), term.width - 2)
  515.       end
  516.       term.color(colors.white, colors.black)
  517.       if (#txt > 0) then
  518.         for i = 1, #txt do
  519.           if (i + 7 < term.height - 1) then
  520.             term.writeXY(2, i + 7, txt[i])
  521.           end
  522.         end
  523.       else
  524.         term.writeXY(2, 7, "No description available.")
  525.       end
  526.      
  527.       term.clearln(term.height, colors.black, colors.white)
  528.       term.writeXY(2, term.height, "[Q]: Quit, [BckSpace]: Back")
  529.       drawUI = nil
  530.     end
  531.     local event, p1 = os.pullEvent()
  532.     if (event == "char" and string.lower(p1) == "q") then
  533.       return "quit"
  534.     elseif (event == "key") then
  535.       if (p1 == keys.backspace) then -- backspace
  536.         done = true
  537.       elseif (p1 == keys.up) then -- arrow up
  538.         if (g == "method") then
  539.           if (#ret > 0) then
  540.             g = "return"
  541.             s = 1
  542.             drawUI = true
  543.           end
  544.         elseif (g == "args") then
  545.           g = "method"
  546.           s = 1
  547.           drawUI = true
  548.         end
  549.       elseif (p1 == keys.down) then -- arrow down
  550.         if (g == "return") then
  551.           g = "method"
  552.           s = 1
  553.           drawUI = true
  554.         elseif (g == "method") then
  555.           if (#args > 0) then
  556.             g = "args"
  557.             s = 1
  558.             drawUI = true
  559.           end
  560.         end
  561.       elseif (p1 == keys.left) then -- arrow left
  562.         if (g == "return" or g == "args") then
  563.           if (s > 1) then
  564.             s = s - 1
  565.             drawUI = true
  566.           end
  567.         end
  568.       elseif (p1 == keys.right) then -- arrow right
  569.         if (g == "return") then
  570.           if (s < #ret) then
  571.             s = s + 1
  572.             drawUI = true
  573.           end
  574.         elseif (g == "args") then
  575.           if (s < #args) then
  576.             s = s + 1
  577.             drawUI = true
  578.           end
  579.         end
  580.       end
  581.     end
  582.   end
  583. end
  584.  
  585. local function methodMenu(dev)
  586.   local lst = peripheral.getMethods(dev)
  587.   local mlst = {}
  588.   local op = nil
  589.   for i = 1, #lst do
  590.     if (lst[i] == "getAdvancedMethodsData") then
  591.       op = true
  592.     elseif (lst[i] == "listMethods") then
  593.       -- Standard listing methods
  594.     else
  595.       table.insert(mlst, lst[i])
  596.     end
  597.   end
  598.   table.sort(mlst)
  599.  
  600.   list = newList()
  601.   list.setList(mlst)
  602.   list.setPos(1, 5)
  603.   list.setHeight(term.height - 6)
  604.   list.setAlign("left")
  605.  
  606.   local done = false
  607.   local drawUI = true
  608.   while not done do
  609.     if (drawUI) then
  610.       term.cls(colors.white, colors.black)
  611.       term.clearln(1, colors.black, colors.white)
  612.       term.writeXY(2, 1, "Hardware Method Browser")
  613.       term.color(colors.white, colors.black)
  614.       term.writeXY(1, 3, "Methods for "..dev..":")
  615.       term.clearln(term.height, colors.black, colors.white)
  616.       if (op) then
  617.         term.writeXY(2, term.height, "[Q]: Quit, [BckSpace]: Back, [Enter]: View")
  618.       else
  619.         term.writeXY(2, term.height, "[Q]: Quit, [BckSpace]: Back")
  620.       end
  621.       drawUI = nil
  622.     end
  623.     list.render()
  624.     local event, p1, p2, p3, p4 = os.pullEvent()
  625.     local r = list.checkEvent(event, p1, p2, p3, p4)
  626.     if (r and op) then
  627.       if (usageMenu(dev, r) == "quit") then
  628.         return "quit"
  629.       else
  630.         drawUI = true
  631.       end
  632.     else
  633.       if (event == "char" and string.lower(p1) == "q") then
  634.         return "quit"
  635.       elseif (event == "key" and p1 == keys.backspace) then
  636.         done = true
  637.       end
  638.     end
  639.   end
  640. end
  641.  
  642. local function deviceMenu(typ)
  643.   local list = newList()
  644.   list.setList(devs[typ])
  645.   list.setPos(1, 3)
  646.   list.setHeight(term.height - 4)
  647.   list.setAlign("left")
  648.   local done = false
  649.   local drawUI = true
  650.   while not done do
  651.     if (drawUI) then
  652.       term.cls(colors.white, colors.black)
  653.       term.clearln(1, colors.black, colors.white)
  654.       term.writeXY(2, 1, "Hardware Method Browser")
  655.       term.clearln(term.height, colors.black, colors.white)
  656.       term.writeXY(2, term.height, "[Q]: Quit, [BckSpace]: Back, [Enter]: View")
  657.       drawUI = nil
  658.     end
  659.     list.render()
  660.     local event, p1, p2, p3, p4 = os.pullEvent()
  661.     local r = list.checkEvent(event, p1, p2, p3, p4)
  662.     if (r) then
  663.       if (methodMenu(r) == "quit") then
  664.         return "quit"
  665.       else
  666.         drawUI = true
  667.       end
  668.     elseif (event == "char" and string.lower(p1) == "q") then
  669.       return "quit"
  670.     elseif (event == "key" and p1 == keys.backspace) then
  671.       done = true
  672.     end
  673.   end
  674. end
  675.  
  676. local function mainLoop()
  677.   devs = getDevices()
  678.   local list = newList()
  679.   list.setList(devs.t)
  680.   list.setPos(1, 3)
  681.   list.setHeight(term.height - 4)
  682.   list.setAlign("left")
  683.   local done = false
  684.   local drawUI = true
  685.   while not done do
  686.     if (drawUI) then
  687.       term.cls(colors.white, colors.black)
  688.       term.clearln(1, colors.black, colors.white)
  689.       term.writeXY(2, 1, "Hardware Method Browser")
  690.       term.clearln(term.height, colors.black, colors.white)
  691.       term.writeXY(2, term.height, "[Q]: Quit, [R]: Refresh, [Enter]: View")
  692.       drawUI = nil
  693.     end
  694.     list.render()
  695.     local event, p1, p2, p3, p4 = os.pullEvent()
  696.     local r = list.checkEvent(event, p1, p2, p3, p4)
  697.     if (r) then
  698.       if (deviceMenu(r) == "quit") then
  699.         done = true
  700.       else
  701.         drawUI = true
  702.       end
  703.     elseif (event == "char") then
  704.       if (string.lower(p1) == "q") then
  705.         done = true
  706.       elseif (string.lower(p1) == "r") then
  707.         devs = getDevices()
  708.         list.setList(devs.t)
  709.         drawUI = true
  710.       end
  711.     elseif (event == "key" and p1 == keys["end"]) then
  712.       done = true
  713.     end
  714.   end
  715.   term.cls(colors.white, colors.black)
  716. end
  717.  
  718. mainLoop()
Add Comment
Please, Sign In to add comment