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.includeKeywords": (bool, False),
"text.includeBodyText": (bool, True),
"text.ignoredKeywords": (str, ""),
"text.addNoteHeadings": (bool, True),
"format.textFont": (str, CONFIG.textFont),
"format.textSize": (int, 12),
@@ -112,6 +113,7 @@ SETTINGS_LABELS = {
"text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
"text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
"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.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.setLineHeight(self._build.getFloat("format.lineHeight"))
bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
bldObj.setSynopsis(self._build.getBool("text.includeSynopsis"))
bldObj.setComments(self._build.getBool("text.includeComments"))
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):
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]] = []
# User Settings
self._textFont = "Serif" # Output text font
self._textSize = 11 # Output text size
self._textFixed = False # Fixed width text
self._lineHeight = 1.15 # Line height in units of em
self._blockIndent = 4.00 # Block indent in units of em
self._doJustify = False # Justify text
self._doBodyText = True # Include body text
self._doSynopsis = False # Also process synopsis comments
self._doComments = False # Also process comments
self._doKeywords = False # Also process keywords like tags and references
self._textFont = "Serif" # Output text font
self._textSize = 11 # Output text size
self._textFixed = False # Fixed width text
self._lineHeight = 1.15 # Line height in units of em
self._blockIndent = 4.00 # Block indent in units of em
self._doJustify = False # Justify text
self._doBodyText = True # Include body text
self._doSynopsis = False # Also process synopsis comments
self._doComments = False # Also process comments
self._doKeywords = False # Also process keywords like tags and references
self._skipKeywords = set() # Keywords to ignore
# Margins
self._marginTitle = (1.000, 0.500)
@@ -363,6 +364,11 @@ class Tokenizer(ABC):
self._doKeywords = state
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:
"""Keep original markdown during build."""
self._keepMarkdown = state
@@ -530,11 +536,13 @@ class Tokenizer(ABC):
tmpMarkdown.append("%s\n" % aLine)
elif aLine[0] == "@":
self._tokens.append((
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
))
if self._doKeywords and self._keepMarkdown:
tmpMarkdown.append("%s\n" % aLine)
valid, bits, _ = self._project.index.scanThis(aLine)
if valid and bits and bits[0] not in self._skipKeywords:
self._tokens.append((
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
))
if self._doKeywords and self._keepMarkdown:
tmpMarkdown.append("%s\n" % aLine)
elif aLine[:2] == "# ":
nHead += 1
+38 -5
View File
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
)
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.extensions.switch import NSwitch
from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox
@@ -966,16 +966,32 @@ class _ContentTab(NScrollableForm):
iPx = SHARED.theme.baseIconSize
# Text Content
self.incBodyText = NSwitch(self, height=iPx)
self.incSynopsis = NSwitch(self, height=iPx)
self.incComments = 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.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
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
self.addNoteHead = NSwitch(self, height=iPx)
@@ -990,22 +1006,39 @@ class _ContentTab(NScrollableForm):
def loadContent(self) -> None:
"""Populate the widgets."""
self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
self.incComments.setChecked(self._build.getBool("text.includeComments"))
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._updateIgnoredKeywords()
return
def saveContent(self) -> None:
"""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.includeComments", self.incComments.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())
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