dbgcommands.py 5.63 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
# Command Handlers for the debugger.

# Not in the debugger package, as I always want these interfaces to be
# available, even if the debugger has not yet been (or can not be)
# imported
import win32ui, win32con
from . import scriptutils
import warnings
from pywin.scintilla.control import CScintillaEditInterface

IdToBarNames = {
	win32ui.IDC_DBG_STACK : ("Stack",0),
	win32ui.IDC_DBG_BREAKPOINTS : ("Breakpoints",0),
	win32ui.IDC_DBG_WATCH : ("Watch",1),
	}

class DebuggerCommandHandler:
	def HookCommands(self):
		commands = ( (self.OnStep, None, win32ui.IDC_DBG_STEP),
		                  (self.OnStepOut, self.OnUpdateOnlyBreak, win32ui.IDC_DBG_STEPOUT),
		                  (self.OnStepOver, None, win32ui.IDC_DBG_STEPOVER),
		                  (self.OnGo, None, win32ui.IDC_DBG_GO),
		                  (self.OnClose, self.OnUpdateClose, win32ui.IDC_DBG_CLOSE),
		                  (self.OnAdd, self.OnUpdateAddBreakpoints, win32ui.IDC_DBG_ADD),
		                  (self.OnClearAll, self.OnUpdateClearAllBreakpoints, win32ui.IDC_DBG_CLEAR),
#		                  (self.OnDebuggerToolbar, self.OnUpdateDebuggerToolbar, win32ui.ID_DEBUGGER_TOOLBAR),
		                )

		frame = win32ui.GetMainFrame()

		for methHandler, methUpdate, id in commands:
			frame.HookCommand(methHandler, id);
			if not methUpdate is None:
				frame.HookCommandUpdate(methUpdate, id)

		for id in list(IdToBarNames.keys()):
			frame.HookCommand( self.OnDebuggerBar, id)
			frame.HookCommandUpdate(self.OnUpdateDebuggerBar, id)

	def OnDebuggerToolbar(self, id, code):
		if code==0:
			return not win32ui.GetMainFrame().OnBarCheck(id)

	def OnUpdateDebuggerToolbar(self, cmdui):
		win32ui.GetMainFrame().OnUpdateControlBarMenu(cmdui)
		cmdui.Enable(1)

	def _GetDebugger(self):
		try:
			import pywin.debugger
			return pywin.debugger.currentDebugger
		except ImportError:
			return None

	def _DoOrStart(self, doMethod, startFlag):
		d=self._GetDebugger()
		if d is not None and d.IsDebugging():
			method = getattr(d, doMethod)
			method()
		else:
			scriptutils.RunScript(defName=None, defArgs=None, bShowDialog = 0, debuggingType=startFlag)

	def OnStep(self, msg, code):
		self._DoOrStart("do_set_step", scriptutils.RS_DEBUGGER_STEP)

	def OnStepOver(self, msg, code):
		self._DoOrStart("do_set_next", scriptutils.RS_DEBUGGER_STEP)

	def OnStepOut(self, msg, code):
		d=self._GetDebugger()
		if d is not None and d.IsDebugging():
			d.do_set_return()

	def OnGo(self, msg, code):
		self._DoOrStart("do_set_continue", scriptutils.RS_DEBUGGER_GO)

	def OnClose(self, msg, code):
		d=self._GetDebugger()
		if d is not None:
			if d.IsDebugging():
				d.set_quit()
			else:
				d.close()

	def OnUpdateClose(self, cmdui):
		d=self._GetDebugger()
		if d is not None and d.inited:
			cmdui.Enable(1)
		else:
			cmdui.Enable(0)

	def OnAdd(self, msg, code):
		doc, view = scriptutils.GetActiveEditorDocument()
		if doc is None:
			## Don't do a messagebox, as this could be triggered from the app's
			## idle loop whenever the debug toolbar is visible, giving a never-ending
			## series of dialogs.  This can happen when the OnUpdate handler
			## for the toolbar button IDC_DBG_ADD fails, since MFC falls back to
			## sending a normal command if the UI update command fails.
			## win32ui.MessageBox('There is no active window - no breakpoint can be added')
			warnings.warn('There is no active window - no breakpoint can be added')
			return None
		pathName = doc.GetPathName()
		lineNo = view.LineFromChar(view.GetSel()[0])+1
		# If I have a debugger, then tell it, otherwise just add a marker
		d=self._GetDebugger()
		if d is None:
			import pywin.framework.editor.color.coloreditor
			doc.MarkerToggle(lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT)
		else:
			if d.get_break(pathName, lineNo):
				win32ui.SetStatusText('Clearing breakpoint',1)
				rc = d.clear_break(pathName, lineNo)
			else:
				win32ui.SetStatusText('Setting breakpoint',1)
				rc = d.set_break(pathName, lineNo)
			if rc:
				win32ui.MessageBox(rc)
			d.GUIRespondDebuggerData()

	def OnClearAll(self, msg, code):
		win32ui.SetStatusText('Clearing all breakpoints')
		d=self._GetDebugger()
		if d is None:
			import pywin.framework.editor
			import pywin.framework.editor.color.coloreditor
			for doc in pywin.framework.editor.editorTemplate.GetDocumentList():
				doc.MarkerDeleteAll(pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT)
		else:
			d.clear_all_breaks()
			d.UpdateAllLineStates()
			d.GUIRespondDebuggerData()

	def OnUpdateOnlyBreak(self, cmdui):
		d=self._GetDebugger()
		ok = d is not None and d.IsBreak()
		cmdui.Enable(ok)

	def OnUpdateAddBreakpoints(self, cmdui):
		doc, view = scriptutils.GetActiveEditorDocument()
		if doc is None or not isinstance(view, CScintillaEditInterface):
			enabled = 0
		else:
			enabled = 1
			lineNo = view.LineFromChar(view.GetSel()[0])+1
			import pywin.framework.editor.color.coloreditor
			cmdui.SetCheck(doc.MarkerAtLine(lineNo, pywin.framework.editor.color.coloreditor.MARKER_BREAKPOINT) != 0)
		cmdui.Enable(enabled)

	def OnUpdateClearAllBreakpoints(self, cmdui):
		d=self._GetDebugger()
		cmdui.Enable(d is None or len(d.breaks)!=0)

	def OnUpdateDebuggerBar(self, cmdui):
		name, always = IdToBarNames.get(cmdui.m_nID)
		enabled = always
		d=self._GetDebugger()
		if d is not None and d.IsDebugging() and name is not None:
			enabled = 1
			bar = d.GetDebuggerBar(name)
			cmdui.SetCheck(bar.IsWindowVisible())
		cmdui.Enable(enabled)

	def OnDebuggerBar(self, id, code):
		name = IdToBarNames.get(id)[0]
		d=self._GetDebugger()
		if d is not None and name is not None:
			bar = d.GetDebuggerBar(name)
			newState = not bar.IsWindowVisible()
			win32ui.GetMainFrame().ShowControlBar(bar, newState, 1)