122 lines
3.6 KiB
Plaintext
122 lines
3.6 KiB
Plaintext
|
#!/usr/bin/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('-p', '--path', type='string', action='callback', callback=add_path)
|
||
|
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()
|