Leo*_*son 5 python terminal syntax-highlighting readline raw-input
我正在尝试编写具有语法突出显示功能的交互式解释器的版本。
到目前为止,这是我工作得相当不错的内容(使用祝福和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('')
Run Code Online (Sandbox Code Playgroud)
键入时确实会为线条着色...

问题是;
我真正想要的是当光标移动或行缓冲区更改时的回调/钩子-这些可能吗?我可以将stdin置于逐字节模式下,然后以某种方式将字节传递给raw_input的内部缓冲版本,并触发回调吗?
PS它目前还不能处理多行字符串("""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('')
Run Code Online (Sandbox Code Playgroud)
我一直在寻找的东西是PyOS_InputHook被称为
因此,这意味着我可以放弃繁忙的监视线程,并且意味着(几乎)不使用任何CPU。
最终的问题是,在按下按键时会立即调用输入挂钩。从stdin读取输入之前(对于可打印字符),将其附加到行缓冲区。结果是对最新字符的着色延迟了0.1秒。
我通过在0.001秒的延迟下在线程中绘制来解决问题。