From 5af49dfc6fe04b41659e0a4816041c91c47ed4c7 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:45:00 +0100 Subject: [PATCH] Add a separate setting for alternating dialogue/narration --- novelwriter/config.py | 9 ++++++--- novelwriter/dialogs/preferences.py | 23 ++++++++++++++++++----- novelwriter/text/patterns.py | 12 +++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/novelwriter/config.py b/novelwriter/config.py index 9e010c55..45dc01d9 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -161,8 +161,9 @@ class Config: self.dialogStyle = 2 # Quote type to use for dialogue self.allowOpenDial = True # Allow open-ended dialogue quotes - self.narratorBreak = "" # Symbol to use for narrator break self.dialogLine = "" # Symbol to use for dialogue line + self.narratorBreak = "" # Symbol to use for narrator break + self.narratorDialog = "" # Symbol for alternating between dialogue and narrator self.altDialogOpen = "" # Alternative dialog symbol, open self.altDialogClose = "" # Alternative dialog symbol, close self.highlightEmph = True # Add colour to text emphasis @@ -657,10 +658,11 @@ class Config: self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath) self.dialogStyle = conf.rdInt(sec, "dialogstyle", self.dialogStyle) self.allowOpenDial = conf.rdBool(sec, "allowopendial", self.allowOpenDial) + self.dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine) self.narratorBreak = conf.rdStr(sec, "narratorbreak", self.narratorBreak) + self.narratorDialog = conf.rdStr(sec, "narratordialog", self.narratorDialog) self.altDialogOpen = conf.rdStr(sec, "altdialogopen", self.altDialogOpen) self.altDialogClose = conf.rdStr(sec, "altdialogclose", self.altDialogClose) - self.dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine) self.highlightEmph = conf.rdBool(sec, "highlightemph", self.highlightEmph) self.stopWhenIdle = conf.rdBool(sec, "stopwhenidle", self.stopWhenIdle) self.userIdleTime = conf.rdInt(sec, "useridletime", self.userIdleTime) @@ -766,10 +768,11 @@ class Config: "showfullpath": str(self.showFullPath), "dialogstyle": str(self.dialogStyle), "allowopendial": str(self.allowOpenDial), + "dialogline": str(self.dialogLine), "narratorbreak": str(self.narratorBreak), + "narratordialog": str(self.narratorDialog), "altdialogopen": str(self.altDialogOpen), "altdialogclose": str(self.altDialogClose), - "dialogline": str(self.dialogLine), "highlightemph": str(self.highlightEmph), "stopwhenidle": str(self.stopWhenIdle), "useridletime": str(self.userIdleTime), diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 6723cd4a..444729ad 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -583,8 +583,18 @@ class GuiPreferences(NDialog): self.narratorBreak.setAlignment(QtAlignCenter) self.narratorBreak.setText(CONFIG.narratorBreak) self.mainForm.addRow( - self.tr("Alternating dialogue/narration symbol"), self.narratorBreak, - self.tr("Alternates dialogue highlighting within a paragraph.") + self.tr("Dialogue narrator break symbol"), self.narratorBreak, + self.tr("Symbol to indicate injected narrator break in dialogue") + ) + + self.narratorDialog = QLineEdit(self) + self.narratorDialog.setMaxLength(1) + self.narratorDialog.setFixedWidth(boxFixed) + self.narratorDialog.setAlignment(QtAlignCenter) + self.narratorDialog.setText(CONFIG.narratorDialog) + self.mainForm.addRow( + self.tr("Alternating dialogue/narration symbol"), self.narratorDialog, + self.tr("Alternates dialogue highlighting within any paragraph.") ) self.highlightEmph = NSwitch(self) @@ -952,8 +962,9 @@ class GuiPreferences(NDialog): # Text Highlighting dialogueStyle = self.dialogStyle.currentData() allowOpenDial = self.allowOpenDial.isChecked() - narratorBreak = self.narratorBreak.text().strip() dialogueLine = uniqueCompact(self.dialogLine.text()) + narratorBreak = self.narratorBreak.text().strip() + narratorDialog = self.narratorDialog.text().strip() altDialogOpen = compact(self.altDialogOpen.text()) altDialogClose = compact(self.altDialogClose.text()) highlightEmph = self.highlightEmph.isChecked() @@ -961,8 +972,9 @@ class GuiPreferences(NDialog): updateSyntax |= CONFIG.dialogStyle != dialogueStyle updateSyntax |= CONFIG.allowOpenDial != allowOpenDial - updateSyntax |= CONFIG.narratorBreak != narratorBreak updateSyntax |= CONFIG.dialogLine != dialogueLine + updateSyntax |= CONFIG.narratorBreak != narratorBreak + updateSyntax |= CONFIG.narratorDialog != narratorDialog updateSyntax |= CONFIG.altDialogOpen != altDialogOpen updateSyntax |= CONFIG.altDialogClose != altDialogClose updateSyntax |= CONFIG.highlightEmph != highlightEmph @@ -970,8 +982,9 @@ class GuiPreferences(NDialog): CONFIG.dialogStyle = dialogueStyle CONFIG.allowOpenDial = allowOpenDial - CONFIG.narratorBreak = narratorBreak CONFIG.dialogLine = dialogueLine + CONFIG.narratorBreak = narratorBreak + CONFIG.narratorDialog = narratorDialog CONFIG.altDialogOpen = altDialogOpen CONFIG.altDialogClose = altDialogClose CONFIG.highlightEmph = highlightEmph diff --git a/novelwriter/text/patterns.py b/novelwriter/text/patterns.py index 9d1bca24..6bfa6d9d 100644 --- a/novelwriter/text/patterns.py +++ b/novelwriter/text/patterns.py @@ -114,12 +114,13 @@ REGEX_PATTERNS = RegExPatterns() class DialogParser: - __slots__ = ("_quotes", "_dialog", "_narrator", "_break", "_enabled") + __slots__ = ("_quotes", "_dialog", "_narrator", "_alternate", "_break", "_enabled") def __init__(self) -> None: self._quotes = None self._dialog = "" self._narrator = "" + self._alternate = "" self._break = re.compile("") self._enabled = False return @@ -135,6 +136,7 @@ class DialogParser: self._quotes = REGEX_PATTERNS.dialogStyle self._dialog = uniqueCompact(CONFIG.dialogLine) self._narrator = CONFIG.narratorBreak.strip()[:1] + self._alternate = CONFIG.narratorDialog.strip()[:1] self._break = re.compile( f"({self._narrator}\\s?.*?)(\\s?(?:{self._narrator}[{punct}]?|$))", re.UNICODE ) @@ -145,8 +147,10 @@ class DialogParser: """Caller wrapper for dialogue processing.""" temp: list[int] = [] if text: + plain = True if self._dialog and text[0] in self._dialog: # The whole line is dialogue + plain = False temp.append(0) temp.append(len(text)) if self._narrator: @@ -160,6 +164,7 @@ class DialogParser: elif self._quotes: # The line contains quoted dialogue for res in self._quotes.finditer(text): + plain = False temp.append(res.start(0)) temp.append(res.end(0)) if self._narrator: @@ -169,9 +174,10 @@ class DialogParser: temp.append(res.start(2)) else: temp.append(res.end(0)) - elif not self._dialog and self._narrator: + + if plain and self._alternate: pos = 0 - for num, bit in enumerate(text.split(self._narrator)): + for num, bit in enumerate(text.split(self._alternate)): length = len(bit) + int(num > 0) if num%2: temp.append(pos)