python tkinter 文本小部件中的 Pygments 语法荧光笔

Pygments syntax highlighter in python tkinter text widget

我一直在尝试将语法突出显示与 tkinter 文本小部件结合起来。但是,使用在 this post 上找到的代码,我无法让它工作。没有错误,但文本没有突出显示,每个字符后都会跳过一行。如果有更好的方法将语法突出显示与 tkinter 文本小部件结合起来,我会很高兴听到它。这是我能找到的复制问题的最小代码:

import Tkinter
import ScrolledText
from pygments import lex
from pygments.lexers import PythonLexer

root = Tkinter.Tk(className=" How do I put an end to this behavior?")
textPad = ScrolledText.ScrolledText(root, width=100, height=80)
textPad.tag_configure("Token.Comment", foreground="#b21111")
code = textPad.get("1.0", "end-1c")
# Parse the code and insert into the widget
def syn(event=None):
    for token, content in lex(code, PythonLexer()):
        textPad.insert("end", content, str(token))
textPad.pack()
root.bind("<Key>", syn)
root.mainloop()

到目前为止,我还没有找到解决这个问题的方法(否则我不会在这里发帖)。任何有关突出显示 tkinter 文本小部件的语法的帮助将不胜感激。

注意:这是 python 2.7 和 Windows 7.

要突出显示某些单词,您可以这样做:

textarea.tag_remove("tagname","1.0",tkinter.END)
first = "1.0"
while(True):
    first = textarea.search("word_you_are_looking_for", first, nocase=False, stopindex=tkinter.END)
    if not first:
        break
    last = first+"+"+str(len("word_you_are_looking_for"))+"c"
    textarea.tag_add("tagname", first, last)
    first = last
textarea.tag_config("tagname", foreground="#00FF00")

您链接到的问题中的代码更多地设计用于突出显示现有文本,而您似乎在键入时试图突出显示它。

我可以提供一些帮助您入门的建议,尽管我从未这样做过,也不知道最有效的解决方案是什么。此答案中的解决方案只是一个起点,不能保证它确实适合您的问题。

简短的概要是这样的:不要设置插入任何内容的绑定。相反,只需突出显示默认绑定插入的内容。

为此,第一步是绑定 <KeyRelease> 而不是 <Key>。不同之处在于 <KeyRelease> 将在插入字符 之后 发生,而 <Key> 将在插入字符 之前发生。

其次,您需要从词法分析器获取标记,并将标签应用于每个标记的文本。为此,您需要跟踪词法分析器在文档中的位置,然后使用令牌的长度来确定令牌的结尾。

在下面的解决方案中,我创建了一个标记 ("range_start") 来指定文件中 pygments 词法分析器所在的当前位置,然后根据开始计算标记 "range_end",并且pygments 返回的令牌的长度。我不知道这在面对多字节字符时有多健壮。现在,让我们假设单字节字符。

def syn(event=None):
    textPad.mark_set("range_start", "1.0")
    data = textPad.get("1.0", "end-1c")
    for token, content in lex(data, PythonLexer()):
        textPad.mark_set("range_end", "range_start + %dc" % len(content))
        textPad.tag_add(str(token), "range_start", "range_end")
        textPad.mark_set("range_start", "range_end")

这是非常低效的,因为它会在每次按键时将突出显示重新应用到整个文档。有一些方法可以最大限度地减少这种情况,例如只在每个单词后突出显示,或者在 GUI 空闲时突出显示,或者使用其他某种触发器。