Restrict dialogue line symbols
This commit is contained in:
+10
-1
@@ -40,7 +40,7 @@ from PyQt6.QtCore import QCoreApplication, QMimeData, QUrl
|
|||||||
from PyQt6.QtGui import QAction, QDesktopServices, QFont, QFontDatabase, QFontInfo
|
from PyQt6.QtGui import QAction, QDesktopServices, QFont, QFontDatabase, QFontInfo
|
||||||
from PyQt6.QtWidgets import QMenu, QMenuBar, QWidget
|
from PyQt6.QtWidgets import QMenu, QMenuBar, QWidget
|
||||||
|
|
||||||
from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst
|
from novelwriter.constants import nwConst, nwLabels, nwQuotes, nwUnicode, trConst
|
||||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
|
|
||||||
@@ -298,6 +298,15 @@ def uniqueCompact(text: str) -> str:
|
|||||||
return "".join(sorted(set(compact(text))))
|
return "".join(sorted(set(compact(text))))
|
||||||
|
|
||||||
|
|
||||||
|
def processDialogSymbols(symbols: str) -> str:
|
||||||
|
"""Process dialogue line symbols."""
|
||||||
|
result = ""
|
||||||
|
for c in uniqueCompact(symbols):
|
||||||
|
if c in nwQuotes.ALLOWED:
|
||||||
|
result += c
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def elide(text: str, length: int) -> str:
|
def elide(text: str, length: int) -> str:
|
||||||
"""Elide a piece of text to a maximum length."""
|
"""Elide a piece of text to a maximum length."""
|
||||||
if len(text) > (cut := max(4, length)):
|
if len(text) > (cut := max(4, length)):
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ from PyQt6.QtWidgets import QApplication
|
|||||||
|
|
||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
NWConfigParser, checkInt, checkPath, describeFont, fontMatcher,
|
NWConfigParser, checkInt, checkPath, describeFont, fontMatcher,
|
||||||
formatTimeStamp
|
formatTimeStamp, processDialogSymbols
|
||||||
)
|
)
|
||||||
from novelwriter.constants import nwFiles, nwHtmlUnicode, nwQuotes, nwUnicode
|
from novelwriter.constants import nwFiles, nwHtmlUnicode, nwQuotes, nwUnicode
|
||||||
from novelwriter.error import formatException, logException
|
from novelwriter.error import formatException, logException
|
||||||
@@ -680,7 +680,7 @@ class Config:
|
|||||||
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
|
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
|
||||||
self.dialogStyle = conf.rdInt(sec, "dialogstyle", self.dialogStyle)
|
self.dialogStyle = conf.rdInt(sec, "dialogstyle", self.dialogStyle)
|
||||||
self.allowOpenDial = conf.rdBool(sec, "allowopendial", self.allowOpenDial)
|
self.allowOpenDial = conf.rdBool(sec, "allowopendial", self.allowOpenDial)
|
||||||
self.dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine)
|
dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine)
|
||||||
narratorBreak = conf.rdStr(sec, "narratorbreak", self.narratorBreak)
|
narratorBreak = conf.rdStr(sec, "narratorbreak", self.narratorBreak)
|
||||||
narratorDialog = conf.rdStr(sec, "narratordialog", self.narratorDialog)
|
narratorDialog = conf.rdStr(sec, "narratordialog", self.narratorDialog)
|
||||||
self.altDialogOpen = conf.rdStr(sec, "altdialogopen", self.altDialogOpen)
|
self.altDialogOpen = conf.rdStr(sec, "altdialogopen", self.altDialogOpen)
|
||||||
@@ -721,6 +721,7 @@ class Config:
|
|||||||
logger.info("Using straight double quotes, so disabling auto-replace")
|
logger.info("Using straight double quotes, so disabling auto-replace")
|
||||||
self.doReplaceDQuote = False
|
self.doReplaceDQuote = False
|
||||||
|
|
||||||
|
self.dialogLine = processDialogSymbols(dialogLine)
|
||||||
self.narratorBreak = narratorBreak if narratorBreak in nwQuotes.DASHES else ""
|
self.narratorBreak = narratorBreak if narratorBreak in nwQuotes.DASHES else ""
|
||||||
self.narratorDialog = narratorDialog if narratorDialog in nwQuotes.DASHES else ""
|
self.narratorDialog = narratorDialog if narratorDialog in nwQuotes.DASHES else ""
|
||||||
|
|
||||||
|
|||||||
@@ -512,6 +512,12 @@ class nwQuotes:
|
|||||||
"\u2015": QT_TRANSLATE_NOOP("Constant", "Horizontal bar"),
|
"\u2015": QT_TRANSLATE_NOOP("Constant", "Horizontal bar"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALLOWED: Final[list[str]] = [
|
||||||
|
"\u0027", "\u0022", "\u2018", "\u2019", "\u201a", "\u201b", "\u201c", "\u201d", "\u201e",
|
||||||
|
"\u201f", "\u2e42", "\u2039", "\u203a", "\u00ab", "\u00bb", "\u300c", "\u300d", "\u300e",
|
||||||
|
"\u300f", "\u2013", "\u2014", "\u2015",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class nwUnicode:
|
class nwUnicode:
|
||||||
"""Supported unicode character constants and their HTML equivalents."""
|
"""Supported unicode character constants and their HTML equivalents."""
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ from PyQt6.QtWidgets import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.common import compact, describeFont, uniqueCompact
|
from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact
|
||||||
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL
|
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL
|
||||||
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
|
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
|
||||||
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
||||||
@@ -1033,7 +1033,7 @@ class GuiPreferences(NDialog):
|
|||||||
# Text Highlighting
|
# Text Highlighting
|
||||||
dialogueStyle = self.dialogStyle.currentData()
|
dialogueStyle = self.dialogStyle.currentData()
|
||||||
allowOpenDial = self.allowOpenDial.isChecked()
|
allowOpenDial = self.allowOpenDial.isChecked()
|
||||||
dialogueLine = uniqueCompact(self.dialogLine.text())
|
dialogueLine = processDialogSymbols(self.dialogLine.text())
|
||||||
narratorBreak = self.narratorBreak.currentData()
|
narratorBreak = self.narratorBreak.currentData()
|
||||||
narratorDialog = self.narratorDialog.currentData()
|
narratorDialog = self.narratorDialog.currentData()
|
||||||
altDialogOpen = compact(self.altDialogOpen.text())
|
altDialogOpen = compact(self.altDialogOpen.text())
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ from novelwriter.common import (
|
|||||||
formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion,
|
formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion,
|
||||||
fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout,
|
fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout,
|
||||||
isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe,
|
isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe,
|
||||||
minmax, numberToRoman, openExternalPath, readTextFile, simplified,
|
minmax, numberToRoman, openExternalPath, processDialogSymbols,
|
||||||
transferCase, uniqueCompact, xmlElement, xmlIndent, xmlSubElem, yesNo
|
readTextFile, simplified, transferCase, uniqueCompact, xmlElement,
|
||||||
|
xmlIndent, xmlSubElem, yesNo
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.mocked import causeOSError
|
from tests.mocked import causeOSError
|
||||||
@@ -377,6 +378,14 @@ def testBaseCommon_uniqueCompact():
|
|||||||
assert uniqueCompact("3 2 1") == "123"
|
assert uniqueCompact("3 2 1") == "123"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.base
|
||||||
|
def testBaseCommon_processDialogSymbols():
|
||||||
|
"""Test the processDialogSymbols function."""
|
||||||
|
assert processDialogSymbols("abc") == ""
|
||||||
|
assert processDialogSymbols("\u00ab\u00ab\u00bb\u00bb") == "\u00ab\u00bb"
|
||||||
|
assert processDialogSymbols("-\u2013\u2014\u2015") == "\u2013\u2014\u2015"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.base
|
@pytest.mark.base
|
||||||
def testBaseCommon_elide():
|
def testBaseCommon_elide():
|
||||||
"""Test the elide function."""
|
"""Test the elide function."""
|
||||||
|
|||||||
Reference in New Issue
Block a user