ZNZNCOOP

debugger

Dec 26th, 2016
246
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Данный код частично сгенерирован программой FormsMaker
  2. -- http://computercraft.ru/topic/1044-sistema-vizualnogo-programmirovaniia-formsmaker/
  3. local gpu=require("component").gpu
  4. local term = require('term')
  5. local eventPull=require("event").pull
  6. local forms=require("forms")
  7. local serialize=require("serialization").serialize
  8. local keys = require("keyboard").keys
  9.  
  10. local padRight=require("text").padRight
  11. local len=require("unicode").len
  12. local sub=require("unicode").sub
  13.  
  14. local scr  -- Хранит содержимое экрана
  15. local fnCode --функция, содержащая код программы
  16. local ENV  -- Окружение, под которым работает программа
  17. local args={...}
  18.  
  19. local function saveScreen() -- Сохраняем текущий экран в таблицу scr
  20.   scr={fc=gpu.getForeground(),bc=gpu.getBackground(),blink=term.getCursorBlink()}
  21.   scr.W,scr.H = gpu.getResolution()
  22.   scr.posX, scr.posY = term.getCursor()
  23.   for i=1,scr.H do
  24.     scr[i]={}
  25.     local FC,BC
  26.     for j=1,scr.W do
  27.       local c,fc,bc=gpu.get(j,i)
  28.       if fc==FC then fc=nil end
  29.       if bc==BC then bc=nil end
  30.       if fc or bc then
  31.         table.insert(scr[i],{fc=fc,bc=bc,c=""})
  32.         FC,BC=fc or FC, bc or BC
  33.       end
  34.       scr[i][#scr[i]].c=scr[i][#scr[i]].c .. c
  35.     end
  36.   end
  37.   gpu.setResolution(80,25) os.sleep(0)
  38. end
  39.  
  40. local function loadScreen()  -- Восстанавливаем содержимое экрана
  41.   gpu.setResolution(scr.W,scr.H) os.sleep(0)
  42.   term.setCursorBlink(false)
  43.   for i=1,scr.H do
  44.     local curX=1
  45.     for j=1,#scr[i] do
  46.       if scr[i][j].fc then gpu.setForeground(scr[i][j].fc) end
  47.       if scr[i][j].bc then gpu.setBackground(scr[i][j].bc) end
  48.       gpu.set(curX,i,scr[i][j].c) curX=curX+len(scr[i][j].c)
  49.     end
  50.   end
  51.   gpu.setForeground(scr.fc)
  52.   gpu.setBackground(scr.bc)
  53.   term.setCursor(scr.posX,scr.posY)
  54.   term.setCursorBlink(scr.blink)
  55. end
  56. saveScreen()
  57.  
  58. local function review()  -- Пересчитываем окно просмотра
  59.   local res,ok
  60.   for i=1,#lstVars.items do
  61.     res=load("return "..lstVars.items[i],nil,nil,ENV)
  62.     if res then
  63.       ok,res=pcall(res)
  64.       if ok then res=serialize(res,true):gsub("\n","")
  65.       else res=res:match("]:1:(.*)") end
  66.     else res="Ошибка" end
  67.     lstVars.lines[i]=" "..lstVars.items[i].." = "..res
  68.   end
  69. end
  70.  
  71. local function Main() Form1:setActive() end
  72.  
  73. local thread     -- Поток, в котором выполняется программа
  74. local linePtr=0  -- Указатель на исполняемую строку
  75. local ok,param  -- Параметры обмена между потоками
  76.  
  77. local function runDebug(condStep,condCur)
  78.   if not fnCode then return end
  79.   loadScreen()
  80.   if condCur then
  81.     while lstText.items[lstText.index]==nil and lstText.index<#lstText.lines do lstText.index=lstText.index+1 end
  82.   end
  83.   repeat
  84.     if not thread then thread=coroutine.create(fnCode) param="debug" end  -- Первый запуск
  85.     if param=="debug" then ok,param,linePtr=coroutine.resume(thread,table.unpack(args,2))
  86.     else  ok,param,linePtr=coroutine.resume(thread,coroutine.yield(param)) end   -- Возобновление работы
  87.     if not ok or coroutine.status( thread ) == "dead" then thread=nil end
  88.   until not thread or (param=="debug" and (condStep or (condCur and lstText.index==linePtr) or lstText.items[linePtr]))
  89.   saveScreen()
  90.   review()
  91.   if ok then
  92.     if thread then
  93.       if linePtr<lstText.shift+1 then lstText.shift=linePtr-1 end
  94.       if linePtr>lstText.shift+lstText.H-2 then lstText.shift=linePtr-lstText.H+2 end
  95.     end
  96.     Form1:redraw()
  97.   else lbError2.caption=param FormError:setActive() end
  98. end
  99.  
  100. forms.ignoreAll()
  101.  
  102. Form1=forms.addForm()
  103. Form1.H=1
  104. Form1.color=65535
  105.  
  106. btStop=Form1:addButton(1,1,"Стоп(F2)",
  107.   function()
  108.     thread=nil
  109.     lstText:redraw()
  110.   end
  111. )
  112. btStop.fontColor=0
  113. btStop.color=Form1.color
  114.  
  115. btBrkPt=Form1:addButton(11,1,"ТочОст(F4)",
  116.   function()
  117.     if lstText.items[lstText.index]~=nil then
  118.       lstText.items[lstText.index] = not lstText.items[lstText.index]
  119.     end
  120.   end
  121. )
  122. btBrkPt.color=Form1.color
  123. btBrkPt.fontColor=0
  124.  
  125. btScreen=Form1:addButton(22,1,"Экран(F5)",
  126.   function ()
  127.     local ev
  128.     loadScreen()
  129.     repeat ev=eventPull() until ev=="key_down" or ev=="touch"
  130.     gpu.setResolution(80,25)
  131.     Form1:redraw()
  132.   end
  133. )
  134. btScreen.color=Form1.color
  135. btScreen.W=9
  136. btScreen.fontColor=0
  137.  
  138. btView=Form1:addButton(32,1,"Просм(F6)",function() edView.text="" FormView:setActive() edView:touch(_,_,0) end)
  139. btView.color=Form1.color
  140. btView.fontColor=0
  141. btView.W=9
  142.  
  143. btCur=Form1:addButton(42,1,"ДоКур(F7)",function() runDebug(false,true) end)
  144. btCur.color=Form1.color
  145. btCur.fontColor=0
  146. btCur.W=9
  147.  
  148. btStep=Form1:addButton(52,1,"Шаг(F8)", function() runDebug(true,false) end )
  149. btStep.color=Form1.color
  150. btStep.fontColor=0
  151. btStep.W=8
  152.  
  153. btRun=Form1:addButton(60,1,"Пуск(F9)",function() runDebug(false,false) end )
  154. btRun.color=Form1.color
  155. btRun.fontColor=0
  156. btRun.W=9
  157.  
  158. btExit=Form1:addButton(69,1,"Выход(F10)",forms.stop)
  159. btExit.fontColor=0
  160. btExit.color=Form1.color
  161.  
  162. btAbout=Form1:addButton(80,1,"?",function() FormAbout:setActive() end)
  163. btAbout.fontColor=0
  164. btAbout.W=1
  165. btAbout.color=Form1.color
  166.  
  167. local eventKey={
  168.   [keys.f2]=btStop.onClick,
  169.   [keys.f4]=btBrkPt.onClick,
  170.   [keys.f5]=btScreen.onClick,
  171.   [keys.f6]=btView.onClick,
  172.   [keys.f7]=btCur.onClick,
  173.   [keys.f8]=btStep.onClick,
  174.   [keys.f9]=btRun.onClick,
  175.   [keys.f10]=btExit.onClick,
  176. }
  177. eventKey[keys.up]=function()
  178.   if lstText.index>1 then
  179.     lstText.index=lstText.index-1
  180.     if lstText.index<lstText.shift+1 then lstText.shift=lstText.index-1 end
  181.     lstText:redraw()
  182.   end
  183. end
  184.  
  185. eventKey[keys.down]=function()
  186.   if lstText.index<#lstText.lines then
  187.     lstText.index=lstText.index+1
  188.     if lstText.index>lstText.shift+lstText.H-2 then lstText.shift=lstText.index-lstText.H+2 end
  189.     lstText:redraw()
  190.   end
  191. end
  192.  
  193. eventKey[keys.delete]=function()
  194.   if lstVars.index>0 then
  195.     table.remove(lstVars.lines,lstVars.index)
  196.     table.remove(lstVars.items,lstVars.index)
  197.     if lstVars.index>#lstVars.lines then lstVars.index=#lstVars.lines end
  198.     lstVars:redraw()
  199.   end
  200. end
  201.  
  202. eventKey[keys.enter]=function()
  203.   if Form1:isActive() then
  204.     edExec.text=""
  205.     Execute:setActive()
  206.     edExec:touch(_,_,0)
  207.   end
  208. end
  209.  
  210. function evKeyDownonEvent(self, _, _, code)
  211.   if eventKey[code] then eventKey[code]() end
  212. end
  213.  
  214. evKeyDown=Form1:addEvent("key_down",evKeyDownonEvent)
  215.  
  216. function lstTextPaint(self)
  217.   local n
  218.   for i=1,self.H-2 do
  219.     n=i+self.shift
  220.     if thread and n==linePtr then gpu.setForeground(0x000000) gpu.setBackground(0x00ff00) -- текущая строка
  221.     elseif n==self.index then gpu.setForeground(self.sfColor) gpu.setBackground(self.selColor) -- курсор
  222.     elseif self.items[n] then gpu.setForeground(0xffffff) gpu.setBackground(0xff0000) -- точка останова
  223.     else gpu.setForeground(self.fontColor) gpu.setBackground(self.color)
  224.     end
  225.     gpu.set(self.X+1,self.Y+i, padRight(sub(self.lines[i+self.shift] or "",1,self.W-2),self.W-2))
  226.   end
  227.   lbCur.caption="["..self.index.."]"
  228.   lbCur.left=self.W-#lbCur.caption-1
  229.   if thread then lbMode.caption="RUN:"..linePtr else lbMode.caption="STOP" end
  230.   lbMode.W=#lbMode.caption
  231. end
  232.  
  233. function lstTextInsert(self,line,item)
  234.   self.lines[#self.lines+1]=line
  235.   self.items[#self.lines]=item
  236.   if self.index<1 then self.index=1 end
  237.   if #self.lines<self.shift+self.H-1 then self:redraw() end
  238. end
  239.  
  240. lstText=Form1:addList(1,2)
  241. lstText.H=18
  242. lstText.W=80
  243. lstText.color=128
  244. lstText.paint=lstTextPaint
  245. lstText.insert=lstTextInsert
  246.  
  247. lbFileName=lstText:addLabel(33,1," Код не загружен ")
  248. lbFileName.W=17
  249. lbFileName.color=lstText.color
  250.  
  251. lbCur=lstText:addLabel(72,18,"[0]")
  252. lbCur.color=lstText.color
  253.  
  254. lbMode=lstText:addLabel(3,18,"STOP")
  255. lbMode.color=lstText.color
  256.  
  257. lstVars=Form1:addList(1,20)
  258. lstVars.H=6
  259. lstVars.W=80
  260. lstVars.color=32768
  261.  
  262. Label1=lstVars:addLabel(35,1," Просмотр ")
  263. Label1.color=lstVars.color
  264.  
  265. FormError=forms.addForm()
  266. FormError.top=7
  267. FormError.H=12
  268. FormError.border=1
  269. FormError.W=53
  270. FormError.left=15
  271. FormError.color=8388608
  272.  
  273. lbError1=FormError:addLabel(24,3,"Ошибка")
  274. lbError1.W=6
  275. lbError1.color=FormError.color
  276.  
  277. lbError2=FormError:addLabel(4,5,"lbError2")
  278. lbError2.autoSize=false
  279. lbError2.H=4
  280. lbError2.W=47
  281. lbError2.centered=true
  282. lbError2.color=FormError.color
  283.  
  284. btOk=FormError:addButton(22,10,"Ok",Main)
  285.  
  286. FormAbout=forms.addForm()
  287. FormAbout.H=8
  288. FormAbout.border=1
  289. FormAbout.W=24
  290. FormAbout.color=0x008000
  291. FormAbout.left=math.floor((80-FormAbout.W)/2)
  292. FormAbout.top =math.floor((25-FormAbout.H)/2)
  293.  
  294. lbAbout=FormAbout:addLabel(2,3,"Отладчик луа-кода\nВерсия 1.2\n от Zer0Galaxy")
  295. lbAbout.W=FormAbout.W-2
  296. lbAbout.H=3
  297. lbAbout.color=FormAbout.color
  298. lbAbout.centered=true
  299. lbAbout.autoSize=false
  300. lbError2.color=FormError.color
  301.  
  302. btAboutOk=FormAbout:addButton(8,7,"Ok",Main)
  303.  
  304. FormView=forms.addForm()
  305. FormView.W=49
  306. FormView.left=17
  307. FormView.H=10
  308. FormView.top=7
  309. FormView.color=32768
  310. FormView.border=1
  311.  
  312. edView=FormView:addEdit(4,4)
  313. edView.color=FormView.color
  314. edView.W=43
  315.  
  316. btViewOk=FormView:addButton(11,8,"Ok",
  317.   function ()
  318.   if edView.text~="" then
  319.     lstVars:insert("",edView.text)
  320.     review()
  321.     Main()
  322.   end
  323. end)
  324.  
  325. btViewCancel=FormView:addButton(30,8,"Отмена",Main)
  326.  
  327. lbView=FormView:addLabel(5,3,"Выражение для просмотра:")
  328. lbView.W=41
  329. lbView.centered=true
  330. lbView.autoSize=false
  331. lbView.color=FormView.color
  332.  
  333. Execute=forms.addForm()
  334. Execute.H=10
  335. Execute.left=12
  336. Execute.W=59
  337. Execute.border=1
  338. Execute.top=8
  339. Execute.color=0x787878
  340.  
  341. lbExec=Execute:addLabel(5,3,"Выполнить:")
  342. lbExec.W=10
  343. lbExec.color=Execute.color
  344.  
  345. edExec=Execute:addEdit(4,4)
  346. edExec.W=53
  347. edExec.color=Execute.color
  348.  
  349. function btExeOkClick()
  350.   if edExec.text~="" then
  351.     local f,err,ok=load(edExec.text,nil,nil,ENV)
  352.     if f then
  353.       loadScreen()
  354.       ok,err=pcall(f)
  355.       saveScreen()
  356.       if ok then err=nil end
  357.       review()
  358.     end
  359.     if err then lbError2.caption=err FormError:setActive() return
  360.     end
  361.   end
  362.   Main()
  363. end
  364.  
  365. btExeOk=Execute:addButton(17,8,"OK",btExeOkClick)
  366.  
  367. btExeCans=Execute:addButton(33,8,"Отмена",Main)
  368.  
  369.  
  370. fileName=args[1]
  371. if fileName then codeFile=io.open(fileName) end
  372. local linesLoad,bug
  373. local err="Код не загружен"
  374.  
  375. function readline()
  376.   linesLoad=linesLoad+1
  377.   if linesLoad<=#lstText.lines then
  378.     if lstText.items[linesLoad]~=nil then
  379.       return "coroutine.yield('debug'," .. linesLoad .. ") " ..lstText.lines[linesLoad].."\r"
  380.     end
  381.     return lstText.lines[linesLoad].."\r"
  382.   else
  383.     bug=false
  384.     local line=codeFile:read()
  385.     if line then
  386.       if line:sub(-1) == "\r" then line = line:sub(1, -2) end
  387.       if line:match("^%s*%a") then  --если строка начинается с буквы
  388.         lstText:insert(" "..line,false)  -- добавляем возможность точки останова
  389.         return "coroutine.yield('debug'," .. #lstText.lines .. ") " ..line.."\r"
  390.       end
  391.       lstText:insert(" "..line)
  392.       return line.."\r"
  393.     end
  394.   end
  395. end
  396. ENV={}
  397. for k,v in pairs(_G) do ENV[k]=v end
  398.  
  399. if codeFile then
  400.   lbFileName.caption=" "..fileName.." "
  401.   lbFileName.W=#lbFileName.caption
  402.   lbFileName.left=(lstText.W-lbFileName.W)/2
  403.   repeat
  404.     linesLoad = 0 bug=true
  405.     fnCode,err=load(readline,fileName,nil,ENV)
  406.     if not fnCode then lstText.items[linesLoad]=nil end
  407.   until fnCode or bug
  408.   codeFile:close()
  409. end
  410.  
  411. if fnCode then forms.run(Form1)
  412. else lbError2.caption=err forms.run(FormError) end
  413.  
  414. loadScreen()
RAW Paste Data