Tkinter:文本小部件的语法突出显示

问题描述 投票:0回答:6

任何人都可以解释如何向 Tkinter

Text
小部件添加语法突出显示吗?

每次程序找到匹配的单词时,它都会将该单词着色为我想要的颜色。例如:将单词

tkinter
涂成粉红色,将
in
涂成蓝色。但是当我输入
Tkinter
时,它会将
Tk--ter
着色为黄色,将
in
着色为蓝色。

我该如何解决这个问题?谢谢!

python text syntax tkinter
6个回答
6
投票

这是tfpf 答案的扩展

当您调用

ic.make_pat()
时,它会返回用于 Python 格式化的整个正则表达式。虽然在一些额外的表达方式中使用
OR
看起来很方便,但它并没有真正给你太多的控制权,而且很快就会变得很麻烦。一种可能更有用且绝对更可定制的方法是打印/复制/粘贴
ic.make_pat()
,并将其分解,如下所示。这还有一个额外的副作用,即您不必担心如何在 python 版本中调用
ic.make_pat()
,因为执行此操作后,您根本不会使用
ic.make_pat()

#syntax highlighter patterns
KEYWORD   = r"\b(?P<KEYWORD>False|None|True|and|as|assert|async|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\b"
EXCEPTION = r"([^.'\"\\#]\b|^)(?P<EXCEPTION>ArithmeticError|AssertionError|AttributeError|BaseException|BlockingIOError|BrokenPipeError|BufferError|BytesWarning|ChildProcessError|ConnectionAbortedError|ConnectionError|ConnectionRefusedError|ConnectionResetError|DeprecationWarning|EOFError|Ellipsis|EnvironmentError|Exception|FileExistsError|FileNotFoundError|FloatingPointError|FutureWarning|GeneratorExit|IOError|ImportError|ImportWarning|IndentationError|IndexError|InterruptedError|IsADirectoryError|KeyError|KeyboardInterrupt|LookupError|MemoryError|ModuleNotFoundError|NameError|NotADirectoryError|NotImplemented|NotImplementedError|OSError|OverflowError|PendingDeprecationWarning|PermissionError|ProcessLookupError|RecursionError|ReferenceError|ResourceWarning|RuntimeError|RuntimeWarning|StopAsyncIteration|StopIteration|SyntaxError|SyntaxWarning|SystemError|SystemExit|TabError|TimeoutError|TypeError|UnboundLocalError|UnicodeDecodeError|UnicodeEncodeError|UnicodeError|UnicodeTranslateError|UnicodeWarning|UserWarning|ValueError|Warning|WindowsError|ZeroDivisionError)\b"
BUILTIN   = r"([^.'\"\\#]\b|^)(?P<BUILTIN>abs|all|any|ascii|bin|breakpoint|callable|chr|classmethod|compile|complex|copyright|credits|delattr|dir|divmod|enumerate|eval|exec|exit|filter|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|isinstance|issubclass|iter|len|license|locals|map|max|memoryview|min|next|oct|open|ord|pow|print|quit|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|sum|type|vars|zip)\b"
DOCSTRING = r"(?P<DOCSTRING>(?i:r|u|f|fr|rf|b|br|rb)?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?|(?i:r|u|f|fr|rf|b|br|rb)?\"\"\"[^\"\\]*((\\.|\"(?!\"\"))[^\"\\]*)*(\"\"\")?)"
STRING    = r"(?P<STRING>(?i:r|u|f|fr|rf|b|br|rb)?'[^'\\\n]*(\\.[^'\\\n]*)*'?|(?i:r|u|f|fr|rf|b|br|rb)?\"[^\"\\\n]*(\\.[^\"\\\n]*)*\"?)"
TYPES     = r"\b(?P<TYPES>bool|bytearray|bytes|dict|float|int|list|str|tuple|object)\b"
NUMBER    = r"\b(?P<NUMBER>((0x|0b|0o|#)[\da-fA-F]+)|((\d*\.)?\d+))\b"
CLASSDEF  = r"(?<=\bclass)[ \t]+(?P<CLASSDEF>\w+)[ \t]*[:\(]" #recolor of DEFINITION for class definitions
DECORATOR = r"(^[ \t]*(?P<DECORATOR>@[\w\d\.]+))"
INSTANCE  = r"\b(?P<INSTANCE>super|self|cls)\b"
COMMENT   = r"(?P<COMMENT>#[^\n]*)"
SYNC      = r"(?P<SYNC>\n)"

