xref: /aosp_15_r20/external/antlr/runtime/JavaScript/tests/functional/rhino-python.input (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot"""This is a substantially improved version of the older Interpreter.py demo
2*16467b97STreehugger RobotIt creates a simple GUI JPython console window with simple history
3*16467b97STreehugger Robotas well as the ability to interupt running code (with the ESC key).
4*16467b97STreehugger Robot
5*16467b97STreehugger RobotLike Interpreter.py, this is still just a demo, and needs substantial
6*16467b97STreehugger Robotwork before serious use.
7*16467b97STreehugger Robot
8*16467b97STreehugger RobotThanks to Geza Groma ([email protected]) for several valuable
9*16467b97STreehugger Robotideas for this tool -- his JPConsole is a more refined implementation
10*16467b97STreehugger Robotof similar ideas.
11*16467b97STreehugger Robot"""
12*16467b97STreehugger Robot
13*16467b97STreehugger Robotfrom Styles import Styles
14*16467b97STreehugger Robotfrom Keymap import Keymap
15*16467b97STreehugger Robot
16*16467b97STreehugger Robotfrom pawt import swing, colors
17*16467b97STreehugger Robotfrom java.awt.event.KeyEvent import VK_UP, VK_DOWN
18*16467b97STreehugger Robotfrom java.awt.event import ActionEvent
19*16467b97STreehugger Robotfrom java.lang import Thread, System
20*16467b97STreehugger Robotfrom code import compile_command
21*16467b97STreehugger Robotimport string, sys, re
22*16467b97STreehugger Robot
23*16467b97STreehugger Robotclass OutputBuffer:
24*16467b97STreehugger Robot	def __init__(self, console, stylename):
25*16467b97STreehugger Robot		self.console = console
26*16467b97STreehugger Robot		self.stylename = stylename
27*16467b97STreehugger Robot
28*16467b97STreehugger Robot	def flush(self):
29*16467b97STreehugger Robot		pass
30*16467b97STreehugger Robot
31*16467b97STreehugger Robot	def write(self, text):
32*16467b97STreehugger Robot		self.console.write(text, self.stylename)
33*16467b97STreehugger Robot
34*16467b97STreehugger Robotclass Console:
35*16467b97STreehugger Robot	def __init__(self, styles=None, keymap=None):
36*16467b97STreehugger Robot		if styles is None:
37*16467b97STreehugger Robot			styles = Styles()
38*16467b97STreehugger Robot			basic = styles.add('normal', tabsize=3, fontSize=12, fontFamily="Courier")
39*16467b97STreehugger Robot			styles.add('error', parent=basic, foreground=colors.red)
40*16467b97STreehugger Robot			styles.add('output', parent=basic, foreground=colors.blue)
41*16467b97STreehugger Robot			styles.add('input', parent=basic, foreground=colors.black)
42*16467b97STreehugger Robot			styles.add('prompt', parent=basic, foreground=colors.purple)
43*16467b97STreehugger Robot		self.styles = styles
44*16467b97STreehugger Robot
45*16467b97STreehugger Robot		# This is a hack to get at an inner class
46*16467b97STreehugger Robot		# This will not be required in JPython-1.1
47*16467b97STreehugger Robot		ForegroundAction = getattr(swing.text, 'StyledEditorKit$ForegroundAction')
48*16467b97STreehugger Robot		self.inputAction = ForegroundAction("start input", colors.black)
49*16467b97STreehugger Robot
50*16467b97STreehugger Robot		if keymap is None:
51*16467b97STreehugger Robot			keymap = Keymap()
52*16467b97STreehugger Robot		keymap.bind('enter', self.enter)
53*16467b97STreehugger Robot		keymap.bind('tab', self.tab)
54*16467b97STreehugger Robot		keymap.bind('escape', self.escape)
55*16467b97STreehugger Robot		keymap.bind('up', self.uphistory)
56*16467b97STreehugger Robot		keymap.bind('down', self.downhistory)
57*16467b97STreehugger Robot
58*16467b97STreehugger Robot		self.keymap = keymap
59*16467b97STreehugger Robot
60*16467b97STreehugger Robot		self.document = swing.text.DefaultStyledDocument(self.styles)
61*16467b97STreehugger Robot		self.document.setLogicalStyle(0, self.styles.get('normal'))
62*16467b97STreehugger Robot
63*16467b97STreehugger Robot		self.textpane = swing.JTextPane(self.document)
64*16467b97STreehugger Robot		self.textpane.keymap = self.keymap
65*16467b97STreehugger Robot
66*16467b97STreehugger Robot		self.history = []
67*16467b97STreehugger Robot		self.oldHistoryLength = 0
68*16467b97STreehugger Robot		self.historyPosition = 0
69*16467b97STreehugger Robot
70*16467b97STreehugger Robot		self.command = []
71*16467b97STreehugger Robot		self.locals = {}
72*16467b97STreehugger Robot
73*16467b97STreehugger Robot	def write(self, text, stylename='normal'):
74*16467b97STreehugger Robot		style = self.styles.get(stylename)
75*16467b97STreehugger Robot		self.document.insertString(self.document.length, text, style)
76*16467b97STreehugger Robot
77*16467b97STreehugger Robot	def beep(self):
78*16467b97STreehugger Robot		self.textpane.toolkit.beep()
79*16467b97STreehugger Robot
80*16467b97STreehugger Robot	def startUserInput(self, prompt=None):
81*16467b97STreehugger Robot		if prompt is not None:
82*16467b97STreehugger Robot			self.write(prompt, 'prompt')
83*16467b97STreehugger Robot		self.startInput = self.document.createPosition(self.document.length-1)
84*16467b97STreehugger Robot		#self.document.setCharacterAttributes(self.document.length-1, 1, self.styles.get('input'), 1)
85*16467b97STreehugger Robot		self.textpane.caretPosition = self.document.length
86*16467b97STreehugger Robot		ae = ActionEvent(self.textpane, ActionEvent.ACTION_PERFORMED, 'start input')
87*16467b97STreehugger Robot		self.inputAction.actionPerformed(ae)
88*16467b97STreehugger Robot
89*16467b97STreehugger Robot	def getinput(self):
90*16467b97STreehugger Robot		offset = self.startInput.offset
91*16467b97STreehugger Robot		line = self.document.getText(offset+1, self.document.length-offset)
92*16467b97STreehugger Robot		return string.rstrip(line)
93*16467b97STreehugger Robot
94*16467b97STreehugger Robot	def replaceinput(self, text):
95*16467b97STreehugger Robot		offset = self.startInput.offset + 1
96*16467b97STreehugger Robot		self.document.remove(offset, self.document.length-offset)
97*16467b97STreehugger Robot		self.write(text, 'input')
98*16467b97STreehugger Robot
99*16467b97STreehugger Robot	def enter(self):
100*16467b97STreehugger Robot		line = self.getinput()
101*16467b97STreehugger Robot		self.write('\n', 'input')
102*16467b97STreehugger Robot
103*16467b97STreehugger Robot		self.history.append(line)
104*16467b97STreehugger Robot		self.handleLine(line)
105*16467b97STreehugger Robot
106*16467b97STreehugger Robot	def gethistory(self, direction):
107*16467b97STreehugger Robot		historyLength = len(self.history)
108*16467b97STreehugger Robot		if self.oldHistoryLength < historyLength:
109*16467b97STreehugger Robot			# new line was entered after last call
110*16467b97STreehugger Robot			self.oldHistoryLength = historyLength
111*16467b97STreehugger Robot			if self.history[self.historyPosition] != self.history[-1]:
112*16467b97STreehugger Robot				self.historyPosition = historyLength
113*16467b97STreehugger Robot
114*16467b97STreehugger Robot		pos = self.historyPosition + direction
115*16467b97STreehugger Robot
116*16467b97STreehugger Robot		if 0 <= pos < historyLength:
117*16467b97STreehugger Robot			self.historyPosition = pos
118*16467b97STreehugger Robot			self.replaceinput(self.history[pos])
119*16467b97STreehugger Robot		else:
120*16467b97STreehugger Robot			self.beep()
121*16467b97STreehugger Robot
122*16467b97STreehugger Robot	def uphistory(self):
123*16467b97STreehugger Robot		self.gethistory(-1)
124*16467b97STreehugger Robot
125*16467b97STreehugger Robot	def downhistory(self):
126*16467b97STreehugger Robot		self.gethistory(1)
127*16467b97STreehugger Robot
128*16467b97STreehugger Robot	def tab(self):
129*16467b97STreehugger Robot		self.write('\t', 'input')
130*16467b97STreehugger Robot
131*16467b97STreehugger Robot	def escape(self):
132*16467b97STreehugger Robot		if (not hasattr(self, 'pythonThread') or self.pythonThread is None or not self.pythonThread.alive):
133*16467b97STreehugger Robot			self.beep()
134*16467b97STreehugger Robot			return
135*16467b97STreehugger Robot
136*16467b97STreehugger Robot		self.pythonThread.stopPython()
137*16467b97STreehugger Robot
138*16467b97STreehugger Robot	def capturePythonOutput(self, stdoutStyle='output', stderrStyle='error'):
139*16467b97STreehugger Robot		import sys
140*16467b97STreehugger Robot		sys.stdout = OutputBuffer(self, stdoutStyle)
141*16467b97STreehugger Robot		sys.stderr = OutputBuffer(self, stderrStyle)
142*16467b97STreehugger Robot
143*16467b97STreehugger Robot	def handleLine(self, text):
144*16467b97STreehugger Robot		self.command.append(text)
145*16467b97STreehugger Robot
146*16467b97STreehugger Robot		try:
147*16467b97STreehugger Robot			code = compile_command(string.join(self.command, '\n'))
148*16467b97STreehugger Robot		except SyntaxError:
149*16467b97STreehugger Robot			traceback.print_exc(0)
150*16467b97STreehugger Robot			self.command = []
151*16467b97STreehugger Robot			self.startUserInput(str(sys.ps1)+'\t')
152*16467b97STreehugger Robot			return
153*16467b97STreehugger Robot
154*16467b97STreehugger Robot		if code is None:
155*16467b97STreehugger Robot			self.startUserInput(str(sys.ps2)+'\t')
156*16467b97STreehugger Robot			return
157*16467b97STreehugger Robot
158*16467b97STreehugger Robot		self.command = []
159*16467b97STreehugger Robot
160*16467b97STreehugger Robot		pt = PythonThread(code, self)
161*16467b97STreehugger Robot		self.pythonThread = pt
162*16467b97STreehugger Robot		pt.start()
163*16467b97STreehugger Robot
164*16467b97STreehugger Robot	def newInput(self):
165*16467b97STreehugger Robot		self.startUserInput(str(sys.ps1)+'\t')
166*16467b97STreehugger Robot
167*16467b97STreehugger Robotimport traceback
168*16467b97STreehugger Robot
169*16467b97STreehugger Robotclass PythonThread(Thread):
170*16467b97STreehugger Robot	def __init__(self, code, console):
171*16467b97STreehugger Robot		self.code = code
172*16467b97STreehugger Robot		self.console = console
173*16467b97STreehugger Robot		self.locals = console.locals
174*16467b97STreehugger Robot
175*16467b97STreehugger Robot	def run(self):
176*16467b97STreehugger Robot		try:
177*16467b97STreehugger Robot			exec self.code in self.locals
178*16467b97STreehugger Robot
179*16467b97STreehugger Robot		#Include these lines to actually exit on a sys.exit() call
180*16467b97STreehugger Robot		#except SystemExit, value:
181*16467b97STreehugger Robot		#	raise SystemExit, value
182*16467b97STreehugger Robot
183*16467b97STreehugger Robot		except:
184*16467b97STreehugger Robot			exc_type, exc_value, exc_traceback = sys.exc_info()
185*16467b97STreehugger Robot			l = len(traceback.extract_tb(sys.exc_traceback))
186*16467b97STreehugger Robot			try:
187*16467b97STreehugger Robot				1/0
188*16467b97STreehugger Robot			except:
189*16467b97STreehugger Robot				m = len(traceback.extract_tb(sys.exc_traceback))
190*16467b97STreehugger Robot			traceback.print_exception(exc_type, exc_value, exc_traceback, l-m)
191*16467b97STreehugger Robot
192*16467b97STreehugger Robot		self.console.newInput()
193*16467b97STreehugger Robot
194*16467b97STreehugger Robot	def stopPython(self):
195*16467b97STreehugger Robot		#Should spend 2 seconds trying to kill thread in nice Python style first...
196*16467b97STreehugger Robot		self.stop()
197*16467b97STreehugger Robot
198*16467b97STreehugger Robotheader = """\
199*16467b97STreehugger RobotJPython %(version)s on %(platform)s
200*16467b97STreehugger Robot%(copyright)s
201*16467b97STreehugger Robot""" % {'version':sys.version, 'platform':sys.platform, 'copyright':sys.copyright}
202*16467b97STreehugger Robot
203*16467b97STreehugger Robotif __name__ == '__main__':
204*16467b97STreehugger Robot	c = Console()
205*16467b97STreehugger Robot	pane = swing.JScrollPane(c.textpane)
206*16467b97STreehugger Robot	swing.test(pane, size=(500,400), name='JPython Console')
207*16467b97STreehugger Robot	c.write(header, 'output')
208*16467b97STreehugger Robot	c.capturePythonOutput()
209*16467b97STreehugger Robot	c.textpane.requestFocus()
210*16467b97STreehugger Robot	c.newInput()
211