pmacs3/tools/epython

123 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python
import code
import optparse
import os
import sys
import StringIO
import traceback
class EPython(object):
def __init__(self, globals_, locals_):
self.lines = []
self.globals = globals_
self.locals = locals_
def reset(self):
self.lines = []
def prompt(self):
if self.lines:
return "PROMPT:..>"
else:
return "PROMPT:>>>"
def handle(self, line):
if line.startswith('ENTER:'):
self.push(line[6:-1])
elif line.startswith('COMPLETE:'):
self.complete(line[9:-1])
else:
print "ERROR:invalid input"
def complete(self, s):
candidates = []
names = s.split('.')
obj = None
i = 0
name = names[0]
if len(names) > 1:
while i < len(names):
name = names[i]
if obj is None:
if name in self.locals:
obj = self.locals[name]
elif name in self.globals:
obj = self.globals[name]
else:
break
else:
if hasattr(obj, name):
obj = getattr(obj, name)
else:
break
i += 1
if i == len(names) - 1:
base = '.'.join(names[:-1])
if base:
base += '.'
if obj is not None:
newnames = dir(obj)
else:
newnames = set()
newnames.update(dir(__builtins__))
newnames.update(self.locals)
newnames.update(self.globals)
candidates = [base + x for x in newnames if x.startswith(name)]
print "COMPLETIONS:%s" % ('|'.join(candidates))
def push(self, s):
self.lines.append(s)
s2 = '\n'.join(self.lines)
try:
code_obj = code.compile_command(s2)
if code_obj is None:
return
try:
exec code_obj in self.globals, self.locals
except Exception, e:
print str(e) + "\n" + traceback.format_exc()
except (SyntaxError, OverflowError, ValueError), e:
print str(e) + "\n" + traceback.format_exc()
self.reset()
def main(self):
while True:
print '\n' + self.prompt()
sys.stdout.flush()
line = sys.stdin.readline()
if not line:
break
self.handle(line)
if __name__ == "__main__":
stanzas = []
def add_eval(option, opt, value, parser):
stanzas.append(('eval', value))
def add_path(option, opt, value, parser):
stanzas.append(('path', value))
parser = optparse.OptionParser()
parser.add_option('-e', '--eval', type='string', action='callback', callback=add_eval)
parser.add_option('-r', '--run', type='string', action='callback', callback=add_path)
parser.add_option('-p', '--pipe', action='store_true')
parser.parse_args()
del parser, add_path, add_eval
__EP = EPython(globals_=globals(), locals_=locals())
sys.path.insert(0, os.getcwd())
for (type_, value) in stanzas:
#break
if type_ == 'eval':
exec value in __EP.globals, __EP.locals
__EP.push(value)
elif type_ == 'path':
f = open(value, 'r')
exec f in __EP.globals, __EP.locals
f.close()
else:
raise Exception, 'how can this happen?'
del stanzas
__EP.reset()
__EP.main()