然后您可以按照适合您的顺序连接所有这些模式,如下所示:

PROG   = rf"{KEYWORD}|{BUILTIN}|{EXCEPTION}|{TYPES}|{COMMENT}|{DOCSTRING}|{STRING}|{SYNC}|{INSTANCE}|{DECORATOR}|{NUMBER}|{CLASSDEF}"

您可能会注意到

DEFINITION
不存在于上述任何模式中。这是因为上面的模式是针对
.prog
的,但是
DEFINITION
模式是由
.idprog
决定的。下面是我的。我希望类定义具有不同的颜色,因此我的模式忽略了前面带有
class
的定义。如果您不打算对
DEFINITION
做出一些例外,则根本不必搞乱它。

#original - r"\s+(\w+)"
IDPROG = r"(?<!class)\s+(\w+)"

接下来要考虑的是

tagdefs
。您无需逐行添加/修改关键点,只需预定义
tagdefs
。下面是一个例子。请注意,上面第一组模式中使用的每个
regex group
名称都用下面对象中的键表示。另请注意,此处包含
DEFINITION
。下面的每个对象都变为
options
tag_configure
,并且您可以使用
option
接受的任何
tag_configure
。颜色和字体是我自己的,示例中不需要包含它们。

TAGDEFS   = {   'COMMENT'    : {'foreground': CHARBLUE  , 'background': None},
                'TYPES'      : {'foreground': CLOUD2    , 'background': None},
                'NUMBER'     : {'foreground': LEMON     , 'background': None},
                'BUILTIN'    : {'foreground': OVERCAST  , 'background': None},
                'STRING'     : {'foreground': PUMPKIN   , 'background': None},
                'DOCSTRING'  : {'foreground': STORMY    , 'background': None},
                'EXCEPTION'  : {'foreground': CLOUD2    , 'background': None, 'font':FONTBOLD},
                'DEFINITION' : {'foreground': SAILOR    , 'background': None, 'font':FONTBOLD},
                'DECORATOR'  : {'foreground': CLOUD2    , 'background': None, 'font':FONTITAL},
                'INSTANCE'   : {'foreground': CLOUD     , 'background': None, 'font':FONTITAL},
                'KEYWORD'    : {'foreground': DK_SEAFOAM, 'background': None, 'font':FONTBOLD},
                'CLASSDEF'   : {'foreground': PURPLE    , 'background': None, 'font':FONTBOLD},
            }

'''
#what literally happens to this data when it is applied
for tag, cfg in self.tagdefs.items():
    self.tag_configure(tag, **cfg)
'''

一旦完成设置,您就可以轻松插入所有内容。如果您制作自定义文本小部件,您可以将以下内容放入

__init__
中,并将
YourTextWidget
更改为
self
。否则,只需将
YourTextWidget
更改为您想要连接到的文本小部件的实例名称(如 tfpf 的答案 中所示)。

cd         = ic.ColorDelegator()
cd.prog    = re.compile(PROG, re.S|re.M)
cd.idprog  = re.compile(IDPROG, re.S)
cd.tagdefs = {**cd.tagdefs, **TAGDEFS}
ip.Percolator(YourTextWidget).insertfilter(cd)

cd.tagdefs = {**cd.tagdefs, **TAGDEFS}

我为什么要这么做?我们不会使用此方法省略任何值。如果

KEYWORD
tagdefs
中定义,但不在
TAGDEFS
中怎么办?如果我们不首先将
tagdefs
解压到自身中,我们就会丢失
KEYWORD

总结系统的这一端:运行一个大的正则表达式,无论

regex group
名称匹配,都会成为要应用的标签的名称。无论您创建什么新的
regex groups
都应该(也许必须)在
.tagdefs
中具有相同名称的密钥。


4
投票

这是igwd 的回答的后续内容。

idlelib.colorizer.ColorDelegator
idlelib.percolator.Percolator
似乎没有很好地记录,所以我决定发布我发现的内容。

如果您希望突出显示“tkinter”和“in”等单词,您可能需要普通的 Python 语法突出显示和一些附加内容。

import idlelib.colorizer as ic
import idlelib.percolator as ip
import re
import tkinter as tk

root = tk.Tk()
root.title('Python Syntax Highlighting')

text = tk.Text(root)
text.pack()

cdg = ic.ColorDelegator()
cdg.prog = re.compile(r'\b(?P<MYGROUP>tkinter)\b|' + ic.make_pat(), re.S)
cdg.idprog = re.compile(r'\s+(\w+)', re.S)

cdg.tagdefs['MYGROUP'] = {'foreground': '#7F7F7F', 'background': '#FFFFFF'}

# These five lines are optional. If omitted, default colours are used.
cdg.tagdefs['COMMENT'] = {'foreground': '#FF0000', 'background': '#FFFFFF'}
cdg.tagdefs['KEYWORD'] = {'foreground': '#007F00', 'background': '#FFFFFF'}
cdg.tagdefs['BUILTIN'] = {'foreground': '#7F7F00', 'background': '#FFFFFF'}
cdg.tagdefs['STRING'] = {'foreground': '#7F3F00', 'background': '#FFFFFF'}
cdg.tagdefs['DEFINITION'] = {'foreground': '#007F7F', 'background': '#FFFFFF'}

ip.Percolator(text).insertfilter(cdg)

root.mainloop()

上述 MWE 适用于 Python 3.8。在 Python 3.10 上,只需将

cdg.prog = re.compile(r'\b(?P<MYGROUP>tkinter)\b|' + ic.make_pat(), re.S)
替换为
cdg.prog = re.compile(r'\b(?P<MYGROUP>tkinter)\b|' + ic.make_pat().pattern, re.S)
。我还没有用其他 Python 版本测试过这个。


2
投票

这些代码可以在IDLE中实现语法高亮。 您可以复制源代码并修改某些内容。

import tkinter as tk
from idlelib.percolator import Percolator
from idlelib.colorizer import ColorDelegator
main = tk.Tk()
text = tk.Text(main)
text.pack()
Percolator(text).insertfilter(ColorDelegator())
main.mainloop()

0
投票

您可以使用

tag
来执行此操作。您可以将标签配置为具有某些背景、字体、文本大小、颜色等。然后将这些标签添加到您要配置的文本中。

所有这些都在文档中。


0
投票

使用标签。我将实施那里给出的概念。

示例:

import tkinter as tk

root = tk.Tk()
root.title("Begueradj")
text = tk.Text(root)
# Insert some text
text.insert(tk.INSERT, "Security ")
text.insert(tk.END, " Pentesting ")
text.insert(tk.END, "Hacking ")
text.insert(tk.END, "Coding")
text.pack()
# Create some tags
text.tag_add("one", "1.0", "1.8")
text.tag_add("two", "1.10", "1.20")
text.tag_add("three", "1.21", "1.28")
text.tag_add("four", "1.29", "1.36")
#Configure the tags
text.tag_config("one", background="yellow", foreground="blue")
text.tag_config("two", background="black", foreground="green")
text.tag_config("three", background="blue", foreground="yellow")
text.tag_config("four", background="red", foreground="black")
#Start the program
root.mainloop()

演示:


0
投票

选项:

  • 代币化示例:此处

  • pygments示例:here其中使用 get_style_by_name("default").list_styles() 作为内置样式;将 lexer 替换为 PythonLexer for Python

  • 花哨的完成者

  • idlelib示例:

    from tkinter import Tk
    from tkinter import Text
    from idlelib.colorizer import ColorDelegator, color_config
    from idlelib.percolator import Percolator
    from idlelib.undo import UndoDelegator
    
    
    class CustomEditor:
        def __init__(self):
            self.root = Tk()
            self.text = text = Text(self.root)
            text.pack()
    
            self.perc = perc = Percolator(text)
            self.undo = undo = UndoDelegator()
            perc.insertfilter(undo)
            self.color = None
            self.code_context = None
            self.ResetColorizer()
    
        def _add_colorizer(self):
            if self.color:
                return
            self.color = ColorDelegator()
            self.perc.insertfilterafter(filter=self.color, after=self.undo)
    
        def _rm_colorizer(self):
            if not self.color:
                return
            self.color.removecolors()
            self.perc.removefilter(self.color)
            self.color = None
    
        def ResetColorizer(self):
            self._rm_colorizer()
            self._add_colorizer()
            color_config(self.text)
    
    
    editor = CustomEditor()
    editor.text.insert(1.0, "print('Hello')\n")
    editor.text.focus_set()
    editor.root.mainloop()
    
© www.soinside.com 2019 - 2024. All rights reserved.