Rewrite narrator break for dialogue highlighting (#2068)
This commit is contained in:
@@ -543,33 +543,6 @@ class GuiPreferences(NDialog):
|
|||||||
self.tr("Applies to the selected quote styles.")
|
self.tr("Applies to the selected quote styles.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.allowOpenDial = NSwitch(self)
|
|
||||||
self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
|
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Allow open-ended dialogue"), self.allowOpenDial,
|
|
||||||
self.tr("Highlight dialogue line with no closing quote.")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.narratorBreak = QLineEdit(self)
|
|
||||||
self.narratorBreak.setMaxLength(1)
|
|
||||||
self.narratorBreak.setFixedWidth(boxFixed)
|
|
||||||
self.narratorBreak.setAlignment(QtAlignCenter)
|
|
||||||
self.narratorBreak.setText(CONFIG.narratorBreak)
|
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Dialogue narrator break symbol"), self.narratorBreak,
|
|
||||||
self.tr("Symbol to indicate injected narrator break.")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.dialogLine = QLineEdit(self)
|
|
||||||
self.dialogLine.setMaxLength(1)
|
|
||||||
self.dialogLine.setFixedWidth(boxFixed)
|
|
||||||
self.dialogLine.setAlignment(QtAlignCenter)
|
|
||||||
self.dialogLine.setText(CONFIG.dialogLine)
|
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Dialogue line symbol"), self.dialogLine,
|
|
||||||
self.tr("Lines starting with this symbol are dialogue.")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.altDialogOpen = QLineEdit(self)
|
self.altDialogOpen = QLineEdit(self)
|
||||||
self.altDialogOpen.setMaxLength(4)
|
self.altDialogOpen.setMaxLength(4)
|
||||||
self.altDialogOpen.setFixedWidth(boxFixed)
|
self.altDialogOpen.setFixedWidth(boxFixed)
|
||||||
@@ -587,6 +560,33 @@ class GuiPreferences(NDialog):
|
|||||||
self.tr("Custom highlighting of dialogue text.")
|
self.tr("Custom highlighting of dialogue text.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.allowOpenDial = NSwitch(self)
|
||||||
|
self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
|
||||||
|
self.mainForm.addRow(
|
||||||
|
self.tr("Allow open-ended dialogue"), self.allowOpenDial,
|
||||||
|
self.tr("Highlight dialogue line with no closing quote.")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.dialogLine = QLineEdit(self)
|
||||||
|
self.dialogLine.setMaxLength(1)
|
||||||
|
self.dialogLine.setFixedWidth(boxFixed)
|
||||||
|
self.dialogLine.setAlignment(QtAlignCenter)
|
||||||
|
self.dialogLine.setText(CONFIG.dialogLine)
|
||||||
|
self.mainForm.addRow(
|
||||||
|
self.tr("Dialogue line symbol"), self.dialogLine,
|
||||||
|
self.tr("Lines starting with this symbol are dialogue.")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.narratorBreak = QLineEdit(self)
|
||||||
|
self.narratorBreak.setMaxLength(1)
|
||||||
|
self.narratorBreak.setFixedWidth(boxFixed)
|
||||||
|
self.narratorBreak.setAlignment(QtAlignCenter)
|
||||||
|
self.narratorBreak.setText(CONFIG.narratorBreak)
|
||||||
|
self.mainForm.addRow(
|
||||||
|
self.tr("Dialogue narrator break symbol"), self.narratorBreak,
|
||||||
|
self.tr("Symbol to indicate injected narrator break.")
|
||||||
|
)
|
||||||
|
|
||||||
self.highlightEmph = NSwitch(self)
|
self.highlightEmph = NSwitch(self)
|
||||||
self.highlightEmph.setChecked(CONFIG.highlightEmph)
|
self.highlightEmph.setChecked(CONFIG.highlightEmph)
|
||||||
self.mainForm.addRow(
|
self.mainForm.addRow(
|
||||||
|
|||||||
@@ -194,7 +194,10 @@ class Tokenizer(ABC):
|
|||||||
nwShortcode.FOOTNOTE_B: TextFmt.FNOTE,
|
nwShortcode.FOOTNOTE_B: TextFmt.FNOTE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Dialogue
|
||||||
self._rxDialogue: list[tuple[re.Pattern, tuple[int, str], tuple[int, str]]] = []
|
self._rxDialogue: list[tuple[re.Pattern, tuple[int, str], tuple[int, str]]] = []
|
||||||
|
self._dialogLine = ""
|
||||||
|
self._narratorBreak = ""
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -331,21 +334,13 @@ class Tokenizer(ABC):
|
|||||||
REGEX_PATTERNS.dialogStyle,
|
REGEX_PATTERNS.dialogStyle,
|
||||||
(TextFmt.COL_B, "dialog"), (TextFmt.COL_E, ""),
|
(TextFmt.COL_B, "dialog"), (TextFmt.COL_E, ""),
|
||||||
))
|
))
|
||||||
if CONFIG.dialogLine:
|
|
||||||
self._rxDialogue.append((
|
|
||||||
REGEX_PATTERNS.dialogLine,
|
|
||||||
(TextFmt.COL_B, "dialog"), (TextFmt.COL_E, ""),
|
|
||||||
))
|
|
||||||
if CONFIG.narratorBreak:
|
|
||||||
self._rxDialogue.append((
|
|
||||||
REGEX_PATTERNS.narratorBreak,
|
|
||||||
(TextFmt.COL_E, ""), (TextFmt.COL_B, "dialog"),
|
|
||||||
))
|
|
||||||
if CONFIG.altDialogOpen and CONFIG.altDialogClose:
|
if CONFIG.altDialogOpen and CONFIG.altDialogClose:
|
||||||
self._rxDialogue.append((
|
self._rxDialogue.append((
|
||||||
REGEX_PATTERNS.altDialogStyle,
|
REGEX_PATTERNS.altDialogStyle,
|
||||||
(TextFmt.COL_B, "altdialog"), (TextFmt.COL_E, ""),
|
(TextFmt.COL_B, "altdialog"), (TextFmt.COL_E, ""),
|
||||||
))
|
))
|
||||||
|
self._dialogLine = CONFIG.dialogLine.strip()[:1]
|
||||||
|
self._narratorBreak = CONFIG.narratorBreak.strip()[:1]
|
||||||
return
|
return
|
||||||
|
|
||||||
def setTitleMargins(self, upper: float, lower: float) -> None:
|
def setTitleMargins(self, upper: float, lower: float) -> None:
|
||||||
@@ -1149,6 +1144,19 @@ class Tokenizer(ABC):
|
|||||||
temp.append((res.start(0), 0, fmtB, clsB))
|
temp.append((res.start(0), 0, fmtB, clsB))
|
||||||
temp.append((res.end(0), 0, fmtE, clsE))
|
temp.append((res.end(0), 0, fmtE, clsE))
|
||||||
|
|
||||||
|
if self._dialogLine and text.startswith(self._dialogLine):
|
||||||
|
if self._narratorBreak:
|
||||||
|
pos = 0
|
||||||
|
for num, bit in enumerate(text[1:].split(self._narratorBreak), 1):
|
||||||
|
length = len(bit) + 1
|
||||||
|
if num%2:
|
||||||
|
temp.append((pos, 0, TextFmt.COL_B, "dialog"))
|
||||||
|
temp.append((pos + length, 0, TextFmt.COL_E, ""))
|
||||||
|
pos += length
|
||||||
|
else:
|
||||||
|
temp.append((0, 0, TextFmt.COL_B, "dialog"))
|
||||||
|
temp.append((len(text), 0, TextFmt.COL_E, ""))
|
||||||
|
|
||||||
# Post-process text and format
|
# Post-process text and format
|
||||||
result = text
|
result = text
|
||||||
formats = []
|
formats = []
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
"_tHandle", "_isNovel", "_isInactive", "_spellCheck", "_spellErr",
|
"_tHandle", "_isNovel", "_isInactive", "_spellCheck", "_spellErr",
|
||||||
"_hStyles", "_minRules", "_txtRules", "_cmnRules",
|
"_hStyles", "_minRules", "_txtRules", "_cmnRules", "_dialogLine",
|
||||||
|
"_narratorBreak",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, document: QTextDocument) -> None:
|
def __init__(self, document: QTextDocument) -> None:
|
||||||
@@ -78,6 +79,9 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
self._txtRules: list[tuple[re.Pattern, dict[int, QTextCharFormat]]] = []
|
self._txtRules: list[tuple[re.Pattern, dict[int, QTextCharFormat]]] = []
|
||||||
self._cmnRules: list[tuple[re.Pattern, dict[int, QTextCharFormat]]] = []
|
self._cmnRules: list[tuple[re.Pattern, dict[int, QTextCharFormat]]] = []
|
||||||
|
|
||||||
|
self._dialogLine = ""
|
||||||
|
self._narratorBreak = ""
|
||||||
|
|
||||||
self.initHighlighter()
|
self.initHighlighter()
|
||||||
|
|
||||||
logger.debug("Ready: GuiDocHighlighter")
|
logger.debug("Ready: GuiDocHighlighter")
|
||||||
@@ -132,6 +136,9 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
self._txtRules.clear()
|
self._txtRules.clear()
|
||||||
self._cmnRules.clear()
|
self._cmnRules.clear()
|
||||||
|
|
||||||
|
self._dialogLine = CONFIG.dialogLine.strip()[:1]
|
||||||
|
self._narratorBreak = CONFIG.narratorBreak.strip()[:1]
|
||||||
|
|
||||||
# Multiple or Trailing Spaces
|
# Multiple or Trailing Spaces
|
||||||
if CONFIG.showMultiSpaces:
|
if CONFIG.showMultiSpaces:
|
||||||
rxRule = re.compile(r"[ ]{2,}|[ ]*$", re.UNICODE)
|
rxRule = re.compile(r"[ ]{2,}|[ ]*$", re.UNICODE)
|
||||||
@@ -159,20 +166,6 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
}
|
}
|
||||||
self._txtRules.append((rxRule, hlRule))
|
self._txtRules.append((rxRule, hlRule))
|
||||||
|
|
||||||
if CONFIG.dialogLine:
|
|
||||||
rxRule = REGEX_PATTERNS.dialogLine
|
|
||||||
hlRule = {
|
|
||||||
0: self._hStyles["dialog"],
|
|
||||||
}
|
|
||||||
self._txtRules.append((rxRule, hlRule))
|
|
||||||
|
|
||||||
if CONFIG.narratorBreak:
|
|
||||||
rxRule = REGEX_PATTERNS.narratorBreak
|
|
||||||
hlRule = {
|
|
||||||
0: self._hStyles["text"],
|
|
||||||
}
|
|
||||||
self._txtRules.append((rxRule, hlRule))
|
|
||||||
|
|
||||||
if CONFIG.altDialogOpen and CONFIG.altDialogClose:
|
if CONFIG.altDialogOpen and CONFIG.altDialogClose:
|
||||||
rxRule = REGEX_PATTERNS.altDialogStyle
|
rxRule = REGEX_PATTERNS.altDialogStyle
|
||||||
hlRule = {
|
hlRule = {
|
||||||
@@ -411,6 +404,17 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
self.setCurrentBlockState(BLOCK_TEXT)
|
self.setCurrentBlockState(BLOCK_TEXT)
|
||||||
hRules = self._txtRules if self._isNovel else self._minRules
|
hRules = self._txtRules if self._isNovel else self._minRules
|
||||||
|
|
||||||
|
if self._dialogLine and text.startswith(self._dialogLine):
|
||||||
|
if self._narratorBreak:
|
||||||
|
tPos = 0
|
||||||
|
for tNum, tBit in enumerate(text[1:].split(self._narratorBreak), 1):
|
||||||
|
tLen = len(tBit) + 1
|
||||||
|
if tNum%2:
|
||||||
|
self.setFormat(tPos, tLen, self._hStyles["dialog"])
|
||||||
|
tPos += tLen
|
||||||
|
else:
|
||||||
|
self.setFormat(0, len(text), self._hStyles["dialog"])
|
||||||
|
|
||||||
if hRules:
|
if hRules:
|
||||||
for rX, hRule in hRules:
|
for rX, hRule in hRules:
|
||||||
for res in re.finditer(rX, text[xOff:]):
|
for res in re.finditer(rX, text[xOff:]):
|
||||||
|
|||||||
@@ -96,18 +96,6 @@ class RegExPatterns:
|
|||||||
rxEnd = "|$" if CONFIG.allowOpenDial else ""
|
rxEnd = "|$" if CONFIG.allowOpenDial else ""
|
||||||
return re.compile(f"\\B[{symO}].*?(?:[{symC}]\\B{rxEnd})", re.UNICODE)
|
return re.compile(f"\\B[{symO}].*?(?:[{symC}]\\B{rxEnd})", re.UNICODE)
|
||||||
|
|
||||||
@property
|
|
||||||
def dialogLine(self) -> re.Pattern:
|
|
||||||
"""Dialogue line rule based on user settings."""
|
|
||||||
sym = re.escape(CONFIG.dialogLine)
|
|
||||||
return re.compile(f"^{sym}.*?$", re.UNICODE)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def narratorBreak(self) -> re.Pattern:
|
|
||||||
"""Dialogue narrator break rule based on user settings."""
|
|
||||||
sym = re.escape(CONFIG.narratorBreak)
|
|
||||||
return re.compile(f"\\B{sym}\\S.*?\\S{sym}\\B", re.UNICODE)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def altDialogStyle(self) -> re.Pattern:
|
def altDialogStyle(self) -> re.Pattern:
|
||||||
"""Dialogue alternative rule based on user settings."""
|
"""Dialogue alternative rule based on user settings."""
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
%%~name: New Scene
|
%%~name: New Scene
|
||||||
%%~path: 000000000000d/000000000000f
|
%%~path: 000000000000d/000000000000f
|
||||||
%%~kind: NOVEL/DOCUMENT
|
%%~kind: NOVEL/DOCUMENT
|
||||||
%%~hash: 2a863dc53e09b0b1b0294ae7ea001853dddd596d
|
%%~hash: 0566024662fb6ed7ed645717addd64dabf058915
|
||||||
%%~date: 2023-10-17 20:52:56/2023-10-17 20:53:01
|
%%~date: 2024-10-27 13:03:13/2024-10-27 13:03:18
|
||||||
# Novel
|
# Novel
|
||||||
|
|
||||||
## Chapter
|
## Chapter
|
||||||
@@ -34,6 +34,10 @@ This is another paragraph of much longer nonsense text. It is in fact 1 very ver
|
|||||||
|
|
||||||
Some “ double quoted text with spaces padded ”.
|
Some “ double quoted text with spaces padded ”.
|
||||||
|
|
||||||
|
– Hi, I am a character speaking.
|
||||||
|
|
||||||
|
– Hi, I am also a character speaking, – said another character. – How are you?
|
||||||
|
|
||||||
@object: NoSpaceAdded
|
@object: NoSpaceAdded
|
||||||
|
|
||||||
% synopsis: No space before this colon.
|
% synopsis: No space before this colon.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="3" timeStamp="2024-04-14 23:46:11">
|
<novelWriterXML appVersion="2.6a3" hexVersion="0x020600a3" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-27 13:01:24">
|
||||||
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="3">
|
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="6">
|
||||||
<name>New Project</name>
|
<name>New Project</name>
|
||||||
<author>Jane Doe</author>
|
<author>Jane Doe</author>
|
||||||
</project>
|
</project>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
|
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
|
||||||
</importance>
|
</importance>
|
||||||
</settings>
|
</settings>
|
||||||
<content items="11" novelWords="142" notesWords="27">
|
<content items="11" novelWords="161" notesWords="27">
|
||||||
<item handle="0000000000008" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL">
|
<item handle="0000000000008" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL">
|
||||||
<meta expanded="yes" />
|
<meta expanded="yes" />
|
||||||
<name status="s000000" import="i000004">Novel</name>
|
<name status="s000000" import="i000004">Novel</name>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<name status="s000000" import="i000004" active="yes">New Chapter</name>
|
<name status="s000000" import="i000004" active="yes">New Chapter</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="000000000000f" parent="000000000000d" root="0000000000008" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="000000000000f" parent="000000000000d" root="0000000000008" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="no" heading="H1" charCount="808" wordCount="135" paraCount="15" cursorPos="1026" />
|
<meta expanded="no" heading="H1" charCount="918" wordCount="154" paraCount="17" cursorPos="1140" />
|
||||||
<name status="s000000" import="i000004" active="yes">New Scene</name>
|
<name status="s000000" import="i000004" active="yes">New Scene</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="0000000000009" parent="None" root="0000000000009" order="1" type="ROOT" class="PLOT">
|
<item handle="0000000000009" parent="None" root="0000000000009" order="1" type="ROOT" class="PLOT">
|
||||||
|
|||||||
@@ -1251,8 +1251,6 @@ def testFmtToken_Dialogue(mockGUI):
|
|||||||
CONFIG.dialogStyle = 3
|
CONFIG.dialogStyle = 3
|
||||||
CONFIG.altDialogOpen = "::"
|
CONFIG.altDialogOpen = "::"
|
||||||
CONFIG.altDialogClose = "::"
|
CONFIG.altDialogClose = "::"
|
||||||
CONFIG.dialogLine = "\u2013"
|
|
||||||
CONFIG.narratorBreak = "\u2013"
|
|
||||||
|
|
||||||
project = NWProject()
|
project = NWProject()
|
||||||
tokens = BareTokenizer(project)
|
tokens = BareTokenizer(project)
|
||||||
@@ -1305,7 +1303,24 @@ def testFmtToken_Dialogue(mockGUI):
|
|||||||
BlockFmt.NONE
|
BlockFmt.NONE
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
# Dialogue line
|
||||||
|
CONFIG.dialogLine = "\u2013"
|
||||||
|
tokens.setDialogueHighlight(True)
|
||||||
|
tokens._text = "\u2013 Dialogue line without narrator break.\n"
|
||||||
|
tokens.tokenizeText()
|
||||||
|
assert tokens._blocks == [(
|
||||||
|
BlockTyp.TEXT, "",
|
||||||
|
"\u2013 Dialogue line without narrator break.",
|
||||||
|
[
|
||||||
|
(0, TextFmt.COL_B, "dialog"),
|
||||||
|
(39, TextFmt.COL_E, ""),
|
||||||
|
],
|
||||||
|
BlockFmt.NONE
|
||||||
|
)]
|
||||||
|
|
||||||
# Dialogue line with narrator break
|
# Dialogue line with narrator break
|
||||||
|
CONFIG.narratorBreak = "\u2013"
|
||||||
|
tokens.setDialogueHighlight(True)
|
||||||
tokens._text = "\u2013 Dialogue with a narrator break, \u2013he said,\u2013 see?\n"
|
tokens._text = "\u2013 Dialogue with a narrator break, \u2013he said,\u2013 see?\n"
|
||||||
tokens.tokenizeText()
|
tokens.tokenizeText()
|
||||||
assert tokens._blocks == [(
|
assert tokens._blocks == [(
|
||||||
@@ -1314,7 +1329,7 @@ def testFmtToken_Dialogue(mockGUI):
|
|||||||
[
|
[
|
||||||
(0, TextFmt.COL_B, "dialog"),
|
(0, TextFmt.COL_B, "dialog"),
|
||||||
(34, TextFmt.COL_E, ""),
|
(34, TextFmt.COL_E, ""),
|
||||||
(44, TextFmt.COL_B, "dialog"),
|
(43, TextFmt.COL_B, "dialog"),
|
||||||
(49, TextFmt.COL_E, ""),
|
(49, TextFmt.COL_E, ""),
|
||||||
],
|
],
|
||||||
BlockFmt.NONE
|
BlockFmt.NONE
|
||||||
|
|||||||
@@ -258,7 +258,6 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
|
|||||||
# Syntax Highlighting
|
# Syntax Highlighting
|
||||||
CONFIG.dialogStyle = 3
|
CONFIG.dialogStyle = 3
|
||||||
CONFIG.dialogLine = "–"
|
CONFIG.dialogLine = "–"
|
||||||
CONFIG.narratorBreak = "–"
|
|
||||||
CONFIG.altDialogOpen = "<|"
|
CONFIG.altDialogOpen = "<|"
|
||||||
CONFIG.altDialogClose = "|>"
|
CONFIG.altDialogClose = "|>"
|
||||||
|
|
||||||
@@ -431,6 +430,9 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
|
|||||||
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
|
|
||||||
|
# Dialogue
|
||||||
|
# ========
|
||||||
|
|
||||||
for c in "\"Full line double quoted text.\"":
|
for c in "\"Full line double quoted text.\"":
|
||||||
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
||||||
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
@@ -453,6 +455,25 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
|
|||||||
docEditor._typPadBefore = ""
|
docEditor._typPadBefore = ""
|
||||||
docEditor._typPadAfter = ""
|
docEditor._typPadAfter = ""
|
||||||
|
|
||||||
|
# Dialogue Line
|
||||||
|
for c in "-- Hi, I am a character speaking.":
|
||||||
|
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
||||||
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
|
|
||||||
|
# Narrator Break
|
||||||
|
CONFIG.narratorBreak = "–"
|
||||||
|
docEditor = nwGUI.docEditor
|
||||||
|
docEditor._qDocument.syntaxHighlighter.initHighlighter()
|
||||||
|
|
||||||
|
for c in "-- Hi, I am also a character speaking, -- said another character. -- How are you?":
|
||||||
|
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
||||||
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
|
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
|
||||||
|
|
||||||
|
# Special Formatting
|
||||||
|
# ==================
|
||||||
|
|
||||||
# Insert spaces before colon, but ignore tags and synopsis
|
# Insert spaces before colon, but ignore tags and synopsis
|
||||||
docEditor._typPadBefore = ":"
|
docEditor._typPadBefore = ":"
|
||||||
|
|
||||||
|
|||||||
@@ -327,35 +327,9 @@ def testTextPatterns_DialogueSpecial():
|
|||||||
CONFIG.fmtDQuoteClose = nwUnicode.U_RDQUO
|
CONFIG.fmtDQuoteClose = nwUnicode.U_RDQUO
|
||||||
|
|
||||||
CONFIG.dialogStyle = 3
|
CONFIG.dialogStyle = 3
|
||||||
CONFIG.dialogLine = nwUnicode.U_ENDASH
|
|
||||||
CONFIG.narratorBreak = nwUnicode.U_ENDASH
|
|
||||||
CONFIG.altDialogOpen = "::"
|
CONFIG.altDialogOpen = "::"
|
||||||
CONFIG.altDialogClose = "::"
|
CONFIG.altDialogClose = "::"
|
||||||
|
|
||||||
# Dialogue Line
|
|
||||||
# =============
|
|
||||||
regEx = REGEX_PATTERNS.dialogLine
|
|
||||||
|
|
||||||
# Check dialogue line in first position
|
|
||||||
assert allMatches(regEx, "\u2013 one two three") == [
|
|
||||||
[("\u2013 one two three", 0, 15)]
|
|
||||||
]
|
|
||||||
|
|
||||||
# Check dialogue line in second position
|
|
||||||
assert allMatches(regEx, " \u2013 one two three") == []
|
|
||||||
|
|
||||||
# Narrator Break
|
|
||||||
# ==============
|
|
||||||
regEx = REGEX_PATTERNS.narratorBreak
|
|
||||||
|
|
||||||
# Narrator break with no padding
|
|
||||||
assert allMatches(regEx, "one \u2013two\u2013 three") == [
|
|
||||||
[("\u2013two\u2013", 4, 9)]
|
|
||||||
]
|
|
||||||
|
|
||||||
# Narrator break with padding
|
|
||||||
assert allMatches(regEx, "one \u2013 two \u2013 three") == []
|
|
||||||
|
|
||||||
# Alternative Dialogue
|
# Alternative Dialogue
|
||||||
# ====================
|
# ====================
|
||||||
regEx = REGEX_PATTERNS.altDialogStyle
|
regEx = REGEX_PATTERNS.altDialogStyle
|
||||||
|
|||||||
Reference in New Issue
Block a user