Add option to ignore certain keywords in manuscript (#1132)

This commit is contained in:
Veronica Berglyd Olsen
2024-03-02 15:24:07 +01:00
parent 415d46d659
commit aea4192213
4 changed files with 65 additions and 21 deletions
+2
View File
@@ -69,6 +69,7 @@ SETTINGS_TEMPLATE = {
"text.includeComments": (bool, False), "text.includeComments": (bool, False),
"text.includeKeywords": (bool, False), "text.includeKeywords": (bool, False),
"text.includeBodyText": (bool, True), "text.includeBodyText": (bool, True),
"text.ignoredKeywords": (str, ""),
"text.addNoteHeadings": (bool, True), "text.addNoteHeadings": (bool, True),
"format.textFont": (str, CONFIG.textFont), "format.textFont": (str, CONFIG.textFont),
"format.textSize": (int, 12), "format.textSize": (int, 12),
@@ -112,6 +113,7 @@ SETTINGS_LABELS = {
"text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"), "text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
"text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"), "text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
"text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"), "text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
"text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
"text.grpInsert": QT_TRANSLATE_NOOP("Builds", "Insert Content"), "text.grpInsert": QT_TRANSLATE_NOOP("Builds", "Insert Content"),
"text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"), "text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"),
+2 -1
View File
@@ -303,10 +303,11 @@ class NWBuildDocument:
bldObj.setJustify(self._build.getBool("format.justifyText")) bldObj.setJustify(self._build.getBool("format.justifyText"))
bldObj.setLineHeight(self._build.getFloat("format.lineHeight")) bldObj.setLineHeight(self._build.getFloat("format.lineHeight"))
bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
bldObj.setSynopsis(self._build.getBool("text.includeSynopsis")) bldObj.setSynopsis(self._build.getBool("text.includeSynopsis"))
bldObj.setComments(self._build.getBool("text.includeComments")) bldObj.setComments(self._build.getBool("text.includeComments"))
bldObj.setKeywords(self._build.getBool("text.includeKeywords")) bldObj.setKeywords(self._build.getBool("text.includeKeywords"))
bldObj.setBodyText(self._build.getBool("text.includeBodyText")) bldObj.setIgnoredKeywords(self._build.getStr("text.ignoredKeywords"))
if isinstance(bldObj, ToHtml): if isinstance(bldObj, ToHtml):
bldObj.setStyles(self._build.getBool("html.addStyles")) bldObj.setStyles(self._build.getBool("html.addStyles"))
+23 -15
View File
@@ -130,16 +130,17 @@ class Tokenizer(ABC):
self._tokens: list[tuple[int, int, str, list[tuple[int, int]], int]] = [] self._tokens: list[tuple[int, int, str, list[tuple[int, int]], int]] = []
# User Settings # User Settings
self._textFont = "Serif" # Output text font self._textFont = "Serif" # Output text font
self._textSize = 11 # Output text size self._textSize = 11 # Output text size
self._textFixed = False # Fixed width text self._textFixed = False # Fixed width text
self._lineHeight = 1.15 # Line height in units of em self._lineHeight = 1.15 # Line height in units of em
self._blockIndent = 4.00 # Block indent in units of em self._blockIndent = 4.00 # Block indent in units of em
self._doJustify = False # Justify text self._doJustify = False # Justify text
self._doBodyText = True # Include body text self._doBodyText = True # Include body text
self._doSynopsis = False # Also process synopsis comments self._doSynopsis = False # Also process synopsis comments
self._doComments = False # Also process comments self._doComments = False # Also process comments
self._doKeywords = False # Also process keywords like tags and references self._doKeywords = False # Also process keywords like tags and references
self._skipKeywords = set() # Keywords to ignore
# Margins # Margins
self._marginTitle = (1.000, 0.500) self._marginTitle = (1.000, 0.500)
@@ -363,6 +364,11 @@ class Tokenizer(ABC):
self._doKeywords = state self._doKeywords = state
return return
def setIgnoredKeywords(self, keywords: str) -> None:
"""Comma separated string of keywords to ignore."""
self._skipKeywords = set(x.lower().strip() for x in keywords.split(","))
return
def setKeepMarkdown(self, state: bool) -> None: def setKeepMarkdown(self, state: bool) -> None:
"""Keep original markdown during build.""" """Keep original markdown during build."""
self._keepMarkdown = state self._keepMarkdown = state
@@ -530,11 +536,13 @@ class Tokenizer(ABC):
tmpMarkdown.append("%s\n" % aLine) tmpMarkdown.append("%s\n" % aLine)
elif aLine[0] == "@": elif aLine[0] == "@":
self._tokens.append(( valid, bits, _ = self._project.index.scanThis(aLine)
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign if valid and bits and bits[0] not in self._skipKeywords:
)) self._tokens.append((
if self._doKeywords and self._keepMarkdown: self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
tmpMarkdown.append("%s\n" % aLine) ))
if self._doKeywords and self._keepMarkdown:
tmpMarkdown.append("%s\n" % aLine)
elif aLine[:2] == "# ": elif aLine[:2] == "# ":
nHead += 1 nHead += 1
+38 -5
View File
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.constants import nwHeadFmt, nwLabels, trConst from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
from novelwriter.core.buildsettings import BuildSettings, FilterMode from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox
@@ -966,16 +966,32 @@ class _ContentTab(NScrollableForm):
iPx = SHARED.theme.baseIconSize iPx = SHARED.theme.baseIconSize
# Text Content # Text Content
self.incBodyText = NSwitch(self, height=iPx)
self.incSynopsis = NSwitch(self, height=iPx) self.incSynopsis = NSwitch(self, height=iPx)
self.incComments = NSwitch(self, height=iPx) self.incComments = NSwitch(self, height=iPx)
self.incKeywords = NSwitch(self, height=iPx) self.incKeywords = NSwitch(self, height=iPx)
self.incBodyText = NSwitch(self, height=iPx)
self.ignoredKeywords = QLineEdit(self)
self.mnKeywords = QMenu(self)
for keyword in nwKeyWords.VALID_KEYS:
self.mnKeywords.addAction(
trConst(nwLabels.KEY_NAME[keyword]),
lambda keyword=keyword: self._updateIgnoredKeywords(keyword)
)
self.ignoredKeywordsButton = QToolButton(self)
self.ignoredKeywordsButton.setIcon(SHARED.theme.getIcon("add"))
self.ignoredKeywordsButton.setMenu(self.mnKeywords)
self.ignoredKeywordsButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
self.addGroupLabel(self._build.getLabel("text.grpContent")) self.addGroupLabel(self._build.getLabel("text.grpContent"))
self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis) self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
self.addRow(self._build.getLabel("text.includeComments"), self.incComments) self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords) self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText) self.addRow(self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
button=self.ignoredKeywordsButton, stretch=(1, 1))
# Insert Content # Insert Content
self.addNoteHead = NSwitch(self, height=iPx) self.addNoteHead = NSwitch(self, height=iPx)
@@ -990,22 +1006,39 @@ class _ContentTab(NScrollableForm):
def loadContent(self) -> None: def loadContent(self) -> None:
"""Populate the widgets.""" """Populate the widgets."""
self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis")) self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
self.incComments.setChecked(self._build.getBool("text.includeComments")) self.incComments.setChecked(self._build.getBool("text.includeComments"))
self.incKeywords.setChecked(self._build.getBool("text.includeKeywords")) self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
self.incBodyText.setChecked(self._build.getBool("text.includeBodyText")) self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings")) self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
self._updateIgnoredKeywords()
return return
def saveContent(self) -> None: def saveContent(self) -> None:
"""Save choices back into build object.""" """Save choices back into build object."""
self._updateIgnoredKeywords()
self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked()) self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
self._build.setValue("text.includeComments", self.incComments.isChecked()) self._build.setValue("text.includeComments", self.incComments.isChecked())
self._build.setValue("text.includeKeywords", self.incKeywords.isChecked()) self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
self._build.setValue("text.includeBodyText", self.incBodyText.isChecked()) self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked()) self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
return return
##
# Internal Functions
##
def _updateIgnoredKeywords(self, keyword: str | None = None) -> None:
"""Update the ignored keywords list."""
current = [x.lower().strip() for x in self.ignoredKeywords.text().split(",")]
if keyword:
current.append(keyword)
verified = set(x for x in current if x in nwKeyWords.VALID_KEYS)
self.ignoredKeywords.setText(", ".join(verified))
return
# END Class _ContentTab # END Class _ContentTab