349 lines
10 KiB
Lua
349 lines
10 KiB
Lua
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
|
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
|
---------------------------------------------------------
|
|
local ide = ide
|
|
|
|
-- Create the Debug menu and attach the callback functions
|
|
|
|
local frame = ide.frame
|
|
local menuBar = frame.menuBar
|
|
|
|
local openDocuments = ide.openDocuments
|
|
local debugger = ide.debugger
|
|
local filetree = ide.filetree
|
|
|
|
------------------------
|
|
-- Interpreters and Menu
|
|
local targetMenu
|
|
local interpreters = {}
|
|
local lastinterpreter
|
|
do
|
|
local interpreternames = {}
|
|
local lkinterpreters = {}
|
|
for i,v in pairs(ide.interpreters) do
|
|
interpreters[ID ("debug.interpreter."..i)] = v
|
|
v.fname = i
|
|
lastinterpreter = i
|
|
table.insert(interpreternames,v.name)
|
|
lkinterpreters[v.name] = i
|
|
end
|
|
assert(lastinterpreter,"no interpreters defined")
|
|
table.sort(interpreternames)
|
|
|
|
local targetargs = {}
|
|
for i,v in ipairs(interpreternames) do
|
|
local id = ID ("debug.interpreter."..lkinterpreters[v])
|
|
local inter = interpreters[id]
|
|
table.insert(targetargs,{id,inter.name,inter.description,wx.wxITEM_CHECK})
|
|
end
|
|
targetMenu = wx.wxMenu(targetargs)
|
|
end
|
|
|
|
local debugTab = {
|
|
{ ID_RUN, "&Run\tF6", "Execute the current project/file" },
|
|
{ ID_COMPILE, "&Compile\tF7", "Test compile the Lua file" },
|
|
{ ID_START_DEBUG, "Start &Debugging\tF5", "Start a debugging session" },
|
|
{ ID_ATTACH_DEBUG, "&Start Debugger Server\tShift-F6", "Allow a client to start a debugging session" },
|
|
{ },
|
|
{ ID_STOP_DEBUG, "S&top Debugging\tShift-F12", "Stop and end the debugging session" },
|
|
{ ID_STEP, "St&ep\tF11", "Step into the next line" },
|
|
{ ID_STEP_OVER, "Step &Over\tF10", "Step over the next line" },
|
|
{ ID_STEP_OUT, "Step O&ut\tShift-F10", "Step out of the current function" },
|
|
{ ID_TRACE, "Tr&ace", "Trace execution showing each executed line" },
|
|
{ ID_BREAK, "&Break", "Stop execution of the program at the next executed line of code" },
|
|
{ },
|
|
{ ID_TOGGLEBREAKPOINT, "Toggle &Breakpoint\tF9", "Toggle Breakpoint" },
|
|
--{ ID "view.debug.callstack", "V&iew Call Stack", "View the LUA call stack" },
|
|
{ },
|
|
{ ID_CLEAROUTPUT, "C&lear Output Window", "Clear the output window before compiling or debugging", wx.wxITEM_CHECK },
|
|
}
|
|
|
|
local debugMenu = wx.wxMenu(debugTab)
|
|
local debugMenuRun = {start="Start &Debugging\tF5", continue="Co&ntinue\tF5"}
|
|
|
|
local targetDirMenu = wx.wxMenu{
|
|
{ID "debug.projectdir.choose","Choose ..."},
|
|
{ID "debug.projectdir.fromfile","From current filepath"},
|
|
{},
|
|
{ID "debug.projectdir.currentdir",""}
|
|
}
|
|
|
|
debugMenu:Append(0,"Lua &interpreter",targetMenu,"Set the interpreter to be used")
|
|
debugMenu:Append(0,"Project directory",targetDirMenu,"Set the project directory to be used")
|
|
menuBar:Append(debugMenu, "&Project")
|
|
|
|
-----------------------------
|
|
-- Project directory handling
|
|
|
|
function ProjectUpdateProjectDir(projdir,skiptree)
|
|
ide.config.path.projectdir = projdir
|
|
menuBar:SetLabel(ID "debug.projectdir.currentdir",projdir)
|
|
frame:SetStatusText(projdir)
|
|
if (not skiptree) then
|
|
ide.filetree:updateProjectDir(projdir)
|
|
end
|
|
end
|
|
ProjectUpdateProjectDir(ide.config.path.projectdir)
|
|
|
|
local function projChoose(event)
|
|
local editor = GetEditor()
|
|
local saved = false
|
|
local fn = wx.wxFileName(
|
|
editor and openDocuments[editor:GetId()].filePath or "")
|
|
fn:Normalize() -- want absolute path for dialog
|
|
|
|
local projectdir = ide.config.path.projectdir
|
|
|
|
local filePicker = wx.wxDirDialog(frame, "Chose a project directory",
|
|
projectdir~="" and projectdir or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
|
local res = filePicker:ShowModal(true)
|
|
if res == wx.wxID_OK then
|
|
ProjectUpdateProjectDir(filePicker:GetPath())
|
|
end
|
|
return true
|
|
end
|
|
|
|
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
projChoose)
|
|
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
|
projChoose)
|
|
|
|
local function projFromFile(event)
|
|
local editor = GetEditor()
|
|
if not editor then return end
|
|
local id = editor:GetId()
|
|
local filepath = openDocuments[id].filePath
|
|
if not filepath then return end
|
|
local fn = wx.wxFileName(filepath)
|
|
fn:Normalize() -- want absolute path for dialog
|
|
|
|
if ide.interpreter then ProjectUpdateProjectDir(ide.interpreter:fprojdir(fn)) end
|
|
end
|
|
frame:Connect(ID "debug.projectdir.fromfile", wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
projFromFile)
|
|
|
|
------------------------------------
|
|
-- Interpreter Selection and Running
|
|
|
|
local function selectInterpreter(id)
|
|
for i,inter in pairs(interpreters) do
|
|
menuBar:Check(i, false)
|
|
end
|
|
menuBar:Check(id, true)
|
|
ide.interpreter = interpreters[id]
|
|
ReloadLuaAPI()
|
|
end
|
|
|
|
function ProjectSetInterpreter(name)
|
|
local id = IDget("debug.interpreter."..name)
|
|
if (not interpreters[id]) then return end
|
|
selectInterpreter(id)
|
|
end
|
|
|
|
local function evSelectInterpreter (event)
|
|
local chose = event:GetId()
|
|
selectInterpreter(chose)
|
|
end
|
|
|
|
for id,inter in pairs(interpreters) do
|
|
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectInterpreter)
|
|
end
|
|
|
|
do
|
|
local defaultid = (
|
|
IDget("debug.interpreter."..ide.config.interpreter) or
|
|
ID ("debug.interpreter."..lastinterpreter)
|
|
)
|
|
ide.interpreter = interpreters[defaultid]
|
|
menuBar:Check(defaultid, true)
|
|
end
|
|
|
|
local function getNameToRun()
|
|
local editor = GetEditor()
|
|
|
|
-- test compile it before we run it, if successful then ask to save
|
|
-- only compile if lua api
|
|
if (editor.spec.apitype and
|
|
editor.spec.apitype == "lua" and
|
|
not CompileProgram(editor)) then
|
|
return
|
|
end
|
|
|
|
local id = editor:GetId()
|
|
if not openDocuments[id].filePath then SetDocumentModified(id, true) end
|
|
if not SaveIfModified(editor) then return end
|
|
|
|
return wx.wxFileName(openDocuments[id].filePath)
|
|
end
|
|
|
|
local function runInterpreter(wfilename, withdebugger)
|
|
ClearAllCurrentLineMarkers()
|
|
if not wfilename then return end
|
|
local pid = ide.interpreter:frun(wfilename, withdebugger)
|
|
if withdebugger then debugger.pid = pid end
|
|
end
|
|
|
|
function ProjectRun()
|
|
runInterpreter(getNameToRun())
|
|
end
|
|
|
|
function ProjectDebug()
|
|
if (debugger.server ~= nil) then
|
|
if (not debugger.running) then
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.run()
|
|
end
|
|
else
|
|
runInterpreter(getNameToRun(), true)
|
|
end
|
|
end
|
|
|
|
-----------------------
|
|
-- Actions
|
|
|
|
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
local line = editor:LineFromPosition(editor:GetCurrentPos())
|
|
DebuggerToggleBreakpoint(editor, line)
|
|
end)
|
|
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((ide.interpreter) and (ide.interpreter.hasdebugger) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_COMPILE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
CompileProgram(editor)
|
|
end)
|
|
frame:Connect(ID_COMPILE, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server == nil) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_RUN, wx.wxEVT_COMMAND_MENU_SELECTED, ProjectRun)
|
|
frame:Connect(ID_RUN, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server == nil) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
if (ide.interpreter.fattachdebug) then ide.interpreter:fattachdebug() end
|
|
end)
|
|
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((ide.interpreter) and (ide.interpreter.fattachdebug) and
|
|
(not debugger.listening) and (debugger.server == nil) and (editor ~= nil))
|
|
end)
|
|
|
|
local lastcontinue
|
|
frame:Connect(ID_START_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED, ProjectDebug)
|
|
frame:Connect(ID_START_DEBUG, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((ide.interpreter) and (ide.interpreter.hasdebugger) and
|
|
((debugger.server == nil) or (debugger.server ~= nil and not debugger.running)) and (editor ~= nil))
|
|
local curcontinue = (debugger.server ~= nil)
|
|
if curcontinue == lastcontinue then return end
|
|
lastcontinue = curcontinue
|
|
if curcontinue then
|
|
debugMenu:SetLabel(ID_START_DEBUG, debugMenuRun.continue)
|
|
else
|
|
debugMenu:SetLabel(ID_START_DEBUG, debugMenuRun.start)
|
|
end
|
|
end)
|
|
|
|
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.terminate()
|
|
end)
|
|
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_STEP, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.step()
|
|
end)
|
|
frame:Connect(ID_STEP, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_STEP_OVER, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.over()
|
|
end)
|
|
frame:Connect(ID_STEP_OVER, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_STEP_OUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.out()
|
|
end)
|
|
frame:Connect(ID_STEP_OUT, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_TRACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
ClearAllCurrentLineMarkers()
|
|
debugger.trace()
|
|
end)
|
|
frame:Connect(ID_TRACE, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
|
end)
|
|
|
|
frame:Connect(ID_BREAK, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
if debugger.server then
|
|
debugger.breaknow()
|
|
end
|
|
end)
|
|
frame:Connect(ID_BREAK, wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
local editor = GetEditor()
|
|
event:Enable((debugger.server ~= nil) and (debugger.running) and (editor ~= nil))
|
|
end)
|
|
|
|
--[[
|
|
frame:Connect(ID "view.debug.callstack", wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
if debugger.server then
|
|
DebuggerCreateStackWindow()
|
|
end
|
|
end)
|
|
frame:Connect(ID "view.debug.callstack", wx.wxEVT_UPDATE_UI,
|
|
function (event)
|
|
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
|
end)
|
|
]]
|
|
|
|
frame:Connect(wx.wxEVT_IDLE,
|
|
function(event)
|
|
if (debugger.update) then
|
|
debugger.update()
|
|
end
|
|
end)
|