-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathinput
executable file
·210 lines (164 loc) · 5.76 KB
/
input
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
"""This is a substantially improved version of the older Interpreter.py demo
It creates a simple GUI JPython console window with simple history
as well as the ability to interupt running code (with the ESC key).
Like Interpreter.py, this is still just a demo, and needs substantial
work before serious use.
Thanks to Geza Groma ([email protected]) for several valuable
ideas for this tool -- his JPConsole is a more refined implementation
of similar ideas.
"""
from Styles import Styles
from Keymap import Keymap
from pawt import swing, colors
from java.awt.event.KeyEvent import VK_UP, VK_DOWN
from java.awt.event import ActionEvent
from java.lang import Thread, System
from code import compile_command
import string, sys, re
class OutputBuffer:
def __init__(self, console, stylename):
self.console = console
self.stylename = stylename
def flush(self):
pass
def write(self, text):
self.console.write(text, self.stylename)
class Console:
def __init__(self, styles=None, keymap=None):
if styles is None:
styles = Styles()
basic = styles.add('normal', tabsize=3, fontSize=12, fontFamily="Courier")
styles.add('error', parent=basic, foreground=colors.red)
styles.add('output', parent=basic, foreground=colors.blue)
styles.add('input', parent=basic, foreground=colors.black)
styles.add('prompt', parent=basic, foreground=colors.purple)
self.styles = styles
# This is a hack to get at an inner class
# This will not be required in JPython-1.1
ForegroundAction = getattr(swing.text, 'StyledEditorKit$ForegroundAction')
self.inputAction = ForegroundAction("start input", colors.black)
if keymap is None:
keymap = Keymap()
keymap.bind('enter', self.enter)
keymap.bind('tab', self.tab)
keymap.bind('escape', self.escape)
keymap.bind('up', self.uphistory)
keymap.bind('down', self.downhistory)
self.keymap = keymap
self.document = swing.text.DefaultStyledDocument(self.styles)
self.document.setLogicalStyle(0, self.styles.get('normal'))
self.textpane = swing.JTextPane(self.document)
self.textpane.keymap = self.keymap
self.history = []
self.oldHistoryLength = 0
self.historyPosition = 0
self.command = []
self.locals = {}
def write(self, text, stylename='normal'):
style = self.styles.get(stylename)
self.document.insertString(self.document.length, text, style)
def beep(self):
self.textpane.toolkit.beep()
def startUserInput(self, prompt=None):
if prompt is not None:
self.write(prompt, 'prompt')
self.startInput = self.document.createPosition(self.document.length-1)
#self.document.setCharacterAttributes(self.document.length-1, 1, self.styles.get('input'), 1)
self.textpane.caretPosition = self.document.length
ae = ActionEvent(self.textpane, ActionEvent.ACTION_PERFORMED, 'start input')
self.inputAction.actionPerformed(ae)
def getinput(self):
offset = self.startInput.offset
line = self.document.getText(offset+1, self.document.length-offset)
return string.rstrip(line)
def replaceinput(self, text):
offset = self.startInput.offset + 1
self.document.remove(offset, self.document.length-offset)
self.write(text, 'input')
def enter(self):
line = self.getinput()
self.write('\n', 'input')
self.history.append(line)
self.handleLine(line)
def gethistory(self, direction):
historyLength = len(self.history)
if self.oldHistoryLength < historyLength:
# new line was entered after last call
self.oldHistoryLength = historyLength
if self.history[self.historyPosition] != self.history[-1]:
self.historyPosition = historyLength
pos = self.historyPosition + direction
if 0 <= pos < historyLength:
self.historyPosition = pos
self.replaceinput(self.history[pos])
else:
self.beep()
def uphistory(self):
self.gethistory(-1)
def downhistory(self):
self.gethistory(1)
def tab(self):
self.write('\t', 'input')
def escape(self):
if (not hasattr(self, 'pythonThread') or self.pythonThread is None or not self.pythonThread.alive):
self.beep()
return
self.pythonThread.stopPython()
def capturePythonOutput(self, stdoutStyle='output', stderrStyle='error'):
import sys
sys.stdout = OutputBuffer(self, stdoutStyle)
sys.stderr = OutputBuffer(self, stderrStyle)
def handleLine(self, text):
self.command.append(text)
try:
code = compile_command(string.join(self.command, '\n'))
except SyntaxError:
traceback.print_exc(0)
self.command = []
self.startUserInput(str(sys.ps1)+'\t')
return
if code is None:
self.startUserInput(str(sys.ps2)+'\t')
return
self.command = []
pt = PythonThread(code, self)
self.pythonThread = pt
pt.start()
def newInput(self):
self.startUserInput(str(sys.ps1)+'\t')
import traceback
class PythonThread(Thread):
def __init__(self, code, console):
self.code = code
self.console = console
self.locals = console.locals
def run(self):
try:
exec self.code in self.locals
#Include these lines to actually exit on a sys.exit() call
#except SystemExit, value:
# raise SystemExit, value
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
l = len(traceback.extract_tb(sys.exc_traceback))
try:
1/0
except:
m = len(traceback.extract_tb(sys.exc_traceback))
traceback.print_exception(exc_type, exc_value, exc_traceback, l-m)
self.console.newInput()
def stopPython(self):
#Should spend 2 seconds trying to kill thread in nice Python style first...
self.stop()
header = """\
JPython %(version)s on %(platform)s
%(copyright)s
""" % {'version':sys.version, 'platform':sys.platform, 'copyright':sys.copyright}
if __name__ == '__main__':
c = Console()
pane = swing.JScrollPane(c.textpane)
swing.test(pane, size=(500,400), name='JPython Console')
c.write(header, 'output')
c.capturePythonOutput()
c.textpane.requestFocus()
c.newInput()