dbgcommands.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. # Command Handlers for the debugger.
  2. # Not in the debugger package, as I always want these interfaces to be
  3. # available, even if the debugger has not yet been (or can not be)
  4. # imported
  5. import win32ui, win32con
  6. from . import scriptutils
  7. import warnings
  8. from pywin.scintilla.control import CScintillaEditInterface
  9. IdToBarNames = {
  10. win32ui.IDC_DBG_STACK : ("Stack",0),
  11. win32ui.IDC_DBG_BREAKPOINTS : ("Breakpoints",0),
  12. win32ui.IDC_DBG_WATCH : ("Watch",1),
  13. }
  14. class DebuggerCommandHandler:
  15. def HookCommands(self):
  16. commands = ( (self.OnStep, None, win32ui.IDC_DBG_STEP),
  17. (self.OnStepOut, self.OnUpdateOnlyBreak, win32ui.IDC_DBG_STEPOUT),
  18. (self.OnStepOver, None, win32ui.IDC_DBG_STEPOVER),
  19. (self.OnGo, None, win32ui.IDC_DBG_GO),
  20. (self.OnClose, self.OnUpdateClose, win32ui.IDC_DBG_CLOSE),
  21. (self.OnAdd, self.OnUpdateAddBreakpoints, win32ui.IDC_DBG_ADD),
  22. (self.OnClearAll, self.OnUpdateClearAllBreakpoints, win32ui.IDC_DBG_CLEAR),
  23. # (self.OnDebuggerToolbar, self.OnUpdateDebuggerToolbar, win32ui.ID_DEBUGGER_TOOLBAR),
  24. )
  25. frame = win32ui.GetMainFrame()
  26. for methHandler, methUpdate, id in commands:
  27. frame.HookCommand(methHandler, id);
  28. if not methUpdate is None:
  29. frame.HookCommandUpdate(methUpdate, id)
  30. for id in list(IdToBarNames.keys()):
  31. frame.HookCommand( self.OnDebuggerBar, id)
  32. frame.HookCommandUpdate(self.OnUpdateDebuggerBar, id)
  33. def OnDebuggerToolbar(self, id, code):
  34. if code==0:
  35. return not win32ui.GetMainFrame().OnBarCheck(id)
  36. def OnUpdateDebuggerToolbar(self, cmdui):
  37. win32ui.GetMainFrame().OnUpdateControlBarMenu(cmdui)
  38. cmdui.Enable(1)
  39. def _GetDebugger(self):
  40. try:
  41. import pywin.debugger
  42. return pywin.debugger.currentDebugger
  43. except ImportError:
  44. return None
  45. def _DoOrStart(self, doMethod, startFlag):
  46. d=self._GetDebugger()
  47. if d is not None and d.IsDebugging():
  48. method = getattr(d, doMethod)
  49. method()
  50. else:
  51. scriptutils.RunScript(defName=None, defArgs=None, bShowDialog = 0, debuggingType=startFlag)
  52. def OnStep(self, msg, code):
  53. self._DoOrStart("do_set_step", scriptutils.RS_DEBUGGER_STEP)
  54. def OnStepOver(self, msg, code):
  55. self._DoOrStart("do_set_next", scriptutils.RS_DEBUGGER_STEP)
  56. def OnStepOut(self, msg, code):
  57. d=self._GetDebugger()
  58. if d is not None and d.IsDebugging():
  59. d.do_set_return()
  60. def OnGo(self, msg, code):
  61. self._DoOrStart("do_set_continue", scriptutils.RS_DEBUGGER_GO)
  62. def OnClose(self, msg, code):
  63. d=self._GetDebugger()
  64. if d is not None:
  65. if d.IsDebugging():
  66. d.set_quit()
  67. else:
  68. d.close()
  69. def OnUpdateClose(self, cmdui):
  70. d=self._GetDebugger()
  71. if d is not None and d.inited:
  72. cmdui.Enable(1)
  73. else:
  74. cmdui.Enable(0)
  75. def OnAdd(self, msg, code):
  76. doc, view = scriptutils.GetActiveEditorDocument()
  77. if doc is None:
  78. ## Don't do a messagebox, as this could be triggered from the app's
  79. ## idle loop whenever the debug toolbar is visible, giving a never-ending
  80. ## series of dialogs. This can happen when the OnUpdate handler
  81. ## for the toolbar button IDC_DBG_ADD fails, since MFC falls back to
  82. ## sending a normal command if the UI update command fails.
  83. ## win32ui.MessageBox('There is no active window - no breakpoint can be added')
  84. warnings.warn('There is no active window - no breakpoint can be added')
  85. return None
  86. pathName = doc.GetPathName()
  87. lineNo = view.LineFromChar(view.GetSel()[0])+1
  88. # If I have a debugger, then tell it, otherwise just add a marker
  89. d=self._GetDebugger()
  90. if d is None:
  91. import pywin.framework.editor.color.coloreditor
  92. doc.MarkerToggle(lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT)
  93. else:
  94. if d.get_break(pathName, lineNo):
  95. win32ui.SetStatusText('Clearing breakpoint',1)
  96. rc = d.clear_break(pathName, lineNo)
  97. else:
  98. win32ui.SetStatusText('Setting breakpoint',1)
  99. rc = d.set_break(pathName, lineNo)
  100. if rc:
  101. win32ui.MessageBox(rc)
  102. d.GUIRespondDebuggerData()
  103. def OnClearAll(self, msg, code):
  104. win32ui.SetStatusText('Clearing all breakpoints')
  105. d=self._GetDebugger()
  106. if d is None:
  107. import pywin.framework.editor
  108. import pywin.framework.editor.color.coloreditor
  109. for doc in pywin.framework.editor.editorTemplate.GetDocumentList():
  110. doc.MarkerDeleteAll(pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT)
  111. else:
  112. d.clear_all_breaks()
  113. d.UpdateAllLineStates()
  114. d.GUIRespondDebuggerData()
  115. def OnUpdateOnlyBreak(self, cmdui):
  116. d=self._GetDebugger()
  117. ok = d is not None and d.IsBreak()
  118. cmdui.Enable(ok)
  119. def OnUpdateAddBreakpoints(self, cmdui):
  120. doc, view = scriptutils.GetActiveEditorDocument()
  121. if doc is None or not isinstance(view, CScintillaEditInterface):
  122. enabled = 0
  123. else:
  124. enabled = 1
  125. lineNo = view.LineFromChar(view.GetSel()[0])+1
  126. import pywin.framework.editor.color.coloreditor
  127. cmdui.SetCheck(doc.MarkerAtLine(lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT) != 0)
  128. cmdui.Enable(enabled)
  129. def OnUpdateClearAllBreakpoints(self, cmdui):
  130. d=self._GetDebugger()
  131. cmdui.Enable(d is None or len(d.breaks)!=0)
  132. def OnUpdateDebuggerBar(self, cmdui):
  133. name, always = IdToBarNames.get(cmdui.m_nID)
  134. enabled = always
  135. d=self._GetDebugger()
  136. if d is not None and d.IsDebugging() and name is not None:
  137. enabled = 1
  138. bar = d.GetDebuggerBar(name)
  139. cmdui.SetCheck(bar.IsWindowVisible())
  140. cmdui.Enable(enabled)
  141. def OnDebuggerBar(self, id, code):
  142. name = IdToBarNames.get(id)[0]
  143. d=self._GetDebugger()
  144. if d is not None and name is not None:
  145. bar = d.GetDebuggerBar(name)
  146. newState = not bar.IsWindowVisible()
  147. win32ui.GetMainFrame().ShowControlBar(bar, newState, 1)