only load python in vimrc when opening c,cpp files
[pygdb.git] / DbgTerminal.py
1 #!/usr/bin/python
2 #shuber, 2008-06-04
3
4 __author__ = "shuber"
5
6
7 import gobject
8 import gtk
9 import os
10 import pango
11 import pty
12 import re
13 import string
14 import sys
15 import time
16 import threading
17 import vte
18
19 import ClientIOTerminal
20
21
22
23 class DbgTerminal (vte.Terminal):
24
25 def __init__(self, clientCmd):
26
27 vte.Terminal.__init__(self)
28
29 #Set members
30 self.childpid = None
31 self.history = [""]
32 self.isactive = True
33 self.lastc, self.lastr = 0,0
34 self.gotActiveCallback = []
35 self.gotInactiveCallback = []
36 self.activityChanged = None
37
38 #Start debugger
39 self.clientCmd = clientCmd
40 #Open pseudo-terminal where to-be-debugged process reads/writes to
41 self.client_ptymaster, self.client_ptyslave = pty.openpty()
42
43 #Set up terminal window and initialize debugger
44 self.connect("cursor-moved", self.contents_changed)
45 self.connect("child-exited", quitHandler)
46 gobject.timeout_add(50, self.checkActivityChanged)
47
48 #font description
49 fontdesc = pango.FontDescription("monospace 9")
50 self.set_font(fontdesc)
51
52
53 def initialize(self):
54 self.childpid = self.fork_command( self.getCommand(), self.getArgv())
55 self.waitForPrompt(0)
56 self.setPty(self.client_ptyslave)
57
58 def stopDbg(self):
59
60 if self.childpid != None:
61 #9=KILL, 15=TERM
62 os.kill(self.childpid, 15);
63 self.childpid = None
64
65 def getClientExecuteable(self):
66 return string.split(self.clientCmd)[0]
67
68
69 def toAbsPath(self, path):
70 """convert path to an absolute path relative to the client
71 executable we debug."""
72
73 #Current working dir
74 pwd = os.getcwd() + "/"
75
76 #executeable path
77 client = self.getClientExecuteable()
78 client = relToAbsPath(pwd, client)
79
80 return relToAbsPath(client, path)
81
82
83 def checkActivityChanged(self):
84
85 try:
86
87 #There was activity
88 if self.activityChanged != None:
89
90 res = self.activityChanged
91 self.activityChanged = None
92
93 status, param = res
94 if self.isActive():
95 print "got active: ", res
96 for cb in self.gotActiveCallback:
97 cb(status, param)
98 else:
99 print "got inactive: ", res
100 for cb in self.gotInactiveCallback:
101 cb(status, param)
102 except Exception, e:
103 print e
104
105 return True
106
107
108
109 def contents_changed(self, term):
110 assert( self.getHistoryLen()>0 )
111
112 c,r = term.get_cursor_position()
113 text = self.get_text_range(self.lastr,0,r,c,lambda *w:True)
114 self.lastc, self.lastr = c,r
115
116 #Remove annoying \n at the end
117 assert(text[-1] == "\n")
118 text = text[:-1]
119
120 #Get the lines and remove empty lines
121 lines = string.split(text, "\n")
122
123 #Remove the incomplete line
124 len = max(0,self.getHistoryLen())
125 self.history[-1] = lines[0]
126 self.history += lines[1:]
127
128
129 #Check if activity status has been changed
130 for i in range(len, self.getHistoryLen()):
131 line = self.history[i]
132
133 res = self.testForInactivity(i)
134 if res != None:
135 while self.activityChanged != None:
136 print "wait for pending activity"
137 gtk.main_iteration()
138
139 self.setActive(False)
140 self.activityChanged = res
141
142 res = self.testForActivity(i)
143 if res != None:
144 while self.activityChanged != None:
145 print "wait for pending activity"
146 gtk.main_iteration()
147
148 self.setActive(True)
149 self.activityChanged = res
150
151
152
153
154 def waitForNewline(self):
155 l = self.getHistoryLen()
156 while not self.getHistoryLen() > l:
157 gtk.main_iteration()
158
159 def getHistoryLen(self):
160 return len(self.history)
161
162 def waitForRx(self, pat, start):
163
164 rx = re.compile(pat)
165 curr = start
166 while True:
167 assert( curr>=start )
168 for no in range(curr, self.getHistoryLen()):
169 line = self.history[no]
170 if rx.search(line):
171 return no, line
172
173 #Do not forget the last line
174 curr = max(start,self.getHistoryLen()-1)
175 lr, lc = self.lastr, self.lastc
176
177 while (self.lastr, self.lastc) == (lr,lc):
178 gtk.main_iteration()
179
180
181 def getCommand(self):
182 return self.getArgv()[0];
183
184 def getArgv(self):
185 raise NotImplementedError()
186
187 def setPty(self, pty):
188 raise NotImplementedError()
189
190 def setRun(self):
191 raise NotImplementedError()
192
193 def setContinue(self):
194 raise NotImplementedError()
195
196 def setStepover(self):
197 raise NotImplementedError()
198
199 def setStepin(self):
200 raise NotImplementedError()
201
202 def setStepout(self):
203 raise NotImplementedError()
204
205 def setQuit(self):
206 raise NotImplementedError()
207
208 def setBreakpoint(self, file, lineno, condition=False):
209 raise NotImplementedError()
210
211 def delBreakpoint(self, breakpoint):
212 raise NotImplementedError()
213
214 def getExpression(self, expr):
215 raise NotImplementedError()
216
217 def listCodeSnippet(self):
218 raise NotImplementedError()
219
220 def getBacktrace(self):
221 raise NotImplementedError()
222
223 def waitForPrompt(self, his):
224 raise NotImplementedError()
225
226 def testForActivity(self, his):
227 raise NotImplementedError()
228
229 def testForInactivity(self, his):
230 raise NotImplementedError()
231
232 def setActive(self, isactive):
233 self.isactive = isactive
234
235 def isActive(self):
236 return self.isactive
237
238
239
240 def quitHandler(*w):
241 try:
242 gtk.main_quit()
243 except:
244 pass
245
246
247 def relToAbsPath(absfile, relfile):
248 """When an absfile is given and a relfile is given by
249 relative paths relative to absfile, determine the abs
250 path of relfile"""
251
252 #Get directories except for "." parts
253 relsplit = filter(lambda x: x!=".", string.split(relfile, os.sep))
254 #Get the directories of absfile withouth the trailing filename
255 abssplit = string.split(absfile, os.sep)[:-1]
256
257 #Determine number of ".." and remove them
258 up=0
259 while relsplit[0] == "..":
260 up += 1
261 del relsplit[0]
262 del abssplit[-1]
263
264 return string.join(abssplit + relsplit, os.sep)
265
266
267 class DbgWindow (gtk.Window):
268
269 clientIOWnd = None
270
271
272 def __init__(self, terminal):
273
274 #Set up some members
275 self.terminal = terminal
276
277 #Set up GTK stuff
278 gtk.Window.__init__(self)
279 self.connect("destroy", quitHandler)
280
281 #Set title and add terminal
282 self.set_title("Debugger I/O")
283 self.terminal.history = []
284 self.terminal.history_length = 5
285 self.add(self.terminal)
286
287 #Show the window
288 self.show_all()
289
290 def toggleClientIOWindow(self):
291 if not self.clientIOWnd:
292 self.clientIOWnd = ClientIOTerminal.ClientIOWindow(self, \
293 self.terminal.client_ptymaster)
294 else:
295 self.clientIOWnd.destroy()
296 self.clientIOWnd = None
297
298 def isClientIOWindowExisting(self):
299 return self.clientIOWnd != None
300
301
302