mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Get rid of QRegExp
It is not available in PyQt6 and we anyway use the python re module everywhere else
This commit is contained in:
parent
93f3ef821b
commit
3bff1f494f
@ -5,10 +5,10 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
import json, os, traceback
|
import json, os, traceback, re
|
||||||
|
|
||||||
from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont,
|
from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont,
|
||||||
QRegExp, QApplication, QTextCharFormat, QColor, QCursor,
|
QApplication, QTextCharFormat, QColor, QCursor,
|
||||||
QIcon, QSize, QPalette, QLineEdit, QByteArray, QFontInfo,
|
QIcon, QSize, QPalette, QLineEdit, QByteArray, QFontInfo,
|
||||||
QFontDatabase, QVBoxLayout, QTableWidget, QTableWidgetItem,
|
QFontDatabase, QVBoxLayout, QTableWidget, QTableWidgetItem,
|
||||||
QComboBox, QAbstractItemView, QTextOption, QFontMetrics)
|
QComboBox, QAbstractItemView, QTextOption, QFontMetrics)
|
||||||
@ -42,9 +42,6 @@ class ParenPosition:
|
|||||||
|
|
||||||
class TemplateHighlighter(QSyntaxHighlighter):
|
class TemplateHighlighter(QSyntaxHighlighter):
|
||||||
|
|
||||||
Config = {}
|
|
||||||
Rules = []
|
|
||||||
Formats = {}
|
|
||||||
BN_FACTOR = 1000
|
BN_FACTOR = 1000
|
||||||
|
|
||||||
KEYWORDS = ["program", 'if', 'then', 'else', 'elif', 'fi', 'for', 'rof',
|
KEYWORDS = ["program", 'if', 'then', 'else', 'elif', 'fi', 'for', 'rof',
|
||||||
@ -52,44 +49,44 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
def __init__(self, parent=None, builtin_functions=None):
|
def __init__(self, parent=None, builtin_functions=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.initializeFormats()
|
self.initializeFormats()
|
||||||
|
self.initialize_rules(builtin_functions)
|
||||||
TemplateHighlighter.Rules.append((QRegExp(
|
|
||||||
r"\b[a-zA-Z]\w*\b(?!\(|\s+\()"
|
|
||||||
r"|\$+#?[a-zA-Z]\w*"),
|
|
||||||
"identifier"))
|
|
||||||
|
|
||||||
TemplateHighlighter.Rules.append((QRegExp(
|
|
||||||
"|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS])),
|
|
||||||
"keyword"))
|
|
||||||
|
|
||||||
TemplateHighlighter.Rules.append((QRegExp(
|
|
||||||
"|".join([r"\b%s\b" % builtin for builtin in
|
|
||||||
(builtin_functions if builtin_functions else
|
|
||||||
formatter_functions().get_builtins())])),
|
|
||||||
"builtin"))
|
|
||||||
|
|
||||||
TemplateHighlighter.Rules.append((QRegExp(
|
|
||||||
r"\b[+-]?[0-9]+[lL]?\b"
|
|
||||||
r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
|
|
||||||
r"|\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"),
|
|
||||||
"number"))
|
|
||||||
|
|
||||||
stringRe = QRegExp(r"""(?:[^:]'[^']*'|"[^"]*")""")
|
|
||||||
stringRe.setMinimal(True)
|
|
||||||
TemplateHighlighter.Rules.append((stringRe, "string"))
|
|
||||||
|
|
||||||
lparenRe = QRegExp(r'\(')
|
|
||||||
lparenRe.setMinimal(True)
|
|
||||||
TemplateHighlighter.Rules.append((lparenRe, "lparen"))
|
|
||||||
rparenRe = QRegExp(r'\)')
|
|
||||||
rparenRe.setMinimal(True)
|
|
||||||
TemplateHighlighter.Rules.append((rparenRe, "rparen"))
|
|
||||||
|
|
||||||
self.regenerate_paren_positions()
|
self.regenerate_paren_positions()
|
||||||
self.highlighted_paren = False
|
self.highlighted_paren = False
|
||||||
|
|
||||||
|
def initialize_rules(self, builtin_functions):
|
||||||
|
r = []
|
||||||
|
|
||||||
|
def a(a, b):
|
||||||
|
r.append((re.compile(a), b))
|
||||||
|
|
||||||
|
a(
|
||||||
|
r"\b[a-zA-Z]\w*\b(?!\(|\s+\()"
|
||||||
|
r"|\$+#?[a-zA-Z]\w*",
|
||||||
|
"identifier")
|
||||||
|
|
||||||
|
a(
|
||||||
|
"|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS]),
|
||||||
|
"keyword")
|
||||||
|
|
||||||
|
a(
|
||||||
|
"|".join([r"\b%s\b" % builtin for builtin in
|
||||||
|
(builtin_functions if builtin_functions else
|
||||||
|
formatter_functions().get_builtins())]),
|
||||||
|
"builtin")
|
||||||
|
|
||||||
|
a(
|
||||||
|
r"\b[+-]?[0-9]+[lL]?\b"
|
||||||
|
r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
|
||||||
|
r"|\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b",
|
||||||
|
"number")
|
||||||
|
|
||||||
|
a(r"""(?:[^:]'[^']*'|"[^"]*")""", "string")
|
||||||
|
|
||||||
|
a(r'\(', "lparen")
|
||||||
|
a(r'\)', "rparen")
|
||||||
|
self.Rules = tuple(r)
|
||||||
|
|
||||||
def initializeFormats(self):
|
def initializeFormats(self):
|
||||||
font_name = gprefs.get('gpm_template_editor_font', None)
|
font_name = gprefs.get('gpm_template_editor_font', None)
|
||||||
size = gprefs['gpm_template_editor_font_size']
|
size = gprefs['gpm_template_editor_font_size']
|
||||||
@ -98,7 +95,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
font.setFixedPitch(True)
|
font.setFixedPitch(True)
|
||||||
font.setPointSize(size)
|
font.setPointSize(size)
|
||||||
font_name = font.family()
|
font_name = font.family()
|
||||||
Config = self.Config
|
Config = self.Config = {}
|
||||||
Config["fontfamily"] = font_name
|
Config["fontfamily"] = font_name
|
||||||
pal = QApplication.instance().palette()
|
pal = QApplication.instance().palette()
|
||||||
for name, color, bold, italic in (
|
for name, color, bold, italic in (
|
||||||
@ -118,6 +115,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
baseFormat.setFontFamily(Config["fontfamily"])
|
baseFormat.setFontFamily(Config["fontfamily"])
|
||||||
Config["fontsize"] = size
|
Config["fontsize"] = size
|
||||||
baseFormat.setFontPointSize(Config["fontsize"])
|
baseFormat.setFontPointSize(Config["fontsize"])
|
||||||
|
self.Formats = {}
|
||||||
|
|
||||||
for name in ("normal", "keyword", "builtin", "comment", "identifier",
|
for name in ("normal", "keyword", "builtin", "comment", "identifier",
|
||||||
"string", "number", "lparen", "rparen"):
|
"string", "number", "lparen", "rparen"):
|
||||||
@ -146,17 +144,15 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
self.setFormat(0, textLength, self.Formats["comment"])
|
self.setFormat(0, textLength, self.Formats["comment"])
|
||||||
return
|
return
|
||||||
|
|
||||||
for regex, format_ in TemplateHighlighter.Rules:
|
for regex, format_ in self.Rules:
|
||||||
i = regex.indexIn(text)
|
for m in regex.finditer(text):
|
||||||
while i >= 0:
|
i, length = m.start(), m.end() - m.start()
|
||||||
length = regex.matchedLength()
|
|
||||||
if format_ in ['lparen', 'rparen']:
|
if format_ in ['lparen', 'rparen']:
|
||||||
pp = self.find_paren(bn, i)
|
pp = self.find_paren(bn, i)
|
||||||
if pp and pp.highlight:
|
if pp and pp.highlight:
|
||||||
self.setFormat(i, length, self.Formats[format_])
|
self.setFormat(i, length, self.Formats[format_])
|
||||||
else:
|
else:
|
||||||
self.setFormat(i, length, self.Formats[format_])
|
self.setFormat(i, length, self.Formats[format_])
|
||||||
i = regex.indexIn(text, i + length)
|
|
||||||
|
|
||||||
if self.generate_paren_positions:
|
if self.generate_paren_positions:
|
||||||
t = str(text)
|
t = str(text)
|
||||||
@ -178,7 +174,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
i = len(t)
|
i = len(t)
|
||||||
else:
|
else:
|
||||||
i = i + j
|
i = i + j
|
||||||
elif c in ['(', ')']:
|
elif c in ('(', ')'):
|
||||||
pp = ParenPosition(bn, i, c)
|
pp = ParenPosition(bn, i, c)
|
||||||
self.paren_positions.append(pp)
|
self.paren_positions.append(pp)
|
||||||
self.paren_pos_map[bn*self.BN_FACTOR+i] = pp
|
self.paren_pos_map[bn*self.BN_FACTOR+i] = pp
|
||||||
@ -186,7 +182,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
def rehighlight(self):
|
def rehighlight(self):
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
||||||
QSyntaxHighlighter.rehighlight(self)
|
super().rehighlight()
|
||||||
QApplication.restoreOverrideCursor()
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
def check_cursor_pos(self, chr_, block, pos_in_block):
|
def check_cursor_pos(self, chr_, block, pos_in_block):
|
||||||
@ -196,7 +192,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
|||||||
if pp.block == block and pp.pos == pos_in_block:
|
if pp.block == block and pp.pos == pos_in_block:
|
||||||
found_pp = i
|
found_pp = i
|
||||||
|
|
||||||
if chr_ not in ['(', ')']:
|
if chr_ not in ('(', ')'):
|
||||||
if self.highlighted_paren:
|
if self.highlighted_paren:
|
||||||
self.rehighlight()
|
self.rehighlight()
|
||||||
self.highlighted_paren = False
|
self.highlighted_paren = False
|
||||||
@ -887,7 +883,8 @@ class EmbeddedTemplateDialog(TemplateDialog):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication([])
|
from calibre.gui2 import Application
|
||||||
|
app = Application([])
|
||||||
from calibre.ebooks.metadata.book.base import field_metadata
|
from calibre.ebooks.metadata.book.base import field_metadata
|
||||||
d = TemplateDialog(None, '{title}', fm=field_metadata)
|
d = TemplateDialog(None, '{title}', fm=field_metadata)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
@ -8,7 +8,7 @@ import re, os
|
|||||||
from qt.core import (QIcon, QFont, QLabel, QListWidget, QAction, QEvent,
|
from qt.core import (QIcon, QFont, QLabel, QListWidget, QAction, QEvent,
|
||||||
QListWidgetItem, QTextCharFormat, QApplication, QSyntaxHighlighter,
|
QListWidgetItem, QTextCharFormat, QApplication, QSyntaxHighlighter,
|
||||||
QCursor, QColor, QWidget, QPixmap, QSplitterHandle, QToolButton,
|
QCursor, QColor, QWidget, QPixmap, QSplitterHandle, QToolButton,
|
||||||
Qt, pyqtSignal, QRegExp, QSize, QSplitter, QPainter, QPageSize, QPrinter,
|
Qt, pyqtSignal, QSize, QSplitter, QPainter, QPageSize, QPrinter,
|
||||||
QLineEdit, QComboBox, QPen, QGraphicsScene, QMenu, QStringListModel, QKeySequence,
|
QLineEdit, QComboBox, QPen, QGraphicsScene, QMenu, QStringListModel, QKeySequence,
|
||||||
QCompleter, QTimer, QRect, QGraphicsView, QPagedPaintDevice, QPalette, QClipboard)
|
QCompleter, QTimer, QRect, QGraphicsView, QPagedPaintDevice, QPalette, QClipboard)
|
||||||
|
|
||||||
@ -810,7 +810,7 @@ class EncodingComboBox(QComboBox): # {{{
|
|||||||
|
|
||||||
class PythonHighlighter(QSyntaxHighlighter): # {{{
|
class PythonHighlighter(QSyntaxHighlighter): # {{{
|
||||||
|
|
||||||
Rules = []
|
Rules = ()
|
||||||
Formats = {}
|
Formats = {}
|
||||||
|
|
||||||
KEYWORDS = ["and", "as", "assert", "break", "class", "continue", "def",
|
KEYWORDS = ["and", "as", "assert", "break", "class", "continue", "def",
|
||||||
@ -834,34 +834,41 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
if not self.Rules:
|
||||||
|
self.initialize_class_members()
|
||||||
|
|
||||||
self.initializeFormats()
|
@classmethod
|
||||||
|
def initialize_class_members(cls):
|
||||||
|
cls.initializeFormats()
|
||||||
|
r = []
|
||||||
|
|
||||||
PythonHighlighter.Rules.append((QRegExp(
|
def a(a, b):
|
||||||
"|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS])),
|
r.append((a, b))
|
||||||
"keyword"))
|
|
||||||
PythonHighlighter.Rules.append((QRegExp(
|
a(re.compile(
|
||||||
"|".join([r"\b%s\b" % builtin for builtin in self.BUILTINS])),
|
"|".join([r"\b%s\b" % keyword for keyword in cls.KEYWORDS])),
|
||||||
"builtin"))
|
"keyword")
|
||||||
PythonHighlighter.Rules.append((QRegExp(
|
a(re.compile(
|
||||||
|
"|".join([r"\b%s\b" % builtin for builtin in cls.BUILTINS])),
|
||||||
|
"builtin")
|
||||||
|
a(re.compile(
|
||||||
"|".join([r"\b%s\b" % constant
|
"|".join([r"\b%s\b" % constant
|
||||||
for constant in self.CONSTANTS])), "constant"))
|
for constant in cls.CONSTANTS])), "constant")
|
||||||
PythonHighlighter.Rules.append((QRegExp(
|
a(re.compile(
|
||||||
r"\b[+-]?[0-9]+[lL]?\b"
|
r"\b[+-]?[0-9]+[lL]?\b"
|
||||||
r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
|
r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
|
||||||
r"|\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"),
|
r"|\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"),
|
||||||
"number"))
|
"number")
|
||||||
PythonHighlighter.Rules.append((QRegExp(
|
a(re.compile(
|
||||||
r"\bPyQt5\b|\bQt?[A-Z][a-z]\w+\b"), "pyqt"))
|
r"\bPyQt5\b|\bQt?[A-Z][a-z]\w+\b"), "pyqt")
|
||||||
PythonHighlighter.Rules.append((QRegExp(r"\b@\w+\b"), "decorator"))
|
a(re.compile(r"\b@\w+\b"), "decorator")
|
||||||
stringRe = QRegExp(r"""(?:'[^']*'|"[^"]*")""")
|
stringRe = re.compile(r"""(?:'[^']*?'|"[^"]*?")""")
|
||||||
stringRe.setMinimal(True)
|
a(stringRe, "string")
|
||||||
PythonHighlighter.Rules.append((stringRe, "string"))
|
cls.stringRe = re.compile(r"""(:?"["]".*?"["]"|'''.*?''')""")
|
||||||
self.stringRe = QRegExp(r"""(:?"["]".*"["]"|'''.*''')""")
|
a(cls.stringRe, "string")
|
||||||
self.stringRe.setMinimal(True)
|
cls.tripleSingleRe = re.compile(r"""'''(?!")""")
|
||||||
PythonHighlighter.Rules.append((self.stringRe, "string"))
|
cls.tripleDoubleRe = re.compile(r'''"""(?!')''')
|
||||||
self.tripleSingleRe = QRegExp(r"""'''(?!")""")
|
cls.Rules = tuple(r)
|
||||||
self.tripleDoubleRe = QRegExp(r'''"""(?!')''')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def initializeFormats(cls):
|
def initializeFormats(cls):
|
||||||
@ -896,36 +903,31 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
|
|||||||
prevState = self.previousBlockState()
|
prevState = self.previousBlockState()
|
||||||
|
|
||||||
self.setFormat(0, textLength,
|
self.setFormat(0, textLength,
|
||||||
PythonHighlighter.Formats["normal"])
|
self.Formats["normal"])
|
||||||
|
|
||||||
if text.startswith("Traceback") or text.startswith("Error: "):
|
if text.startswith("Traceback") or text.startswith("Error: "):
|
||||||
self.setCurrentBlockState(ERROR)
|
self.setCurrentBlockState(ERROR)
|
||||||
self.setFormat(0, textLength,
|
self.setFormat(0, textLength,
|
||||||
PythonHighlighter.Formats["error"])
|
self.Formats["error"])
|
||||||
return
|
return
|
||||||
if prevState == ERROR and \
|
if prevState == ERROR and \
|
||||||
not (text.startswith('>>>') or text.startswith("#")):
|
not (text.startswith('>>>') or text.startswith("#")):
|
||||||
self.setCurrentBlockState(ERROR)
|
self.setCurrentBlockState(ERROR)
|
||||||
self.setFormat(0, textLength,
|
self.setFormat(0, textLength,
|
||||||
PythonHighlighter.Formats["error"])
|
self.Formats["error"])
|
||||||
return
|
return
|
||||||
|
|
||||||
for regex, format in PythonHighlighter.Rules:
|
for regex, fmt in PythonHighlighter.Rules:
|
||||||
i = regex.indexIn(text)
|
for m in regex.finditer(text):
|
||||||
while i >= 0:
|
self.setFormat(m.start(), m.end() - m.start(), self.Formats[fmt])
|
||||||
length = regex.matchedLength()
|
|
||||||
self.setFormat(i, length,
|
|
||||||
PythonHighlighter.Formats[format])
|
|
||||||
i = regex.indexIn(text, i + length)
|
|
||||||
|
|
||||||
# Slow but good quality highlighting for comments. For more
|
# Slow but good quality highlighting for comments. For more
|
||||||
# speed, comment this out and add the following to __init__:
|
# speed, comment this out and add the following to __init__:
|
||||||
# PythonHighlighter.Rules.append((QRegExp(r"#.*"), "comment"))
|
# PythonHighlighter.Rules.append((re.compile(r"#.*"), "comment"))
|
||||||
if not text:
|
if not text:
|
||||||
pass
|
pass
|
||||||
elif text[0] == "#":
|
elif text[0] == "#":
|
||||||
self.setFormat(0, len(text),
|
self.setFormat(0, len(text), self.Formats["comment"])
|
||||||
PythonHighlighter.Formats["comment"])
|
|
||||||
else:
|
else:
|
||||||
stack = []
|
stack = []
|
||||||
for i, c in enumerate(text):
|
for i, c in enumerate(text):
|
||||||
@ -935,33 +937,33 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
|
|||||||
else:
|
else:
|
||||||
stack.append(c)
|
stack.append(c)
|
||||||
elif c == "#" and len(stack) == 0:
|
elif c == "#" and len(stack) == 0:
|
||||||
self.setFormat(i, len(text),
|
self.setFormat(i, len(text), self.Formats["comment"])
|
||||||
PythonHighlighter.Formats["comment"])
|
|
||||||
break
|
break
|
||||||
|
|
||||||
self.setCurrentBlockState(NORMAL)
|
self.setCurrentBlockState(NORMAL)
|
||||||
|
|
||||||
if self.stringRe.indexIn(text) != -1:
|
if self.stringRe.search(text) is not None:
|
||||||
return
|
return
|
||||||
# This is fooled by triple quotes inside single quoted strings
|
# This is fooled by triple quotes inside single quoted strings
|
||||||
for i, state in ((self.tripleSingleRe.indexIn(text),
|
for m, state in (
|
||||||
TRIPLESINGLE),
|
(self.tripleSingleRe.search(text), TRIPLESINGLE),
|
||||||
(self.tripleDoubleRe.indexIn(text),
|
(self.tripleDoubleRe.search(text), TRIPLEDOUBLE)
|
||||||
TRIPLEDOUBLE)):
|
):
|
||||||
|
i = -1 if m is None else m.start()
|
||||||
if self.previousBlockState() == state:
|
if self.previousBlockState() == state:
|
||||||
if i == -1:
|
if i == -1:
|
||||||
i = len(text)
|
i = len(text)
|
||||||
self.setCurrentBlockState(state)
|
self.setCurrentBlockState(state)
|
||||||
self.setFormat(0, i + 3,
|
self.setFormat(0, i + 3,
|
||||||
PythonHighlighter.Formats["string"])
|
self.Formats["string"])
|
||||||
elif i > -1:
|
elif i > -1:
|
||||||
self.setCurrentBlockState(state)
|
self.setCurrentBlockState(state)
|
||||||
self.setFormat(i, len(text),
|
self.setFormat(i, len(text),
|
||||||
PythonHighlighter.Formats["string"])
|
self.Formats["string"])
|
||||||
|
|
||||||
def rehighlight(self):
|
def rehighlight(self):
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
||||||
QSyntaxHighlighter.rehighlight(self)
|
super().rehighlight()
|
||||||
QApplication.restoreOverrideCursor()
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user