diff --git a/novelwriter/config.py b/novelwriter/config.py index 1627cade..91945fe3 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -158,9 +158,10 @@ class Config: self.autoScrollPos = 30 # Start point for typewriter-like scrolling self.scrollPastEnd = True # Scroll past end of document, and centre cursor - self.highlightQuotes = True # Highlight text in quotes - self.allowOpenSQuote = False # Allow open-ended single quotes - self.allowOpenDQuote = True # Allow open-ended double quotes + self.dialogueStyle = 2 # Quote type to use for dialogue + self.allowOpenDial = True # Allow open-ended dialogue quotes + self.narratorBreak = "" # Symbol to use for narrator break + self.dialogueLine = "" # Symbol to use for dialogue line self.highlightEmph = True # Add colour to text emphasis self.stopWhenIdle = True # Stop the status bar clock when the user is idle @@ -618,9 +619,10 @@ class Config: self.showMultiSpaces = conf.rdBool(sec, "showmultispaces", self.showMultiSpaces) self.incNotesWCount = conf.rdBool(sec, "incnoteswcount", self.incNotesWCount) self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath) - self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes) - self.allowOpenSQuote = conf.rdBool(sec, "allowopensquote", self.allowOpenSQuote) - self.allowOpenDQuote = conf.rdBool(sec, "allowopendquote", self.allowOpenDQuote) + self.dialogueStyle = conf.rdInt(sec, "dialoguestyle", self.dialogueStyle) + self.allowOpenDial = conf.rdBool(sec, "allowopendial", self.allowOpenDial) + self.narratorBreak = conf.rdStr(sec, "narratorbreak", self.narratorBreak) + self.dialogueLine = conf.rdStr(sec, "dialogueline", self.dialogueLine) self.highlightEmph = conf.rdBool(sec, "highlightemph", self.highlightEmph) self.stopWhenIdle = conf.rdBool(sec, "stopwhenidle", self.stopWhenIdle) self.userIdleTime = conf.rdInt(sec, "useridletime", self.userIdleTime) @@ -726,9 +728,10 @@ class Config: "showmultispaces": str(self.showMultiSpaces), "incnoteswcount": str(self.incNotesWCount), "showfullpath": str(self.showFullPath), - "highlightquotes": str(self.highlightQuotes), - "allowopensquote": str(self.allowOpenSQuote), - "allowopendquote": str(self.allowOpenDQuote), + "dialoguestyle": str(self.dialogueStyle), + "allowopendial": str(self.allowOpenDial), + "narratorbreak": str(self.narratorBreak), + "dialogueline": str(self.dialogueLine), "highlightemph": str(self.highlightEmph), "stopwhenidle": str(self.stopWhenIdle), "useridletime": str(self.userIdleTime), diff --git a/novelwriter/gui/dochighlight.py b/novelwriter/gui/dochighlight.py index 29fe9504..9ecd0270 100644 --- a/novelwriter/gui/dochighlight.py +++ b/novelwriter/gui/dochighlight.py @@ -94,6 +94,7 @@ class GuiDocHighlighter(QSyntaxHighlighter): colBreak.setAlpha(64) # Create Character Formats + self._addCharFormat("text", SHARED.theme.colText) self._addCharFormat("header1", SHARED.theme.colHead, "b", 1.8) self._addCharFormat("header2", SHARED.theme.colHead, "b", 1.6) self._addCharFormat("header3", SHARED.theme.colHead, "b", 1.4) @@ -107,9 +108,7 @@ class GuiDocHighlighter(QSyntaxHighlighter): self._addCharFormat("strike", SHARED.theme.colHidden, "s") self._addCharFormat("mspaces", SHARED.theme.colError, "err") self._addCharFormat("nobreak", colBreak, "bg") - self._addCharFormat("dialog1", SHARED.theme.colDialN) - self._addCharFormat("dialog2", SHARED.theme.colDialD) - self._addCharFormat("dialog3", SHARED.theme.colDialS) + self._addCharFormat("dialog", SHARED.theme.colDialog) self._addCharFormat("replace", SHARED.theme.colRepTag) self._addCharFormat("hidden", SHARED.theme.colHidden) self._addCharFormat("markup", SHARED.theme.colHidden) @@ -127,6 +126,9 @@ class GuiDocHighlighter(QSyntaxHighlighter): self._spellErr.setUnderlineColor(SHARED.theme.colSpell) self._spellErr.setUnderlineStyle(QTextCharFormat.UnderlineStyle.SpellCheckUnderline) + self._txtRules.clear() + self._cmnRules.clear() + # Multiple or Trailing Spaces if CONFIG.showMultiSpaces: rxRule = QRegularExpression(r"[ ]{2,}|[ ]*$") @@ -146,36 +148,38 @@ class GuiDocHighlighter(QSyntaxHighlighter): self._txtRules.append((rxRule, hlRule)) self._cmnRules.append((rxRule, hlRule)) - # Quoted Strings - if CONFIG.highlightQuotes: - fmtDblO = CONFIG.fmtDQuoteOpen - fmtDblC = CONFIG.fmtDQuoteClose - fmtSngO = CONFIG.fmtSQuoteOpen - fmtSngC = CONFIG.fmtSQuoteClose + # Dialogue + if CONFIG.dialogueStyle > 0: + symO = "" + symC = "" + if CONFIG.dialogueStyle in (1, 3): + symO += CONFIG.fmtSQuoteOpen + symC += CONFIG.fmtSQuoteClose + if CONFIG.dialogueStyle in (2, 3): + symO += CONFIG.fmtDQuoteOpen + symC += CONFIG.fmtDQuoteClose - # Straight Quotes - rxRule = QRegularExpression(r'(\B")(.*?)("\B)') + rxEnd = "|$" if CONFIG.allowOpenDial else "" + rxRule = QRegularExpression(f"(\\B[{symO}])(.*?)([{symC}]\\B{rxEnd})") rxRule.setPatternOptions(QRegExUnicode) hlRule = { - 0: self._hStyles["dialog1"], + 0: self._hStyles["dialog"], } self._txtRules.append((rxRule, hlRule)) - # Double Quotes - dblEnd = "|$" if CONFIG.allowOpenDQuote else "" - rxRule = QRegularExpression(f"(\\B{fmtDblO})(.*?)({fmtDblC}\\B{dblEnd})") + if sym := CONFIG.dialogueLine: + rxRule = QRegularExpression(f"^{sym}.*?$") rxRule.setPatternOptions(QRegExUnicode) hlRule = { - 0: self._hStyles["dialog2"], + 0: self._hStyles["dialog"], } self._txtRules.append((rxRule, hlRule)) - # Single Quotes - sngEnd = "|$" if CONFIG.allowOpenSQuote else "" - rxRule = QRegularExpression(f"(\\B{fmtSngO})(.*?)({fmtSngC}\\B{sngEnd})") + if sym := CONFIG.narratorBreak: + rxRule = QRegularExpression(f"({sym}\\b)(.*?)(\\b{sym})") rxRule.setPatternOptions(QRegExUnicode) hlRule = { - 0: self._hStyles["dialog3"], + 0: self._hStyles["text"], } self._txtRules.append((rxRule, hlRule)) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 5ecc4444..ebcf5e04 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -95,9 +95,7 @@ class GuiTheme: self.colHead = QColor(0, 0, 0) self.colHeadH = QColor(0, 0, 0) self.colEmph = QColor(0, 0, 0) - self.colDialN = QColor(0, 0, 0) - self.colDialD = QColor(0, 0, 0) - self.colDialS = QColor(0, 0, 0) + self.colDialog = QColor(0, 0, 0) self.colHidden = QColor(0, 0, 0) self.colNote = QColor(0, 0, 0) self.colCode = QColor(0, 0, 0) @@ -338,9 +336,7 @@ class GuiTheme: self.colHead = self._parseColour(confParser, cnfSec, "headertext") self.colHeadH = self._parseColour(confParser, cnfSec, "headertag") self.colEmph = self._parseColour(confParser, cnfSec, "emphasis") - self.colDialN = self._parseColour(confParser, cnfSec, "straightquotes") - self.colDialD = self._parseColour(confParser, cnfSec, "doublequotes") - self.colDialS = self._parseColour(confParser, cnfSec, "singlequotes") + self.colDialog = self._parseColour(confParser, cnfSec, "dialog") self.colHidden = self._parseColour(confParser, cnfSec, "hidden") self.colNote = self._parseColour(confParser, cnfSec, "note") self.colCode = self._parseColour(confParser, cnfSec, "shortcode")