我正在尝试编写一个具有语法高亮的交互式解释器版本。
到目前为止,我的功能相当不错(使用祝福和 pygments 模块)...
import code
import readline
import threading
import blessings
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers import PythonLexer
def check_line():
global current_line
try:
while True:
line = readline.get_line_buffer()
if line != current_line:
current_line = line
do_colour()
except:
pass
def do_colour():
global terminal
raw_line = readline.get_line_buffer()
line = highlight(raw_line, lexer, formatter)[:-1]
with terminal.location(x = 4):
print line,
readline.redisplay()
current_line = ''
terminal = blessings.Terminal()
lexer = PythonLexer()
formatter = TerminalFormatter()
console = code.InteractiveConsole()
colour_thread = threading.Thread(target=check_line)
colour_thread.setDaemon(True)
colour_thread.start()
console.interact('')
在您键入行时会对行进行着色...
问题是;
我真正想要的是当光标移动或行缓冲区改变时的回调/钩子 - 这些是否可能?我可以将stdin放入逐字节模式,然后以某种方式将字节传递给raw_input的内部缓冲版本,并触发回调吗?
P.S目前它还没有处理多行字符串("""like this"""
),但这不是一个非常困难的修复。
修改
好的,我有点儿,这里是最新的代码......
import code, ctypes, readline, blessings, signal, threading
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers import PythonLexer
def slight_delay():
threading.Timer(0.001, draw).start()
return 0
def draw():
raw_line = readline.get_line_buffer()
line = highlight(raw_line, lexer, formatter)[:-1]
with lock:
with terminal.location(x = 4):
print line,
readline.redisplay()
def keyboard_interrupt(c, frame): # Ctrl-C throws in C code otherwise
pass
callback = ctypes.PYFUNCTYPE(ctypes.c_int)(slight_delay)
hook_ptr = ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
hook_ptr.value = ctypes.cast(callback, ctypes.c_void_p).value
signal.signal(signal.SIGINT, keyboard_interrupt)
terminal = blessings.Terminal()
lexer = PythonLexer()
formatter = TerminalFormatter()
console = code.InteractiveConsole()
lock = threading.Lock()
console.interact('')
我正在寻找的是PyOS_InputHook,它被称为
所以这意味着我可以放弃繁忙的监视线程并意味着我不会(几乎)使用任何CPU。
最后一个问题是输入挂钩在按键时被称为立即;在从stdin读取输入之前和(对于可打印的字符)连接到行缓冲区。结果是,对最近的角色着色有0.1秒的延迟。
我通过在0.001秒延迟的线程中进行绘图,以一种黑客的方式解决了这个问题。