Advertisement
Jummit

Computercraft Web Browser

Mar 24th, 2018
1,464
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.92 KB | None | 0 0
  1. local w, h = term.getSize()
  2. local buffer = window.create(term.current(), 1, 1, w, h)
  3. local oldTerm = term.redirect(buffer)
  4. local succ, mess = pcall(function()
  5. rednet.open("top")
  6. local history = {}
  7. local currentSite = 1
  8. local siteElements = {}
  9. local programElements = {}
  10. local onSite = false
  11. local moveToSite
  12. serverId = 0
  13. local getFileFromServer = function(site, serverIp)
  14.   local serverIp = serverIp
  15.   rednet.broadcast(site, "get")
  16.   local siteData = {
  17.     "Error 404",
  18.     "",
  19.     "Site does not exist"
  20.   }
  21.   local startTime = os.clock()
  22.   local timer = os.startTimer(0.5)
  23.  
  24.   while true do
  25.     local event, senderId, message, protocol = os.pullEventRaw()
  26.     if event == "rednet_message" then
  27.       if protocol == "send"..site and not serverIp or (senderId == serverIp) then
  28.         local serverIp = serverId
  29.         siteData = textutils.unserialize(message)
  30.         break
  31.       end
  32.     elseif event == "timer" then
  33.       break
  34.     end
  35.   end
  36.   os.cancelTimer(timer)
  37.   return siteData, serverIp
  38. end
  39. local loadSite
  40. local newElement = function(elementTab)
  41.   return function(argTab)
  42.     return setmetatable(
  43.       argTab,
  44.         {
  45.           __index = elementTab
  46.         }
  47.       )
  48.   end
  49. end
  50. local lastPage = function()
  51.   if history[currentSite-1] then
  52.     currentSite = currentSite - 1
  53.     siteElements, serverIp = loadSite(getFileFromServer(history[currentSite]))
  54.   end
  55. end
  56. local nextPage = function()
  57.   if history[currentSite+1] then
  58.     currentSite = currentSite + 1
  59.     siteElements, serverIp = loadSite(getFileFromServer(history[currentSite]))
  60.   end
  61. end
  62. local uiElements = {
  63.   button = newElement({
  64.     mouse_click = function(self, button, x, y)
  65.       if self.t then error("test") end
  66.       if x>=self.x and y>=self.y then
  67.         if x<self.x+self.w and y<self.y+self.h then
  68.           if self.clickedFunc then self:clickedFunc() end
  69.         end
  70.       end
  71.     end,
  72.     draw = function(self)
  73.       if self.text then
  74.         self.text:draw()
  75.       end
  76.     end
  77.   }),
  78.   text = newElement({
  79.     draw = function(self)
  80.       term.setCursorPos(self.x, self.y)
  81.       term.setTextColor(self.color)
  82.       if self.backgroundColor then
  83.         term.setBackgroundColor(self.backgroundColor)
  84.       else
  85.         term.setBackgroundColor(colors.white)
  86.       end
  87.       term.write(self.text)
  88.     end
  89.   }),
  90.   image = newElement({
  91.     draw = function(self)
  92.       for lineNum = 1, #self.image do
  93.         local line = self.image[lineNum]
  94.         term.setCursorPos(self.x, lineNum+self.y-1)
  95.         for x = 1, #line do
  96.           local char = string.sub(line, x, x)
  97.           if char == " " then
  98.             local xpos, ypos = term.getCursorPos()
  99.             term.setCursorPos(xpos+1, ypos)
  100.           else
  101.             term.blit(char, char, char)
  102.           end
  103.         end
  104.       end
  105.     end
  106.   }),
  107.   script = newElement({}),
  108.   box = newElement({
  109.     draw = function(self)
  110.       paintutils.drawFilledBox(self.x, self.y, self.x+self.w, self.y+self.h, self.color)
  111.     end
  112.   }),
  113.   line = newElement({
  114.     draw = function(self)
  115.       paintutils.drawLine(self.x, self.y, self.x2, self.y2, self.color)
  116.     end
  117.   })
  118. }
  119. local elements = {
  120.   image = function(path)
  121.     local image = getFileFromServer(path)
  122.     local x, y = term.getCursorPos()
  123.     term.setCursorPos(x, y+#image)
  124.  
  125.     return uiElements.image({image = image, x = x, y = y})
  126.   end,
  127.   text = function(text)
  128.     local x, y = term.getCursorPos()
  129.     term.setCursorPos(x, y+1)
  130.     return uiElements.text({
  131.       text = text, color = term.getTextColor(), x = x, y = y
  132.     })
  133.   end,
  134.   set = function(x, y)
  135.     term.setCursorPos(tonumber(x), tonumber(y))
  136.   end,
  137.   move = function(mx, my)
  138.     local x, y = term.getCursorPos()
  139.     term.setCursorPos(x+mx, y+(my or 0))
  140.   end,
  141.   link = function(path, text)
  142.     local x, y = term.getCursorPos()
  143.     local text = text or path
  144.     term.setCursorPos(x, y+1)
  145.     return {
  146.       uiElements.text({
  147.         text = text, color = colors.blue, x = x, y = y
  148.       }),
  149.       uiElements.button({
  150.         w = #text, h = 1,
  151.         clickedFunc = function(self)
  152.           moveToSite(path)
  153.         end,
  154.         x = x, y = y
  155.       })
  156.     }
  157.   end,
  158.   color = function(color)
  159.     term.setTextColor(colors[color])
  160.   end,
  161.   script = function(path)
  162.     local script = getFileFromServer(path)
  163.     local scriptString = ""
  164.     for lineNum = 1, #script do
  165.       scriptString = scriptString .. script[lineNum].."\n"
  166.     end
  167.     local x, y = term.getCursorPos()
  168.     local returnElement = uiElements.script({
  169.       x = x, y = y,
  170.       path = path,
  171.       serverId = serverId
  172.     })
  173.     local succ
  174.     local func, mess = load(scriptString, path, "t", setmetatable(returnElement,{__index = _G}))
  175.     if func then
  176.       succ, mess = pcall(func)
  177.       if succ then
  178.         return returnElement
  179.       end
  180.     end
  181.     return uiElements.text({
  182.       x = 1, y = h-1,
  183.       text = mess, color = colors.red
  184.     })
  185.   end,
  186.   box = function(w, h)
  187.     local x, y = term.getCursorPos()
  188.     return uiElements.box({
  189.       x = x, y = y, w = w, h = h, color = term.getTextColor()
  190.     })
  191.   end,
  192.   line = function(x2, y2)
  193.     local x, y = term.getCursorPos()
  194.     return uiElements.line({
  195.       x = x, y = y, x2 = x+x2, y2 = y+y2, color = term.getTextColor()
  196.     })
  197.   end
  198. }
  199. local newElements = function(tab)
  200.   return setmetatable(tab,
  201.     {
  202.       __index = {
  203.         draw = function(self)
  204.           for elementNum = 1, #self do
  205.             local element = self[elementNum]
  206.             if element[1] then
  207.               self.draw(element)
  208.             else
  209.               if element.draw then
  210.                 element:draw()
  211.               end
  212.             end
  213.           end
  214.         end,
  215.         scroll = function(self, move, hard)
  216.           for i = 1, #self do
  217.             if self[i][1] then
  218.               self.scroll(self[i], move, self[i].movable or hard)
  219.             else
  220.               if self[i].y and (self[i].moveable or hard) then
  221.                 self[i].y = self[i].y - move
  222.               end
  223.             end
  224.           end
  225.         end,
  226.         update = function(self, event, ...)
  227.           if event == "mouse_scroll" then
  228.             if self.scroll then
  229.               self:scroll(({...})[1])
  230.             end
  231.           end
  232.           for elementNum = 1, #self do
  233.             local element = self[elementNum]
  234.             if element[1] then
  235.               self.update(element, event, ...)
  236.             else
  237.               if element.update then
  238.                 element:update(event, ...)
  239.               end
  240.               if element[event] then
  241.                 element[event](element, ...)
  242.               end
  243.             end
  244.           end
  245.         end
  246.       }
  247.     }
  248.   )
  249. end
  250. local searchElements = newElements({movable=true})
  251. loadSite = function(siteData)
  252.   local siteElements = newElements({})
  253.   term.setCursorPos(2, 2)
  254.   for lineNum = 1, #siteData do
  255.     local line = siteData[lineNum]
  256.     local element = string.match(line, "^%S+")
  257.     local arguments = {}
  258.     if string.sub(line, 1, 1) == " " then
  259.       element = "text"
  260.       arguments = {string.sub(line, 2)}
  261.     elseif not element then
  262.       element = "text"
  263.       arguments = {line}
  264.     else
  265.       for arg in string.gmatch(string.sub(line, #element+2), "[^,]+") do
  266.         table.insert(arguments, arg)
  267.       end
  268.     end
  269.     if elements[element] then
  270.       table.insert(siteElements, elements[element](table.unpack(arguments)))
  271.     end
  272.   end
  273.   siteElements:scroll(-1, true)
  274.   return siteElements
  275. end
  276. moveToSite = function(site)
  277.   for i = currentSite+1, #history do
  278.     table.remove(history, i)
  279.   end
  280.   currentSite = currentSite + 1
  281.   table.insert(history, site)
  282.   siteElements, serverId = loadSite(getFileFromServer(site))
  283. end
  284. local search = function(str)
  285.   if str ~= "" then
  286.     searchElements = {}
  287.     onSite = false
  288.     rednet.broadcast(str, "find")
  289.     local results = {}
  290.     os.startTimer(0.1)
  291.     while true do
  292.       local event, var1, var2, var3 = os.pullEventRaw()
  293.       if event == "rednet_message" and var3 == "findResult" then
  294.         local siteResults = textutils.unserialize(var2)
  295.         for i = 1, #siteResults do
  296.           table.insert(results, siteResults[i])
  297.         end
  298.       elseif event == "timer" then
  299.         break
  300.       end
  301.     end
  302.  
  303.     local sortedResults = table.sort(
  304.       results,
  305.       function(list1, list2)
  306.         return list1.num>list2.num
  307.       end
  308.     )
  309.     local y = 4
  310.     for i = 1, #results do
  311.       if results[i].num > 0 then
  312.         local name = string.match(results[i].page, "[^/]*$")
  313.         if name == "website" then
  314.           name = string.match(results[i].page, "[^'mc.'']%a*.sol")
  315.         end
  316.         name = string.upper(string.sub(name, 1, 1))..string.sub(name, 2)
  317.         local siteText = getFileFromServer(results[i].page)
  318.         local tipText = ""
  319.         local altTipText = ""
  320.         for i = 1, #siteText do
  321.           if string.sub(siteText[i], 1, 1) == " " then
  322.             local line = string.sub(siteText[i], 2)
  323.             tipText = string.match(line, ".*"..str..".*") or tipText
  324.             altTipText = string.match(string.lower(line), ".*"..string.lower(str)..".*") or altTipText
  325.           end
  326.         end
  327.         if tipText == "" then tipText = altTipText end
  328.         table.insert(
  329.           searchElements,
  330.           {
  331.             movable = true,
  332.             uiElements.box({
  333.               x = 3, y = y, w = 40, h = 2, color = colors.lightGray
  334.             }),
  335.             uiElements.button({
  336.               x = 3, y = y, w = 40, h = 3, clickedFunc = function()
  337.                 searchElements = newElements({})
  338.                 onSite = true
  339.                 moveToSite(results[i].page)
  340.               end
  341.             }),
  342.             uiElements.text({
  343.               x = 3, y = y,
  344.               text = name,
  345.               color = colors.black,
  346.               backgroundColor = colors.lightGray
  347.             }),
  348.             uiElements.text({
  349.               x = 3, y = y+1,
  350.               text = results[i].page,
  351.               color = colors.gray,
  352.               backgroundColor = colors.lightGray
  353.             }),
  354.             uiElements.text({
  355.               x = 3, y = y+2,
  356.               text = string.sub(tipText, 1, 41),
  357.               color = colors.gray,
  358.               backgroundColor = colors.lightGray
  359.             })
  360.           }
  361.         )
  362.         y = y + 4
  363.       end
  364.     end
  365.     table.insert(searchElements,
  366.     uiElements.text({
  367.       x=1, y = 2, color = colors.gray,
  368.       text = "Search had "..#searchElements.." results",
  369.     }))
  370.     searchElements = newElements(searchElements)
  371.   end
  372. end
  373. programElements = newElements({
  374.   uiElements.line({
  375.     x = 1, y = 1, x2 = w, y2 = 1, color = colors.gray
  376.   }),
  377.   uiElements.button({
  378.     x = 2, y = 1, w = 3, h = 1,
  379.     text = uiElements.text({
  380.       x = 2, y = 1, text = " < ", color = colors.gray, backgroundColor = colors.lightGray
  381.     }),
  382.     clickedFunc = function()
  383.       lastPage()
  384.     end
  385.   }),
  386.   uiElements.button({
  387.     x = 6, y = 1, w = 3, h = 1,
  388.     text = uiElements.text({
  389.       x = 6, y = 1, text = " > ", color = colors.gray, backgroundColor = colors.lightGray
  390.     }),
  391.     clickedFunc = function()
  392.       nextPage()
  393.     end
  394.   }),
  395.   uiElements.button({
  396.     x = 11, y = 1, w = 20, h = 1,
  397.     text = uiElements.text({
  398.       x = 11, y = 1, text = "search...       ", color = colors.gray, backgroundColor = colors.lightGray
  399.     }),
  400.     clickedFunc = function(self)
  401.       term.setCursorPos(self.x, self.y)
  402.       term.setBackgroundColor(colors.lightGray)
  403.       term.setTextColor(colors.black)
  404.       search(io.read())
  405.     end
  406.   }),
  407.   uiElements.button({
  408.     x = w, y = 1, h = 1, w = 1,
  409.     clickedFunc = function(self)
  410.       term.setBackgroundColor(colors.black)
  411.       term.clear()
  412.       term.setCursorPos(1, 1)
  413.       error("", 0)
  414.     end,
  415.     text = uiElements.text({
  416.       x = w, y = 1, text = "X", color = colors.orange, backgroundColor = colors.red
  417.     }),
  418.   })
  419. })
  420.  
  421. while true do
  422.   buffer.setVisible(false)
  423.   term.setBackgroundColor(colors.white)
  424.   term.clear()
  425.   if onSite then
  426.     siteElements:draw()
  427.   else
  428.     searchElements:draw()
  429.   end
  430.   programElements:draw()
  431.   buffer.setVisible(true)
  432.   local event, var1, var2, var3 = os.pullEventRaw()
  433.   if event == "mouse_scroll" then
  434.     if onSite then
  435.       siteElements:scroll(var1, true)
  436.     else
  437.       programElements:scroll(var1)
  438.     end
  439.   end
  440.   if event == "key" then
  441.     local key = keys.getName(var1)
  442.     if key == "left" then
  443.       lastPage()
  444.     elseif key == "right" then
  445.       nextPage()
  446.     end
  447.     if onSite and key == "r" then
  448.       --moveToSite(history[currentSite])
  449.     end
  450.   end
  451.   programElements:update(event, var1, var2, var3)
  452.   if onSite then
  453.     siteElements:update(event, var1, var2, var3)
  454.   else
  455.     searchElements:update(event, var1, var2, var3)
  456.   end
  457. end
  458. end)
  459. term.redirect(oldTerm)
  460. buffer.setVisible(false)
  461. term.setBackgroundColor(colors.black)
  462. term.setTextColor(colors.red)
  463. term.clear()
  464. term.setCursorPos(1, 1)
  465. print(mess)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement