Make some minor improvements to handling of tags and references
This commit is contained in:
+31
-13
@@ -227,7 +227,7 @@ class NWIndex:
|
||||
"""Scan a piece of text associated with a handle. This will
|
||||
update the indices accordingly. This function takes the handle
|
||||
and text as separate inputs as we want to primarily scan the
|
||||
files before we save them in which case we already have the
|
||||
files before we save them, in which case we already have the
|
||||
text.
|
||||
"""
|
||||
theItem = self.theProject.tree[tHandle]
|
||||
@@ -238,9 +238,8 @@ class NWIndex:
|
||||
logger.info("Not indexing non-file item '%s'", tHandle)
|
||||
return False
|
||||
|
||||
# Delete tags and create new item entry
|
||||
for tTag in self._itemIndex.allItemTags(tHandle):
|
||||
del self._tagsIndex[tTag]
|
||||
# Keep a record of existing tags, and create a new item entry
|
||||
itemTags = dict.fromkeys(self._itemIndex.allItemTags(tHandle), False)
|
||||
self._itemIndex.add(tHandle, theItem)
|
||||
|
||||
# Run word counter for the whole text
|
||||
@@ -279,7 +278,7 @@ class NWIndex:
|
||||
nTitle = nLine
|
||||
|
||||
elif aLine.startswith("@"):
|
||||
self._indexKeyword(tHandle, aLine, nTitle, theItem.itemClass)
|
||||
self._indexKeyword(tHandle, aLine, nTitle, theItem.itemClass, itemTags)
|
||||
|
||||
elif aLine.startswith("%"):
|
||||
if nTitle > 0:
|
||||
@@ -300,6 +299,12 @@ class NWIndex:
|
||||
if nTitle == 0:
|
||||
self._indexWordCounts(tHandle, theText, nTitle)
|
||||
|
||||
# Prune no longer used tags
|
||||
for tTag, isActive in itemTags.items():
|
||||
if not isActive:
|
||||
logger.verbose("Deleting removed tag '%s'", tTag)
|
||||
del self._tagsIndex[tTag]
|
||||
|
||||
# Update timestamps for index changes
|
||||
nowTime = round(time())
|
||||
self._timeIndex = nowTime
|
||||
@@ -359,9 +364,11 @@ class NWIndex:
|
||||
self._itemIndex.setHeadingSynopsis(tHandle, sTitle, theText)
|
||||
return
|
||||
|
||||
def _indexKeyword(self, tHandle, aLine, nTitle, itemClass):
|
||||
def _indexKeyword(self, tHandle, aLine, nTitle, itemClass, itemTags):
|
||||
"""Validate and save the information about a reference to a tag
|
||||
in another file.
|
||||
in another file, or the setting of a tag in the file. A record
|
||||
of active tags is updated so that no longer used tags can be
|
||||
pruned later.
|
||||
"""
|
||||
isValid, theBits, _ = self.scanThis(aLine)
|
||||
if not isValid or len(theBits) < 2:
|
||||
@@ -374,8 +381,10 @@ class NWIndex:
|
||||
|
||||
sTitle = f"T{nTitle:06d}"
|
||||
if theBits[0] == nwKeyWords.TAG_KEY:
|
||||
self._tagsIndex.add(theBits[1], tHandle, sTitle, itemClass)
|
||||
self._itemIndex.setHeadingTag(tHandle, sTitle, theBits[1])
|
||||
tagName = theBits[1]
|
||||
self._tagsIndex.add(tagName, tHandle, sTitle, itemClass)
|
||||
self._itemIndex.setHeadingTag(tHandle, sTitle, tagName)
|
||||
itemTags[tagName] = True
|
||||
else:
|
||||
self._itemIndex.addHeadingReferences(tHandle, sTitle, theBits[1:], theBits[0])
|
||||
|
||||
@@ -884,6 +893,11 @@ class ItemIndex:
|
||||
|
||||
|
||||
class IndexItem:
|
||||
"""This object represents the index data of a project item (NWItem).
|
||||
It holds a record of all the headings in the text, and the meta data
|
||||
associated with each heading. It also holds a pointer to the project
|
||||
item.
|
||||
"""
|
||||
|
||||
def __init__(self, tHandle, tItem):
|
||||
self._handle = tHandle
|
||||
@@ -1027,6 +1041,10 @@ class IndexItem:
|
||||
|
||||
|
||||
class IndexHeading:
|
||||
"""This object represents a section of text in a project item
|
||||
associated with a single (valid) heading. It holds a separate record
|
||||
of all references made under each heading.
|
||||
"""
|
||||
|
||||
def __init__(self, key, level="H0", title=""):
|
||||
self._key = key
|
||||
@@ -1148,7 +1166,7 @@ class IndexHeading:
|
||||
def packReferences(self):
|
||||
"""Pack references into a dictionary for saving to cache.
|
||||
"""
|
||||
return {key: list(value) for key, value in self._refs.items()}
|
||||
return {key: ",".join(value) for key, value in self._refs.items()}
|
||||
|
||||
def unpackData(self, data):
|
||||
"""Unpack a heading entry from a dictionary.
|
||||
@@ -1170,9 +1188,9 @@ class IndexHeading:
|
||||
for tagKey, refTypes in data.items():
|
||||
if not isinstance(tagKey, str):
|
||||
raise ValueError("itemIndex reference key must be a string")
|
||||
if not isinstance(refTypes, list):
|
||||
raise ValueError("itemIndex reference types must be a list")
|
||||
for refType in refTypes:
|
||||
if not isinstance(refTypes, str):
|
||||
raise ValueError("itemIndex reference types must be a string")
|
||||
for refType in refTypes.split(","):
|
||||
if refType in nwKeyWords.VALID_KEYS:
|
||||
self.addReference(tagKey, refType)
|
||||
else:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
### Making a Scene
|
||||
|
||||
@pov: Jane
|
||||
@char: John
|
||||
@char: John, Jane
|
||||
@location: Earth
|
||||
|
||||
A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
### Jane Cannot Find John
|
||||
|
||||
@pov: Jane
|
||||
@focus: John
|
||||
@location: Space
|
||||
|
||||
Jane has been looking all over for John. He’s nowhere to be found on Earth, so Jane goes to space.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
### We Found John!
|
||||
|
||||
@pov: John
|
||||
@focus: John
|
||||
@location: Mars
|
||||
|
||||
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.
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
@tag: Earth
|
||||
@location: Space
|
||||
|
||||
Third planet from the sun, fairly dense, and with lots of people on it.
|
||||
Third planet from the sun, fairly dense, and with lots of people on it.
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"T000001": {"level": "H2", "title": "Chapter One", "tag": "", "cCount": 419, "wCount": 67, "pCount": 1, "synopsis": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam."}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"88243afbe5ed8": {
|
||||
@@ -45,7 +45,7 @@
|
||||
"T000013": {"level": "H4", "title": "Scene One, Section Two", "tag": "", "cCount": 1561, "wCount": 230, "pCount": 2, "synopsis": ""}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"f96ec11c6a3da": {
|
||||
@@ -55,7 +55,7 @@
|
||||
"T000015": {"level": "H4", "title": "Scene Two, Section Two", "tag": "", "cCount": 2009, "wCount": 301, "pCount": 3, "synopsis": ""}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"846352075de7d": {
|
||||
@@ -70,7 +70,7 @@
|
||||
"T000001": {"level": "H2", "title": "Chapter Two", "tag": "", "cCount": 477, "wCount": 70, "pCount": 1, "synopsis": "Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue."}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"eb103bc70c90c": {
|
||||
@@ -79,7 +79,7 @@
|
||||
"T000001": {"level": "H3", "title": "Scene Three", "tag": "", "cCount": 3006, "wCount": 439, "pCount": 4, "synopsis": "Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"f8c0562e50f1b": {
|
||||
@@ -88,7 +88,7 @@
|
||||
"T000001": {"level": "H3", "title": "Scene Four", "tag": "", "cCount": 3839, "wCount": 563, "pCount": 6, "synopsis": "Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo."}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"47666c91c7ccf": {
|
||||
@@ -97,7 +97,7 @@
|
||||
"T000001": {"level": "H3", "title": "Scene Five", "tag": "", "cCount": 3644, "wCount": 543, "pCount": 5, "synopsis": "Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus."}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Bod": ["@pov"], "Main": ["@plot"], "Europe": ["@location"]}
|
||||
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
|
||||
}
|
||||
},
|
||||
"4c4f28287af27": {
|
||||
@@ -106,7 +106,7 @@
|
||||
"T000001": {"level": "H1", "title": "Nobody Owens", "tag": "Bod", "cCount": 1864, "wCount": 284, "pCount": 3, "synopsis": ""}
|
||||
},
|
||||
"references": {
|
||||
"T000001": {"Main": ["@plot"]}
|
||||
"T000001": {"Main": "@plot"}
|
||||
}
|
||||
},
|
||||
"2426c6f0ca922": {
|
||||
|
||||
Reference in New Issue
Block a user