codekingpro/portable-devtools
114k
1# Command Handlers for the debugger.2 3# Not in the debugger package, as I always want these interfaces to be4# available, even if the debugger has not yet been (or can not be)5# imported6import warnings7 8import win32ui9from pywin.scintilla.control import CScintillaEditInterface10 11from . import scriptutils12 13IdToBarNames = {14 win32ui.IDC_DBG_STACK: ("Stack", 0),15 win32ui.IDC_DBG_BREAKPOINTS: ("Breakpoints", 0),16 win32ui.IDC_DBG_WATCH: ("Watch", 1),17}18 19 20class DebuggerCommandHandler:21 def HookCommands(self):22 commands = (23 (self.OnStep, None, win32ui.IDC_DBG_STEP),24 (self.OnStepOut, self.OnUpdateOnlyBreak, win32ui.IDC_DBG_STEPOUT),25 (self.OnStepOver, None, win32ui.IDC_DBG_STEPOVER),26 (self.OnGo, None, win32ui.IDC_DBG_GO),27 (self.OnClose, self.OnUpdateClose, win32ui.IDC_DBG_CLOSE),28 (self.OnAdd, self.OnUpdateAddBreakpoints, win32ui.IDC_DBG_ADD),29 (self.OnClearAll, self.OnUpdateClearAllBreakpoints, win32ui.IDC_DBG_CLEAR),30 # (self.OnDebuggerToolbar, self.OnUpdateDebuggerToolbar, win32ui.ID_DEBUGGER_TOOLBAR),31 )32 33 frame = win32ui.GetMainFrame()34 35 for methHandler, methUpdate, id in commands:36 frame.HookCommand(methHandler, id)37 if not methUpdate is None:38 frame.HookCommandUpdate(methUpdate, id)39 40 for id in list(IdToBarNames.keys()):41 frame.HookCommand(self.OnDebuggerBar, id)42 frame.HookCommandUpdate(self.OnUpdateDebuggerBar, id)43 44 def OnDebuggerToolbar(self, id, code):45 if code == 0:46 return not win32ui.GetMainFrame().OnBarCheck(id)47 48 def OnUpdateDebuggerToolbar(self, cmdui):49 win32ui.GetMainFrame().OnUpdateControlBarMenu(cmdui)50 cmdui.Enable(1)51 52 def _GetDebugger(self):53 try:54 import pywin.debugger55 56 return pywin.debugger.currentDebugger57 except ImportError:58 return None59 60 def _DoOrStart(self, doMethod, startFlag):61 d = self._GetDebugger()62 if d is not None and d.IsDebugging():63 method = getattr(d, doMethod)64 method()65 else:66 scriptutils.RunScript(67 defName=None, defArgs=None, bShowDialog=0, debuggingType=startFlag68 )69 70 def OnStep(self, msg, code):71 self._DoOrStart("do_set_step", scriptutils.RS_DEBUGGER_STEP)72 73 def OnStepOver(self, msg, code):74 self._DoOrStart("do_set_next", scriptutils.RS_DEBUGGER_STEP)75 76 def OnStepOut(self, msg, code):77 d = self._GetDebugger()78 if d is not None and d.IsDebugging():79 d.do_set_return()80 81 def OnGo(self, msg, code):82 self._DoOrStart("do_set_continue", scriptutils.RS_DEBUGGER_GO)83 84 def OnClose(self, msg, code):85 d = self._GetDebugger()86 if d is not None:87 if d.IsDebugging():88 d.set_quit()89 else:90 d.close()91 92 def OnUpdateClose(self, cmdui):93 d = self._GetDebugger()94 if d is not None and d.inited:95 cmdui.Enable(1)96 else:97 cmdui.Enable(0)98 99 def OnAdd(self, msg, code):100 doc, view = scriptutils.GetActiveEditorDocument()101 if doc is None:102 ## Don't do a messagebox, as this could be triggered from the app's103 ## idle loop whenever the debug toolbar is visible, giving a never-ending104 ## series of dialogs. This can happen when the OnUpdate handler105 ## for the toolbar button IDC_DBG_ADD fails, since MFC falls back to106 ## sending a normal command if the UI update command fails.107 ## win32ui.MessageBox('There is no active window - no breakpoint can be added')108 warnings.warn("There is no active window - no breakpoint can be added")109 return None110 pathName = doc.GetPathName()111 lineNo = view.LineFromChar(view.GetSel()[0]) + 1112 # If I have a debugger, then tell it, otherwise just add a marker113 d = self._GetDebugger()114 if d is None:115 import pywin.framework.editor.color.coloreditor116 117 doc.MarkerToggle(118 lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT119 )120 else:121 if d.get_break(pathName, lineNo):122 win32ui.SetStatusText("Clearing breakpoint", 1)123 rc = d.clear_break(pathName, lineNo)124 else:125 win32ui.SetStatusText("Setting breakpoint", 1)126 rc = d.set_break(pathName, lineNo)127 if rc:128 win32ui.MessageBox(rc)129 d.GUIRespondDebuggerData()130 131 def OnClearAll(self, msg, code):132 win32ui.SetStatusText("Clearing all breakpoints")133 d = self._GetDebugger()134 if d is None:135 import pywin.framework.editor136 import pywin.framework.editor.color.coloreditor137 138 for doc in pywin.framework.editor.editorTemplate.GetDocumentList():139 doc.MarkerDeleteAll(140 pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT141 )142 else:143 d.clear_all_breaks()144 d.UpdateAllLineStates()145 d.GUIRespondDebuggerData()146 147 def OnUpdateOnlyBreak(self, cmdui):148 d = self._GetDebugger()149 ok = d is not None and d.IsBreak()150 cmdui.Enable(ok)151 152 def OnUpdateAddBreakpoints(self, cmdui):153 doc, view = scriptutils.GetActiveEditorDocument()154 if doc is None or not isinstance(view, CScintillaEditInterface):155 enabled = 0156 else:157 enabled = 1158 lineNo = view.LineFromChar(view.GetSel()[0]) + 1159 import pywin.framework.editor.color.coloreditor160 161 cmdui.SetCheck(162 doc.MarkerAtLine(163 lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT164 )165 != 0166 )167 cmdui.Enable(enabled)168 169 def OnUpdateClearAllBreakpoints(self, cmdui):170 d = self._GetDebugger()171 cmdui.Enable(d is None or len(d.breaks) != 0)172 173 def OnUpdateDebuggerBar(self, cmdui):174 name, always = IdToBarNames.get(cmdui.m_nID)175 enabled = always176 d = self._GetDebugger()177 if d is not None and d.IsDebugging() and name is not None:178 enabled = 1179 bar = d.GetDebuggerBar(name)180 cmdui.SetCheck(bar.IsWindowVisible())181 cmdui.Enable(enabled)182 183 def OnDebuggerBar(self, id, code):184 name = IdToBarNames.get(id)[0]185 d = self._GetDebugger()186 if d is not None and name is not None:187 bar = d.GetDebuggerBar(name)188 newState = not bar.IsWindowVisible()189 win32ui.GetMainFrame().ShowControlBar(bar, newState, 1)190 