Advertisement
SergOmarov

forms.lua

Sep 29th, 2015
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.20 KB | None | 0 0
  1. --Authors: Zer0Galaxy,SergOmarov
  2. local computer=require("computer")
  3. local fs=require("component").proxy(computer.getBootAddress())
  4. _print=function(...)
  5. local t={...}
  6. local f=fs.open("log.test","a")
  7. for i=1,#t do
  8. fs.write(f,tostring(t[i]).."\n")
  9. end
  10. fs.close(f)
  11.  
  12. end
  13. local gpu=require("component").gpu
  14. local isPrimary=require("component").isPrimary
  15. local event=require("event")
  16. local len=require("unicode").len
  17. local sub=require("unicode").sub
  18. local uchar=require("unicode").char
  19. local term=require("term")
  20. local pushSignal=require("computer").pushSignal
  21. local kbd  = require("component").keyboard
  22. local wrap = require("text").wrap
  23. local padRight=require("text").padRight
  24. local isControl= require("keyboard").isControl
  25.  
  26. local forms={}
  27. local mouseEv={touch=true, scroll=true, drag=true, drop=true}
  28. local activeForm
  29.  
  30. local TComponent={left=1,top=1, color=0, fontColor=0xffffff, border=0, visible=true, tag=0, type=function() return "unknown" end}
  31. TComponent.__index=TComponent
  32.  
  33. function TComponent:paint() end
  34.  
  35. function TComponent:isVisible()
  36.   if not self.visible then return false end
  37.   if self.parent then return self.parent:isVisible()
  38.   else return self==activeForm
  39.   end
  40. end
  41.  
  42. function TComponent:draw()
  43.   if self.parent then self.X=self.parent.X+self.left-1 self.Y=self.parent.Y+self.top-1
  44.   else self.X=self.left self.Y=self.top end
  45.   gpu.setBackground(self.color)
  46.   gpu.setForeground(self.fontColor)
  47.   local brd=nil
  48.   if self.border==1 then brd={"┌","─","┐","└","│","┘"}
  49.   elseif self.border==2 then brd={"╔","═","╗","╚","║","╝"}
  50.   end
  51.   if brd then
  52.     gpu.set(self.X,self.Y, brd[1]..string.rep(brd[2],self.W-2)..brd[3])
  53.     for i=self.Y+1,self.Y+self.H-2 do
  54.       gpu.set(self.X,i, brd[5]..string.rep(" ",self.W-2)..brd[5])
  55.     end
  56.     gpu.set(self.X,self.Y+self.H-1, brd[4]..string.rep(brd[2],self.W-2)..brd[6])
  57.   else gpu.fill(self.X,self.Y,self.W,self.H," ") end
  58.   self:paint()
  59.   if self.elements then
  60.     for i=1,#self.elements do
  61.       if self.elements[i].visible then self.elements[i]:draw() end
  62.     end
  63.   end
  64. end
  65.  
  66. function TComponent:redraw() if self:isVisible() then self:draw() end end
  67.  
  68. function TComponent:makeChild(el)
  69.   if not self.elements then self.elements={} end
  70.   el.parent=self
  71.   table.insert(self.elements,el)
  72. end
  73.  
  74. function TComponent:mouseEv(ev,x,y,btn,user)
  75.   if self.elements then
  76.     for i=#self.elements,1,-1 do
  77.         local e=self.elements[i]
  78.         if(ev=="touch")then--Скрывать всплывающее меню по любому клику если клик прошел по самому меню - то запоминает
  79.         local ee=forms.currentMenu
  80.             if(forms.currentMenu and forms.currentMenu:isVisible())then
  81.                 if(ee.X and x>=ee.X and x<ee.X+ee.W and y>=ee.Y and y<ee.Y+ee.H )then
  82.                     forms.lastMenu=forms.currentMenu
  83.                 else
  84.                     forms.lastMenu=nil
  85.                 end
  86.                 forms.currentMenu:hide()
  87.             end
  88.         end
  89.         if (e.visible or e==forms.lastMenu) and e.X and x>=e.X and x<e.X+e.W and y>=e.Y and y<e.Y+e.H then
  90.             e:mouseEv(ev,x,y,btn,user)
  91.             return
  92.         end
  93.     end
  94.   end  
  95.   if self[ev] then self[ev](self, x-self.X+1,y-self.Y+1,btn,user) end
  96. end
  97.  
  98. function TComponent:hide()
  99.   if self.parent then
  100.     self.visible=false
  101.     self.parent:draw()
  102.   else
  103.     gpu.setBackground(0)
  104.     gpu.fill(self.X,self.Y,self.W,self.H," ")
  105.   end
  106. end
  107.  
  108. function TComponent:show()
  109.   if self.parent then
  110.     self.visible=true
  111.     self.parent:draw()
  112.   else
  113.     self:draw()
  114.   end
  115. end
  116.  
  117. function TComponent:destruct()
  118.   if self.parent then
  119.     for i=1,#self.parent.elements do
  120.       if self.parent.elements[i]==self then table.remove(self.parent.elements,i) break end
  121.     end
  122.   end
  123. end
  124.  
  125. function forms.activeForm() return activeForm end
  126.  
  127. ----------Визуальные компоненты---------
  128. ------------------Form------------------
  129. local TForm=setmetatable({type=function() return "Form" end},TComponent)
  130. TForm.__index=TForm
  131.  
  132. function TForm:isActive() return self==activeForm end
  133.  
  134. function TForm:setActive()
  135.   if activeForm~=self then
  136.     activeForm=self
  137.     self:show()
  138.   end  
  139. end
  140.  
  141. function forms.addForm()
  142.   local obj={}
  143.   TForm.W, TForm.H=gpu.getResolution()
  144.   return setmetatable(obj,TForm)
  145. end
  146.  
  147. ------------------Button----------------
  148. local TButton=setmetatable({W=10, H=1, color=0x606060, type=function() return "Button" end},TComponent)
  149. TButton.__index=TButton
  150.  
  151. function TButton:touch(x, y, btn, user)
  152.   if self.onClick and btn==0 then self:onClick(user) end
  153. end
  154.  
  155. function TButton:paint()
  156.   gpu.set(self.X+(self.W-len(self.caption))/2,self.Y+(self.H-1)/2, self.caption)
  157. end
  158.  
  159. function TComponent:addButton(left, top, caption, onClick)
  160.   local obj={left=left, top=top, caption=caption or "Button", onClick=onClick}
  161.   self:makeChild(obj)
  162.   return setmetatable(obj,TButton)
  163. end
  164.  
  165. ------------------LevelingFrame-----------------Пока не пашет
  166. local TLevelingFrame=setmetatable({W=20, H=10, border=1, type=function() return "LevelingFrame" end,isLeveling=true},TComponent)
  167. TLevelingFrame.__index=TLevelingFrame
  168. function TLevelingFrame:removeLeveledObject(object,h)
  169. self.pleft,self.ptop=self.pleft-object.left,self.ptop-(h or object.top)
  170.  
  171. end
  172. function TLevelingFrame:getNewPosition(w,h)
  173. h=h or 0
  174. local p1,p2=self.pleft,self.ptop
  175. self.pleft,self.ptop=self.pleft+w,self.ptop+h
  176. return p1,p2
  177.  
  178. end
  179.  
  180. function TComponent:addLevelingFrame(left, top, border)
  181.   local obj={left=left, top=top, border=border,pleft=0,ptop=0}
  182.   self:makeChild(obj)
  183.   return setmetatable(obj,TLevelingFrame)
  184. end
  185.  
  186. ------------------Label-----------------
  187. local TLabel=setmetatable({H=1, centered=false, alignRight=false, autoSize=true, type=function() return "Label" end} ,TComponent)
  188. TLabel.__index=TLabel
  189.  
  190. function TLabel:paint()
  191.  local line
  192.  local value=tostring(self.caption)
  193.  if self.autoSize then
  194.    self.W,self.H=0,0
  195.    for line in value:gmatch("([^\n]+)") do
  196.      self.H=self.H+1
  197.      if len(line)>self.W then self.W=len(line) end
  198.    end
  199.    if self.W<1 then self.W=1 end
  200.    if self.H<1 then self.H=1 end
  201.  end
  202.  for i=0,self.H-1 do
  203.   if not value then break end
  204.   line, value = wrap(value, self.W, self.W)
  205.   if self.centered then gpu.set(self.X+(self.W-len(line))/2,self.Y+i, line)
  206.   else
  207.     if self.alignRight then gpu.set(self.X+self.W-len(line),self.Y+i, line)
  208.     else gpu.set(self.X,self.Y+i, line) end
  209.   end
  210.  end
  211. end
  212.  
  213. function TComponent:addLabel(left, top, caption)
  214.   local obj={left=left, top=top, caption=caption or "Label"}
  215.   obj.W=len(obj.caption)
  216.   self:makeChild(obj)
  217.   return setmetatable(obj,TLabel)
  218. end
  219.  
  220. ------------------Edit------------------
  221. local TEdit=setmetatable({W=20, H=3, text="", border=1, type=function() return "Edit" end},TComponent)
  222. TEdit.__index=TEdit
  223.  
  224. function TEdit:paint()
  225.   if type(self.text)=="table" then
  226.     for i=1,self.H-2 do gpu.set(self.X+1,self.Y+i,sub(self.text[i] or "",1,self.W-2)) end
  227.   else gpu.set(self.X+1,self.Y+1, sub(self.text,1,self.W-2))
  228.   end
  229. end
  230.  
  231. local function editText(text,left,top,W,H)
  232. local running=true
  233. local scrollX, scrollY = 0, 0
  234. local posX, posY =1, 1
  235. local writeText
  236.  
  237. local function setCursor(nx,ny)
  238.   posX=nx or posX
  239.   posY=ny or posY
  240.   if #text<1 then text[1]="" end
  241.   if posY>#text then posY=#text end
  242.   if posY<1 then posY=1 end
  243.   if posX>len(text[posY])+1 then posX=len(text[posY])+1 end
  244.   if posX<1 then posX=1 end
  245.   local redraw=false
  246.   if posY<=scrollY then scrollY=posY-1 redraw=true end
  247.   if posY>scrollY+H then scrollY=posY-H redraw=true end
  248.   if posX<=scrollX then scrollX=posX-1 redraw=true end
  249.   if posX>scrollX+W then scrollX=posX-W redraw=true end
  250.   if redraw then writeText()
  251.   else term.setCursor(left+posX-scrollX-1, top+posY-scrollY-1) end
  252. end
  253.  
  254. local function writeLine(n)
  255.   gpu.set(left,top+n-scrollY-1,padRight(sub(text[n] or "",scrollX+1,scrollX+W),W))
  256. end
  257.  
  258. function writeText()
  259.   for i=1,H do writeLine(i+scrollY) end
  260.   setCursor()
  261. end
  262.  
  263. local function insert(value)
  264.   if not value or len(value) < 1 then return end
  265.   text[posY]=sub(text[posY],1,posX-1)..value..sub(text[posY],posX)
  266.   writeLine(posY)
  267.   setCursor(posX+len(value))
  268. end
  269.  
  270. local keys={}
  271. keys[203]=function()    -- Left
  272.   if posX>1 then setCursor(posX-1)
  273.   else if posY>1 then posY=posY-1 setCursor(len(text[posY])+1) end
  274.   end
  275. end
  276. keys[205]=function()   -- Right
  277.   if posX<=len(text[posY]) then setCursor(posX+1)
  278.   else if posY<#text then setCursor(1,posY+1) end
  279.   end
  280. end
  281. keys[199]=function() setCursor(1) end   -- Home
  282. keys[207]=function() setCursor(len(text[posY])+1) end   -- End
  283. keys[211]=function()    -- Del
  284.   if posX<=len(text[posY]) then
  285.     text[posY]=sub(text[posY],1,posX-1)..sub(text[posY],posX+1)
  286.     writeLine(posY)
  287.   else
  288.     if posY<#text then
  289.       text[posY]=text[posY]..text[posY+1]
  290.       table.remove(text,posY+1)
  291.       writeText()
  292.     end
  293.   end
  294. end
  295. keys[14] =function()    -- BackSp
  296.   if posX>1 then
  297.     text[posY]=sub(text[posY],1,posX-2)..sub(text[posY],posX)
  298.     writeLine(posY)
  299.     setCursor(posX-1)
  300.   else
  301.     if posY>1 then
  302.       posX,posY,text[posY-1]=len(text[posY-1])+1,posY-1,text[posY-1]..text[posY]
  303.       table.remove(text,posY+1)
  304.       writeText()
  305.     end
  306.   end
  307. end
  308. keys[15] =function() insert("  ") end   -- Tab
  309.  
  310. local function onKeyDown(char, code)
  311.   if keys[code] then keys[code]()
  312.   else if not isControl(char) then insert(uchar(char)) end
  313.   end
  314. end
  315.  
  316. local function onClipboard(value)
  317. end
  318.  
  319. local function onClick(x,y)
  320.   if x>=left and x<left+W and y>=top and y<top+H then
  321.     setCursor(x+scrollX-left+1,y+scrollY-top+1)
  322.   else running=false
  323.   end
  324. end
  325.  
  326. local function onScroll(direction)
  327. end
  328.  
  329. if type(text)=="table" then
  330.   keys[68] =function() running=false end   -- F10
  331.   keys[200]=function() setCursor(posX,posY-1) end   -- Up
  332.   keys[208]=function() setCursor(posX,posY+1) end   -- Down
  333.   keys[28] =function()   -- Enter
  334.     local n=len(text[posY]:match("^%s*"))
  335.     table.insert(text,posY+1,string.rep(" ",n)..sub(text[posY],posX))
  336.     text[posY]=sub(text[posY],1,posX-1)
  337.     posX,posY=n+1,posY+1
  338.     writeText()
  339.   end
  340. else
  341.   posX=len(text)+1
  342.   text={tostring(text)}
  343.   keys[28] =function() running=false end   -- Enter
  344. end
  345. term.setCursorBlink(true)
  346. writeText()
  347. while running do
  348.   local event, address, arg1, arg2, arg3 = event.pull()
  349.   if type(address) == "string" and isPrimary(address) then
  350.     term.setCursorBlink(false)
  351.     if event == "key_down" then onKeyDown(arg1, arg2)
  352.     elseif event == "clipboard" then onClipboard(arg1)
  353.     elseif event == "touch" or event == "drag" then onClick(arg1, arg2)
  354.     elseif event == "scroll" then onScroll(arg3)
  355.     end
  356.     term.setCursorBlink(true)
  357.   end
  358. end
  359. term.setCursorBlink(false)
  360. return text[1]
  361. end
  362.  
  363. function TEdit:touch(x, y, btn, user)
  364.   if btn==0 then
  365.     gpu.setBackground(self.color)
  366.     gpu.setForeground(self.fontColor)
  367.     if type(self.text)=="table" then editText(self.text,self.X+1,self.Y+1,self.W-2,self.H-2)
  368.     else self.text=editText(self.text,self.X+1,self.Y+1,self.W-2,1) end
  369.     self:draw()
  370.     if self.onEnter then self:onEnter(user) end
  371.   end
  372. end
  373.  
  374. function TComponent:addEdit(left, top, onEnter)
  375.   local obj={left=left, top=top, onEnter=onEnter}
  376.   self:makeChild(obj)
  377.   return setmetatable(obj,TEdit)
  378. end
  379.  
  380. ------------------Frame-----------------
  381. local TFrame=setmetatable({W=20, H=10, border=1, type=function() return "Frame" end},TComponent)
  382. TFrame.__index=TFrame
  383.  
  384. function TComponent:addFrame(left, top, border)
  385.   local obj={left=left, top=top, border=border}
  386.   self:makeChild(obj)
  387.   return setmetatable(obj,TFrame)
  388. end
  389.  
  390. ------------------List------------------
  391. local TList=setmetatable({W=20, H=10, border=2, selColor=0x0000ff, sfColor=0xffff00, shift=0, index=0,
  392.   type=function() return "List" end},TComponent)
  393. TList.__index=TList
  394.  
  395. function TList:paint()
  396.   local b= self.border==0 and 0 or 1
  397.   for i=1,self.H-2*b do
  398.     if i+self.shift==self.index then gpu.setForeground(self.sfColor) gpu.setBackground(self.selColor) end
  399.     gpu.set(self.X+b,self.Y+i+b-1, padRight(sub(self.lines[i+self.shift] or "",1,self.W-2*b),self.W-2*b))
  400.     if i+self.shift==self.index then gpu.setForeground(self.fontColor) gpu.setBackground(self.color) end
  401.   end
  402. end
  403.  
  404. function TList:clear()
  405.   self.shift=0 self.index=0 self.lines={} self.items={}
  406.   self:redraw()
  407. end
  408.  
  409. function TList:insert(pos,line,item)
  410.   if type(pos)~="number" then pos,line,item=#self.lines+1,pos,line end
  411.   table.insert(self.lines,pos,line)
  412.   table.insert(self.items,pos,item or false)
  413.   if self.index<1 then self.index=1 end
  414.   if pos<self.shift+self.H-1 then self:redraw() end
  415. end
  416.  
  417. function TList:sort(comp)
  418.   comp=comp or function(list,i,j) return list.lines[j]<list.lines[i] end
  419.   for i=1,#self.lines-1 do
  420.     for j=i+1,#self.lines do
  421.       if comp(self,i,j) then
  422.         if self.index==i then self.index=j
  423.         elseif self.index==j then self.index=i end
  424.         self.lines[i],self.lines[j]=self.lines[j],self.lines[i]
  425.         self.items[i],self.items[j]=self.items[j],self.items[i]
  426.       end
  427.     end
  428.   end
  429.   self:redraw()
  430. end
  431.  
  432. function TList:touch(x, y, btn, user)
  433.   local b= self.border==0 and 0 or 1
  434.   if x>b and x<=self.W-b and y>b and y<=self.H-b and btn==0 then
  435.     local i=self.shift+y-b
  436.     if self.index~=i and self.lines[i] then
  437.       self.index=i
  438.       self:redraw()
  439.       if self.onChange then self:onChange(self.lines[i],self.items[i],user) end
  440.     end
  441.   end
  442. end
  443.  
  444. function TList:scroll(x, y, sh, user)
  445.   local b= self.border==0 and 0 or 1
  446.   self.shift=self.shift-sh
  447.   if self.shift>#(self.lines)-self.H+2*b then self.shift=#(self.lines)-self.H+2*b end
  448.   if self.shift<0 then self.shift=0 end
  449.   self:redraw()
  450. end
  451.  
  452. function TComponent:addList(left, top, onChange)
  453.   local obj={left=left, top=top, lines={}, items={}, onChange=onChange}
  454.   self:makeChild(obj)
  455.   return setmetatable(obj,TList)
  456. end
  457.  
  458. local work
  459. ---------Невизуальные компоненты--------
  460. local TInvisible=setmetatable({W=10, H=3, border=2, draw=function() end},TComponent)
  461. TInvisible.__index=TInvisible
  462. ------------------Event-----------------
  463. local TEvent=setmetatable({type=function() return "Event" end},TInvisible)
  464. TEvent.__index=TEvent
  465.  
  466. function TEvent:run()
  467.   if self.onEvent then forms.listen(self.eventName, self.onEvent) end
  468. end
  469.  
  470. function TEvent:stop()
  471.   forms.ignore(self.eventName, self.onEvent)
  472. end
  473.  
  474. function TComponent:addEvent(eventName, onEvent)
  475.   local obj={eventName=eventName, onEvent=onEvent}
  476.   self:makeChild(obj)
  477.   setmetatable(obj,TEvent)
  478.   obj:run()
  479.   return obj
  480. end
  481.  
  482. ------------------Timer-----------------
  483. local TTimer=setmetatable({Enabled=true, type=function() return "Timer" end},TInvisible)
  484. TTimer.__index=TTimer
  485.  
  486. function TTimer:run()
  487.   self.Enabled=nil
  488.   if self.onTime then
  489.     self.timerId=event.timer(self.interval,
  490.     function ()
  491.       if self.Enabled and work then
  492.         self.onTime(self)
  493.       else
  494.         self:stop()
  495.       end
  496.     end,
  497.     math.huge
  498.     )
  499.   end
  500. end
  501. function TTimer:stop()
  502.   self.Enabled=false
  503.   event.cancel(self.timerId)
  504. end
  505.  
  506. function TComponent:addTimer(interval, onTime)
  507.   local obj={interval=interval, onTime=onTime}
  508.   self:makeChild(obj)
  509.   setmetatable(obj,TTimer)
  510.   obj:run()
  511.   return obj
  512. end
  513.  
  514. -----------Обработчик событий-----------
  515. local listeners={}
  516.  
  517. function forms.listen(name, callback)
  518.   checkArg(1, name, "string")
  519.   checkArg(2, callback, "function")
  520.   if listeners[name] then
  521.     for i = 1, #listeners[name] do
  522.       if listeners[name][i] == callback then
  523.         return false
  524.       end
  525.     end
  526.   else
  527.     listeners[name] = {}
  528.   end
  529.   table.insert(listeners[name], callback)
  530.   return true
  531. end
  532.  
  533. function forms.ignore(name, callback)
  534.   checkArg(1, name, "string")
  535.   checkArg(2, callback, "function")
  536.   if listeners[name] then
  537.     for i = 1, #listeners[name] do
  538.       if listeners[name][i] == callback then
  539.         table.remove(listeners[name], i)
  540.         if #listeners[name] == 0 then
  541.           listeners[name] = nil
  542.         end
  543.         return true
  544.       end
  545.     end
  546.   end
  547.   return false
  548. end
  549.  
  550. function forms.ignoreAll()
  551.   listeners={}
  552. end
  553. ----------------------------------------
  554.  
  555. local TMenu=setmetatable({W=0, H=10, selColor=0x0000ff, sfColor=0xffff00,
  556.   type=function() return "Menu" end},TComponent)
  557. TMenu.__index=TMenu
  558. function TMenu:clear()
  559.   self:redraw()
  560. end
  561.  
  562. function TMenu:paint()
  563. gpu.setForeground(self.sfColor)
  564. gpu.setBackground(self.selColor)
  565. local y=self.top-1
  566. local x=self.left
  567. for i=1,#self.items do
  568. self.W=math.max(self.W,#self.items[i][1])
  569. end
  570. self.H=#self.items
  571. for i=1,#self.items do
  572. gpu.set(x,y+i,self.items[i][1])
  573. end
  574. end
  575. function TMenu:insert(pos,item)
  576. table.insert(self.items,pos,item)
  577. self:redraw()
  578. end
  579. local oShow=TMenu.show
  580. function TMenu:show()
  581. oShow(self)
  582. if(forms.currentMenu)then
  583. forms.currentMenu:hide()
  584. end
  585. forms.currentMenu=self
  586. end
  587. local oHide=TMenu.hide
  588. function TMenu:hide()
  589. oHide(self)
  590. forms.currentMenu=nil
  591. end
  592.  
  593. function TMenu:touch(x, y, btn, user)
  594. _print("touch")
  595. self:hide()
  596. local select=self.items[y] or {""}
  597. if(x<=#select[1])then
  598. self.items[y][2]()
  599. end
  600. end
  601.  
  602. function TComponent:addMenu(left, top,items)
  603.   local obj={left=left, top=top, items=items}
  604.   local menu=setmetatable(obj,TMenu)
  605.   self:makeChild(menu)
  606.   --local menu=setmetatable(obj,TMenu)
  607.   menu:hide()
  608.   return menu
  609. end
  610.  
  611. function forms.run(form)
  612.   work=true
  613.   local Fc, Bc = gpu.getForeground(), gpu.getBackground()
  614.   activeForm=form
  615.   activeForm:draw()
  616.   while work do
  617.     local ev,adr,x,y,btn,user=event.pull()
  618.     if mouseEv[ev] and adr==gpu.getScreen() then activeForm:mouseEv(ev,x,y,btn,user) end
  619.     if listeners[ev] then
  620.       for i=1,#listeners[ev] do listeners[ev][i](ev,adr,x,y,btn,user) end
  621.     end
  622.     if listeners[""] then
  623.       for i=1,#listeners[""] do listeners[""][i](ev,adr,x,y,btn,user) end
  624.     end
  625.   end
  626.   gpu.setForeground(Fc)
  627.   gpu.setBackground(Bc)
  628.   forms.ignoreAll()
  629. end
  630.  
  631. function forms.stop()
  632.   work=false
  633. end
  634.  
  635. --Загрузчик внешних модулей, динамический
  636.  
  637. _G.forms=forms
  638. _G.TComponent=TComponent
  639. _G.gpu=gpu
  640. local fs=require("component").proxy(require("computer").getBootAddress())
  641. function forms.getModulesList()
  642. return fs.list("lib/formsparts/")
  643. end
  644. function forms.loadModule(file)
  645. if(file:sub(-1,-1)=="-")then return end
  646. if(file:sub(1,1)~="/")then file="lib/formsparts/"..file end
  647. local f=fs.open(file,"r")
  648. if(f)then
  649. local d=fs.read(f,math.huge)
  650. fs.close(f)
  651. load(d,"","",_G)()
  652. end
  653.  
  654. end
  655.  
  656. return forms
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement