-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSyntaxHighlighter.py
More file actions
68 lines (62 loc) · 2.64 KB
/
SyntaxHighlighter.py
File metadata and controls
68 lines (62 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# SyntaxHighlighter.py
# compile once at import time
import re
import tkinter as tk
_pattern_comment = re.compile(
r"/\*[\s\S]*?\*/" # /* … */
r"|//.*?$" # // …
r"|#.*?$" # # …
r"|'''[\s\S]*?'''" # ''' … '''
r"|<!--[\s\S]*?-->", # HTML comment
re.MULTILINE
)
_pattern_string = re.compile(
r'"(?:\\.|[^"\\])*"' # "…"
r"|'(?:\\.|[^'\\])*'" # '…'
r"|`(?:\\.|[^`\\])*`", # `...` backtick
re.MULTILINE
)
_pattern_number = re.compile(
r"\b\d+(\.\d+)?\b" # numbers, including floats
)
# _pattern_operator = re.compile(
# r"(\+\+|--|\+|-|\*|\/|%|->|%|==|!=|>=|<=|>|<|!==|<>|&&|\|\||@|=|\+=|-=|\*=|===|%=)"
# )
class SyntaxHighlighter:
"""Attach to a Tk.Text widget to color comments and strings."""
def __init__(self, text_widget: tk.Text):
self.text = text_widget
# set up tags - these colors meant for DARK background
self.text.tag_configure('comment', foreground='gray')
self.text.tag_configure('string', foreground='goldenrod3')
self.text.tag_configure('number', foreground='LightGoldenrod3')
# self.text.tag_configure('operator',foreground='cyan')
# bind change event
self.text.bind('<<Modified>>', self._on_modified)
def _on_modified(self, event=None):
if self.text.edit_modified():
self._highlight_all()
# reset modified flag
self.text.edit_modified(False)
def _highlight_all(self):
"""Remove old tags and re‐apply to entire content."""
content = self.text.get('1.0', 'end-1c')
# clear
self.text.tag_remove('comment', '1.0', 'end')
self.text.tag_remove('string', '1.0', 'end')
self.text.tag_remove('number', '1.0', 'end')
# self.text.tag_remove('operator','1.0', 'end')
# apply strings first, comments after so that comments override strings
for m in _pattern_string.finditer(content):
self._apply_tag('string', m.start(), m.end())
for m in _pattern_comment.finditer(content):
self._apply_tag('comment', m.start(), m.end())
for m in _pattern_number.finditer(content):
self._apply_tag('number', m.start(), m.end())
# for m in _pattern_operator.finditer(content):
# self._apply_tag('operator', m.start(), m.end())
def _apply_tag(self, tag: str, start_idx: int, end_idx: int):
"""Convert character‐offset indices to Tk indices and add tag."""
start = self.text.index(f'1.0+{start_idx}c')
end = self.text.index(f'1.0+{end_idx}c')
self.text.tag_add(tag, start, end)