Add option to ignore certain keywords in manuscript (#1132)
This commit is contained in:
@@ -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"),
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user