3
# 95% of the code from 'Bruce: the presentation tool' by Richard Jones
4
# http://code.google.com/p/bruce-tpt/
8
__docformat__ = 'restructuredtext'
15
from pyglet import graphics
16
from pyglet import text
17
from pyglet.text import caret, document, layout
20
from cocos.director import director
21
from base_layers import Layer
22
from util_layers import ColorLayer
24
__all__ = ['PythonInterpreterLayer']
27
def __init__(self, display, realstdout):
29
self.realstdout = realstdout
32
def write(self, data):
35
class MyInterpreter(code.InteractiveInterpreter):
36
def __init__(self, locals, display):
38
code.InteractiveInterpreter.__init__(self, locals=locals)
40
def execute(self, input):
41
old_stdout = sys.stdout
42
sys.stdout = Output(self.write, old_stdout)
43
more = self.runsource(input)
44
sys.stdout = old_stdout
47
class PythonInterpreterLayer(ColorLayer):
48
'''Runs an interactive Python interpreter as a child `Layer` of the current `Scene`.
51
cfg = {'code.font_name':'Arial',
53
'code.color':(255,255,255,255),
54
'caret.color':(255,255,255),
59
prompt = ">>> " #: python prompt
60
prompt_more = "... " #: python 'more' prompt
63
is_event_handler = True #: enable pyglet's events
66
super(PythonInterpreterLayer, self).__init__( 32,32,32,192 )
68
self.content = self.prompt
69
local_vars = director.interpreter_locals
70
local_vars["self"] = self
71
self.interpreter = MyInterpreter(
72
local_vars, self._write)
74
self.current_input = []
81
super(PythonInterpreterLayer, self).on_enter()
83
vw,vh = cocos.director.director.get_window_size()
86
self.document = document.FormattedDocument(self.content)
87
self.document.set_style(0, len(self.document.text), {
88
'font_name': self.cfg['code.font_name'],
89
'font_size': self.cfg['code.font_size'],
90
'color': self.cfg['code.color'],
93
self.batch = graphics.Batch()
95
# generate the document
96
self.layout = layout.IncrementalTextLayout(self.document,
97
vw, vh, multiline=True, batch=self.batch)
98
self.layout.anchor_y= 'top'
100
self.caret = caret.Caret(self.layout, color=self.cfg['caret.color'] )
101
self.caret.on_activate()
103
self.on_resize(vw, vh)
105
self.start_of_line = len(self.document.text)
107
def on_resize(self, x, y):
108
vw, vh = director.get_window_size()
109
self.layout.begin_update()
110
self.layout.height = vh
112
self.layout.width = vw - 4
114
self.layout.end_update()
117
x,y = director.window.width, director.window.height
118
self.layout.top_group._scissor_width=x-4
120
self.caret.position = len(self.document.text)
123
super(PythonInterpreterLayer, self).on_exit()
124
self.content = self.document.text
130
def on_key_press(self, symbol, modifiers):
131
if symbol == pyglet.window.key.TAB:
132
return self.caret.on_text('\t')
133
elif symbol in (pyglet.window.key.ENTER, pyglet.window.key.NUM_ENTER):
137
line = self.document.text[self.start_of_line:]
138
if line.strip() == 'help()':
139
line = 'print "help() not supported, sorry!"'
140
self.current_input.append(line)
141
self.history_pos = len(self.history)
143
self.history[self.history_pos-1] = line.strip()
144
self.history.append('')
147
if not self.doing_more:
148
more = self.interpreter.execute('\n'.join(self.current_input))
150
if self.doing_more and not line.strip():
151
self.doing_more = False
152
self.interpreter.execute('\n'.join(self.current_input))
154
more = more or self.doing_more
156
self.current_input = []
157
self._write(self.prompt)
159
self.doing_more = True
160
self._write(self.prompt_more)
161
self.start_of_line = len(self.document.text)
162
self.caret.position = len(self.document.text)
163
elif symbol == pyglet.window.key.SPACE:
166
return pyglet.event.EVENT_UNHANDLED
167
return pyglet.event.EVENT_HANDLED
169
def on_text(self, symbol):
170
# squash carriage return - we already handle them above
172
return pyglet.event.EVENT_HANDLED
174
self._scroll_to_bottom()
175
return self.caret.on_text(symbol)
177
def on_text_motion(self, motion):
178
at_sol = self.caret.position == self.start_of_line
180
if motion == pyglet.window.key.MOTION_UP:
181
# move backward in history, storing the current line of input
182
# if we're at the very end of time
183
line = self.document.text[self.start_of_line:]
184
if self.history_pos == len(self.history)-1:
185
self.history[self.history_pos] = line
186
self.history_pos = max(0, self.history_pos-1)
187
self.document.delete_text(self.start_of_line,
188
len(self.document.text))
189
self._write(self.history[self.history_pos])
190
self.caret.position = len(self.document.text)
191
elif motion == pyglet.window.key.MOTION_DOWN:
192
# move forward in the history
193
self.history_pos = min(len(self.history)-1, self.history_pos+1)
194
self.document.delete_text(self.start_of_line,
195
len(self.document.text))
196
self._write(self.history[self.history_pos])
197
self.caret.position = len(self.document.text)
198
elif motion == pyglet.window.key.MOTION_BACKSPACE:
199
# can't delete the prompt
201
return self.caret.on_text_motion(motion)
202
elif motion == pyglet.window.key.MOTION_LEFT:
203
# can't move back beyond start of line
205
return self.caret.on_text_motion(motion)
206
elif motion == pyglet.window.key.MOTION_PREVIOUS_WORD:
207
# can't move back word beyond start of line
209
return self.caret.on_text_motion(motion)
211
return self.caret.on_text_motion(motion)
212
return pyglet.event.EVENT_HANDLED
215
self.document.insert_text(len(self.document.text), s, {
216
'font_name': self.cfg['code.font_name'],
217
'font_size': self.cfg['code.font_size'],
218
'color': self.cfg['code.color'],
220
self._scroll_to_bottom()
222
def _scroll_to_bottom(self):
223
# on key press always move the view to the bottom of the screen
224
if self.layout.height < self.layout.content_height:
225
self.layout.anchor_y= 'bottom'
227
self.layout.view_y = 0
228
if self.caret.position < self.start_of_line:
229
self.caret.position = len(self.document.text)
232
super( PythonInterpreterLayer, self).draw()