Reworked the title formatting functionality. All keywords can be used in all headings, and also added scene numbers.

This commit is contained in:
Veronica K. B. Olsen
2020-05-11 19:00:01 +02:00
parent 4dead91af2
commit 7c1f3144bd
4 changed files with 82 additions and 64 deletions
+18 -13
View File
@@ -1,25 +1,30 @@
<h1>Help!</h1> <h1>Help!</h1>
<p>A brief guide to make the most out of the Build Project tool.</p> <p><i>A brief guide to make the most out of the Build Novel Project tool.</i></p>
<h2>Novel Title Formats</h2> <h2>Novel Title Formats</h2>
<p>The format of the various title levels in the files under the Novel folder can be customised in <p>The format of the various title levels in the files under the Novel folder can be customised in
these settings. The actual title given in the headings of your files will replace all these settings. The actual title given in the headings of your files will for instance replace
occurrences of the keyword <mark>%title%</mark>. Any static text will be left as-is in the all occurrences of the keyword <mark>%title%</mark>. Any static text will be left as-is in the
final title. An empty field means the title isn't written out at all.</p> final title. An empty field means the title isn't written out at all.</p>
<p>The available formatting keywords are:</p> <p>The available formatting keywords are:</p>
<p><mark>%title%</mark> &ndash; This is replaced with the text you put in your headings in your <p><mark>%title%</mark> &ndash; This is replaced with the text you put in your headings in your
documents</p> documents</p>
<p><mark>%num%</mark> &ndash; This is replaced with the chapter number of your chapter type <p><mark>%chnum%</mark> &ndash; This is replaced with the chapter number of your chapter type
headings. These are generated automaticall starting from 1.</p> headings. These are generated automaticall starting from 1, but ignoring chapter headings in
<p><mark>%numword%</mark> &ndash; This is replaced with the chapter number of your chapter type files with "Unnumbered" layout.</p>
headings, but instead of an arabic number, the word for it is used instead, e.g. One, Two, <p><mark>%chnumword%</mark> &ndash; This is replaced with the chapter number, but instead of an
Fifteen, Twenty-Five, etc.</p> arabic number, the word for it is used, e.g. One, Two, Fifteen, Twenty-Five, etc.</p>
<p><mark>%scnum%</mark> &ndash; This is replaced with the scene number. The number is reset to one
for each new chapter, so it is the scene number within the current chapter.</p>
<p><mark>%scabsnum%</mark> &ndash; This is replaced with the absolute scene number. That is, the
number is counted from the first scene in the novel, and not reset for each chapter.</p>
<p><mark>\\</mark> &ndash; Two backslashes are replaced by a line break.</p> <p><mark>\\</mark> &ndash; Two backslashes are replaced by a line break.</p>
<p><b>Note:</b> The Scene format is treated slightly differently than the other title formats. If a <p><b>Note:</b> The Scene and Section formats are treated slightly differently than the other title
scene format is a constant text, that is, contains no <mark>%title%</mark>, it will be treated formats. If the format is a constant text, that is, contains no <mark>%keyword%</mark> tags, it
as a scene separator instead. Scene separators are centred, and not shown if the chapter starts will be treated as a separator instead. Scene and Section separators are centred, and for
directly on the first scene. If the field is blank, a large space between the scenes is added scenes, not shown if placed directly after the chapter heading. For instance, it you want the
instead.</p> classic three asterisk <mark>* * *</mark> separator between scenes, just put that into the
scene format box, and nothing else.</p>
<h2>Build Overrides</h2> <h2>Build Overrides</h2>
<p><b>Novel Outline Mode:</b> This option will build an outline version of the novel rather than the <p><b>Novel Outline Mode:</b> This option will build an outline version of the novel rather than the
+53 -40
View File
@@ -104,6 +104,8 @@ class Tokenizer():
# Instance Variables # Instance Variables
self.numChapter = 0 # Counter for chapter numbers self.numChapter = 0 # Counter for chapter numbers
self.numChScene = 0 # Counter for scene number within chapter
self.numAbsScene = 0 # Counter for scene number within novel
self.firstScene = False # Flag to indicate that the first scene of the chapter self.firstScene = False # Flag to indicate that the first scene of the chapter
return return
@@ -370,23 +372,53 @@ class Tokenizer():
tType = tToken[0] tType = tToken[0]
tText = tToken[1] tText = tToken[1]
# In case we see text before a scene, we reset the flag
if tType == self.T_TEXT: if tType == self.T_TEXT:
self.firstScene = False self.firstScene = False
elif tType == self.T_HEAD2: # Novel Chapter elif tType == self.T_HEAD1:
if not isUnNum: # Main Title
self.numChapter += 1 # ==========
tText = self._formatChapter(tText,isUnNum)
tText = self._formatHeading(self.fmtTitle, tText)
self.theTokens[n] = ( self.theTokens[n] = (
tType, tType,
tText, tText,
None, None,
self.A_LEFT | self.A_PBB_R self.A_LEFT | self.A_PBB_R
) )
self.firstScene = True
elif tType == self.T_HEAD3: # Novel Scene elif tType == self.T_HEAD2:
tTemp = self._formatScene(tText) # Novel Chapter
# =============
# Numbered or Unnumbered
if isUnNum:
tText = self._formatHeading(self.fmtUnNum, tText)
else:
self.numChapter += 1
tText = self._formatHeading(self.fmtChapter, tText)
# Format the chapter header
self.theTokens[n] = (
tType,
tText,
None,
self.A_LEFT | self.A_PBB_R
)
# Set scene variables
self.firstScene = True
self.numChScene = 0
elif tType == self.T_HEAD3:
# Novel Scene
# ===========
self.numChScene += 1
self.numAbsScene += 1
tTemp = self._formatHeading(self.fmtScene, tText)
if tTemp == "" and self.hideScene: if tTemp == "" and self.hideScene:
self.theTokens[n] = ( self.theTokens[n] = (
self.T_EMPTY, self.T_EMPTY,
@@ -431,10 +463,15 @@ class Tokenizer():
None, None,
self.A_LEFT | self.A_PBA_AV self.A_LEFT | self.A_PBA_AV
) )
# Definitely no longer the first scene
self.firstScene = False self.firstScene = False
elif tType == self.T_HEAD4: # Novel Section elif tType == self.T_HEAD4:
tTemp = self._formatSection(tText) # Novel Section
# =============
tTemp = self._formatHeading(self.fmtSection, tText)
if tTemp == "" and self.hideSection: if tTemp == "" and self.hideSection:
self.theTokens[n] = ( self.theTokens[n] = (
self.T_EMPTY, self.T_EMPTY,
@@ -500,38 +537,14 @@ class Tokenizer():
# Internal Functions # Internal Functions
## ##
def _formatTitle(self, theText): def _formatHeading(self, theTitle, theText):
"""Replace tokens for headers level 1. """Replaces the %keyword% strings.
""" """
theTitle = self.fmtTitle theTitle = theTitle.replace(r"%title%", theText)
theTitle = theTitle.replace("%title%", theText) theTitle = theTitle.replace(r"%chnum%", str(self.numChapter))
return theTitle theTitle = theTitle.replace(r"%scnum%", str(self.numChScene))
theTitle = theTitle.replace(r"%scabsnum%", str(self.numAbsScene))
def _formatChapter(self, theText, noNum): theTitle = theTitle.replace(r"%chnumword%", numberToWord(self.numChapter,"en"))
"""Replace tokens for headers level 2.
"""
if noNum:
theTitle = self.fmtUnNum
theTitle = theTitle.replace("%title%", theText)
else:
theTitle = self.fmtChapter
theTitle = theTitle.replace("%title%", theText)
theTitle = theTitle.replace("%num%", str(self.numChapter))
theTitle = theTitle.replace("%numword%", numberToWord(self.numChapter,"en"))
return theTitle
def _formatScene(self, theText):
"""Replace tokens for headers level 3.
"""
theTitle = self.fmtScene
theTitle = theTitle.replace("%title%", theText)
return theTitle
def _formatSection(self, theText):
"""Replace tokens for headers level 4.
"""
theTitle = self.fmtSection
theTitle = theTitle.replace("%title%", theText)
return theTitle return theTitle
# END Class Tokenizer # END Class Tokenizer
+6 -6
View File
@@ -69,7 +69,7 @@ class GuiBuildNovel(QDialog):
self.htmlText = "" self.htmlText = ""
self.setWindowTitle("Build Project") self.setWindowTitle("Build Novel Project")
self.setMinimumWidth(800) self.setMinimumWidth(800)
self.setMinimumHeight(800) self.setMinimumHeight(800)
@@ -315,11 +315,11 @@ class GuiBuildNovel(QDialog):
doBodyText = True doBodyText = True
if outlineMode: if outlineMode:
fmtTitle = "%title%" fmtTitle = r"%title%"
fmtChapter = "Chapter: %title%" fmtChapter = r"Chapter %chnum%: %title%"
fmtUnnumbered = "Chapter: %title%" fmtUnnumbered = r"%title%"
fmtScene = "Scene: %title%" fmtScene = r"Scene %chnum%.%scnum%: %title%"
fmtSection = "Section: %title%" fmtSection = r"Section: %title%"
doBodyText = False doBodyText = False
incSynopsis = True incSynopsis = True
novelFiles = True novelFiles = True
+5 -5
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="263" autoCount="31" timeStamp="2020-05-10 23:14:34"> <novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="279" autoCount="37" timeStamp="2020-05-11 18:58:21">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
@@ -10,8 +10,8 @@
<settings> <settings>
<spellCheck>True</spellCheck> <spellCheck>True</spellCheck>
<autoOutline>True</autoOutline> <autoOutline>True</autoOutline>
<lastEdited>6a2d6d5f4f401</lastEdited> <lastEdited>96b68994dfa3d</lastEdited>
<lastViewed>b3e74dbc1f584</lastViewed> <lastViewed>6a2d6d5f4f401</lastViewed>
<lastWordCount>875</lastWordCount> <lastWordCount>875</lastWordCount>
<autoReplace> <autoReplace>
<A>B</A> <A>B</A>
@@ -20,9 +20,9 @@
</autoReplace> </autoReplace>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%.\\%title%</chapter> <chapter>Chapter %chnum%.\\%title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>Scene %chnum%.%scnum%: %title%</scene>
<section></section> <section></section>
<withSynopsis>True</withSynopsis> <withSynopsis>True</withSynopsis>
<withComments>False</withComments> <withComments>False</withComments>