fixing bug, when getting text from terminal: started at line -1
[pygdb.git] / DbgTerminal.py
1 #!/usr/bin/python
2 #shuber, 2008-06-04
3
4 __author__ = "shuber"
5
6
7 import gtk
8 import os
9 import pango
10 import pty
11 import string
12 import sys
13 import time
14 import threading
15 import vte
16
17 import ClientIOTerminal
18
19
20
21 class DbgTerminal (vte.Terminal):
22
23 def __init__(self, clientCmd):
24
25 vte.Terminal.__init__(self)
26
27 #Set members
28 self.childpid = None
29 self.history = []
30 self.isactive = True
31
32 #Start debugger
33 self.clientCmd = clientCmd
34 #Open pseudo-terminal where to-be-debugged process reads/writes to
35 self.client_ptymaster, self.client_ptyslave = pty.openpty()
36
37 #Set up terminal window and initialize debugger
38 self.connect("cursor-moved", self.contents_changed)
39 self.connect("child-exited", quitHandler)
40
41 #font description
42 fontdesc = pango.FontDescription("monospace 9")
43 self.set_font(fontdesc)
44
45
46 def initialize(self):
47 self.childpid = self.fork_command( self.getCommand(), self.getArgv())
48 self.waitForActivation(0)
49 self.setPty(self.client_ptyslave)
50
51 def stopDbg(self):
52
53 if self.childpid != None:
54 #9=KILL, 15=TERM
55 os.kill(self.childpid, 15);
56 self.childpid = None
57
58
59
60 def contents_changed(self, term):
61 c,r = term.get_cursor_position()
62 text = self.get_text_range(max(self.getHistoryLen()-1,0),0,r,-1,lambda *w:True)
63
64 #Remove annoying \n at the end
65 assert(text[-1] == "\n")
66 text = text[:-1]
67
68 #Remove the incomplete line
69 if self.getHistoryLen()>0 and self.history[-1]!='\n':
70 del self.history[-1]
71
72 #Get the lines and remove empty lines
73 lines = string.split(text, "\n")
74
75 #Add lines to history. The last line contains no "\n" at the end!
76 self.history += [l+"\n" for l in lines[:-1]]
77 self.history += [lines[-1]]
78
79 assert(r == self.getHistoryLen()-1)
80
81
82 def waitForNewline(self):
83 l = self.getHistoryLen()
84 while not self.getHistoryLen() > l:
85 gtk.main_iteration()
86
87 def getHistoryLen(self):
88 return len(self.history)
89
90 def waitForRx(self, rx, start):
91
92 curr = start
93
94 while True:
95 for no in range(max(curr-1,start), self.getHistoryLen()):
96 line = self.history[no]
97 if rx.search(line):
98 return no, line
99
100 curr = max(start,self.getHistoryLen())
101 gtk.main_iteration()
102
103
104 def getCommand(self):
105 return self.getArgv()[0];
106
107 def getArgv(self):
108 raise NotImplementedError()
109
110 def setPty(self, pty):
111 raise NotImplementedError()
112
113 def setRun(self):
114 raise NotImplementedError()
115
116 def setContinue(self):
117 raise NotImplementedError()
118
119 def setStepover(self):
120 raise NotImplementedError()
121
122 def setStepin(self):
123 raise NotImplementedError()
124
125 def setQuit(self):
126 raise NotImplementedError()
127
128 def setBreakpoint(self, file, lineno, condition=False):
129 raise NotImplementedError()
130
131 def delBreakpoint(self, breakpoint):
132 raise NotImplementedError()
133
134 def getExpression(self, expr):
135 raise NotImplementedError()
136
137 def waitForActivation(self, his):
138 raise NotImplementedError()
139
140 def setActive(self, isactive):
141 self.isactive = isactive
142
143 def isActive(self):
144 return self.isactive
145
146
147
148 def quitHandler(*w):
149 try:
150 gtk.main_quit()
151 except:
152 pass
153 sys.exit(0)
154
155
156
157 class DbgWindow (gtk.Window):
158
159 clientIOWnd = None
160
161
162 def __init__(self, terminal):
163
164 #Set up some members
165 self.terminal = terminal
166
167 #Set up GTK stuff
168 gtk.Window.__init__(self)
169 self.connect("destroy", quitHandler)
170
171 #Set title and add terminal
172 self.set_title("Debugger I/O")
173 self.terminal.history = []
174 self.terminal.history_length = 5
175 self.add(self.terminal)
176
177 #Show the window
178 self.show_all()
179
180 def toggleClientIOWindow(self):
181 if not self.clientIOWnd:
182 self.clientIOWnd = ClientIOTerminal.ClientIOWindow(self, \
183 self.terminal.client_ptymaster)
184 else:
185 self.clientIOWnd.destroy()
186 self.clientIOWnd = None
187
188 def isClientIOWindowExisting(self):
189 return self.clientIOWnd != None
190
191
192