Use stdlib re for dialogue matching
This commit is contained in:
@@ -33,7 +33,7 @@ from functools import partial
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
from PyQt5.QtCore import QCoreApplication
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
@@ -234,7 +234,7 @@ class Tokenizer(ABC):
|
|||||||
nwShortcode.FOOTNOTE_B: self.FMT_FNOTE,
|
nwShortcode.FOOTNOTE_B: self.FMT_FNOTE,
|
||||||
}
|
}
|
||||||
|
|
||||||
self._rxDialogue: list[tuple[QRegularExpression, int, int]] = []
|
self._rxDialogue: list[tuple[re.Pattern, int, int]] = []
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1136,11 +1136,9 @@ class Tokenizer(ABC):
|
|||||||
# Match Dialogue
|
# Match Dialogue
|
||||||
if self._rxDialogue and hDialog:
|
if self._rxDialogue and hDialog:
|
||||||
for regEx, fmtB, fmtE in self._rxDialogue:
|
for regEx, fmtB, fmtE in self._rxDialogue:
|
||||||
rxItt = regEx.globalMatch(text, 0)
|
for match in re.finditer(regEx, text):
|
||||||
while rxItt.hasNext():
|
temp.append((match.start(0), 0, fmtB, ""))
|
||||||
rxMatch = rxItt.next()
|
temp.append((match.end(0), 0, fmtE, ""))
|
||||||
temp.append((rxMatch.capturedStart(0), 0, fmtB, ""))
|
|
||||||
temp.append((rxMatch.capturedEnd(0), 0, fmtE, ""))
|
|
||||||
|
|
||||||
# Post-process text and format
|
# Post-process text and format
|
||||||
result = text
|
result = text
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import re
|
|||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import QRegularExpression, Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QBrush, QColor, QFont, QSyntaxHighlighter, QTextBlockUserData,
|
QBrush, QColor, QFont, QSyntaxHighlighter, QTextBlockUserData,
|
||||||
QTextCharFormat, QTextDocument
|
QTextCharFormat, QTextDocument
|
||||||
@@ -398,29 +398,15 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
if hRules:
|
if hRules:
|
||||||
for rX, hRule in hRules:
|
for rX, hRule in hRules:
|
||||||
if isinstance(rX, QRegularExpression):
|
for match in re.finditer(rX, text[xOff:]):
|
||||||
rxItt = rX.globalMatch(text, xOff)
|
for xM, hFmt in hRule.items():
|
||||||
while rxItt.hasNext():
|
xPos = match.start(xM) + xOff
|
||||||
rxMatch = rxItt.next()
|
xEnd = match.end(xM) + xOff
|
||||||
for xM, hFmt in hRule.items():
|
for x in range(xPos, xEnd):
|
||||||
xPos = rxMatch.capturedStart(xM)
|
cFmt = self.format(x)
|
||||||
xEnd = rxMatch.capturedEnd(xM)
|
if cFmt.fontStyleName() != "markup":
|
||||||
for x in range(xPos, xEnd):
|
cFmt.merge(hFmt)
|
||||||
cFmt = self.format(x)
|
self.setFormat(x, 1, cFmt)
|
||||||
if cFmt.fontStyleName() != "markup":
|
|
||||||
cFmt.merge(hFmt)
|
|
||||||
self.setFormat(x, 1, cFmt)
|
|
||||||
else:
|
|
||||||
for match in re.finditer(rX, text[xOff:]):
|
|
||||||
for xM, hFmt in hRule.items():
|
|
||||||
# print(f"'{match.group(xM)}'", match.start(xM), match.end(xM))
|
|
||||||
xPos = match.start(xM) + xOff
|
|
||||||
xEnd = match.end(xM) + xOff
|
|
||||||
for x in range(xPos, xEnd):
|
|
||||||
cFmt = self.format(x)
|
|
||||||
if cFmt.fontStyleName() != "markup":
|
|
||||||
cFmt.merge(hFmt)
|
|
||||||
self.setFormat(x, 1, cFmt)
|
|
||||||
|
|
||||||
data = self.currentBlockUserData()
|
data = self.currentBlockUserData()
|
||||||
if not isinstance(data, TextBlockData):
|
if not isinstance(data, TextBlockData):
|
||||||
|
|||||||
@@ -25,11 +25,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt5.QtCore import QRegularExpression
|
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.constants import nwRegEx
|
from novelwriter.constants import nwRegEx
|
||||||
from novelwriter.types import QRegExUnicode
|
|
||||||
|
|
||||||
|
|
||||||
class RegExPatterns:
|
class RegExPatterns:
|
||||||
@@ -67,7 +64,7 @@ class RegExPatterns:
|
|||||||
return self._rxSCValue
|
return self._rxSCValue
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dialogStyle(self) -> QRegularExpression:
|
def dialogStyle(self) -> re.Pattern:
|
||||||
"""Dialogue detection rule based on user settings."""
|
"""Dialogue detection rule based on user settings."""
|
||||||
symO = ""
|
symO = ""
|
||||||
symC = ""
|
symC = ""
|
||||||
@@ -79,34 +76,26 @@ class RegExPatterns:
|
|||||||
symC += CONFIG.fmtDQuoteClose
|
symC += CONFIG.fmtDQuoteClose
|
||||||
|
|
||||||
rxEnd = "|$" if CONFIG.allowOpenDial else ""
|
rxEnd = "|$" if CONFIG.allowOpenDial else ""
|
||||||
rxRule = QRegularExpression(f"\\B[{symO}].*?(?:[{symC}]\\B{rxEnd})")
|
return re.compile(f"\\B[{symO}].*?(?:[{symC}]\\B{rxEnd})", re.UNICODE)
|
||||||
rxRule.setPatternOptions(QRegExUnicode)
|
|
||||||
return rxRule
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dialogLine(self) -> QRegularExpression:
|
def dialogLine(self) -> re.Pattern:
|
||||||
"""Dialogue line rule based on user settings."""
|
"""Dialogue line rule based on user settings."""
|
||||||
sym = QRegularExpression.escape(CONFIG.dialogLine)
|
sym = re.escape(CONFIG.dialogLine)
|
||||||
rxRule = QRegularExpression(f"^{sym}.*?$")
|
return re.compile(f"^{sym}.*?$", re.UNICODE)
|
||||||
rxRule.setPatternOptions(QRegExUnicode)
|
|
||||||
return rxRule
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def narratorBreak(self) -> QRegularExpression:
|
def narratorBreak(self) -> re.Pattern:
|
||||||
"""Dialogue narrator break rule based on user settings."""
|
"""Dialogue narrator break rule based on user settings."""
|
||||||
sym = QRegularExpression.escape(CONFIG.narratorBreak)
|
sym = re.escape(CONFIG.narratorBreak)
|
||||||
rxRule = QRegularExpression(f"\\B{sym}\\S.*?\\S{sym}\\B")
|
return re.compile(f"\\B{sym}\\S.*?\\S{sym}\\B", re.UNICODE)
|
||||||
rxRule.setPatternOptions(QRegExUnicode)
|
|
||||||
return rxRule
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def altDialogStyle(self) -> QRegularExpression:
|
def altDialogStyle(self) -> re.Pattern:
|
||||||
"""Dialogue alternative rule based on user settings."""
|
"""Dialogue alternative rule based on user settings."""
|
||||||
symO = QRegularExpression.escape(CONFIG.altDialogOpen)
|
symO = re.escape(CONFIG.altDialogOpen)
|
||||||
symC = QRegularExpression.escape(CONFIG.altDialogClose)
|
symC = re.escape(CONFIG.altDialogClose)
|
||||||
rxRule = QRegularExpression(f"\\B{symO}.*?{symC}\\B")
|
return re.compile(f"\\B{symO}.*?{symC}\\B", re.UNICODE)
|
||||||
rxRule.setPatternOptions(QRegExUnicode)
|
|
||||||
return rxRule
|
|
||||||
|
|
||||||
|
|
||||||
REGEX_PATTERNS = RegExPatterns()
|
REGEX_PATTERNS = RegExPatterns()
|
||||||
|
|||||||
@@ -24,30 +24,19 @@ import re
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PyQt5.QtCore import QRegularExpression
|
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.constants import nwUnicode
|
from novelwriter.constants import nwUnicode
|
||||||
from novelwriter.text.patterns import REGEX_PATTERNS
|
from novelwriter.text.patterns import REGEX_PATTERNS
|
||||||
|
|
||||||
|
|
||||||
def allMatches(regEx: QRegularExpression, text: str) -> list[list[str]]:
|
def allMatches(regEx: re.Pattern, text: str) -> list[list[str]]:
|
||||||
"""Get all matches for a regex."""
|
"""Get all matches for a regex."""
|
||||||
result = []
|
result = []
|
||||||
if isinstance(regEx, QRegularExpression):
|
for match in re.finditer(regEx, text):
|
||||||
itt = regEx.globalMatch(text, 0)
|
result.append([
|
||||||
while itt.hasNext():
|
(match.group(n), match.start(n), match.end(n))
|
||||||
match = itt.next()
|
for n in range((match.lastindex or 0) + 1)
|
||||||
result.append([
|
])
|
||||||
(match.captured(n), match.capturedStart(n), match.capturedEnd(n))
|
|
||||||
for n in range(match.lastCapturedIndex() + 1)
|
|
||||||
])
|
|
||||||
else:
|
|
||||||
for match in re.finditer(regEx, text):
|
|
||||||
result.append([
|
|
||||||
(match.group(n), match.start(n), match.end(n))
|
|
||||||
for n in range((match.lastindex or -1) + 1)
|
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user