You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
2.9 KiB
133 lines
2.9 KiB
#!/usr/bin/env python3 |
|
# (c) 2015 Taeyeon Mori |
|
# execute a python file as if the lines were entered into an interactive prompt |
|
|
|
import sys |
|
import io |
|
import code |
|
|
|
try: |
|
import pygments, pygments.lexers, pygments.formatters |
|
except: |
|
hl = None |
|
else: |
|
pyg_lex = pygments.lexers.PythonLexer() |
|
pyg_fmt = pygments.formatters.Terminal256Formatter() |
|
def hl(code): |
|
return pygments.highlight(code, pyg_lex, pyg_fmt) |
|
|
|
|
|
class IOIPythonPrefix: |
|
def __init__(self, init=1): |
|
self.count = init |
|
self.ctx = "" |
|
self.__enter__() |
|
|
|
def inc(self, by=1): |
|
self.count += by |
|
|
|
def __call__(self, ctx): |
|
self.ctx = ctx |
|
return self |
|
|
|
def __enter__(self): |
|
self.prefix = "%s\033[0m[\033[31m%2d\033[0m] " % (self.ctx, self.count) |
|
|
|
def __exit__(self, *a): |
|
pass |
|
|
|
|
|
class IOPrefixWrapper: |
|
def __init__(self, parent, pfx): |
|
self.parent = parent |
|
self.prefix = pfx |
|
self.nl = True |
|
|
|
def write(self, text): |
|
lines = text.splitlines(True) |
|
if lines: |
|
if self.nl: |
|
self.parent.write(self.prefix.prefix) |
|
self.parent.write(lines[0]) |
|
for line in lines[1:]: |
|
self.parent.write(self.prefix.prefix) |
|
self.parent.write(line) |
|
self.nl = lines[-1].endswith("\n") |
|
|
|
def flush(self): |
|
return self.parent.flush() |
|
|
|
|
|
xcount = IOIPythonPrefix() |
|
sys.stdout = IOPrefixWrapper(sys.stdout, xcount) |
|
interp = code.InteractiveInterpreter() |
|
|
|
|
|
def print_in_x(cmd_lines): |
|
with xcount("\033[34mIn "): |
|
print(">>>", cmd_lines[0], end="") |
|
for line in cmd_lines[1:]: |
|
print("...", line, end="") |
|
|
|
def print_in_hl(cmd_lines): |
|
print_in_x(hl("".join(cmd_lines)).splitlines(True)) |
|
|
|
if hl: |
|
print_in = print_in_hl |
|
else: |
|
print_in = print_in_x |
|
|
|
|
|
|
|
def compile_lines(lines): |
|
return code.compile_command("".join(lines)) |
|
|
|
def isindent(c): |
|
return c in " \t" |
|
|
|
|
|
with open(sys.argv[1]) as f: |
|
ln = 0 |
|
peekbuf = [] |
|
|
|
def readline(): |
|
global ln, peekbuf |
|
ln += 1 |
|
if peekbuf: |
|
l = peekbuf.pop(0) |
|
else: |
|
l = f.readline() |
|
if not l: |
|
raise SystemExit() |
|
return l |
|
|
|
def peekline(n=0): |
|
global peekbuf |
|
while len(peekbuf) <= n: |
|
peekbuf.append(f.readline()) |
|
return peekbuf[n] |
|
|
|
def peekindent(): |
|
i = 0 |
|
while not peekline(i).strip(): |
|
i += 1 |
|
return isindent(peekline(i)[0]) |
|
|
|
while True: |
|
cmd_lines = [readline()] |
|
|
|
c = compile_lines(cmd_lines) |
|
if not c: |
|
while not c: |
|
cmd_lines.append(readline()) |
|
while peekindent(): |
|
cmd_lines.append(readline()) |
|
c = compile_lines(cmd_lines) |
|
|
|
print_in(cmd_lines) |
|
|
|
with xcount("\033[33mOut"): |
|
interp.runcode(c) |
|
#sys.stdout.parent.write("\n") |
|
xcount.inc() |
|
|
|
|