Merge pull request #234 from vkbo/view_details
View Details, and Link Navigation
This commit is contained in:
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
## Version 0.7 RC1 [2020-xx-xx]
|
## Version 0.7 RC1 [2020-xx-xx]
|
||||||
|
|
||||||
|
**User Interface**
|
||||||
|
|
||||||
|
* The back-references list now shows references to any tag in the open document, not just the first tag. Issue #227, PR #234.
|
||||||
|
* Clicking a tag now tries to scroll to the header where the tag is set. The index needed a couple of minor changes for this feature, so this will invalidate the old index for a project, and require a new to be built. This is done automatically. PR #234.
|
||||||
|
|
||||||
**Project Structure**
|
**Project Structure**
|
||||||
|
|
||||||
* The project folder structure has been simplified and cleaned up. We also now freeze the main entry values in the main XML file. The XML file is now given version 1.1, and no further core changes to its structure will be made without bumping this version. We're also locking it to only be opened by version 0.7 or later. An old project file is converted on first open. PR #253.
|
* The project folder structure has been simplified and cleaned up. We also now freeze the main entry values in the main XML file. The XML file is now given version 1.1, and no further core changes to its structure will be made without bumping this version. We're also locking it to only be opened by version 0.7 or later. An old project file is converted on first open. PR #253.
|
||||||
|
|||||||
+17
-17
@@ -199,7 +199,7 @@ class NWIndex():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
for tTag in self.tagIndex:
|
for tTag in self.tagIndex:
|
||||||
if len(self.tagIndex[tTag]) != 3:
|
if len(self.tagIndex[tTag]) != 4:
|
||||||
self.indexBroken = True
|
self.indexBroken = True
|
||||||
|
|
||||||
for tHandle in self.refIndex:
|
for tHandle in self.refIndex:
|
||||||
@@ -228,7 +228,7 @@ class NWIndex():
|
|||||||
if self.indexBroken:
|
if self.indexBroken:
|
||||||
self.clearIndex()
|
self.clearIndex()
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
"The index loaded from project cache contains errors. Rebuilding index.",
|
"The project index is outdated or broken. Rebuilding index.",
|
||||||
nwAlert.WARN
|
nwAlert.WARN
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -260,9 +260,9 @@ class NWIndex():
|
|||||||
logger.debug("Indexing item with handle %s" % tHandle)
|
logger.debug("Indexing item with handle %s" % tHandle)
|
||||||
|
|
||||||
# Check file type, and reset its old index
|
# Check file type, and reset its old index
|
||||||
# Also add a dummy entry for T0 in case the file has no title
|
# Also add a dummy entry T000000 in case the file has no title
|
||||||
self.refIndex[tHandle] = {}
|
self.refIndex[tHandle] = {}
|
||||||
self.refIndex[tHandle]["T0"] = {
|
self.refIndex[tHandle]["T000000"] = {
|
||||||
"tags" : [],
|
"tags" : [],
|
||||||
"updated" : time(),
|
"updated" : time(),
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ class NWIndex():
|
|||||||
|
|
||||||
elif aLine.startswith(r"@"):
|
elif aLine.startswith(r"@"):
|
||||||
self._indexNoteRef(tHandle, aLine, nLine, nTitle)
|
self._indexNoteRef(tHandle, aLine, nLine, nTitle)
|
||||||
self._indexTag(tHandle, aLine, nLine, itemClass)
|
self._indexTag(tHandle, aLine, nLine, nTitle, itemClass)
|
||||||
|
|
||||||
elif aLine.startswith(r"%"):
|
elif aLine.startswith(r"%"):
|
||||||
if nTitle > 0:
|
if nTitle > 0:
|
||||||
@@ -436,7 +436,7 @@ class NWIndex():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _indexTag(self, tHandle, aLine, nLine, itemClass):
|
def _indexTag(self, tHandle, aLine, nLine, nTitle, itemClass):
|
||||||
"""Validate and save the information from a tag.
|
"""Validate and save the information from a tag.
|
||||||
"""
|
"""
|
||||||
isValid, theBits, thePos = self.scanThis(aLine)
|
isValid, theBits, thePos = self.scanThis(aLine)
|
||||||
@@ -444,7 +444,8 @@ class NWIndex():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if theBits[0] == nwKeyWords.TAG_KEY:
|
if theBits[0] == nwKeyWords.TAG_KEY:
|
||||||
self.tagIndex[theBits[1]] = [nLine, tHandle, itemClass.name]
|
sTitle = "T%06d" % nTitle
|
||||||
|
self.tagIndex[theBits[1]] = [nLine, tHandle, itemClass.name, sTitle]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -606,18 +607,17 @@ class NWIndex():
|
|||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
return theRefs
|
return theRefs
|
||||||
|
|
||||||
theTag = None
|
theTags = set()
|
||||||
for tTag in self.tagIndex:
|
for tTag in self.tagIndex:
|
||||||
if tHandle == self.tagIndex[tTag][1]:
|
if tHandle == self.tagIndex[tTag][1]:
|
||||||
theTag = tTag
|
theTags.add(tTag)
|
||||||
break
|
|
||||||
|
|
||||||
if theTag is not None:
|
if theTags:
|
||||||
for tHandle in self.refIndex:
|
for tHandle in self.refIndex:
|
||||||
for sTitle in self.refIndex[tHandle]:
|
for sTitle in self.refIndex[tHandle]:
|
||||||
for nLine, tKey, tTag in self.refIndex[tHandle][sTitle]["tags"]:
|
for _, _, tTag in self.refIndex[tHandle][sTitle]["tags"]:
|
||||||
if tTag == theTag:
|
if tTag in theTags and tHandle not in theRefs:
|
||||||
theRefs[tHandle] = nLine
|
theRefs[tHandle] = sTitle
|
||||||
|
|
||||||
return theRefs
|
return theRefs
|
||||||
|
|
||||||
@@ -626,8 +626,8 @@ class NWIndex():
|
|||||||
"""
|
"""
|
||||||
if theTag in self.tagIndex:
|
if theTag in self.tagIndex:
|
||||||
theRef = self.tagIndex[theTag]
|
theRef = self.tagIndex[theTag]
|
||||||
if len(theRef) == 3:
|
if len(theRef) == 4:
|
||||||
return theRef[1], theRef[0]
|
return theRef[1], theRef[0], theRef[3]
|
||||||
return None, 0
|
return None, 0, "T000000"
|
||||||
|
|
||||||
# END Class NWIndex
|
# END Class NWIndex
|
||||||
|
|||||||
+21
-16
@@ -143,7 +143,7 @@ class ToHtml(Tokenizer):
|
|||||||
parStyle = None
|
parStyle = None
|
||||||
tmpResult = []
|
tmpResult = []
|
||||||
hasHardBreak = False
|
hasHardBreak = False
|
||||||
for tType, tText, tFormat, tStyle in self.theTokens:
|
for tType, tLine, tText, tFormat, tStyle in self.theTokens:
|
||||||
|
|
||||||
# Styles
|
# Styles
|
||||||
aStyle = []
|
aStyle = []
|
||||||
@@ -174,6 +174,11 @@ class ToHtml(Tokenizer):
|
|||||||
else:
|
else:
|
||||||
hStyle = ""
|
hStyle = ""
|
||||||
|
|
||||||
|
if self.linkHeaders:
|
||||||
|
aNm = "<a name='head_%s:T%06d'></a>" % (self.theHandle, tLine)
|
||||||
|
else:
|
||||||
|
aNm = ""
|
||||||
|
|
||||||
# Process TextType
|
# Process TextType
|
||||||
if tType == self.T_EMPTY:
|
if tType == self.T_EMPTY:
|
||||||
if parStyle is None:
|
if parStyle is None:
|
||||||
@@ -191,23 +196,23 @@ class ToHtml(Tokenizer):
|
|||||||
|
|
||||||
elif tType == self.T_TITLE:
|
elif tType == self.T_TITLE:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
tmpResult.append("<h1 class='title'%s>%s</h1>\n" % (hStyle, tHead))
|
tmpResult.append("<h1 class='title'%s>%s%s</h1>\n" % (hStyle, aNm, tHead))
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tType == self.T_HEAD1:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
tmpResult.append("<%s%s>%s</%s>\n" % (h1, hStyle, tHead, h1))
|
tmpResult.append("<%s%s>%s%s</%s>\n" % (h1, hStyle, aNm, tHead, h1))
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
tmpResult.append("<%s%s>%s</%s>\n" % (h2, hStyle, tHead, h2))
|
tmpResult.append("<%s%s>%s%s</%s>\n" % (h2, hStyle, aNm, tHead, h2))
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
tmpResult.append("<%s%s>%s</%s>\n" % (h3, hStyle, tHead, h3))
|
tmpResult.append("<%s%s>%s%s</%s>\n" % (h3, hStyle, aNm, tHead, h3))
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
tmpResult.append("<%s%s>%s</%s>\n" % (h4, hStyle, tHead, h4))
|
tmpResult.append("<%s%s>%s%s</%s>\n" % (h4, hStyle, aNm, tHead, h4))
|
||||||
|
|
||||||
elif tType == self.T_SEP:
|
elif tType == self.T_SEP:
|
||||||
tmpResult.append("<p class='sep'>%s</p>\n" % tText)
|
tmpResult.append("<p class='sep'>%s</p>\n" % tText)
|
||||||
@@ -296,17 +301,17 @@ class ToHtml(Tokenizer):
|
|||||||
refTags = []
|
refTags = []
|
||||||
if theBits[0] in nwLabels.KEY_NAME:
|
if theBits[0] in nwLabels.KEY_NAME:
|
||||||
retText += "<span class='tags'>%s:</span> " % nwLabels.KEY_NAME[theBits[0]]
|
retText += "<span class='tags'>%s:</span> " % nwLabels.KEY_NAME[theBits[0]]
|
||||||
if self.genMode == self.M_PREVIEW:
|
if theBits[0] == nwKeyWords.TAG_KEY:
|
||||||
for tTag in theBits[1:]:
|
retText += "<a name='tag_%s'>%s</a>" % (
|
||||||
refTags.append("<a href='#%s=%s'>%s</a>" % (
|
theBits[1], theBits[1]
|
||||||
theBits[0][1:], tTag, tTag
|
)
|
||||||
))
|
|
||||||
retText += ", ".join(refTags)
|
|
||||||
else:
|
else:
|
||||||
if theBits[0] == nwKeyWords.TAG_KEY:
|
if self.genMode == self.M_PREVIEW:
|
||||||
retText += "<a name='tag_%s'/>%s" % (
|
for tTag in theBits[1:]:
|
||||||
theBits[1], theBits[1]
|
refTags.append("<a href='#%s=%s'>%s</a>" % (
|
||||||
)
|
theBits[0][1:], tTag, tTag
|
||||||
|
))
|
||||||
|
retText += ", ".join(refTags)
|
||||||
else:
|
else:
|
||||||
for tTag in theBits[1:]:
|
for tTag in theBits[1:]:
|
||||||
refTags.append("<a href='#tag_%s'>%s</a>" % (
|
refTags.append("<a href='#tag_%s'>%s</a>" % (
|
||||||
|
|||||||
+144
-51
@@ -102,6 +102,8 @@ class Tokenizer():
|
|||||||
self.hideScene = False # Do not include scene headers
|
self.hideScene = False # Do not include scene headers
|
||||||
self.hideSection = False # Do not include section headers
|
self.hideSection = False # Do not include section headers
|
||||||
|
|
||||||
|
self.linkHeaders = False # Add an anchor before headers
|
||||||
|
|
||||||
# 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.numChScene = 0 # Counter for scene number within chapter
|
||||||
@@ -174,6 +176,10 @@ class Tokenizer():
|
|||||||
self.hideSection = hideSection
|
self.hideSection = hideSection
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def setLinkHeaders(self, linkHeaders):
|
||||||
|
self.linkHeaders = linkHeaders
|
||||||
|
return
|
||||||
|
|
||||||
def setBodyText(self, doBodyText):
|
def setBodyText(self, doBodyText):
|
||||||
self.doBodyText = doBodyText
|
self.doBodyText = doBodyText
|
||||||
return
|
return
|
||||||
@@ -307,12 +313,16 @@ class Tokenizer():
|
|||||||
self.theTokens = []
|
self.theTokens = []
|
||||||
self.theMarkdown = ""
|
self.theMarkdown = ""
|
||||||
tmpMarkdown = []
|
tmpMarkdown = []
|
||||||
|
nLine = 0
|
||||||
for aLine in self.theText.splitlines():
|
for aLine in self.theText.splitlines():
|
||||||
|
nLine += 1
|
||||||
|
|
||||||
# Tag lines starting with specific characters
|
# Tag lines starting with specific characters
|
||||||
if len(aLine.strip()) == 0:
|
if len(aLine.strip()) == 0:
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY, nLine,
|
||||||
|
"", None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("\n")
|
tmpMarkdown.append("\n")
|
||||||
|
|
||||||
@@ -320,45 +330,59 @@ class Tokenizer():
|
|||||||
cLine = aLine[1:].strip()
|
cLine = aLine[1:].strip()
|
||||||
if cLine.lower().startswith("synopsis:"):
|
if cLine.lower().startswith("synopsis:"):
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_SYNOPSIS, cLine[9:].strip(), None, self.A_NONE
|
self.T_SYNOPSIS, nLine,
|
||||||
|
cLine[9:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
if self.doSynopsis:
|
if self.doSynopsis:
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
else:
|
else:
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_COMMENT, aLine[1:].strip(), None, self.A_NONE
|
self.T_COMMENT, nLine,
|
||||||
|
aLine[1:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
if self.doComments:
|
if self.doComments:
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
elif aLine[0] == "@":
|
elif aLine[0] == "@":
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_KEYWORD, aLine[1:].strip(), None, self.A_NONE
|
self.T_KEYWORD, nLine,
|
||||||
|
aLine[1:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
if self.doKeywords:
|
if self.doKeywords:
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
elif aLine[:2] == "# ":
|
elif aLine[:2] == "# ":
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_HEAD1, aLine[2:].strip(), None, self.A_NONE
|
self.T_HEAD1, nLine,
|
||||||
|
aLine[2:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
elif aLine[:3] == "## ":
|
elif aLine[:3] == "## ":
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_HEAD2, aLine[3:].strip(), None, self.A_NONE
|
self.T_HEAD2, nLine,
|
||||||
|
aLine[3:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
elif aLine[:4] == "### ":
|
elif aLine[:4] == "### ":
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_HEAD3, aLine[4:].strip(), None, self.A_NONE
|
self.T_HEAD3, nLine,
|
||||||
|
aLine[4:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
elif aLine[:5] == "#### ":
|
elif aLine[:5] == "#### ":
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_HEAD4, aLine[5:].strip(), None, self.A_NONE
|
self.T_HEAD4, nLine,
|
||||||
|
aLine[5:].strip(), None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
@@ -383,13 +407,17 @@ class Tokenizer():
|
|||||||
# sorted by position
|
# sorted by position
|
||||||
fmtPos = sorted(fmtPos, key=itemgetter(0))
|
fmtPos = sorted(fmtPos, key=itemgetter(0))
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_TEXT, aLine, fmtPos, self.A_NONE
|
self.T_TEXT, nLine,
|
||||||
|
aLine, fmtPos,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|
||||||
# Always add an empty line at the end
|
# Always add an empty line at the end
|
||||||
self.theTokens.append((
|
self.theTokens.append((
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY, nLine,
|
||||||
|
"", None,
|
||||||
|
self.A_NONE
|
||||||
))
|
))
|
||||||
tmpMarkdown.append("\n")
|
tmpMarkdown.append("\n")
|
||||||
|
|
||||||
@@ -413,100 +441,146 @@ class Tokenizer():
|
|||||||
for n in range(len(self.theTokens)):
|
for n in range(len(self.theTokens)):
|
||||||
|
|
||||||
tToken = self.theTokens[n]
|
tToken = self.theTokens[n]
|
||||||
tType = tToken[0]
|
|
||||||
tText = tToken[1]
|
|
||||||
|
|
||||||
# In case we see text before a scene, we reset the flag
|
# In case we see text before a scene, we reset the flag
|
||||||
if tType == self.T_TEXT:
|
if tToken[0] == self.T_TEXT:
|
||||||
self.firstScene = False
|
self.firstScene = False
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tToken[0] == self.T_HEAD1:
|
||||||
# Main Title
|
# Main Title
|
||||||
# ==========
|
# ==========
|
||||||
|
|
||||||
tText = self._formatHeading(self.fmtTitle, tText)
|
tTemp = self._formatHeading(self.fmtTitle, tToken[2])
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, None, self.A_NONE
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tToken[0] == self.T_HEAD2:
|
||||||
# Novel Chapter
|
# Novel Chapter
|
||||||
# =============
|
# =============
|
||||||
|
|
||||||
# Numbered or Unnumbered
|
# Numbered or Unnumbered
|
||||||
if self.isUnNum:
|
if self.isUnNum:
|
||||||
tText = self._formatHeading(self.fmtUnNum, tText)
|
tTemp = self._formatHeading(self.fmtUnNum, tToken[2])
|
||||||
else:
|
else:
|
||||||
self.numChapter += 1
|
self.numChapter += 1
|
||||||
tText = self._formatHeading(self.fmtChapter, tText)
|
tTemp = self._formatHeading(self.fmtChapter, tToken[2])
|
||||||
|
|
||||||
# Format the chapter header
|
# Format the chapter header
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, None, self.A_PBB
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_PBB
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set scene variables
|
# Set scene variables
|
||||||
self.firstScene = True
|
self.firstScene = True
|
||||||
self.numChScene = 0
|
self.numChScene = 0
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tToken[0] == self.T_HEAD3:
|
||||||
# Novel Scene
|
# Novel Scene
|
||||||
# ===========
|
# ===========
|
||||||
|
|
||||||
self.numChScene += 1
|
self.numChScene += 1
|
||||||
self.numAbsScene += 1
|
self.numAbsScene += 1
|
||||||
|
|
||||||
tTemp = self._formatHeading(self.fmtScene, tText)
|
tTemp = self._formatHeading(self.fmtScene, tToken[2])
|
||||||
if tTemp == "" and self.hideScene:
|
if tTemp == "" and self.hideScene:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
elif tTemp == "" and not self.hideScene:
|
elif tTemp == "" and not self.hideScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_SKIP, "", None, self.A_NONE
|
self.T_SKIP,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
elif tTemp == self.fmtScene:
|
elif tTemp == self.fmtScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_SEP, tTemp, None, self.A_CENTRE
|
self.T_SEP,
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_CENTRE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tTemp, None, self.A_NONE
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
# Definitely no longer the first scene
|
# Definitely no longer the first scene
|
||||||
self.firstScene = False
|
self.firstScene = False
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tToken[0] == self.T_HEAD4:
|
||||||
# Novel Section
|
# Novel Section
|
||||||
# =============
|
# =============
|
||||||
|
|
||||||
tTemp = self._formatHeading(self.fmtSection, tText)
|
tTemp = self._formatHeading(self.fmtSection, tToken[2])
|
||||||
if tTemp == "" and self.hideSection:
|
if tTemp == "" and self.hideSection:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_EMPTY, "", None, self.A_NONE
|
self.T_EMPTY,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
elif tTemp == "" and not self.hideSection:
|
elif tTemp == "" and not self.hideSection:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_SKIP, "", None, self.A_NONE
|
self.T_SKIP,
|
||||||
|
tToken[1],
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
elif tTemp == self.fmtSection:
|
elif tTemp == self.fmtSection:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_SEP, tTemp, None, self.A_CENTRE
|
self.T_SEP,
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_CENTRE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tTemp, None, self.A_NONE
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
# For title page and partitions, we need to centre all text.
|
# For title page and partitions, we need to centre all text.
|
||||||
@@ -515,21 +589,30 @@ class Tokenizer():
|
|||||||
# We also swap header level 1 with a title type instead.
|
# We also swap header level 1 with a title type instead.
|
||||||
if self.isTitle or self.isPart:
|
if self.isTitle or self.isPart:
|
||||||
for n, tToken in enumerate(self.theTokens):
|
for n, tToken in enumerate(self.theTokens):
|
||||||
tType = tToken[0]
|
if tToken[0] == self.T_HEAD1:
|
||||||
tText = tToken[1]
|
|
||||||
tFormat = tToken[2]
|
|
||||||
if tType == self.T_HEAD1:
|
|
||||||
if self.isTitle:
|
if self.isTitle:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
self.T_TITLE, tText, tFormat, self.A_PBB_NO | self.A_CENTRE
|
self.T_TITLE,
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
self.A_PBB_NO | self.A_CENTRE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, tFormat, self.A_PBB | self.A_CENTRE
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
self.A_PBB | self.A_CENTRE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, tFormat, self.A_CENTRE
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
self.A_CENTRE
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add a page break after the last entry
|
# Add a page break after the last entry
|
||||||
@@ -537,23 +620,32 @@ class Tokenizer():
|
|||||||
if n >= 0:
|
if n >= 0:
|
||||||
tToken = self.theTokens[n]
|
tToken = self.theTokens[n]
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tToken[0], tToken[1], tToken[2], tToken[3] | self.A_PBA
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
tToken[4] | self.A_PBA
|
||||||
)
|
)
|
||||||
|
|
||||||
# A single page is always left-aligned and starts on a fresh
|
# A single page is always left-aligned and starts on a fresh
|
||||||
# page, unless it's empty.
|
# page, unless it's empty.
|
||||||
if self.isPage:
|
if self.isPage:
|
||||||
for n, tToken in enumerate(self.theTokens):
|
for n, tToken in enumerate(self.theTokens):
|
||||||
tType = tToken[0]
|
|
||||||
tText = tToken[1]
|
|
||||||
tFormat = tToken[2]
|
|
||||||
if n == 0:
|
if n == 0:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, tFormat, self.A_LEFT | self.A_PBB
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
self.A_LEFT | self.A_PBB
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (
|
self.theTokens[n] = (
|
||||||
tType, tText, tFormat, self.A_LEFT
|
tToken[0],
|
||||||
|
tToken[1],
|
||||||
|
tToken[2],
|
||||||
|
tToken[3],
|
||||||
|
self.A_LEFT
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -566,10 +658,11 @@ class Tokenizer():
|
|||||||
"""Replaces the %keyword% strings.
|
"""Replaces the %keyword% strings.
|
||||||
"""
|
"""
|
||||||
theTitle = theTitle.replace(r"%title%", theText)
|
theTitle = theTitle.replace(r"%title%", theText)
|
||||||
theTitle = theTitle.replace(r"%ch%", str(self.numChapter))
|
theTitle = theTitle.replace(r"%ch%", str(self.numChapter))
|
||||||
theTitle = theTitle.replace(r"%sc%", str(self.numChScene))
|
theTitle = theTitle.replace(r"%sc%", str(self.numChScene))
|
||||||
theTitle = theTitle.replace(r"%sca%", str(self.numAbsScene))
|
theTitle = theTitle.replace(r"%sca%", str(self.numAbsScene))
|
||||||
theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter,"en"))
|
if r"%chw%" in theTitle:
|
||||||
|
theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter,"en"))
|
||||||
return theTitle
|
return theTitle
|
||||||
|
|
||||||
# END Class Tokenizer
|
# END Class Tokenizer
|
||||||
|
|||||||
@@ -401,6 +401,8 @@ class GuiDocEditor(QTextEdit):
|
|||||||
def setCursorPosition(self, thePosition):
|
def setCursorPosition(self, thePosition):
|
||||||
"""Move the cursor to a given position in the document.
|
"""Move the cursor to a given position in the document.
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(thePosition, int):
|
||||||
|
return False
|
||||||
if thePosition >= 0:
|
if thePosition >= 0:
|
||||||
theCursor = self.textCursor()
|
theCursor = self.textCursor()
|
||||||
theCursor.setPosition(thePosition)
|
theCursor.setPosition(thePosition)
|
||||||
@@ -416,12 +418,13 @@ class GuiDocEditor(QTextEdit):
|
|||||||
def setCursorLine(self, theLine):
|
def setCursorLine(self, theLine):
|
||||||
"""Move the cursor to a given line in the document.
|
"""Move the cursor to a given line in the document.
|
||||||
"""
|
"""
|
||||||
if theLine is None:
|
if not isinstance(theLine, int):
|
||||||
return False
|
return False
|
||||||
if theLine >= 0:
|
if theLine >= 0:
|
||||||
theBlock = self.qDocument.findBlockByLineNumber(theLine)
|
theBlock = self.qDocument.findBlockByLineNumber(theLine)
|
||||||
if theBlock:
|
if theBlock:
|
||||||
self.setCursorPosition(theBlock.position())
|
self.setCursorPosition(theBlock.position())
|
||||||
|
logger.verbose("Cursor moved to line %d" % theLine)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt, QUrl
|
||||||
from PyQt5.QtWidgets import QTextBrowser
|
from PyQt5.QtWidgets import QTextBrowser
|
||||||
from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
|
from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
|
||||||
|
|
||||||
@@ -134,6 +134,7 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
sPos = self.verticalScrollBar().value()
|
sPos = self.verticalScrollBar().value()
|
||||||
aDoc = ToHtml(self.theProject, self.theParent)
|
aDoc = ToHtml(self.theProject, self.theParent)
|
||||||
aDoc.setPreview(True, self.mainConf.viewComments)
|
aDoc.setPreview(True, self.mainConf.viewComments)
|
||||||
|
aDoc.setLinkHeaders(True)
|
||||||
aDoc.setText(tHandle)
|
aDoc.setText(tHandle)
|
||||||
aDoc.doAutoReplace()
|
aDoc.doAutoReplace()
|
||||||
aDoc.tokenizeText()
|
aDoc.tokenizeText()
|
||||||
@@ -164,19 +165,17 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
index being up to date.
|
index being up to date.
|
||||||
"""
|
"""
|
||||||
logger.debug("Loading document from tag '%s'" % theTag)
|
logger.debug("Loading document from tag '%s'" % theTag)
|
||||||
|
tHandle, onLine, sTitle = self.theParent.theIndex.getTagSource(theTag)
|
||||||
if theTag in self.theParent.theIndex.tagIndex.keys():
|
if tHandle is None:
|
||||||
theTarget = self.theParent.theIndex.tagIndex[theTag]
|
self.theParent.makeAlert((
|
||||||
|
"Could not find the reference for tag '%s'. It either doesn't "
|
||||||
|
"exist, or the index is out of date. The index can be updated "
|
||||||
|
"from the Tools menu, or by pressing F9."
|
||||||
|
) % theTag, nwAlert.ERROR)
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
logger.debug("The tag was not found in the index")
|
self.loadText(tHandle)
|
||||||
return False
|
self.navigateTo("#head_%s:%s" % (tHandle, sTitle))
|
||||||
|
|
||||||
if len(theTarget) != 3:
|
|
||||||
# Just to make sure the index is not messed up
|
|
||||||
return False
|
|
||||||
|
|
||||||
self.loadText(theTarget[1])
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def docAction(self, theAction):
|
def docAction(self, theAction):
|
||||||
@@ -200,6 +199,15 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def navigateTo(self, navLink):
|
||||||
|
"""Go to a specific #link in the document.
|
||||||
|
"""
|
||||||
|
if not isinstance(navLink, str):
|
||||||
|
return False
|
||||||
|
if navLink.startswith("#"):
|
||||||
|
self.setSource(QUrl(navLink))
|
||||||
|
return True
|
||||||
|
|
||||||
def updateDocMargins(self):
|
def updateDocMargins(self):
|
||||||
"""Automatically adjust the margins so the text is centred if
|
"""Automatically adjust the margins so the text is centred if
|
||||||
Config.textFixedW is enabled or we're in Zen mode. Otherwise,
|
Config.textFixedW is enabled or we're in Zen mode. Otherwise,
|
||||||
@@ -233,6 +241,33 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
self.updateDocMargins()
|
self.updateDocMargins()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Setters
|
||||||
|
##
|
||||||
|
|
||||||
|
def setCursorPosition(self, thePosition):
|
||||||
|
"""Move the cursor to a given position in the document.
|
||||||
|
"""
|
||||||
|
if not isinstance(thePosition, int):
|
||||||
|
return False
|
||||||
|
if thePosition >= 0:
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
theCursor.setPosition(thePosition)
|
||||||
|
self.setTextCursor(theCursor)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setCursorLine(self, theLine):
|
||||||
|
"""Move the cursor to a given line in the document.
|
||||||
|
"""
|
||||||
|
if not isinstance(theLine, int):
|
||||||
|
return False
|
||||||
|
if theLine >= 0:
|
||||||
|
theBlock = self.qDocument.findBlockByLineNumber(theLine)
|
||||||
|
if theBlock:
|
||||||
|
self.setCursorPosition(theBlock.position())
|
||||||
|
logger.verbose("Cursor moved to line %d" % theLine)
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
@@ -262,25 +297,11 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
"""Slot for a link in the document being clicked.
|
"""Slot for a link in the document being clicked.
|
||||||
"""
|
"""
|
||||||
theLink = theURL.url()
|
theLink = theURL.url()
|
||||||
tHandle = None
|
logger.verbose("Clicked link: '%s'" % theLink)
|
||||||
onLine = 0
|
|
||||||
theTag = ""
|
|
||||||
if len(theLink) > 0:
|
if len(theLink) > 0:
|
||||||
theBits = theLink.split("=")
|
theBits = theLink.split("=")
|
||||||
if len(theBits) == 2:
|
if len(theBits) == 2:
|
||||||
theTag = theBits[1]
|
self.loadFromTag(theBits[1])
|
||||||
tHandle, onLine = self.theParent.theIndex.getTagSource(theBits[1])
|
|
||||||
|
|
||||||
if tHandle is None:
|
|
||||||
self.theParent.makeAlert((
|
|
||||||
"Could not find the reference for tag '%s'. It either doesn't exist, or the index "
|
|
||||||
"is out of date. The index can be updated from the Tools menu.") % theTag,
|
|
||||||
nwAlert.ERROR
|
|
||||||
)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
self.loadText(tHandle)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _makeStyleSheet(self):
|
def _makeStyleSheet(self):
|
||||||
|
|||||||
@@ -107,7 +107,9 @@ class GuiDocViewDetails(QWidget):
|
|||||||
for tHandle in theRefs:
|
for tHandle in theRefs:
|
||||||
tItem = self.theProject.projTree[tHandle]
|
tItem = self.theProject.projTree[tHandle]
|
||||||
if tItem is not None:
|
if tItem is not None:
|
||||||
theList.append("<a href='#tag=%s'>%s</a>" % (tHandle,tItem.itemName))
|
theList.append("<a href='#head_%s:%s'>%s</a>" % (
|
||||||
|
tHandle, theRefs[tHandle], tItem.itemName
|
||||||
|
))
|
||||||
|
|
||||||
self.refList.setText(", ".join(theList))
|
self.refList.setText(", ".join(theList))
|
||||||
self.refList.adjustSize()
|
self.refList.adjustSize()
|
||||||
@@ -122,9 +124,10 @@ class GuiDocViewDetails(QWidget):
|
|||||||
"""Capture the link-click and forward it to the document viewer
|
"""Capture the link-click and forward it to the document viewer
|
||||||
class for handling.
|
class for handling.
|
||||||
"""
|
"""
|
||||||
if len(theLink) == 18:
|
logger.verbose("Clicked link: '%s'" % theLink)
|
||||||
tHandle = theLink[-13:]
|
if len(theLink) == 27:
|
||||||
self.theParent.viewDocument(tHandle)
|
tHandle = theLink[6:19]
|
||||||
|
self.theParent.viewDocument(tHandle, theLink)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _doShowHide(self, chState):
|
def _doShowHide(self, chState):
|
||||||
|
|||||||
+10
-8
@@ -485,7 +485,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.docEditor.saveText()
|
self.docEditor.saveText()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def viewDocument(self, tHandle=None):
|
def viewDocument(self, tHandle=None, navLink=None):
|
||||||
"""Load a document for viewing in the view panel.
|
"""Load a document for viewing in the view panel.
|
||||||
"""
|
"""
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
@@ -503,13 +503,15 @@ class GuiMain(QMainWindow):
|
|||||||
# Make sure main tab is in Editor view
|
# Make sure main tab is in Editor view
|
||||||
self.tabWidget.setCurrentWidget(self.splitView)
|
self.tabWidget.setCurrentWidget(self.splitView)
|
||||||
|
|
||||||
if self.docViewer.loadText(tHandle) and not self.viewPane.isVisible():
|
if self.docViewer.loadText(tHandle):
|
||||||
bPos = self.splitMain.sizes()
|
if not self.viewPane.isVisible():
|
||||||
self.viewPane.setVisible(True)
|
bPos = self.splitMain.sizes()
|
||||||
vPos = [0,0]
|
self.viewPane.setVisible(True)
|
||||||
vPos[0] = int(bPos[1]/2)
|
vPos = [0,0]
|
||||||
vPos[1] = bPos[1]-vPos[0]
|
vPos[0] = int(bPos[1]/2)
|
||||||
self.splitView.setSizes(vPos)
|
vPos[1] = bPos[1]-vPos[0]
|
||||||
|
self.splitView.setSizes(vPos)
|
||||||
|
self.docViewer.navigateTo(navLink)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
### We Found John!
|
### We Found John!
|
||||||
|
|
||||||
@pov: John
|
@pov: John
|
||||||
@location: Mars
|
@location: Mars, OuterSpace
|
||||||
|
|
||||||
Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes.
|
Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes.
|
||||||
|
|||||||
@@ -5,4 +5,10 @@
|
|||||||
|
|
||||||
Space … it’s an awful lot of nothing, with bits in it here and there. Some of which, people like to call home.
|
Space … it’s an awful lot of nothing, with bits in it here and there. Some of which, people like to call home.
|
||||||
|
|
||||||
|
## Outer Space
|
||||||
|
|
||||||
|
@tag: OuterSpace
|
||||||
|
|
||||||
|
Now even further into space!
|
||||||
|
|
||||||
|
You can have more than one tag in a file, as long as there is only one tag per heading.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.1" saveCount="189" autoCount="28" timeStamp="2020-05-28 19:12:56">
|
<novelWriterXML appVersion="0.6.2" hexVersion="0x000602f0" fileVersion="1.1" saveCount="189" autoCount="30" timeStamp="2020-05-28 20:19:28">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
<spellCheck>True</spellCheck>
|
<spellCheck>True</spellCheck>
|
||||||
<autoOutline>True</autoOutline>
|
<autoOutline>True</autoOutline>
|
||||||
<lastEdited>636b6aa9b697b</lastEdited>
|
<lastEdited>636b6aa9b697b</lastEdited>
|
||||||
<lastViewed>ba8a28a246524</lastViewed>
|
<lastViewed>bc0cbd2a407f3</lastViewed>
|
||||||
<lastWordCount>914</lastWordCount>
|
<lastWordCount>941</lastWordCount>
|
||||||
<autoReplace>
|
<autoReplace>
|
||||||
<A>B</A>
|
<A>B</A>
|
||||||
<B>E</B>
|
<B>E</B>
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
<charCount>1199</charCount>
|
<charCount>1199</charCount>
|
||||||
<wordCount>216</wordCount>
|
<wordCount>216</wordCount>
|
||||||
<paraCount>7</paraCount>
|
<paraCount>7</paraCount>
|
||||||
<cursorPos>825</cursorPos>
|
<cursorPos>1066</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
|
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
|
||||||
<name>Another Scene</name>
|
<name>Another Scene</name>
|
||||||
@@ -257,9 +257,9 @@
|
|||||||
<expanded>False</expanded>
|
<expanded>False</expanded>
|
||||||
<exported>True</exported>
|
<exported>True</exported>
|
||||||
<layout>NOTE</layout>
|
<layout>NOTE</layout>
|
||||||
<charCount>115</charCount>
|
<charCount>241</charCount>
|
||||||
<wordCount>24</wordCount>
|
<wordCount>51</wordCount>
|
||||||
<paraCount>1</paraCount>
|
<paraCount>3</paraCount>
|
||||||
<cursorPos>135</cursorPos>
|
<cursorPos>135</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
<item handle="5eaea4e8cdee8" order="2" parent="15c4492bd5107">
|
<item handle="5eaea4e8cdee8" order="2" parent="15c4492bd5107">
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ def testIndexCheckThese(nwTempProj):
|
|||||||
"# Hello World!\n"
|
"# Hello World!\n"
|
||||||
"@pov: Jane"
|
"@pov: Jane"
|
||||||
))
|
))
|
||||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '2858dcd1057d3', 'CHARACTER']}"
|
assert str(theIndex.tagIndex) == "{'Jane': [2, '2858dcd1057d3', 'CHARACTER', 'T000001']}"
|
||||||
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
||||||
|
|
||||||
assert str(theIndex.checkThese(["@tag", "Jane"], cItem)) == "[True, True]"
|
assert str(theIndex.checkThese(["@tag", "Jane"], cItem)) == "[True, True]"
|
||||||
@@ -195,7 +195,7 @@ def testIndexMeta(nwTempProj):
|
|||||||
"\n"
|
"\n"
|
||||||
"Well, not really.\n"
|
"Well, not really.\n"
|
||||||
))
|
))
|
||||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '2858dcd1057d3', 'CHARACTER']}"
|
assert str(theIndex.tagIndex) == "{'Jane': [2, '2858dcd1057d3', 'CHARACTER', 'T000001']}"
|
||||||
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
||||||
|
|
||||||
# The novel structure should contain the pointer to the novel file header
|
# The novel structure should contain the pointer to the novel file header
|
||||||
@@ -214,6 +214,6 @@ def testIndexMeta(nwTempProj):
|
|||||||
|
|
||||||
# The character file should have a record of the reference from the novel file
|
# The character file should have a record of the reference from the novel file
|
||||||
theRefs = theIndex.getBackReferenceList(cHandle)
|
theRefs = theIndex.getBackReferenceList(cHandle)
|
||||||
assert str(theRefs) == "{'41cfc0d1f2d12': 3}"
|
assert str(theRefs) == "{'41cfc0d1f2d12': 'T000001'}"
|
||||||
|
|
||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
|
|||||||
Reference in New Issue
Block a user