Tkinter / Pygments:突出显示的奇怪结果

Posted

技术标签:

【中文标题】Tkinter / Pygments:突出显示的奇怪结果【英文标题】:Tkinter / Pygments: Strange results in highlighting 【发布时间】:2018-06-10 18:01:37 【问题描述】:

我尝试根据标记突出显示文本。令牌可以通过以下代码突出显示,但有一些不需要的结果。一些例子:

假设,我输入了:

a = "a"

尽管第一个 'a' 是 Token.Name,第二个 'a' 是 Token.Literal.String.Double,两个 a 都以相同的颜色突出显示/p>

另一种不需要的情况是,当我输入“if”时,该词被突出显示,如果我继续在“if”一词中添加一些字母,则该词的颜色会按预期更改。但是,当我删除该单词的一些字母直到单词再次变为“if”时,该单词不会像以前那样突出显示。

你能帮我理解这个问题吗?

代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pygments import lex
from pygments.token import Token
from pygments.lexers import Python3Lexer
try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk

ROOT = tk.Tk()
TEXT = tk.Text(master=ROOT, fg="white", bg="black", font="TkDefaultFont 10")
TEXT.pack(fill="both", expand=True)


def tag(event):

    def colorize(word, color):
        index = []
        index1 = TEXT.search(word, "1.0", "end")
        while index1:
            index2 = ".".join([index1.split(".")[0], str(int(index1.split(".")[1]) + len(word))])
            index.append((index1, index2))
            index1 = TEXT.search(word, index2, "end")
        for i, j in index:
            TEXT.tag_add(word, i, j)
            TEXT.tag_configure(word, foreground=color)

    for token, content in lex(TEXT.get("1.0", "end"), Python3Lexer()):
        if token == Token.Literal.Number.Integer:
            colorize(content, color="purple")
        elif token == Token.Keyword:
            colorize(content, color="orange")
        elif token == Token.Operator.Word:
            colorize(content, color="red")
        elif token == Token.Name.Builtin:
            colorize(content, color="blue")
        elif token == Token.Comment.Hashbang or token == Token.Comment.Single:
            colorize(content, color="grey")
        elif token == Token.Keyword.Namespace:
            colorize(content, color="yellow")
        elif token == Token.Namespace:
            colorize(content, color="green")
        elif token == Token.Punctuation:
            colorize(content, color="brown")
        elif token == Token.Literal.String.Double:
            colorize(content, color="cyan")
        elif token == Token.Name:
            colorize(content, color="white")


TEXT.bind("<KeyRelease>", tag)
ROOT.mainloop()

`

【问题讨论】:

你做了什么来调试这个?例如,您是否在循环运行时打印出变量的值以验证它们是否是您认为应该的值? 我在 for 循环中放了一条 print 语句,用于打印内容和令牌。 那么,你是不是声称所有的内容和标记都是正确的,索引也是正确的,但它的颜色是错误的? 我只想说,一旦一个词被识别为token,这个词就会在另一个词中突出显示。例如,如果程序可以将 "a" 识别为 Token.Literal.String.Double ,则突出显示此字符。但不仅是这个字符串文字,还有 Text 小部件中的所有 a。在这里你可以看到截图。 forum.yazbel.com/uploads/default/original/1X/…forum.yazbel.com/uploads/default/original/1X/… 所以我猜,解析有问题。 【参考方案1】:

问题已通过以下代码解决。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
if sys.version_info.major == 2:
    exit()
elif sys.version_info.major == 3:
    import builtins as builtins
    import tkinter as tk
import io
import tokenize
import keyword


root = tk.Tk()
text = tk.Text(master=root, fg="white", bg="black", font="TkDefaultFont 10")
text.pack(fill="both", expand=True)

count = 0


def colorize(*args):
    global count
    row1, col1 = args[0].startz
    row1, col1 = str(row1), str(col1)
    row2, col2 = args[0].end
    row2, col2 = str(row2), str(col2)
    start = ".".join((row1, col1))
    end = ".".join((row2, col2))
    text.tag_add(str(count), start, end)
    try:
        text.tag_config(str(count), foreground=args[1], font=args[2])
    except IndexError:
        text.tag_config(str(count), foreground=args[1])
    count += 1


def search(event):
    try:
        for i in tokenize.tokenize(io.BytesIO(text.get("1.0", "end").encode("utf-8")).readline):
            if i.type == 1:
                if i.string in keyword.kwlist:
                    colorize(i, "orange")
                elif i.string in dir(builtins):
                    colorize(i, "blue")
                else:
                    colorize(i, "white")
            elif i.type == 2:
                colorize(i, "cyan")
            elif i.type == 3:
                colorize(i, "purple")
            elif i.type == 53:
                if i.string == "," or i.string == "." or i.string == ":":
                    colorize(i, "orange")
                elif i.string == "(" or i.string == ")" or i.string == "[" \
                        or i.string == "]" or i.string == "" or i.string == "":
                    colorize(i, "darkred")
                else:
                    colorize(i, "green")
            elif i.type == 57:
                colorize(i, "grey", "TkDefaultFont 10 italic")
    except tokenize.TokenError:
        pass


text.bind("<KeyRelease>", search)
root.mainloop()

【讨论】:

以上是关于Tkinter / Pygments:突出显示的奇怪结果的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Jekyll/Pygments 中突出显示 CSHTML

使用 Pygments 在 Jekyll 中突出显示围栏代码块

Pygments 代码中的行号在 Windows 上的 xampp 中突出显示

Jekyll 博客中突出显示的 pygments 的奇怪背景色调

在 Jekyll/Liquid 和 pygments 的 html 问题中突出显示

Pygments 在 python 脚本中通过管道传输到 less 中断突出显示