Reworked the title formatting functionality. All keywords can be used in all headings, and also added scene numbers.
This commit is contained in:
@@ -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> – This is replaced with the text you put in your headings in your
|
<p><mark>%title%</mark> – This is replaced with the text you put in your headings in your
|
||||||
documents</p>
|
documents</p>
|
||||||
<p><mark>%num%</mark> – This is replaced with the chapter number of your chapter type
|
<p><mark>%chnum%</mark> – 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> – 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> – 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> – 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> – 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> – Two backslashes are replaced by a line break.</p>
|
<p><mark>\\</mark> – 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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user